web-dev-qa-db-fra.com

Réinitialiser la valeur de textarea après la soumission du formulaire

  1. Je veux envoyer un message à userID = 3 en allant à/MyController/Message/3
  2. Ceci exécute l'action Message () [get], j'entre du texte dans la zone de texte et cliquez sur Enregistrer pour afficher le formulaire.
  3. Message () [post] L'action enregistre les modifications, réinitialise la valeur de SomeText en chaîne vide et revient à la vue.

À ce stade, je m'attends à ce que la zone de texte soit vide car j'ai défini ViewData ["SomeText"] sur string.Empty

Pourquoi la valeur de la zone de texte n'est-elle pas mise à jour en chaîne vide après une action de publication?

Voici les actions:

[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();
}

Et la vue correspondante:

<%@ 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>
28
xraminx

Le problème est que HtmlHelper récupère la valeur ModelState, qui est renseignée avec les données publiées. Plutôt que de contourner ce problème en réinitialisant ModelState, pourquoi ne pas rediriger vers l'action [get]. L'action [post] peut également définir un message d'état temporaire comme celui-ci:

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

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

Cela me semble être un comportement plus correct.

39
roryf

Le problème est que votre ModelState est rempli à nouveau avec les valeurs publiées.

Ce que vous pouvez faire, c’est effacer l’action qui a l’attribut Post:

ModelState.Clear();
68
Olivier Payen

Les aides HTML lisent la valeur de ModelState. Et il n'y a pas de moyen élégant de remplacer ce comportement.

Mais si vous ajoutez cette ligne après SaveToDB(ID, SomeText), cela devrait fonctionner:

ModelState["SomeText"].Value = 
    new ValueProviderResult("", "", CultureInfo.CurrentCulture);
7
Çağdaş Tekin

Au lieu d'utiliser ModelState.Clear (), qui efface tout l'état du modèle, vous pouvez effectuer ModelState.Remove ("SomeText"), si vous le souhaitez. Ou restituer l'entrée sans les extensions htmlhelper. Elles sont conçues pour prendre la valeur de ModelState au lieu du modèle (ou viewdata).

1
Kirsten

J'ai tout essayé, mais je n'ai travaillé que lorsque j'ai fait quelque chose comme ceci:

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));

J'espère que cela t'aides.

1
MalachiteBR

Do.th. comme ça:

ajouter:

ModelState.Clear();

avant l'instruction return de la méthode d'action boutons de soumission. Travaille pour moi. Cela pourrait fonctionner pour vous. 

0
user6243946

Est-il possible que l'état du modèle ait été mis à jour avec une erreur? Je pense que la valeur tentée sera extraite de l'état du modèle plutôt que de la vue ou du modèle si l'état du modèle n'est pas valide.

EDIT: J'inclus la section correspondante du code source de l'extension TextArea HtmlHelper ci-dessous. Il me semble que cela correspond exactement à mes attentes - en cas d'erreur de modèle, il extrait la valeur de l'état du modèle, sinon il l'utilise de ViewData. Notez que dans votre méthode Post, la clé "SomeText" ne devrait même pas exister tant que vous ne l’avez pas définie, c’est-à-dire qu’elle ne sera pas reportée de la version du code qui répond à GET.

Étant donné que vous fournissez explicitement une valeur à ViewData, useViewData doit être false, attemptedValue doit être false sauf si une erreur a été définie dans l'état du modèle.

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

C'est un comportement côté client. Je recommanderais d'utiliser javascript. Si vous utilisez JQuery, vous pouvez le faire comme ceci:

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

Je n'utilise plus Javascript, mais je crois en JS classique que c'est comme:

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

(Vous feriez ceci sur l'un des événements de charge. 

<body onload="...">

J'espère que cela t'aides.

0
Jeff Ancel

Je suis à peu près certain que la zone de texte récupère la valeur de Request.Form sous le capot puisque ViewData ["SomeText"] est vide.

0
Mike Geise