2015-04-08 14 views
5

In esecuzione in un problema strano nel mio sito ASP MVC 4. Se l'utente apre il modulo create e tenta di aggiungere un agente al nostro database, per prima cosa eseguiamo la convalida sui campi. Se c'è un errore, salviamo l'agente in stato incompleto e reindirizza l'utente alla pagina di creazione.Razor non renderà PK nascosto nascosto in HiddenFor

L'errore si verifica quando l'utente tenta di salvare nuovamente l'agente. Al primo post-back, l'agente viene salvato nel database e viene generata una PK. Nel secondo post-back, tuttavia, il PK viene inviato al server con un valore di 0 anziché quello che è stato appena generato automaticamente.

Ho aggiunto un alla vista Create, tuttavia questo esegue il rendering con un valore di 0 ogni volta.

Ho anche intensificato tramite il codice per assicurarsi che il PK viene generato dopo il .Save è chiamato, è ancora presente quando return View è chiamato anche assicurato che la proprietà Model.ID contiene lo stesso valore quando la vista è essere reso.

Indipendentemente da ciò, se mi fate clic destro della pagina e visualizzare l'origine, il campo nascosto rende in questo modo:

<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" /> 

Modello

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

View

@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" }) 

Rendered HiddenFor Sezione

<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

Se rimuovo il HiddenFor aiutante e semplicemente tagliare/incollare il tag reso input, sono in grado di catturare il valore PK corret. Tuttavia, questo è un po 'hacky quindi speravo di trovare una soluzione più elegante (se possibile)

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

Ricordo di aver incontrato qualcosa di strano in passato e ho finito per rendere il campo direttamente invece di usare l'helper. se metti sulla tua vista mostra l'id corretto allora? –

+0

Sì, lo fa, tuttavia speravo di trovare una soluzione più elegante ... se è possibile. – NealR

+0

Ho provato diverse cose ma non ho mai avuto successo nel farlo funzionare in quelle situazioni. Ci ho sempre lavorato intorno. Speriamo che qualcun altro abbia una soluzione più elegante –

risposta

6

Variazioni su questa domanda viene chiesto spesso qui. Fondamentalmente si riduce all'oggetto ModelState e al fatto che i suoi valori sovrascrivono i valori sul modello effettivo per la vista. Quando si invia il modulo, 0 viene impostato nell'oggetto ModelState per la proprietà ID. Nell'azione successiva, si salva l'entità, che causa l'aggiornamento della proprietà ID, ma 0 è ancora in ModelState. Quando si restituisce la vista, 0 viene impostato nuovamente come valore per ID, perché, ancora una volta, è ciò che è in ModelState.

Il motivo per cui funziona in questo modo è spiegato meglio da un esempio. Supponiamo che tu abbia un modulo in cui stai modificando un'entità esistente, che ha una proprietà Name impostata su "Foo". L'utente lo modifica nel modulo in "Barra" e quindi pubblica il modulo.Tuttavia, hanno trascurato di compilare un campo obbligatorio, quindi l'errore impedisce il salvataggio dell'aggiornamento. Cosa dovrebbe accadere a questo punto? Se utilizziamo il valore del modello, il campo Name verrà ripristinato su "Foo". Tuttavia, se viene utilizzato ModelState, il campo Name mantiene la modifica dell'utente di "Barra". In quest'ultimo caso, si limitano a correggere l'errore e a pubblicare di nuovo. Nel primo caso, devono rifare tutte le modifiche apportate al modulo in precedenza, il che ovviamente sarebbe un'esperienza utente molto scarsa.

Ora, su come risolvere questo problema. Il modo migliore è seguire lo schema PRG (Post-Redirect-Get). Se l'invio è valido e le modifiche sono state salvate correttamente, non restituire la vista, anche se si desidera che l'utente sia in grado di apportare immediatamente ulteriori modifiche. Se lo si desidera, è sufficiente reindirizzare nuovamente alla stessa azione, ma il processo di reindirizzamento è sufficiente per cancellare ModelState in modo che l'utente stia ora interagendo con il modello aggiornato estratto dal database.

Se ciò non è fattibile, è sufficiente cancellare il numero ModelState. Vorrei sconsigliarne la cancellazione completamente, in quanto è possibile causare una vera e propria frustrazione per l'utente, come descritto nell'esempio sopra. Se davvero non puoi eseguire un reindirizzamento, prova a cancellare solo i valori in ModelState che ti servono davvero.

ModelState.Remove("ID");