ASP.NET MVC模型绑定同一网页的相关实体(ASP.NET MVC Model Binding

2019-09-23 13:50发布

此问题已被我逼疯了几个小时,现在...

在我的领域,我有2个是彼此相关的其他实体SkuItem 。 每个SKU可以有很多的项目。

public class Sku
{
    private readonly EntitySet<Item> items;
    public Sku()
    {
        items = new EntitySet<Item>(AttachItems, DetachItems);
    }
    public int SkuId { get; set; }
    public string LongDescription { get; set; }
    public EntitySet<Item> Items
    {
        get { return items; }
        set{ items.Assign(value);}
    }
    private void AttachItems(Item entity)
    {
        entity.Sku = this;
    }
    private static void DetachItems(Item entity)
    {
        entity.Sku = null;
    }
}

public class Item
{
    public Sku Sku { get; set; }
    public int ItemId { get; set; }
    public string Category { get; set; }
    public string Description { get; set; }
}

我建立一个网页,将允许终端用户在同一时间更新的SKU,并在每个项目上的一些领域的一些领域。

<% using (Html.BeginForm("Save", "Merchant", FormMethod.Post, 
       new { enctype = "multipart/form-data" })) { %>       
<fieldset>
    <legend>Sku</legend>
    <p><label for="SkuId">SkuId:</label>
       <%= Html.TextBox("SkuId", Model.SkuId, 
           new{@readonly="readonly",onfocus="this.blur();"}) %></p>
    <p><label for="LongDescription">LongDescription:</label>
       <%= Html.TextBox("LongDescription", Model.LongDescription) %></p>
</fieldset>
<% for (int i = 0; i < Model.Items.Count; i++) { %>       
<fieldset>
    <legend>Item</legend>
    <p><label for="ItemId">ItemId:</label>
       <%= Html.TextBox(string.Format("items[{0}].{1}", i, "ItemId"), 
           Model.Items[i].ItemId, 
           new { @readonly = "readonly", onfocus = "this.blur();" })%></p>
    <p><label for="Category">Category:</label>
       <%= Html.TextBox(string.Format("items[{0}].{1}", i, "Category"), 
           Model.Items[i].Category)%></p>
    <p><label for="Description">Description:</label>
       <%= Html.TextBox(string.Format("items[{0}].{1}", i, "Description"), 
           Model.Items[i].Description)%></p>
</fieldset>
<%} // for-loop %>
    <p><input type="submit" value="Save" /></p>
<%} // form %> 

我有一些控制代码,通过接受既有作品SkuEntitySetItem ,然后分配ItemsSku

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Save(Sku sku, EntitySet<Item> items)
    {
        if (sku != null)
        {
            if (items != null)
            {
                sku.Items.Assign(items);
            }
        }

        // save Sku to repository ...
        // return Details view ...
    }

这工作,但我注意到,它使得通过两趟DefaultModelBinder每个Item除了为单行程Sku 。 当Sku必然,对于二传手Items被调用,粘合剂即使经过水合的Items收集与正确的价值观。 然而,在调用后items.AssignItems.Count0 。 这就是为什么我要重新分配的控制器代码的项目。 我期待的项目转移到该Items被粘合剂集合。 这将消除每件额外的行程,因为items在我的控制器方法的参数可以被删除。 为什么没有这方面的工作?

Answer 1:

您可能需要为此创建自定义的模型绑定?



Answer 2:

但愿,我正确认识你的问题...

而不是2个参数定义你的保存动作,你尝试只是一个单一的参数定义它,键入SKU的?

这样,你会要重新定义HTML控件类似于下面的示例的项目...

<%=
    Html.TextBox
    (
        string.Format("sku.Items[{0}].{1}", i, "ItemId"), 
        Model.Items[i].ItemId, 
        new { @readonly = "readonly", onfocus = "this.blur();" }
    )
%>


这样一来,你就直接在SKU对象本身填充的项目。


另一个潜在的解决方案将是一个额外的字段添加到您的项目类,如...

Int32 SkuId { get; set; }

通过这种方式,你可以定义一个额外的隐藏字段将被自动绑定到SkuId每个项目的回控制器在您的视图的每个项目。

<%=
    Html.Hidden
    (
        string.Format("sku.Items[{0}].{1}", i, "SkuId"), 
        Model.Items[i].SkuId
    )
%>

然后,您可以只单独的SKU对象的更新项集合。 不管你走哪条路,这两个集合都明确地告诉LINQ to SQL的更新SKU和项目进不去。

你也可以定义自己的粘合剂类,但是这可能更多的工作比它在这种情况下的价值。 只要按照ASP.NET MVC约定,我想你应该能够找到的东西,就会没有感觉就像是一个黑客工作。



Answer 3:

我曾在那里EntitySets没有在我的视图模型正确绑定类似的问题。

我所做的就是创建另一个属性调用的mvc [YourEntitySetPropertyName],作为一个通用的清单,围绕EntitySet的私人领域的包裹:

public List<InvoiceLineItem> MvcInvoiceLineItemList
    {
        get { return _invoiceLineItemList.ToList(); }
        set { _invoiceLineItemList.AddRange(value); }
    }

然后我用的,而不是对我的看法标记的EntitySet的财产。

不会有任何需要通过在控制器方法签名工具只是通过SKU在这一点上的项目:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Save(Sku sku)
{
    if (sku != null)
    {
       // save Sku to repository ...
       // return Details view ...
    }

}


文章来源: ASP.NET MVC Model Binding Related Entities on Same Page