The binding model does not work

I have the following POCO classes:

public class Location { public int LocationId { get; set; } public string Name { get; set; } public string Street { get; set; } public string City { get; set; } public string State { get; set; } public string ZipCode { get; set; } public string Country { get; set; } public float? Latitude { get; set; } public float? Longitude { get; set; } public string PhoneNumber { get; set; } public string EmailAddress { get; set; } public string Website { get; set; } public virtual ICollection<Program> Programs { get; set; } public virtual ICollection<PlayerType> PlayerTypes { get; set; } } public class PlayerType { public int PlayerTypeId { get; set; } public string Name { get; set; } public int SortOrder { get; set; } public bool IsActive { get; set; } public virtual ICollection<Location> Locations { get; set; } } 

And the view model class

 public class LocationViewModel { public Location Location { get; set; } public IList<PlayerType> SelectPlayerTypes { get; set; } public LocationViewModel() { Location = new Location(); } } 

In my creation form, I defined the model as

 @model Locator.Models.LocationViewModel 

And they have the following fields:

 div class="editor-label"> @Html.LabelFor(model => model.Location.Name) </div> <div class="editor-field"> @Html.EditorFor(model => model.Location.Name) @Html.ValidationMessageFor(model => model.Location.Name) </div> 

In my controller for processing POST I have

 [HttpPost] public ActionResult Create(LocationViewModel location) { if (ModelState.IsValid) { locationRepository.InsertOrUpdate(location.Location); locationRepository.Save(); return RedirectToAction("Index"); } location.SelectPlayerTypes = golferTypeRepository.All.Where(p => p.IsActive).ToList(); return View(location); } 

The problem is that I have a Location object, but none of the properties should set the values ​​entered into the form.

Am I doing something wrong here?

thanks

+8
source share
10 answers

Here's the problem:

 [HttpPost] public ActionResult Create(LocationViewModel location) 

Do you see it? This is the name of your action: location argument.

Now look at your view model, it has a property called location :

 public Location Location { get; set; } 

This confuses the model binder. He no longer knows whether to bind the LocationViewModel or its property.

So just rename to avoid conflict:

 [HttpPost] public ActionResult Create(LocationViewModel model) 
+43
source

Just to introduce one more possible reason: I spent a couple of hours searching for an error in my code, and the reason that the binder, which does not work in my case, used a model with public fields, and not public properties:

 public int CustomerName; 

and it should be:

 public int CustomerName { get; set; } 

I have been working on ASP.NET MVC for 3 years, and I have never encountered this before. I hope this saves someone from disappointment;)

+32
source

It is also late to join the party, but after 3 years of working with asp.net mvc, I came across the fact that the disconnected inputs are not located, so the model’s connecting device cannot connect them. See here :

"Disabled items on the form will not be submitted."

It is better to use readonly="readonly" more than disabled. See here .

+4
source

Let me add here yeat another reason why the model binder will not work properly.

I had a model with the ContactPhone property, somewhere along the way I decided to change the name of this property to Phone , then the sudden model binding for this property stopped working when I tried to create a new instance.

The problem was the Create action in my controller. I used the standard Visual Studio forests and created a method signature like this:

 public ActionResult Create([Bind(Include = "Id,ContactPhone, ...")] Customer customer) { ... } 

Note the Bind attribute, scaffolder created the fields using the original ContactPhone name, and since it is a string, it has not been reorganized. Since the new Phone field was not included, this value was ignored by the model’s middleware.

Hope this saves you some time.

Good luck

+2
source

And one more reason: I usually use built-in editors or displays and would never encounter this problem. However, in this case, I needed a semi-standard control. In principle, you drop out with a lot of data attributes in the parameters.

What I was doing for my select tag was:

 <select name="@Html.IdFor(x => x.SubModel.ID)" id="@Html.IdFor(x => x.SubModel)" class="form-control select-control"> 

Now everything was coming back and to untrained eyes it seemed that everything should work and communicate. However, the IdFor helper does helper models with underlining. The model binder does not interpret underscores as an indicator of the class hierarchy. That which should separate them is the point. What comes from NameFor:

 <select name="@Html.NameFor(x => x.SubModel.ID)" id="@Html.IdFor(x => x.SubModel)" class="form-control select-control"> 

NameFor fixed all my problems.

+1
source

To repeat what Tod said, the model’s middleware needs the name attribute on the HTML element to map the properties. I did a quick test form manually and used only the id attribute to identify my elements.

Everything fell into place when I added the name attribute.

 <input type="text" id="Address" name="Address" /> 
+1
source

It saved my day. Slow down the following:

 public ActionResult Edit(int masterId, ConclusionView conclusion) 

ConclusionView has a property called Conclusion , so I almost lost my mind.

0
source

I know it's too late to comment on this. What I did was added the less option less than the constructor in the ViewModel, and everything worked amazingly.

0
source

If someone else has problems with this, if you indicate that your parameter in your post method matches one of your properties, the default model binder will also not work.

0
source

My case was a bit unique, but I hope it helps someone in a similar context. I had a view model that implements IValidatableObject, and the Validate method from this interface returned a null value if successful. I should have returned an empty IEnumerable. Therefore, binding actually occurred, but failed.

Basically, when you get this problem, use Fiddler to view the published data, make sure the published variables match the properties (not the fields!) In your view models, and set a breakpoint in the view model constructor so that the routing mechanism reaches the correct POST method. Good luck

0
source

All Articles