We are observing an issue with how model binding is handling scenarios where data exists in both the query string and form in an .Net Core 3.1.3 MVC action.
According to the documentation model binding should look for data in the following placers in order:
- Form fields
- The request body (For controllers that have the [ApiController] attribute.)
- Route data
- Query string parameters
- Uploaded files
What we are observing is that:
- if you submit a query string which contains the same name/value pairs from the form body (ie Val1=FromQS&Val2=FromQs) it will never use it in model binding regardless of it something is in the form values or not
- but if you submit a query string that prefixes the value names with the variable name of the view model input parameter (ie vm.Val1=FromQS&vm.Val2=FromQs) then the model binder pulls exclusively from the query string ignoring any form inputs.
The sample project contains a page /Home/Demo with 3 input forms.
All 3 forms submit input to both properties of the view model using the standard asp-for syntax to setup the input text boxes. They differ in that:
- No QS does not use any query string at all
- Normal QS appends the query string “Val1=FromQS&Val2=FromQs” to the action
- Vm. QS appends the query string “vm.Val1=FromQS&vm.Val2=FromQs” to the action
I would expect them to behave based on the
- No QS – should behave like a normal form with only the form values available for binding
- Normal QS – the qeuery string should populate the model only if the form fields are left blank
- Vm. Qs – the query string should have no impact on the model as the parameter names are not correct
What actually happens
- No QS – behaves as expected
- Normal Qs – never uses the values in the query string regardless of whether the form is filled in or not
- Vm. Qs – the query string overrides all user input in the form