2009-04-25 10 views
27
  1. voglio inviare un messaggio a userID = 3 andando a/MyController/Messaggio/3
  2. Questo esegue Message() [ottenere] azione, entro in un testo in l'area di testo e fare clic su Salva per inviare il modulo
  3. L'azione Message() [post] salva le modifiche, reimposta il valore di SomeText per svuotare la stringa e torna alla visualizzazione.

A questo punto mi aspetto l'area di testo per essere vuoto perchè ho impostato Viewdata [ "someText"] per string.EmptyRipristinare il valore del textarea dopo modulo di presentazione

Perché valore dell'area di testo non aggiornato alla stringa vuota dopo l'azione post?

Qui ci sono le azioni:

[AcceptVerbs(HttpVerbs.Get)] 
public ActionResult Message(int ID) 
{ 
    ViewData["ID"] = ID; 
    return View(); 
} 

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Message(int ID, string SomeText) 
{ 
    // save Text to database 
    SaveToDB(ID, SomeText); 

    // set the value of SomeText to empty and return to view 
    ViewData["SomeText"] = string.Empty; 
    return View(); 
} 

e la corrispondente vista:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
    Inherits="System.Web.Mvc.ViewPage" %> 
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> 
<% using (Html.BeginForm()) 
    { %> 
     <%= Html.Hidden("ID", ViewData["ID"])%> 
     <label for="SomeText">SomeText:</label> 
     <%= Html.TextArea("SomeText", ViewData["SomeText"]) %> 
     <input type="submit" value="Save" /> 
<% } %> 
</asp:Content> 

risposta

38

Il problema è la HtmlHelper sta recuperando il valore ModelState, che viene riempito con i dati pubblicati. Anziché eseguire l'hacking di tutto ciò reimpostando ModelState, perché non eseguire il reindirizzamento all'azione [get]. L'azione [post] potrebbe anche impostare un messaggio di stato provvisorio in questo modo:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Message(int ID, string SomeText) 
{ 
    // save Text to database 
    SaveToDB(ID, SomeText); 

    TempData["message"] = "Message sent"; 
    return RedirectToAction("Message"); 
} 

Questo mi sembra un comportamento più corretto.

+2

Penso che sia meglio che cancellare il ModelState. Se stai facendo un post, allora non hai davvero bisogno di più di un semplice messaggio che ritorna. Se senti la necessità di restituire un modello completo, probabilmente dovresti fare un get in primo luogo. Guarda anche nello schema PRG; potrebbe chiarire un po 'questo.Questo può anche risolvere quel fastidioso messaggio del browser che a volte si può ottenere quando si aggiorna e chiede se si desidera re-postare un modulo. –

+0

Sto facendo esattamente questo, e sta lavorando sulla maggior parte delle mie forme tranne alcune (forse 2 o 3). Come mai la pagina sta ancora restituendo i valori da 'ModelState' anche dopo averla postata e usando' RedirectToAction ("save", new {id = 0}); 'alla fine di' Save (MyModel vm) '? Cosa posso fare per resettare il modulo dopo averlo postato diverso da 'ModelState.Clear()'? – barnes

+0

Ho trovato la soluzione. 'UpdateTargetId' di' Ajax.BeginForm' è stato fornito con 'Id' errato. – barnes

0

E 'possibile che lo Stato modello è stato aggiornato con un errore? Credo che estrarrà il valore tentato dallo stato del modello anziché dai dati della vista o dal modello se lo stato del modello non è valido.

EDIT: Sto inclusa la sezione dedicata del source code dall'estensione HtmlHelper TextArea di seguito. Mi sembra che faccia esattamente quello che mi aspettavo - se c'è stato un errore del modello, tira il valore dallo stato del modello, altrimenti lo usa da ViewData. Nota che nel tuo metodo Post la chiave "SomeText" non dovrebbe nemmeno esistere fino a quando non la imposti, cioè, non sarà portata avanti dalla versione del codice che risponde al GET.

Poiché si specifica esplicitamente un valore per ViewData, useViewData deve essere falso, attemptedValue deve essere falso a meno che non sia stato impostato un errore nello stato del modello.

