Is this by design in MVC Model Binding?

2019-02-19 18:51发布

问题:

A simple scenario that I've never seen before, but a colleague has just hit - MVC3

  1. Create an action method MyAction(int myProperty = 0)
  2. Create a model that has a property MyProperty
  3. Pass an instance of this model to a strongly typed view, but set the property to 10 in code (don't use the query string parameter!)
  4. In the view, Html.TextBoxFor(x => x.MyProperty)

This should render 10 in the text box.

Now call the action method MyAction?myProperty=8

Shouldn't this still render 10 in the text box?

I see that I can override the property discovered by the expression and assume this is because they are the same name (Query String parameter and model property). Eveything is then in the ViewData but one overrides the other.

Is this by design?

回答1:

This is by design - ModelState is the highest priority value-provider for model properties, higher than even model itself. Without query string parameter, ModelState does not contain value for MyProperty, so framework uses model value.

You can use ModelState.Remove("MyProperty") to ensure using model value



回答2:

If you look at the source code for Html.TextBoxFor you will see that if a value exists in ModelState then it will always use that value before any other.

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

If the value is in ModelState, then it doesn't matter what you set in code.