This problem has been driving me crazy for several hours now...
In my domain, I have 2 entities that are related to each other Sku
and Item
. Each sku can have many items.
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; }
}
I am building a page that will allow the end-user to update some fields on the sku and some fields on each item at the same time.
<% 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 have some controller code that works by accepting both a Sku
and an EntitySet
of Item
and then assigning the Items
to the 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 ...
}
This works, however I have noticed that it makes two trips through the DefaultModelBinder
for each Item
in addition to one trip for the Sku
. When the Sku
is bound, the setter for Items
is called, and the binder even passes in a hydrated Items
collection with the correct values. However, after the call to items.Assign
, Items.Count
is 0
. This is why I have to re-assign the items in the controller code. I was expecting the items to be transferred over to the Items
collection by the binder. This should eliminate the extra trip per item, since the items
parameter on my controller method could be removed. Why isn’t this working?