Question

Ce problème a été me rend fou pendant plusieurs heures maintenant ...

Dans mon domaine, j'ai 2 entités qui sont liées les unes aux autres et Sku Item. Chaque sku peut avoir plusieurs objets.

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

Je construis une page qui permettra à l'utilisateur final de mettre à jour certains champs du sku et des champs sur chaque élément en même temps.

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

I ai un code de commande qui fonctionne à la fois en acceptant un Sku et un EntitySet de Item puis en attribuant la Items au 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 ...
    }

Cela fonctionne, mais je l'ai remarqué que cela fait deux voyages à travers le DefaultModelBinder pour chaque Item en plus d'un voyage pour le Sku. Lorsque le Sku est lié, le dispositif de réglage pour Items est appelée, et le liant passe encore dans une collection de Items hydraté avec les valeurs correctes. Cependant, après l'appel à items.Assign, Items.Count est 0. Voilà pourquoi je dois réattribuer les éléments du code du contrôleur. Je me attendais les éléments à transférer vers la collection Items par le liant. Cela devrait éliminer le voyage supplémentaire par article, puisque le paramètre items sur ma méthode de commande pourrait être supprimée. Pourquoi est-ce pas de travail?

Était-ce utile?

La solution

Vous devrez peut-être créer un modèle de liaison personnalisé pour cela?

Autres conseils

Si tout va bien, je vous comprends bien ... problème

Plutôt que de définir Enregistrer l'action avec 2 paramètres, avez-vous essayé simplement définir ce avec un seul paramètre, de type Sku ?

Vous souhaitez ensuite redéfinir l'élément HTML contrôle similaire à l'exemple suivant ...

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


De cette façon, vous êtes peuplant les éléments directement dans l'objet lui-même Sku.


Une autre solution possible serait d'ajouter un champ supplémentaire à votre classe d'objet, par exemple ...

Int32 SkuId { get; set; }

De cette façon, vous pouvez définir un champ caché supplémentaire pour chaque élément de votre point de vue qui serait lié automatiquement à la SkuId de chaque élément au niveau du contrôleur.

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

Vous pouvez alors simplement mettre à jour votre collection d'éléments indépendamment de votre objet Sku. Quelle que soit la façon dont vous allez, les deux collections doivent dire explicitement LINQ to SQL pour mettre à jour le sku et articles de toute façon.

Vous pouvez également définir votre propre classe de liant, mais c'est probablement plus de travail que cela vaut la peine dans ce cas. Il suffit de suivre les conventions ASP.NET MVC, et je pense que vous devriez être en mesure de trouver quelque chose qui fonctionnera sans se sentir comme il est un hack.

J'ai eu un problème similaire où EntitySets ne sont pas liés correctement dans mon ViewModel.

Ce que je faisais était de créer une autre propriété appelée Mvc [YourEntitySetPropertyName], comme une liste générique, qui enroulé autour des champs privés du EntitySet:

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

J'ai ensuite utilisé qu'au lieu de la propriété EntitySet sur mon balisage de vue.

Il n'y aura pas besoin de passer les éléments de votre méthode de commande simplement passer le Signature- Sku à ce moment:

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

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top