【问题标题】:Model relationships in ASP.NET MVCASP.NET MVC 中的模型关系
【发布时间】:2010-05-26 09:56:26
【问题描述】:

我最近开始评估 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 中处理此类引用?有人有关于这个问题的一些好的提示或教程链接吗?可能包括复杂类型的自动绑定。

【问题讨论】:

    标签: c# .net asp.net-mvc model entity-relationship


    【解决方案1】:

    您可以使用数据传输对象来解决此问题,也可以在实体上使用扩展方法 - 在 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) %>
    

    【讨论】:

    • 感谢您的回答。但是在没有 DTO 的情况下如何设置这个引用(例如在创建表单中)?有一个 SelectList 但这只支持字符串值
    • @Fabiano:完全没有,我现在刚刚编辑。使用IEnumerable&lt;SelectListItem&gt; 进行下拉等 - 或者如果这不是你想要的,告诉我我会编辑。
    【解决方案2】:

    我会将所有内容合并到我的视图模型中:

    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
    }
    

    哈尔

    【讨论】:

    • 另外,如果你需要对你的对象做一些大量的定制,你应该能够实现你自己的模型绑定器并在那里处理它。
    【解决方案3】:

    我更喜欢让我的视图尽可能“愚蠢”,所以我喜欢创建自定义视图模型以进行绑定。

    在您的控制器中,您可以将丰富的域对象映射到视图模型的扁平模型。例如:

    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。

    【讨论】:

    • 感谢您的链接。这是一篇很有帮助的文章。
    猜你喜欢
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 2017-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 2014-12-15
    • 1970-01-01
    相关资源
    最近更新 更多