2015-04-08 7 views
5

Działa w dziwny problem na mojej stronie ASP MVC 4. Jeśli użytkownik otworzy formularz create i spróbuje dodać agenta do naszej bazy danych, oczywiście najpierw przeprowadzimy walidację na tych polach. Jeśli wystąpi błąd, zapisujemy agenta w stanie niepełnym i przekierowujemy użytkownika z powrotem na stronę tworzenia.Brzytwa nie wyrenderuje ukrytych dokładnych PK w HiddenFor

Błąd pojawia się, gdy użytkownik próbuje ponownie zapisać agenta. Przy pierwszym powrocie agent jest zapisywany w bazie danych i generowany jest PK. Jednak w drugim odesłaniu zwrotnym serwer PK jest wysyłany na serwer o wartości 0 zamiast tego, co zostało wygenerowane automatycznie.

Dodałem HiddenFor w widoku Create, jednak renderuje to o wartości 0 za każdym razem.

mam wszedł również za pomocą kodu, aby upewnić się, że PK jest generowany po .Save nazywa, jest wciąż obecny, gdy return View nazywa i zapewnił również, że nieruchomość Model.ID zawiera tę samą wartość, gdy widok jest bycie renderowane.

Niezależnie od tego, czy mam rację kliknij stronę i przeglądać źródła, pole ukryte czyni tak:

<input data-val="false" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="0" /> 

model

public partial class AgentTransmission 
{ 
    public int ID { get; set; } 
    . 
    . 
    . 
} 

Zobacz

@model MonetModelFromDb.Models.AgentTransmission 

@{ 
    ViewBag.Title = "Create new Agent"; 
} 

@Html.HiddenFor(model => model.CreatedDate, new { data_val = "false" }) 
@Html.HiddenFor(model => model.CreatedOperator, new { data_val = "false" }) 
@Html.HiddenFor(model => model.ReferenceNumber, new { data_val = "false" }) 
@Html.HiddenFor(model => model.Region, new { data_val = "false" }) 
@Html.HiddenFor(model => model.INDDist, new { data_val = "false" }) 
@Html.HiddenFor(model => model.LastChangeDate, new { data_val = "false" }) 
@Html.HiddenFor(model => model.LastChangeOperator, new { data_val = "false" }) 
@Html.HiddenFor(model => model.EditTaxId, new { data_val = "false" }) 
@Html.HiddenFor(model => model.ParentId, new { data_val = "false" }) 
@Html.HiddenFor(model => model.IsSubstat, new { data_val = "false" }) 
@Html.HiddenFor(model => model.ID, new { data_val = "false" }) 

Przedstawiane HiddenFor rozdział

<input data-val="false" data-val-date="The field CreatedDate must be a date." id="CreatedDate" name="CreatedDate" type="hidden" value="" /> 
<input data-val="false" id="CreatedOperator" name="CreatedOperator" type="hidden" value="" /> 
<input data-val="false" id="Region" name="Region" type="hidden" value="NM-834" /> 
<input data-val="false" id="INDDist" name="INDDist" type="hidden" value="834" /> 
<input data-val="false" data-val-date="The field LastChangeDate must be a date." data-val-required="The LastChangeDate field is required." id="LastChangeDate" name="LastChangeDate" type="hidden" value="4/8/2015 10:43:30 AM" /> 
<input data-val="false" id="LastChangeOperator" name="LastChangeOperator" type="hidden" value="TYPCLS" /> 
<input data-val="false" data-val-required="The EditTaxId field is required." id="EditTaxId" name="EditTaxId" type="hidden" value="False" /> 
<input data-val="false" data-val-number="The field ParentId must be a number." id="ParentId" name="ParentId" type="hidden" value="" /> 
<input data-val="false" data-val-required="The IsSubstat field is required." id="IsSubstat" name="IsSubstat" type="hidden" value="False" /> 
<input data-val="false" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="0" /> 

Controller

