EF core ASP.net core update helyett insert hibás Id miatt

EF core ASP.net core update helyett insert hibás Id miatt
2020-04-22T19:14:32+02:00
2020-04-23T14:40:56+02:00
2022-10-15T21:16:40+02:00
DerStauner
Sziasztok!

Van egy view, azon egy grid, kiválasztok egy rekordot, majd szerkesztés gomb, majd megjelennek egy popupban a rekord adatai. Módosítás után mentés és a grid frissítése. Viszont ahelyett, hogy az EF módosítaná az adatokat, új rekordot szúr be a módosított adatokkal. Mégpedig azért, mert az Id 0 értéket kap (debug szerint), ami ugye azt jelenti az EF-nek, hogy új rekord. Annak ellenére, hogy a popup tartalmazza az Id-t mint rejtett elem a helyes értékkel (ellenőriztem). DevExtreme komponenseket használok, de szerintem nem ezzel függ össze a hiba.

A kérdés az, hogy miért post-ol vissza 0 Id-t a view, ezáltal pedig új rekord beillesztése történik? A furcsa az, hogy a módosított értékeket visszakapom a kapcsolódó controller akcióban, szóval a model binding ezekre működik.

A modell (validáló attribútumokat eltávolítottam), a Documents egy shadow property:

public class Sender { public long Id { get; set; } public string Name { get; set; } public string Address { get; set; } public string ContactPerson { get; set; } public string ContactEmail { get; set; } public IEnumerable<Document> Documents { get; set; } }
A repository:

public class DataSender : IRepositorySender { private DataContext DataContext; public DataSender(DataContext Context) { DataContext = Context; } public IEnumerable<Sender> Senders => DataContext.Senders; public Sender GetSender(long SenderId) { return DataContext.Senders.Find(SenderId); } public void AddSender(Sender Sender) { DataContext.Senders.Add(Sender); DataContext.SaveChanges(); } public void UpdateSender(Sender Sender) { DataContext.Senders.Update(Sender); DataContext.SaveChanges(); } public void DeleteSender(Sender Sender) { DataContext.Senders.Remove(Sender); DataContext.SaveChanges(); } }
A kapcsolódó controller akciók:

[Route("{SenderId}")] public IActionResult GetSender(long SenderId) { ViewBag.Mode = "update"; return PartialView("Sender", SenderRepository.GetSender(SenderId)); } [HttpPost] public IActionResult UpdateSender(Sender Sender) { SenderRepository.UpdateSender(Sender); return RedirectToAction(nameof(List)); }
És a popup view:

@model Sender <form asp-action=@(ViewBag.Mode == "new" ? "AddSender" : "UpdateSender") asp-controller="Sender" method="post"> @using (Html.DevExtreme().ValidationGroup()) { @(Html.DevExtreme().Form<Sender>() .ID("form") .FormData(Model) .ColCount(1) .Items(items => { items.AddSimpleFor(m => Model.Id).Visible(false); items.AddSimpleFor(m => Model.Name); items.AddSimpleFor(m => Model.Address); items.AddSimpleFor(m => Model.ContactPerson); items.AddSimpleFor(m => Model.ContactEmail); items.AddGroup().Items(groupItem => groupItem.AddSimple().Template( @<text> <div style="text-align: right"> @(Html.DevExtreme().Button().ID("save").Text("Mentés").Width(100).Type(ButtonType.Success).UseSubmitBehavior(true)) @(Html.DevExtreme().Button().ID("cancel").Text("Mégsem").Width(100).Type(ButtonType.Normal).OnClick("close_onClick")) </div> </text>)); }) .LabelLocation(FormLabelLocation.Top) ) } </form>
Köszi.
Mutasd a teljes hozzászólást!
Annak ellenére, hogy a popup tartalmazza az Id-t mint rejtett elem a helyes értékkel (ellenőriztem).

Ebben biztos vagy? Én akármennyire nézem csak azt látom, hogy a visible = false egyszerűen kiveszi a generált html elemet a DOM-ból. Ha az nincs, akkor természetesen a form submit-ban sem lesz benne az id. Mivel nincs benne, ezért a modelledben megmarad a long default értéke, ami 0.

Ha el akarod rejteni az id-t úgy, hogy bent maradjon a DOM-ban (és ezáltal a formodban), akkor azt css-sel tudod megtenni (visibility: none). Legalábbis a DevExtreme dokumentáció alapján nem látok erre más, támogatott módszert. Mindenesetre azt mérlegeld, hogy ezzel a megoldással egy talpraesett felhasználó azt a sendert tudja felülírni, amelyiket csak akarja, hiszen kézzel is lehet http kéréseket faragni, amibe olyan id-t ír, amilyet csak akar.
Mutasd a teljes hozzászólást!

  • A böngészőben lévő DevTools mit mond rá? Milyen HTML kódot állít elő ez a DevExtreme, és milyen request body megy az UpdateSender-nek?
    Mutasd a teljes hozzászólást!
  • Annak ellenére, hogy a popup tartalmazza az Id-t mint rejtett elem a helyes értékkel (ellenőriztem).

    Ebben biztos vagy? Én akármennyire nézem csak azt látom, hogy a visible = false egyszerűen kiveszi a generált html elemet a DOM-ból. Ha az nincs, akkor természetesen a form submit-ban sem lesz benne az id. Mivel nincs benne, ezért a modelledben megmarad a long default értéke, ami 0.

    Ha el akarod rejteni az id-t úgy, hogy bent maradjon a DOM-ban (és ezáltal a formodban), akkor azt css-sel tudod megtenni (visibility: none). Legalábbis a DevExtreme dokumentáció alapján nem látok erre más, támogatott módszert. Mindenesetre azt mérlegeld, hogy ezzel a megoldással egy talpraesett felhasználó azt a sendert tudja felülírni, amelyiket csak akarja, hiszen kézzel is lehet http kéréseket faragni, amibe olyan id-t ír, amilyet csak akar.
    Mutasd a teljes hozzászólást!
  • Az Id értéke mint adat ugyan benne van a html-ben, de balga módon azt hittem, hogy a visible=false egy hidden input element-et jelöl. Miután hozzáadtam egy valóban hidden input element-et:

    @Html.HiddenFor(m => Model.Id)
    és eltávolítottam a DevExtreme vezérlő hívását az Id mezőre, így már működik a frissítés.

    Kérdésem még, hogy egy power user ilyenkor is azt a sendert tudja felülírni, amelyiket akarja? Ha igen, hogyan lehet ezt kiküszöbölni? Van erre valami best practice/standard?
    Mutasd a teljes hozzászólást!
  • Van erre valami best practice/standard?

    Szerver oldali ellenőrzés az adatbázis művelet elvégzése előtt (pl. a postolt ID-t birizgálhatja-e a bellépett user).
    Haladóbb megoldásként CSRF token alkalmazása az űrlapoknál.
    Mutasd a teljes hozzászólást!
  • Igen, az antiforgery token megvan, automatikusan az AddMvc api hívással, ill. asp.net core 2.0-tól felfelé formtag helper-ek meglétével .
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd