aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

ASP.NET MVC: updated model data is not recognised in view

Open tbureck opened this issue 4 years ago • 7 comments

Hi there,

first off, I'm rather new to ASP.NET and its ecosystem, so bear with me if wording is not on spot. I don't want to exclude layer 8 as the root cause of the following problem either, but neither the docs nor intensive usage of search engines helped at all.

Describe the bug

I'm using APS.NET MVC technology for the following.

So, I have a very simple example to cover. Imagine a form, it has two text fields and a checkbox. In order to back this form, I created a simple view model class having two string properties and a bool property. One of the string properties is required while the other is optional.

In my controller there is an action that will simply return a view, getting passed a fresh instance of that model. The view will render the form using the <form asp-route>..., <input asp-for="..."> tags. So far, so good, everything works until now.

Then I have another controller action that is the target of the form. It will check for model validity using the ModelState.IsValid property. If the model is not valid, I want to reset the optional field and unset the checkbox (setting it to false), then render the form again passing the updated model data. Heads up, problem incoming.

Resetting the model and passing it to the view seems to work just fine. Debugging the view shows that the view has the expected data. But, the input elements will still show the data that was input the step before.

This is what I don't understand, to me it would be logical that the optional field should be empty and the checkbox unchecked, because the model data says so. But maybe I'm missing something (essential).

To Reproduce

Okay, I thought "I've tinkered quite a bit in that project, so I'm gonna try to reproduce it in a fresh project". Done so and unfortunately I was able to reproduce it.

The project can be found here

The model class is called CheckBoxTestModel (I stumbled over checkboxes first, then wondered about text fields); the controller is coded in HomeController, views can be seen in Views/Home/Index.cshtml and Views/Home/PostText.cshtml. Apart from these files, it's just the project template.

Further technical details

  • I'm using ASP.NET Core 5 with JetBrains Rider 2020.2 as IDE
❯ dotnet --info
.NET SDK (reflecting any global.json):
 Version:   5.0.100
 Commit:    5044b93829

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19041
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\5.0.100\

Host (useful for support):
  Version: 5.0.0
  Commit:  cf258a14b7

.NET SDKs installed:
  3.0.100 [C:\Program Files\dotnet\sdk]
  3.1.100 [C:\Program Files\dotnet\sdk]
  3.1.403 [C:\Program Files\dotnet\sdk]
  5.0.100 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download

Best regards

tbureck avatar Nov 20 '20 17:11 tbureck

Try this:

ModelState["OptionalField"].AttemptedValue = null;
ModelState["Accept"].AttemptedValue = null;

rezathecoder avatar Nov 22 '20 23:11 rezathecoder

Hi,

thanks for your response. Unfortunately your suggestion didn't make a difference.

Best regards

tbureck avatar Nov 23 '20 17:11 tbureck

Thanks for contacting us. We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We will evaluate the request when we are planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

ghost avatar Nov 23 '20 17:11 ghost

Sorry that last solution did not work. I tried the following code and i guess i achieved what you want:

if ( !ModelState.IsValid ) {
    _logger.LogInformation("Model is invalid. Reset checkbox.");
    model.OptionalField = "";
    model.Accept = false;

    ModelState[nameof(CheckBoxTestModel.OptionalField)].RawValue = null;
    ModelState[nameof(CheckBoxTestModel.Accept)].RawValue = null;

    return this.View("Index", model);
}

Hope this helps

rezathecoder avatar Nov 23 '20 19:11 rezathecoder

Hi,

no worries. This snippet works, but I have to say that it looks rather unsatisfying. I actually want to reset the model's state in a method of the model itself instead of letting the controller handle this, so using ModelState can only be a workaround.

I'm probably not understanding how model binding actually works. Apparently @mkArtakMSFT thinks this is a Docs issue, so I'll try to read into the code a little bit more and if there's no cleaner solution to this than what you've written, I might come up with a different solution altogether.

Anyways, thanks so far :)

Best regards

tbureck avatar Nov 25 '20 17:11 tbureck

Thanks for contacting us.

We're moving this issue to the .NET 7 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

ghost avatar May 24 '22 03:05 ghost

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

ghost avatar Aug 10 '22 17:08 ghost

After reviewing this again and seeing that not many customers stumbled upon this, we've decided to close this issue and take no further action regarding this so that we can focus our efforts on more important / pressing issues.

mkArtakMSFT avatar Oct 11 '22 17:10 mkArtakMSFT