Si les changements de valeur dans le modèle après poste, le formulaire affiche toujours l'ancienne valeur

StackOverflow https://stackoverflow.com/questions/1848586

Question

Ce comportement me fait me demande au sujet de ma santé mentale ..

J'ai une forme qui a deux endroits qui acceptent les entrées, nous allons les appeler ValueA et ValueB. L'utilisateur peut saisir une valeur dans l'une et la forme soumet.

<div id="MyUpdateTarget">
 <% using (Ajax.BeginForm("MyControllerAction", new AjaxOptions { UpdateTargetId = "MyUpdateTarget" })) { %>
  <%=Html.TextBox("ValueA", Model.ValueA, new Dictionary<string, object> {
                                                    { "onchange", "$('#SubmitButton').click(); return false;" },
       }) %>
  <%=Html.TextBox("ValueB", Model.ValueB, new Dictionary<string, object> {
                                                    { "onchange", "$('#SubmitButton').click(); return false;" },
       }) %>
  <input id="SubmitButton" type="submit" value="Save" style="display: none;" />
 <% } %>
</div>

L'action du contrôleur ressemble à ceci:

public ActionResult MyControllerAction(MyViewModel viewModel)
{

// faire d'autres choses ...

 return PartialView("MyPartialView", viewModel);
}

Le ViewModel est simplement ceci:

public class MyViewModel
{
 private int _valueA;
 private int _valueB;

 public int ValueA 
 { 
  get
  {
   return _valueA;
  }
  set
  {
   if (value > 0)
   {
    ValueB = 0;
   }
   _valueA = value;
  } 
 }
 public int ValueB 
 {
  get
  {
   return _valueB;
  }
  set
  {
   if (value > 0)
   {
    ValueA = 0;
   }
   _valueB = value;
  }
 }
}

Maintenant, la pièce inattendue. Dites la page charge initialement et ValueB a une valeur de 7. L'utilisateur change ValueA à 5 et la forme soumet. Je peux mettre un point d'arrêt dans l'action du contrôleur et de voir les deux valeurs dans le paramètre viewmodel. À ce stade, ValueA est 5 et ValueB est 0 (en raison du réglage de ValueA). L'action retourne la viewmodel dans le cadre du PartialView. De retour dans la partie, je peux mettre un point d'arrêt sur la Html.TextBox ( « ValueB », Model.ValueB, ...) en ligne et voir que ValueB est en effet 0. Mais quand la forme rend au navigateur, ValueB a encore valeur de 7. C'est là où je suis coincé. J'ai même changé la cible de mise à jour à un autre div, de sorte que la partie juste recrache la forme quelque part complètement différent, mais il a toujours la valeur initiale de 7, même si j'ai vu à travers le débogage que la valeur était de 0 revenait de la contrôleur.

Y at-il quelque chose que je suis absent?

Était-ce utile?

La solution

Voici le code de la source MVC pour la zone de texte:

     string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string));
                tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : valueParameter**), isExplicitValue);
                break;

Et le code pour GetModelStateValue ()

    internal object GetModelStateValue(string key, Type destinationType) {
        ModelState modelState;
        if (ViewData.ModelState.TryGetValue(key, out modelState)) {
            if (modelState.Value != null) {
                return modelState.Value.ConvertTo(destinationType, null /* culture */);
            }
        }
        return null;
    }

Alors qu'est-ce qui se passe est le « aide » Html recherche la valeur de zone de texte, en faisant correspondre le nom, dans votre ViewData.ModalState, si son dans le dictionnaire ModelState, il complètement ne tient pas compte la valeur fourni.

Donc que si (valeur> 0) {ValueA = 0; } N'a pas d'importance parce que sa va utiliser les valeurs affichées dans ModelState si les noms correspondent.

La façon dont je l'ai fixé est de souffler la ModalState avant que la vue rend pour certaines valeurs que je veux jouer avec mes modèles de vue. Ceci est un code que je l'ai utilisé:

    public static void SanitizeWildcards( Controller controller, params string[] filterStrings )
    {
        foreach( var filterString in filterStrings )
        {
            var modelState = controller.ModelState;

            ModelState modelStateValue;
            if( modelState.TryGetValue(filterString,out 
                    controller.ModelState.SetModelValue(filterString, new ValueProviderResult("","", null));
        }
    }

Autres conseils

Effacement de l'ensemble ModelState pourrait aussi faire l'affaire:

ViewData.ModelState.Clear();

Merci jfar .. c'est le code vb:

Sub CleanForm(ByVal ParamArray Fields() As String)
    Dim modelStateValue As ModelState = Nothing
    For Each Field In Fields
        If ModelState.TryGetValue(Field, modelStateValue) Then
            ModelState.SetModelValue(Field, New ValueProviderResult(Nothing, Nothing, Nothing))
        End If
    Next
End Sub

Comme mentionné @jfar, enlever la variable de la ModelState dans votre contrôleur fera l'affaire. Vous pouvez le faire avec moins de code, bien que (ces jours-ci, au moins).

ModelState.Remove("ValueA");
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top