I noticed that ASP.NET Core MVC will take a query string parameter and use its value to automatically populate a form field with the same name, even if I ignore the query string parameter and explicitly set the model property to null.
I have a reproduction on GitHub.
The Model (Models/HomeIndexModel.cs)
This is a simple record with one property, Email. This is bound to the lone textbox on the form.
public record HomeIndexModel(string? Email);
The Controller Action (Controllers/HomeController.cs)
The controller action takes a string? from the query string and binds it to the email parameter.
Note how we're ignoring this value and explicitly setting the view model's Email property to null.
public IActionResult Index(string? email)
{
// NOTE: Ignore the query string parameter and explicitly set the view model property to null.
return View(new HomeIndexModel(Email: null));
}
The View (Views/Home/Index.cshtml)
The view uses HomeIndexModel as its view model. It has a single form with a textbox for HomeIndexModel's Email property.
@model AspNetCoreMvcQueryStringToForm.Models.HomeIndexModel
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<form>
<label asp-for="Email"> Email
<input type="email" asp-for="Email" />
</label>
</form>
</div>
The Unexpected behavior
If I make a request to the action with an email query string parameter, the Email form field is automatically populated with that value, even though I'm explicitly setting the Email model property to null in the controller action:
Question
How and why is this happening? I must be overlooking something simple.
Is there a way to disable this behavior, preferably at the action level?

Index(string? email)is actually being called? There isn't another overload ofIndex(...)that may be triggered instead?asp-forwill populate form fields fromModelState. Mostly this is so that invalid values will be preserved. eg you can't bind"abc"to anint, but you want to re-render the form with the invalid value.