// If there are any errors for a named field, we add the css attribute. 
    ModelState modelState; 
    if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState)) { 
     if (modelState.Errors.Count > 0) { 
      tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName); 
     } 
    } 

    // The first newline is always trimmed when a TextArea is rendered, so we add an extra one 
    // in case the value being rendered is something like "\r\nHello". 
    // The attempted value receives precedence over the explicitly supplied value parameter. 
    string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string)); 
    tagBuilder.SetInnerText(Environment.NewLine + (attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : value))); 
    return tagBuilder.ToString(TagRenderMode.Normal); 
+0

Non penso ci siano stati errori. Ho avuto lo stesso problema in un'altra forma. Mi sono grattato la testa da qualche giorno ma non sono riuscito a capire perché stia succedendo. È piuttosto fastidioso quando non si ha il controllo su ciò che appare nel modulo dopo l'azione post. Mi stavo chiedendo se sto facendo qualcosa di insolito o sbagliato. – xraminx

0

Questo è un comportamento clientide. Consiglierei di usare javascript. Se si utilizza JQuery, si può fare in questo modo:

<script type="text/javascript"> 
$(function(){ $("#SomeText").val("");}); 
</script> 

io non uso più Javascript, ma credo che in una regolare JS che è come:

document.getElementById("SomeText").value = ""; 

(si dovrebbe fare questo su uno degli eventi di caricamento.

<body onload="..."> 

Spero che questo aiuti.

+0

Io non la penso così. La vista viene renderizzata sul lato server prima di essere trasferita sul mio browser. – xraminx

+0

Sono d'accordo, ma stavo pensando a una soluzione rapida. Non sono sicuro del motivo per cui sta tornando in quel modo. Lo ha sempre fatto per me in un post, pensavo fosse una caratteristica. –

0

sono abbastanza certo textarea è afferrare t ha valore dal Request.Form sotto il cofano visto che ViewData ["SomeText"] è vuoto.

+0

Quindi stai suggerendo che il modo corretto per farlo è il seguente? Request.Form ["SomeMessage"] = string.Empty; – xraminx

+0

No: Request.Form non viene utilizzato dall'estensione HtmlHelper. – tvanfosson

+0

Non lo direi. È possibile assegnare un nome al titolo del parametro querystring e avere la casella di testo con il titolo del nome e il TextBox avrà il valore di querystring. Inoltre estraggono i valori da Request.Form, in quale altro modo otterrebbero i valori per popolare il modulo o restituiscono i risultati quando il modulo viene pubblicato. –

7

Gli helper HTML leggono il valore da ModelState. E non c'è un modo elegante per ignorare questo comportamento.

Ma se si aggiunge questa linea dopo SaveToDB(ID, SomeText), dovrebbe funzionare:

ModelState["SomeText"].Value = 
    new ValueProviderResult("", "", CultureInfo.CurrentCulture); 
+0

Grazie risolto il mio problema ed è stato molto utile! –

68

Il problema è che il ModelState è ri-riempita con i valori iscritti.

Che cosa si può fare è chiaro che sull'azione che ha l'attributo del messaggio:

ModelState.Clear(); 
+1

Questo dovrebbe essere contrassegnato come la migliore risposta. Ho dovuto mantenere un valore booleano nel ViewBag e la funzione RedirectToAction() rimuove i dati da esso. – DaveWut

1

Ho provato di tutto, ma ha funzionato solo quando ho fatto qualcosa di simile:

ModelState.Clear(); 
//This will clear the address that was submited 
viewModel.Address = new Address(); 
viewModel.Message = "Dados salvos com sucesso!"; 
return View("Addresses", ReturnViewModel(viewModel)); 

Spero che questo aiuti.

1

Invece di utilizzare ModelState.Clear() che cancella l'intero stato del modello, è possibile eseguire ModelState.Remove ("SomeText"), se lo si desidera. O rendere l'input senza le estensioni htmlhelper. Sono progettati per prendere il valore da ModelState anziché dal Model (o dal viewdata).

0

Do s.th. in questo modo:

aggiuntivo:

ModelState.Clear(); 

prima della return istruzione del metodo dell'azione presentare pulsanti. Per me va bene. Potrebbe funzionare per te.

Problemi correlati