ASP.NET MVC gotcha? failed

I have a problem with ASP.NET MVC html helpers like TextBoxFor (), HiddenFor (), etc. If I have a model such as Employee with the name of a string member and executing Html.TextBoxFor (p => p.Name), is it wrong for me to assume that ASP.NET MVC will always use the value in the employee name? Because it is not. ASP.NET will override this binding and use what is in POST.

For exmaple, let's say I have the following code:

Model

namespace MvcApplication2.Models { public class Company { public string Name { set; get; } public List<Employee> Employees { set; get; } } public class Employee { public string Name { set; get; } } } 

controller

 namespace MvcApplication2.Controllers { public class HomeController : Controller { public ActionResult Company(string Name) { return View(new Company { Name = Name, Employees = new List<Employee> { new Employee { Name = "Ralph" }, new Employee { Name = "Joe" } } }); } } } 

Home /Company.cshtml

 @using MvcApplication2.Models; @model Company <h2>Company Name: @Model.Name</h2> @foreach (Employee emp in Model.Employees) { Html.RenderPartial("Employee", emp); } 

Home /Employee.cshtml

 @model MvcApplication2.Models.Employee <b>Employee Name: </b> @Html.TextBoxFor(p => p.Name); 

When I hit the relative URL "Home / Company? Name = MSFT", I expected Employee.cshtml to display "Ralph" and "Joe" in the text boxes, but instead display the MSFT for both text fields. What do I need to do so that "Ralph" and "Joe" appear in text boxes? Do I have to make sure that my POST and GET variables never conflict in all layers of my view models (in this case, company and employee classes)? That seems stupid. There should be an easy workaround, right?

Here is a screenshot of the result: enter image description here

+4
source share
2 answers

HtmlHelper and ModelState Methods

It is important to understand the MVC HtmlHelper methods:
They always watch ModelState first, value second, ViewData third.

ModelState important because it contains user-submitted values. If page validation fails, ModelState used to store previous values ​​and error messages.

If you want a POST form, and if everything is valid, you want to display the form again, you either need:

  • Restore from POST to GET (after PRG pattern)
  • Clear ModelState: ModelState.Clear();

EditorFor vs RenderPartial

Another important thing is the difference between EditorFor/DisplayFor vs RenderPartial .

When you use EditorFor/DisplayFor for an element (for example .EditorFor(m => m.Person) ), it adds sorting of the "namespace" to the "Person" template so that the sub-controls have a unique name. For example, in the template .TextBoxFor(p => p.Name) will look like <input name="Person.Name" ...

However, when you use RenderPartial , such a namespace is not created. Therefore .TextBoxFor(p => p.Name) display <input name="Name" ... which will not be unique if you have multiple editors.

+7
source

I understand that this behavior can be frustrating, and it may seem counterintuitive. However, your frustration is the result of an incomplete understanding of how model binding works. There is a logical chain of events that occur during the binding, and if you understand how this works, this will help to avoid such errors.

As Scott noted, MVC will always look first at ModelState. You can avoid this problem by making sure that you do not have querystring parameters with the same name as any properties in your model.

0
source

Source: https://habr.com/ru/post/1387654/


All Articles