Domanda

Questo problema è stato farmi impazzire per diverse ore ormai...

Nel mio dominio, ho 2 soggetti che sono in relazione tra loro Sku e Item.Ogni sku può avere molti elementi.

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

Sto costruendo una pagina che permetterà all'utente di aggiornare alcuni campi il codice e alcuni campi, per ciascuna voce, allo stesso 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 %> 

Ho alcuni controller di codice che funziona accettando sia un Sku e un EntitySet di Item e poi assegnare il Items per il 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 ...
    }

Questo funziona, però ho notato che si fa due viaggi attraverso il DefaultModelBinder per ogni Item oltre ad un viaggio per il Sku.Quando il Sku è associato, il setter Items è chiamato, e il legante addirittura passa in un idratata Items collezione con i valori corretti.Tuttavia, dopo la chiamata a items.Assign, Items.Count è 0.Questo è il motivo per cui ho ri-assegnare gli elementi nel codice del controller.Mi aspettavo il trasferimento di elementi oltre la Items la raccolta da parte del legante.Questo dovrebbe eliminare il percorso aggiuntivo per ogni elemento, dal momento che il items parametro sul mio controller metodo potrebbe essere rimosso.Perché non è questo lavoro?

È stato utile?

Soluzione

Potrebbe essere necessario creare un modello personalizzato legante per questo?

Altri suggerimenti

Si spera, ti sto capendo problema correttamente ...

Invece di definire il tuo Salva azione con 2 parametri, hai provato definire soltanto con un singolo parametro, di tipo Cod

Si potrebbe quindi voler ridefinire la voce di controlli HTML simile al seguente esempio ...

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


In questo modo, si sta popolando gli elementi direttamente nel Cod oggetto stesso.


Un'altra possibile soluzione potrebbe essere quella di aggiungere un ulteriore campo alla classe elemento, ad esempio ...

Int32 SkuId { get; set; }

In questo modo, si potrebbe definire un campo nascosto aggiuntivo per ogni elemento nella vista che sarebbe auto-legato alla SkuId di ogni elemento di nuovo al comando.

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

È quindi possibile solo aggiornare la vostra collezione oggetti in modo indipendente del vostro oggetto Cod. Indipendentemente da quale direzione si va, le due collezioni hanno da dire esplicitamente LINQ to SQL per aggiornare lo SKU e gli elementi in ogni caso.

Si potrebbe anche definire la propria classe legante, ma questo è probabilmente più lavoro che vale la pena in questo caso. Basta seguire le convenzioni ASP.NET MVC, e penso che si dovrebbe essere in grado di trovare qualcosa che funziona senza sentirsi come se fosse un hack.

Ho avuto un problema simile dove Entityset non erano legati correttamente nel mio ViewModel.

Quello che ho fatto è stato creare un'altra proprietà chiamato Mvc[YourEntitySetPropertyName], come un elenco generico, che avvolto intorno i campi privati della EntitySet:

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

Ho utilizzato quindi che invece di EntitySet proprietà il mio punto di vista di markup.

Non ci sarà alcun bisogno di passare gli elementi del controllore firma del metodo - basta passare il codice a questo punto:

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

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top