2009-04-25 4 views
27
  1. Quiero enviar un mensaje a ID de usuario = 3 por ir a/myController/Mensaje/3
  2. Esto ejecuta Mensaje() [obtener] acción, entro en algún texto en el área de texto y haga clic en Guardar para publicar el formulario
  3. Mensaje() [publicar] la acción guarda los cambios, restablece el valor de SomeText a cadena vacía y regresa a la vista.

En este punto, espero que el área de texto para estar vacío porque he puesto ViewData [ "SomeText"] a String.EmptyRestablece el valor del área de texto después de la sumisión de la forma

¿Por qué es valor del área de texto no se actualiza a cadena vacía después de la acción de correos?

Aquí están las acciones:

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

y la vista correspondiente:

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

Respuesta

38

El problema es la HtmlHelper está recuperando el valor ModelState, que se llena con los datos publicados. En lugar de hackear esto al restablecer ModelState, ¿por qué no redirigir a la acción [get]? La acción [post] también podría establecer un mensaje de estado temporal como este:

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

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

Esto me parece un comportamiento más correcto.

+2

Creo que esto es mejor que simplemente borrar el ModelState. Si estás haciendo una publicación, entonces realmente no necesitas más que un simple mensaje. Si sientes la necesidad de devolver un modelo completo, entonces probablemente deberías estar haciendo un get en primer lugar. También mira en el patrón PRG; puede aclarar esto un poco.Esto también puede corregir ese molesto mensaje del navegador que a veces puede obtener al actualizar y le pregunta si desea volver a publicar un formulario. –

+0

Estoy haciendo exactamente esto, y está trabajando en la mayoría de mis formularios, excepto en algunos (2 o 3 tal vez). ¿Cómo es que la página sigue representando los valores de 'ModelState' incluso después de publicarlo y usando' RedirectToAction ("guardar", nuevo {id = 0}); 'al final de' Guardar (MyModel vm) '? ¿Qué puedo hacer para restablecer el formulario después de publicarlo que no sea 'ModelState.Clear()'? – barnes

+0

Encontré la solución. 'UpdateTargetId' de' Ajax.BeginForm' se suministró con el 'Id' incorrecto. – barnes

0

¿Es posible que el estado modelo ha sido actualizado con un error? Creo que extraerá el valor del intento del estado del modelo en lugar de ver los datos o el modelo si el estado del modelo no es válido.

EDITAR: Estoy incluyendo la sección correspondiente de la source code desde la extensión HtmlHelper TextArea a continuación. Me parece que hace exactamente lo que esperaba: si ha habido un error de modelo, extrae el valor del estado del modelo, de lo contrario lo usa de ViewData. Tenga en cuenta que en su método Post, la clave "SomeText" no debería existir hasta que la configure, es decir, no se transferirá desde la versión del código que responde al GET.

Dado que usted proporciona explícitamente un valor para ViewData, useViewData debe ser falso, attemptedValue debe ser falso a menos que se haya establecido un error en el estado del modelo.

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

No creo que haya ningún error. He tenido el mismo problema en otra forma. Me he estado rascando la cabeza durante unos días pero no pude encontrar por qué sucede esto. Es bastante molesto cuando no tienes control sobre lo que aparece en tu formulario después de la acción posterior. Me preguntaba si estoy haciendo algo inusual o incorrecto. – xraminx

0

Eso es un comportamiento del lado del cliente. Yo recomendaría usar javascript. Si utiliza jQuery, puede hacerlo de esta manera:

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

No consumo Javascript más, pero creo en JS regular que es como:

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

(podría hacer esto en uno de los eventos de carga.

<body onload="..."> 

Espero que esto ayude.

+0

No lo creo. La vista se procesa en el servidor antes de enviarla a mi navegador. – xraminx

+0

Estoy de acuerdo, pero estaba pensando en una solución rápida. No estoy seguro de por qué vuelve así. Siempre lo ha hecho para mí en una publicación posterior, pensé que era una característica. –

0

soy bastante seguro de que el área de texto es agarrar t el valor del Request.Form bajo el capó desde ViewData ["SomeText"] está vacío.

+0

¿Está sugiriendo que la forma correcta de hacerlo es la siguiente? Request.Form ["SomeMessage"] = string.Empty; – xraminx

+0

No, la extensión HtmlHelper no utiliza Request.Form. – tvanfosson

+0

No diría eso. Puede nombrar un título de parámetro querystring y tener su cuadro de texto con el título del nombre y el TextBox tendrá el valor de la cadena de consulta. También extraen sus valores del Request.Form, de qué otro modo obtendrían los valores para rellenar el formulario o devolver los resultados cuando se publique el formulario. –

7

Los helpers html leen el valor de ModelState. Y no hay una forma elegante de anular este comportamiento.

Pero si se agrega esta línea después de SaveToDB(ID, SomeText), que debería funcionar:

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

¡Gracias resolvió mi problema y fue muy útil! –

68

El problema es que su ModelState se vuelven a cubrirse con los valores publicados.

Lo que puede hacer es claro que en la acción que tiene el atributo de la publicación:

ModelState.Clear(); 
+1

Esto debería marcarse como la mejor respuesta. Tuve que mantener un valor booleano en la ViewBag y la función RedirectToAction() elimina datos de ella. – DaveWut

1

he intentado todo, pero sólo funcionaba cuando he hecho algo como esto:

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

Espero que esto ayude.

1

En lugar de usar ModelState.Clear() que borra todo el modelo de estado, puede hacer ModelState.Remove ("SomeText"), si así lo desea. O renderiza la entrada sin las extensiones htmlhelper-extensions. Están diseñados para tomar el valor de ModelState en lugar del modelo (o viewdata).

0

Do s.th. de esta manera:

complemento:

ModelState.Clear(); 

antes de la declaración del método return acción de envío botones. Funciona para mi. Podría funcionar para usted.

Cuestiones relacionadas