我通过表单HttpPost将ViewModel从我的View传回Controller。但是,返回的值始终为NULL。
视图模型
public class vmCompanyAddress
{
public StatelyTechAdmin.Models.Company Company { get; set; }
public StatelyTechAdmin.Models.CompanyAddress Address { get; set; }
public SelectList Counties { get; set; }
}
公司类模型
public class Company
{
[Key]
public virtual long CompanyId { get; set; }
[Required]
[Display(Name = "Company Name")]
public virtual string Name { get; set; }
public virtual DateTime CreatedDate { get; set; }
public virtual IEnumerable<CompanyAddress> CompanyAddresses { get; set; }
}
公司地址类型号
public class CompanyAddress
{
[Key]
public virtual long CompanyAddressId { get; set; }
[Required]
public virtual long CompanyId { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[Required]
public virtual int CopmanyAddressTypeId { get; set; }
[ForeignKey("CopmanyAddressTypeId")]
public virtual CompanyAddressType CompanyAddressType { get; set; }
[Display(Name = "Address 1")]
public virtual string Address1 { get; set; }
[Display(Name = "Address 2")]
public virtual string Address2 {get; set; }
[Display(Name = "Town")]
public virtual string Town { get; set; }
[Display(Name = "City")]
public virtual string City { get; set; }
[Required]
public virtual long CountyId { get; set; }
[ForeignKey("CountyId")]
[Display(Name = "County")]
public virtual County County { get; set; }
[Required]
[Display(Name = "Postal Code")]
public virtual string PostalCode { get; set; }
public virtual DateTime CreatedDate { get; set; }
}
控制器(获取):
// GET: /Company/Create
public ActionResult Create()
{
vmCompanyAddress vm = new vmCompanyAddress();
vm.Counties = new SelectList(db.County, "CountyId", "Name", -1);
//vm.Address = new CompanyAddress();
//vm.Company = new Company();
return View(vm);
}
控制器(帖子):
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(vmCompanyAddress company)
{
if (ModelState.IsValid)
{
db.Companies.Add(company.Company);
//Amend Address Company & Address Type before save to DB
company.Address.CompanyId = company.Company.CompanyId;
company.Address.CopmanyAddressTypeId = 1;
db.CompanyAddress.Add(company.Address);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(company);
}
查看(创建)
@model StatelyTechAdmin.ViewModels.vmCompanyAddress
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>Company</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Company.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Company.Name)
@Html.ValidationMessageFor(model => model.Company.Name)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Company.CreatedDate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Company.CreatedDate)
@Html.ValidationMessageFor(model => model.Company.CreatedDate)
</div>
@* Invoice Address *@
<div class="editor-label">
@Html.LabelFor(model => model.Address.Address1)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Address.Address1)
@Html.ValidationMessageFor(model => model.Address.Address1)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Address.Address2)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Address.Address2)
@Html.ValidationMessageFor(model => model.Address.Address2)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Address.Town)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Address.Town)
@Html.ValidationMessageFor(model => model.Address.Town)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Address.City)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Address.City)
@Html.ValidationMessageFor(model => model.Address.City)
</div>
@*<div class="editor-label">
@Html.LabelFor(model => model.Address.County)
</div>
<div class="editor-field">
@Html.DropDownListFor(model => model.Address.CountyId, Model.Counties)
</div>*@
<div class="editor-label">
@Html.LabelFor(model => model.Address.PostalCode)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Address.PostalCode)
@Html.ValidationMessageFor(model => model.Address.PostalCode)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
任何人都可以提供任何建议,说明为什么在填充所有字段时我的返回ViewModel值为NULL?
我已使用网络记录功能在Google Chrome浏览器中进行了检查,并且所有值都以JSON格式发回。
非常感谢。
------------编辑---------------
以下是我可以从Google Chrome网络监视器中看到的内容
Company.Name:ABC123 Company.CreatedDate:2014/05/13 00:00:00 ....
所以它肯定会被退回。
答案 0 :(得分:11)
我能够重现你的问题而感到困惑,因为我知道默认的MVC Model Binder理解复杂的类型。我剥离了大部分代码,只是试图用公司对象来做,但仍然失败了。然后我注意到在vmCompanyAddress中,类的名称也是属性的名称:
public class vmCompanyAddress
{
public StatelyTechAdmin.Models.Company Company { get; set; }
我将属性的名称更改为与类名不同的名称,然后开始工作:
public class vmCompanyAddress
{
public StatelyTechAdmin.Models.Company TheCompany { get; set; }
答案 1 :(得分:10)
我们今天遇到了同样的问题。这个问题中接受的答案只是实际问题的一个肮脏的解决方法。
表单模型中的ClassName和PropertyName可以相同,模型绑定器中没有限制。限制是控制器中操作的参数。您不能将参数命名为表单模型中具有复杂类型的属性。导致绑定程序尝试将HTTP POST表单值company
绑定到控制器中的此参数。它不适合您,因为活页夹尝试将Company
类型的值绑定到CompanyAddress
类型。
要解决您的问题,您只需将参数company
重命名为companyAddressModel
- 或任何不属于您的模型类的属性。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CompanyAddress company)
更改为:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CompanyAddress companyAddressModel)
有关模型绑定的更多信息,请参见此处:http://aspnetmvc.readthedocs.org/projects/mvc/en/latest/models/model-binding.html
MVC将尝试将请求数据绑定到动作参数名称。 MVC将使用参数名称查找每个参数的值 以及其公共可设置属性的名称。 [...] 除路线值外 MVC将绑定来自请求的各个部分的数据,并且这样做 订单。下面是按顺序列出的数据源列表 模型绑定通过它们查看:
- 表单值:这些是使用POST方法在HTTP请求中的表单值。
- 路由值:路由提供的路由值集。
- 查询字符串:URI的查询字符串部分。
来自ASP.NET WebAPI documentation的一个很好的例子,它使用相同的技术:
HttpResponseMessage Put(int id, Product item) { ... }
此处Id
的{{1}}属性映射到控制器中的Product
参数。这将起作用,导致在操作中使用与模型类中相同的原始数据类型。
答案 2 :(得分:2)
我自己没有尝试过,但很久以前有很多类似的问题我用自定义的ModelBinder解决了:我不推荐使用。
我猜你的数据看起来不像:{公司:{...},地址:{...}}?
我认为解决方案是让MVC使用模板和EditorFor()来理解数据的结构。请参阅http://lostechies.com/jimmybogard/2011/09/07/building-forms-for-deep-view-model-graphs-in-asp-net-mvc/以获得一个好例子!
答案 3 :(得分:2)
确保您的ViewModel公开属性而不仅仅是字段。
这有效:
public DAL.Models.Account acct {get;set;}
这不是:
public DAL.Models.Account acct;