views:

1378

answers:

5

Given the following class, what is your opinion on the best way to handle create/edit where Attributes.Count can be any number.

public class Product {
  public int Id {get;set;}
  public string Name {get;set;}
  public IList<Attribute> Attributes {get;set;}
}

public class Attribute {
  public string Name {get;set;}
  public string Value {get;set;}
}

The user should be able to edit both the Product details (Name) and Attribute details (Name/Value) in the same view, including adding and deleting new attributes.

Handling changes in the model is easy, what's the best way to handle the UI and ActionMethod side of things?

A: 

Depends on the experience you are looking to create for the user. I have implemented something similar for tagging content. In the model, Tags are represented as IList, but the UI shows a comma delimited list in a single text field. I then handle merging the items in the list into a string to populate the text field, and I split the input to put items back into the IList in the model.

In my DAL, I then deal with converting the List into LINQ entities, handle inserts and deletes, etc.

It isn't the most straight forward code, but it isn't too difficult to manage and it gives the user an expected interface.

I'm sure there are other ways to handle it but I would focus on what would work best for the user and then work out the mapping details based on that.

Andrew Van Slaars
A: 

Andrew,

I'm thinking something a little more difficult than tags. In this simple case a name / value pair .. color: Red; size: 10; material: cotton.

I think anything that could be used on that could extend to more complex. I.e. Adding a category and adding all its items on the same page. It's relatively easy to add another line using some jQuery, but what's the consensus on sending the info to the ActionMethod?

You can't code:

public ActionResult Whatever(stirng attr1Name, string attr2Name, string attr3Name ...

Also I don't think accepting this would work either:

public ActionResult Whatever(ILIst<Attribute> attributes, string productName ...
Kyle West
You're right. I wasn't thinking in terms of a collection of objects... my brain is stuck on my current project. I guess the FormCollection as mentioned in tvanfosson's response would be the best bet.
Andrew Van Slaars
+3  A: 

Use the FormCollection and iterate through the key/value pairs. Presumably you can use a naming scheme that will allow you to determine which key/value pairs belong to your attribute set.

[AcceptVerbs( HttpVerb.POST )]
public ActionResult Whatever( FormCollection form )
{
 ....
}
tvanfosson
+3  A: 

Use a custom Model Binder, and write the Action methods as you would normally:

ActionResult Edit(
  int id, 
  [ModelBinder(typeof(ProductModelBinder))] Product product
) ...

In your ProductModelBinder, you iterate over the Form Collection values and bind to a Product entity. This keeps the Controller interface intuitive, and can help testing.

class ProductModelBinder : IModelBinder ...
bzlm
+2  A: 

Look at Steve Sanderson’s blog post Editing a variable length list, ASP.NET MVC 2-style.

Controller

Your action method receives your native domain model Product and stays pretty simple:

public ActionResult Edit(Product model)

View

Edit.aspx

<!-- Your Product inputs -->
<!-- ... -->

<!-- Attributes collection edit -->
<% foreach (Attribute attr in Model.Attributes)
   {
       Html.RenderPartial("AttributeEditRow", attr);
   } %>

AttributeEditRow.ascx

Pay your attention to helper extension Html.BeginCollectionItem(string)

<% using(Html.BeginCollectionItem("Attributes")) { %>
    <!-- Your Attribute inputs -->
<% } %>

Adding and editing of new attributes is possible too. See the post.

SergeanT