我最近开始评估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中处理这样的引用?有人有关于此问题的教程的一些好的提示或链接吗?可能包括复杂类型的自动绑定。
答案 0 :(得分:3)
您可以使用数据传输对象来解决此问题,或者您可以在实体中使用扩展方法 - 在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();
}
查看:
使用Expand - Include - 模型类型为'Order':
<%= 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) %>
答案 1 :(得分:1)
我会将所有内容组合到我的视图模型中:
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
}
哈尔
答案 2 :(得分:1)
我更喜欢让我的观点尽可能“愚蠢”,所以我喜欢为绑定创建自定义视图模型。
在控制器中,您可以将富域对象映射到视图模型的更平坦的模型。例如:
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 View Model Patterns。