我最近开始评估 ASP.NET MVC。虽然为仅具有原始属性的模型创建控制器和视图非常简单快捷(如官方页面的入门视频所示),但我没有找到任何处理复杂类型引用的好方法。假设我有这些模型:
public class Customer {
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public IList<Order> Orders { get; set; }
}
public class Address {
public int Id { get; set; }
public string .....
.....
}
public class Order {
public int Id { get; set; }
public Customer Customer { get; set; }
public string OrderName { get; set; }
.....
}
请注意,我在模型中没有外键(就像典型的 LINQ to SQL,示例视频中也使用了外键),但有对象引用。
如何在 ASP.NET MVC 中处理此类引用?有人有关于这个问题的一些好的提示或教程链接吗?也许包括复杂类型的自动绑定。
您可以使用数据传输对象来解决此问题,也可以在实体上使用扩展方法 - 在 EF 中包含方法 -
与原始属性没有什么不同。如果那不是你的意思,请纠正我,然后我会再次帮助你
谢谢
DTO:
public class OrderDTO
{
public int Id { get; set; }
public int CustomerId { get; set; }
public string CustomerName { get; set; }
}
NHibernate 存储库:
public IList<OrderDTO> GetOrders()
{
return Session.Linq<Order>()
.Select(o => new OrderDTO {
Id = o.Id
CustomerId = o.Customer.Id
CustomerName = o.Customer.Name
...
}).ToList();
}
查看:
展开 - 包含 - 模型类型为“订单”:
<%= Model.Customer.Name %>
使用 DTO - 模型类型为“OrderDTO”:
<%= Model.CustomerName %>
编辑:
好吧,首先您可能想使用 FormViewModel 进行创建/编辑操作。像这样;
控制器:
public ActionResult Edit(int id)
{
Order order = null; // OrderService.Get(id);
IList<Customer> customers = null; // CustomerService.GetAll();
OrderFormViewModel model = OrderFormViewModel.Create(order);
model.Customers = customers.Select(c => new SelectListItem {
Value = c.Id,
Text = c.Name
});
return View(model);
}
[HttpPost]
public ActionResult Edit(int customerId, Order order)
{
//customerId - selected from dropdown.
}
public class OrderFormViewModel
{
public static OrderFormViewModel Create(Order order)
{
return new OrderFormViewModel {
Order = order
};
}
public Order Order { get; internal set; }
public IEnumerable<SelectListItem> Customers { get; internal set; }
public int CustomerId { get; internal set; }
}
查看:
<%= Html.DropDownListFor(o => o.CustomerId, Model.Customers) %>
我会将所有内容合并到我的视图模型中:
CustomerViewModel.Customer
CustomerViewModel.Address
CustomerViewModel.Orders // maybe an IEnumerable<Order>
CustomerViewMode.CurrentOrder
您应该能够使用一些输入助手来绑定复杂的对象,而不会遇到太多麻烦:
//.. begin form
<%=Html.HiddenFor(m=>m.Customer.Id)%>
<%=Html.TextboxFor(m=>m.Customer.FirstName)%>
<%=Html.TextBoxFor(m=>m.Address.City)%>
<%=Html.TextBoxFor(m=>m.ActiveOrder.OrderName%>
//.. submit ..
//.. end form ..
如果你的操作方法如下所示,应该可以绑定回来:
[HttpPost]
public ActionResult UpdateComplexObject(string id, CustomerViewModel customerViewModel) {
// if (!id.Equals(customerViewModel.Customer.Id) throw something
// just one of my own conventions to ensure that I am working on the correct active
// entity - string id is bound from the route rules.
ValidateModel(customerViewModel);
service.UpdateCustomer(customerViewModel.Customer);
serviceOrder.UpdateOrder(customerViewModel.ActiveOrder);
serviceAddress.UpdateAddress(customerViewModel.Address);
return RedirectToAction("DisplayComplexObject"); // or whatever
}
哈尔
我更喜欢让我的视图尽可能“哑”,所以我喜欢创建用于绑定的自定义视图模型。
在控制器中,您可以将丰富的域对象映射到视图模型的扁平模型。例如:
public class ChooseCustomerModel {
public Order Order { get; set; }
// Project Customer objects into this container, which is easy to bind to
public IDictionary<int, string> PotentialCustomers { get; set; }
}
如果您正在寻找有关此主题的好材料,我推荐 ASP.NET MVC 视图模型模式。