Вопрос

Эта проблема сводила меня с ума уже несколько часов ...

В моем домене у меня есть 2 объекта, которые связаны друг с другом Sku а также Item. Анкет У каждого 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 %> 

У меня есть код контроллера, который работает, принимая оба Sku и EntitySet из Item а затем назначить Items в Sku.

    [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.Assign, Items.Count является 0. Анкет Вот почему я должен повторно уценить элементы в коде контроллера. Я ожидал, что предметы будут переданы в Items Коллекция у связующего. Это должно устранить дополнительную поездку на предмет, так как items Параметр на моем методе контроллера может быть удален. Почему это не работает?

Это было полезно?

Решение

Возможно, вам придется создать для этого пользовательскую модель переплетения?

Другие советы

Надеюсь, я правильно понимаю вашу проблему ...

А не определять свой Сохранять Действие с 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 SQL, чтобы все равно обновить SKU и элементы.

Вы также можете определить свой собственный класс Binder, но это, вероятно, больше, чем в этом случае стоит. Просто следуйте конвенциям ASP.NET MVC, и я думаю, что вы сможете найти что -то, что сработает, не чувствуя, что это взлом.

У меня была аналогичная проблема, где Entitysets не были должным образом связаны в моей ViewModel.

Что я сделал, так это создал еще одно свойство под названием MVC [YourentitySetPropertyName], как общий список, который обернулся вокруг частных поля объекта:

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 ...
    }

}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top