我的 Linq-SQL 是否破坏了 MVC2 模型绑定?
我正在尝试使用 MVC 2 内置模型绑定来处理来自 Web 表单的 http-post。从我过去几个小时的搜索来看,我发现“对象中的对象”有点挑剔。
我正在寻找任何类型的答案或资源链接来帮助我解决这个问题。我还处于早期阶段,所以如果有更好的方法 - 我洗耳恭听。我一直在自己编写 Linq-SQL,而不是使用代码生成。我认为我正在寻找的最接近的答案是 这里,但我还是没明白。
模型客户端(我对问题所在的最佳猜测):
public class Client
{
public int ClientID { get; set; }
...
[Column(Name = "Address_id")]
internal int AddressID { get; set; }
internal EntityRef<Address> _address;
[System.Data.Linq.Mapping.Association(ThisKey = "AddressID", Storage = "_address")]
public Address Address
{
get { return _address.Entity; }
internal set { _address.Entity = value; AddressID = value.AddressID; }
}
}
模型地址(客户端实体内)
public class Address
{
[Column] public string Address1 { get; set; }
[Column] public string Address2 { get; set; }
[Column] public string City { get; set; }
...
视图模型:
public class ClientFormViewModel
{
public Client Client { get; set; }
...
}
视图:
<!-- id is hidden -->
<%: Html.EditorFor(m => m.Client.ClientID) %>
...
<%: Html.EditorFor(m => m.Client.Address.AddressID) %>
<%: Html.LabelFor(m => m.Client.Address.Address1) %>
<%: Html.EditorFor(m => m.Client.Address.Address1) %><br />
<%: Html.LabelFor(m => m.Client.Address.Address2) %>
<%: Html.EditorFor(m => m.Client.Address.Address2) %><br />
...
控制器:
public ViewResult Edit(int clientId)
{
var client = clientsRepository.Clients.First(x => x.ClientID == clientId);
...
// create view model
var viewModel = new ClientFormViewModel
{
Client = client,
...
};
return View(viewModel);
}
[HttpPost]
public ActionResult Edit(ClientFormViewModel clientForm)
{
if (ModelState.IsValid)
{
clientsRepository.SaveClient(clientForm.Client);
return RedirectToAction("List");
}
else // validation error, so redisplay the same view
...
}
所以我的问题是......当我进入 HttpPost 操作时,clientForm.Client。地址始终为空。虽然,当我查看 ModelState(有效)或使用 Request.["key"] 时,所有键都与我的对象的结构匹配。例如,我看到 ModelState["Client.Address.Address1"]、"Client.Address.Address2" 等。
所有其他基本属性都填写良好,这让我认为 linq-sql 代码破坏了模型绑定。但如何呢?有办法解决吗?如果这些键位于 Request/ModelState 字典中,为什么它们没有映射到对象?我完全错过了一些明显的东西吗?
I am trying to handle the http-post from a web form using MVC 2s built in model binding. From what I have been searching through for the past few hours I have figured it is a bit finicky with "objects within objects."
I'm looking for any kind of answers or links to resources that may help me figure this out. I'm still in the early stages of this also so if there is a better way - I'm all ears. I have been writing the Linq-SQL myself and not using the code generation. I think the closest answer I'm looking for is here, but I'm still not getting it.
Model Client (my best guess for where the issue is):
public class Client
{
public int ClientID { get; set; }
...
[Column(Name = "Address_id")]
internal int AddressID { get; set; }
internal EntityRef<Address> _address;
[System.Data.Linq.Mapping.Association(ThisKey = "AddressID", Storage = "_address")]
public Address Address
{
get { return _address.Entity; }
internal set { _address.Entity = value; AddressID = value.AddressID; }
}
}
Model Address (within client entity)
public class Address
{
[Column] public string Address1 { get; set; }
[Column] public string Address2 { get; set; }
[Column] public string City { get; set; }
...
View Model:
public class ClientFormViewModel
{
public Client Client { get; set; }
...
}
View:
<!-- id is hidden -->
<%: Html.EditorFor(m => m.Client.ClientID) %>
...
<%: Html.EditorFor(m => m.Client.Address.AddressID) %>
<%: Html.LabelFor(m => m.Client.Address.Address1) %>
<%: Html.EditorFor(m => m.Client.Address.Address1) %><br />
<%: Html.LabelFor(m => m.Client.Address.Address2) %>
<%: Html.EditorFor(m => m.Client.Address.Address2) %><br />
...
Controller:
public ViewResult Edit(int clientId)
{
var client = clientsRepository.Clients.First(x => x.ClientID == clientId);
...
// create view model
var viewModel = new ClientFormViewModel
{
Client = client,
...
};
return View(viewModel);
}
[HttpPost]
public ActionResult Edit(ClientFormViewModel clientForm)
{
if (ModelState.IsValid)
{
clientsRepository.SaveClient(clientForm.Client);
return RedirectToAction("List");
}
else // validation error, so redisplay the same view
...
}
So my issue is... when I get into the HttpPost action, the clientForm.Client.Address is always null. Although, when I look into the ModelState (which is valid), or use Request.["key"], all of the keys match the structure of my object. For example, I see ModelState["Client.Address.Address1"], "Client.Address.Address2", etc.
All other basic properties are filled in fine, which make me think the linq-sql code is breaking the model binding. But how? And is there a way to fix it? If those keys are within the Request/ModelState dictionary, why are they not being mapped to the object? Am I totally missing something obvious?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您希望模型绑定器能够成功绑定它,则
Address
setter 必须是public
:就个人而言,我建议您使用视图模型,而不是将这些模型传入和传出的意见。
The
Address
setter must bepublic
if you want the model binder to be able to successfully bind it:Personally I would recommend you using view models instead of passing those models to and from the views.
在 @Darin Dimitrov 提到使用视图模型而不是传递域模型(我认为我已经在这样做)之后,我最终找到了一个解决方案。
我没有依赖默认模型绑定来获取 Linq-SQL 映射,而是创建了一个扁平视图模型。
对我帮助最大的是这两篇文章:
http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx
http://lostechies.com/jimmybogard/2009/06/30/how-we-do- mvc-view-models/
起初我在使用 AutoMapper 时遇到了一些问题,但现在它工作得很好。我会推荐它!
After @Darin Dimitrov mentioned using a view model instead of passing the domain model (which I thought I was already doing), I ended up figuring out a solution.
Instead of relying on the default model binding picking up my Linq-SQL mapping, I created a flattened view model.
What helped me the most were these two posts:
http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx
http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/
I had some issues with AutoMapper at first, but now it works pretty well. I would recommend it!