MVC View ViewModel HttpPost return value is always NULL

筅森魡賤 提交于 2019-12-05 07:59:07

I was able to reproduce your issue and was confused because I know that the default MVC Model Binder understands complex types. I stripped away most of the code and just tried to do it with the Company object, which still failed. I then noticed that in vmCompanyAddress that the name of the class was also the name of the property:

public class vmCompanyAddress
{
     public StatelyTechAdmin.Models.Company Company { get; set; }

I changed the name of the property to something different from the class name and it started working:

public class vmCompanyAddress
{
     public StatelyTechAdmin.Models.Company TheCompany { get; set; }

We had the same problem today. The accepted answer in this question is only a dirty workaround for the actual problem.

ClassName and PropertyName in a form model can be the same, there is no limitation in the model binder. The limitation is the parameter of the action in your controller. You must not name the parameter like a property with complex type in your form model. Cause the binder will try to bind the HTTP POST form value of company to this paramter in your controller. It will not work for you, cause the binder tries to bind the values of a Company Type to CompanyAddress type.

To fix your problem, you simply have to rename the parameter company to companyAddressModel - or anything which is not a property in your model class.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CompanyAddress company)

change to:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CompanyAddress companyAddressModel)

See here for more information about model binding: http://aspnetmvc.readthedocs.org/projects/mvc/en/latest/models/model-binding.html

MVC will try to bind request data to the action parameters by name. MVC will look for values for each parameter using the parameter name and the names of its public settable properties. [...] In addition to route values MVC will bind data from various parts of the request and it does so in a set order. Below is a list of the data sources in the order that model binding looks through them:

  • Form values: These are form values that go in the HTTP request using the POST method.
  • Route values: The set of route values provided by routing.
  • Query strings: The query string part of the URI.

A good example from ASP.NET WebAPI documentation, which is using the same technique:

HttpResponseMessage Put(int id, Product item) { ... }

Here the Id property of Product is mapped to the id parameter in the controller. Which will work, cause in the action the same primitive data type is used as in the model class.

Have not tried this myself but had a lot of similar issues a long time ago that I solved with custom ModelBinder:s which I do not recommend.

I guess your data does not look like: { Company: {...}, Address: {...} }?

I think the solution is to have MVC to understand the structure of the data using templates and EditorFor(). See http://lostechies.com/jimmybogard/2011/09/07/building-forms-for-deep-view-model-graphs-in-asp-net-mvc/ for a good example!

Ensure your ViewModel is exposing properties and not just fields.

This works:

public DAL.Models.Account acct {get;set;}

This doesn't:

public DAL.Models.Account acct;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!