[HttpPost] 
    [MonetAuthorize] 
    public ActionResult Create(AgentTransmission agenttransmission, bool andAddAgent = false) 
    { 
    . 
    . 
    . 
     //Determine if this is first POST or not 
     if (agenttransmission.ID > 0) 
     { 
      db.Entry(agenttransmission).State = EntityState.Modified; 
     } 
     else 
     { 
      db.AgentTransmission.Add(agenttransmission); 
     } 
     db.SaveChanges(); 

     //Send back to view if errors pressent 
     if (!String.IsNullOrWhiteSpace(errorMsg)) 
     { 
      return View(agenttransmission); 
     }   
    } 

EDIT

Jeśli usunąć HiddenFor pomocnika i po prostu wyciąć/wklej renderowany input tag, jestem w stanie uchwycić Corret wartość PK. Jest to jednak trochę hacky więc miałem nadzieję znaleźć bardziej eleganckie rozwiązanie (jeśli to możliwe)

<input data-val="false" id="ID" name="ID" type="hidden" value="@Model.ID" /> 
+0

Pamiętam, jak wpadałem na coś dziwnego w przeszłości i ostatecznie renderowałem to pole bezpośrednio, zamiast korzystać z pomocy. jeśli wstawisz w twoim widoku pokazuje to prawidłowy identyfikator? –

+0

Tak, ale mam nadzieję znaleźć bardziej eleganckie rozwiązanie ... jeśli to możliwe. – NealR

+0

Próbowałem kilku różnych rzeczy, ale nigdy nie udawało mi się sprawić, by działał w takich sytuacjach. Zawsze po prostu pracował nad tym. Mam nadzieję, że ktoś inny będzie miał bardziej eleganckie rozwiązanie –

Odpowiedz

6

Wariacje na to pytanie zadawane są tutaj często. Zasadniczo sprowadza się do obiektu ModelState i faktu, że jego wartości zastępują wartości w rzeczywistym modelu dla widoku. Po opublikowaniu formularza 0 ustawia się w obiekcie ModelState dla właściwości ID. W akcji posta zapisujesz encję, która powoduje aktualizację jej właściwości, ale 0 nadal znajduje się w ModelState. Gdy zwrócisz widok, 0 ponownie ustawia się jako wartość dla ID, ponieważ znowu jest to ModelState.

Powód, dla którego działa w ten sposób najlepiej wyjaśnić na przykładzie. Załóżmy, że masz formularz, w którym edytujesz istniejący obiekt, który ma właściwość Name ustawioną na "Foo". Użytkownik zmienia to w formularzu na "Bar", a następnie publikuje formularz.Jednak zaniedbali wypełnienie wymaganego pola, więc błąd uniemożliwia zapisanie ich aktualizacji. Co powinno się stać w tym momencie? Jeśli użyjemy wartości modelu, pole Name zostanie zresetowane do "Foo". Jednakże, jeśli użyto ModelState, pole Name zachowuje modyfikację użytkownika "Bar". W tym drugim przypadku po prostu naprawiają błąd i publikują ponownie. W pierwszym muszą przerobić wszystkie zmiany, które wprowadzili do formularza wcześniej, co oczywiście byłoby bardzo słabym doświadczeniem użytkownika.

Teraz, jak to naprawić. Najlepszym sposobem jest śledzenie wzoru PRG (Post-Redirect-Get). Jeśli zgłoszenie jest dobre i pomyślnie zapisałeś zmiany, nie zwróć widoku, nawet jeśli chcesz, aby użytkownik mógł natychmiast wprowadzić dodatkowe zmiany. Jeśli chcesz, po prostu przekieruj z powrotem do tej samej akcji, ale proces przekierowania wystarczy, aby wyczyścić ModelState, aby użytkownik teraz wchodził w interakcje ze zaktualizowanym modelem wyciągniętym z bazy danych.

Jeśli to nie jest możliwe, możesz po prostu wyczyścić ModelState. Odradzam usuwanie go całkowicie, ponieważ możesz wywołać bardzo dużą frustrację użytkownika, jak opisano w powyższym przykładzie. Jeśli naprawdę nie możesz wykonać przekierowania, spróbuj tylko wyczyścić wartości, które naprawdę potrzebujesz.

ModelState.Remove("ID"); 
Powiązane problemy