Frage

Dieses Problem hat mich seit mehreren Stunden verrückt gemacht ...

In meiner Domäne habe ich 2 Einheiten, die miteinander verwandt sind Sku und Item. Jeder SKU kann viele Gegenstände haben.

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

Ich erstelle eine Seite, auf der der Endbenutzer einige Felder auf der SKU und einige Felder auf jedem Element gleichzeitig aktualisieren kann.

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

Ich habe einen Controller -Code, der funktioniert, indem ich beide akzeptiere Sku und ein EntitySet von Item und dann die zuweisen die Items zum 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 ...
    }

Dies funktioniert, aber ich habe festgestellt, dass es zwei Reisen durch die macht DefaultModelBinder für jeden Item Zusätzlich zu einer Reise für die Sku. Wenn der Sku ist gebunden, der Setter für Items wird genannt, und der Ordner verläuft sogar in einem hydratisierten Items Sammlung mit den richtigen Werten. Nach dem Anruf an jedoch items.Assign, Items.Count ist 0. Aus diesem Grund muss ich die Elemente im Controller-Code neu zuordnen. Ich hatte erwartet, dass die Gegenstände auf die übertragen werden Items Sammlung von The Binder. Dies sollte die zusätzliche Reise pro Artikel beseitigen, da die items Der Parameter für meine Controller -Methode kann entfernt werden. Warum funktioniert das nicht?

War es hilfreich?

Lösung

Möglicherweise müssen Sie dafür einen benutzerdefinierten Modellbinder erstellen?

Andere Tipps

Hoffentlich verstehe ich Ihr Problem richtig ...

Anstatt Ihre zu definieren Speichern Aktion mit 2 Parametern haben Sie versucht, sie nur mit einem einzigen Parameter zu definieren, vom Typ SKU?

Sie möchten dann das Element HTML -Steuerelemente ähnlich wie das folgende Beispiel neu definieren ...

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


Auf diese Weise bevölkern Sie die Gegenstände direkt im SKU -Objekt selbst.


Eine weitere potenzielle Lösung wäre, Ihrer Artikelklasse ein zusätzliches Feld hinzuzufügen, z. B. ...

Int32 SkuId { get; set; }

Auf diese Weise können Sie ein zusätzliches verstecktes Feld für jedes Element in Ihrer Ansicht definieren, das automatisch für die Skuid jedes Elements am Controller zurückgebunden ist.

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

Sie können dann einfach Ihre Artikelsammlung unabhängig von Ihrem SKU -Objekt aktualisieren. Unabhängig davon, wie Sie gehen, müssen die beiden Sammlungen SQL ausdrücklich sagen, dass er die SKU und die Elemente sowieso aktualisieren muss.

Sie könnten auch Ihre eigene Binderklasse definieren, aber das ist wahrscheinlich mehr Arbeit als es in diesem Fall wert ist. Folgen Sie einfach den ASP.NET -MVC -Konventionen, und ich denke, Sie sollten in der Lage sein, etwas zu finden, das funktionieren wird, ohne das Gefühl zu haben, ein Hack zu sein.

Ich hatte ein ähnliches Problem, bei dem die Entitätssätze in meinem ViewModel nicht richtig gebunden waren.

Ich habe eine andere Eigenschaft namens MVC [yourEntitySetPropertyName] als generische Liste erstellt, die sich um die privaten Felder des EntitySets wickelte:

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

Ich habe das dann anstelle der EntitySet -Eigenschaft für meine Ansichtsmarkup verwendet.

Es müssen nicht die Elemente in Ihrer Controller-Methode-Signatur übergeben werden. An diesem Punkt übergeben Sie einfach die SKU:

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

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top