Pergunta

Esse problema está me deixando louco há várias horas ...

No meu domínio, tenho 2 entidades relacionadas entre si Sku e Item. Cada SKU pode ter muitos itens.

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

Estou construindo uma página que permitirá que o usuário final atualize alguns campos no SKU e alguns campos em cada item ao mesmo tempo.

<% 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 %> 

Eu tenho algum código do controlador que funciona aceitando um Sku e um EntitySet do Item e depois atribuir o Items para o 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 ...
    }

Isso funciona, no entanto, notei que faz duas viagens através do DefaultModelBinder para cada Item Além de uma viagem para o Sku. Quando o Sku está ligado, o setter para Items é chamado, e o fichário até passa em um hidratado Items coleção com os valores corretos. No entanto, depois da chamada para items.Assign, Items.Count é 0. É por isso que tenho que assinar novamente os itens no código do controlador. Eu esperava que os itens fossem transferidos para o Items Coleção pelo fichário. Isso deve eliminar a viagem extra por item, pois o items O parâmetro no meu método do controlador pode ser removido. Por que isso não está funcionando?

Foi útil?

Solução

Pode ser necessário criar um fichário de modelo personalizado para isso?

Outras dicas

Felizmente, estou entendendo seu problema corretamente ...

Em vez de definir o seu Salvar ação com 2 parâmetros, você já tentou defini -lo com um único parâmetro, do tipo Sku?

Você gostaria de redefinir os controles HTML do item semelhante ao exemplo a seguir ...

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


Dessa forma, você está preenchendo os itens diretamente no próprio objeto SKU.


Outra solução potencial seria adicionar um campo adicional à sua classe de itens, como ...

Int32 SkuId { get; set; }

Dessa forma, você pode definir um campo oculto adicional para cada item em sua visualização que seria ligada automaticamente ao skuid de cada item de volta ao controlador.

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

Você pode apenas atualizar sua coleção de itens independentemente do seu objeto SKU. Independentemente de qual caminho você seguir, as duas coleções precisam dizer explicitamente ao LINQ ao SQL para atualizar o SKU e os itens de qualquer maneira.

Você também pode definir sua própria aula de fichário, mas isso provavelmente é mais trabalho do que vale a pena neste caso. Basta seguir as convenções do ASP.NET MVC, e acho que você deve encontrar algo que funcione sem sentir que é um hack.

Eu tive um problema semelhante em que o EntitySets não estava ligado adequadamente no meu viewmodel.

O que eu fiz foi criar outra propriedade chamada MVC [YourEntitySetPropertyName], como uma lista genérica, que envolveu os campos privados do EntitySet:

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

Eu então usei isso em vez da propriedade EntitySet na minha marcação de visualização.

Não haverá necessidade de passar os itens na assinatura do método do controlador- basta passar no SKU nesse ponto:

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

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top