【问题标题】:MVC.Net binding complex models?MVC.Net 绑定复杂模型?
【发布时间】:2013-03-11 01:03:23
【问题描述】:

我有以下代码,现有客户。 我需要创建一个创建订单的表单,并将其传递给我的控制器。

我尝试将我在该页面上的模型类型更改为 Order 而不是 Customer,但是我还必须传递 Order 对象,或者至少传递 OrderId。

型号

public class Customer
{
   public int Id { set; get; }
   public string FirstName { set; get; }
   public string LastName { set; get; }
   public List<Order> Orders { get; set;}
}

public class Order
{
   public int Id { set; get; }
   public string ItemName { set; get; }
   public DateTime SomeDate { set; get; }
}

控制器

public class OrderController : Controller
{
   [HttpPost]
   public Create ActionResult(Customer customer)
   {
      // Customer doesn't have the values that it suppose to have
      // All fields including the array of orders are null
      customerStorage.UpdateOrders(customer);

      return ("ItemListPartial", customer.orders);
   }
}

查看

@model Company.Application.Model.Customer;

@using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" }))
{
    // How can I bind this to Order object ?
    // I can't define model as Order, because then I need to pass Customer Separately
    @Html.TextBoxFor(o => o.Orders[0].ItemName)
    @Html.TextBoxFor(o => o.Orders[0].SomeDate)
    <input type="submit" value="Add" />
}

【问题讨论】:

  • 如果你正在创建一个订单,你的对象应该是一个订单。您想将问题与客户联系起来吗?不确定您为什么不使用 Order 对象进行绑定。
  • public ActionResult(Customer customer) 这是一个错字吗?缺少函数名。
  • @Ravi 谢谢,这是一种修复它的类型。
  • @MikeC。问题是,如果订单对客户一无所知,并且我不想在订单中添加客户 ID,那么如果我将方法切换为期望订单,我将如何知道该订单属于哪个客户?尽量避免hacky代码,而不是单独传递客户ID

标签: asp.net ajax asp.net-mvc razor model-binding


【解决方案1】:

我想您正在寻找这篇博客文章描述的内容: ASP.NET MVC Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries

引自博客:

如果签名看起来像这样:

public ActionResult Blah(IDictionary<string, Company> stocks) {
  // ...
}

我们在 HTML 中给出了这个:

<input type="text" name="stocks[0].Key" value="MSFT" />
<input type="text" name="stocks[0].Value.CompanyName" value="Microsoft Corporation" />
<input type="text" name="stocks[0].Value.Industry" value="Computer Software" />
<input type="text" name="stocks[1].Key" value="AAPL" />
<input type="text" name="stocks[1].Value.CompanyName" value="Apple, Inc." />
<input type="text" name="stocks[1].Value.Industry" value="Consumer Devices" />

像这样:

stocks[0].Key = "MSFT"
stocks[0].Value.CompanyName = "Microsoft Corporation"
stocks[0].Value.Industry = "Computer Software"
stocks[1].Key = "AAPL"
stocks[1].Value.CompanyName = "Apple, Inc."
stocks[1].Value.Industry = "Consumer Devices"

那么就像我们写的一样:

stocks = new Dictionary<string, Company>() {
  { "MSFT", new Company() { CompanyName = "Microsoft Corporation", Industry = "Computer Software" } },
  { "AAPL", new Company() { CompanyName = "Apple, Inc.", Industry = "Consumer Devices" } }
};

【讨论】:

    【解决方案2】:

    这个 IMO 是你应该如何处理这个:

    如果您真的不想制作视图模型,请在您的视图包中传递 customerID(p.s. 可以制作视图模型!)

    public class OrderController : Controller
    {
       public ActionResult Create(int customerID)
       {
          ViewBag.CustomerID = customerID
          Order ord = new Order(o);
          return View(ord);
       }
    }
    

    你的发帖方式:

    [HttpPost]
    public ActionResult Create(int CustomerID, Order order)
    {
      //create your order
    }
    

    你的cshtml

    @model Company.Application.Model.Order;
    
    @using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" }))
    {
        @Html.TextBoxFor(o => o.ItemName)
        @Html.TextBoxFor(o => o.SomeDate)
        @Html.Hidden("CustomerID",ViewBag.CustomerID)
        <input type="submit" value="Add" />
    }
    

    【讨论】:

    • 为什么不能只使用一个新的模型类,它同时具有 Customer 属性和 Order 属性(以及您需要的任何其他属性)。这样,您就可以同时拥有两者并更轻松地将它们捆绑在一起。您不仅限于与您的数据库匹配的模型。我一直这样做。
    • 我通常为我的所有模型制作一个视图模型,我确实提到了它,但 OP 似乎不想这样做,所以我只是对此发表了评论。另外,我认为通过 ViewBag 传递最多两个项目是可以接受的。如果它是 3 个或更多,我可能会比我在这里更强烈地推荐一个视图模型,当然。
    • 确实,尽管 ViewModel 增加了一个额外的层,但根据我的经验,对于复杂的应用程序,这是值得的。我一直在使用 ViewModel 模式和 AutoMapper,到目前为止它真的很棒。
    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 2021-02-05
    • 2016-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多