简体   繁体   中英

ASP.NET MVC 3: Edit a “Collection” of items

I'm currently editing a custom object, which has a dictionnary Dictionary<MyOtherObject,Boolean> .

public class MyObject{
   public int SomeProperties{get;set;}
   public int SomeMoreProperties{get;set;}
   ....
   public Dictionary<MyOtherObject, Boolean> Attributions{get;set;}
}

The goal is that I can have a list of checkbox for every item the dictionary, and decide to check it or not.

I've tried to make and editor template for my "Attribution" property. It displays perfectly, taking in account which values have been selected. But when I submit, I receive a null for the Dictionary.

So what is the good way to do it?

I found this stack overflow post which has almost the same problem, instead that I've a Dictionary and not simple properties. How well MVC handle them?

I can transform my data, but I don't see a way to not have a "List" of element. Also found this but no answers

EDIT My colleague did made some tries, starting to display only a list of bool instead of a list of objects: With an object

public class TheViewObject{
   //other fields
   List<bool> MyList{get;set;}
}

In the view, if we generate the form with @Html.EditorFor(m=>m.MyList) , we got this:

<input checked="checked" class="check-box" data-val="true" data-val-required="The Boolean field is required." id="MyList_0_" name="MyList[0]" value="true" type="checkbox">
<input class="check-box" data-val="true" data-val-required="The Boolean field is required." id="MyList_1_" name="MyList[1]" value="true" type="checkbox">
<input checked="checked" class="check-box" data-val="true" data-val-required="The Boolean field is required." id="MyList_2_" name="MyList[2]" value="true" type="checkbox">
<input name="MyList[0]" value="false" type="hidden"><input name="MyList[1]" value="false" type="hidden"><input name="MyList[2]" value="false" type="hidden">

It works because it knows directly how to handle a List<bool> . This code works and we receive correct data on the form return.

Now if we have a template

@model List<bool> 

@for (int i = 0; i < Model.Count; i++) { 
  @Html.EditorFor(x => Model[i]) 
} 

And the result:

<input checked="checked" class="check-box" data-val="true" data-val-required="The Boolean field is required." id="MyList__0_" name="MyList.[0]" value="true" type="checkbox">
<input name="MyList.[0]" value="false" type="hidden">
<input class="check-box" data-val="true" data-val-required="The Boolean field is required." id="MyList__1_" name="MyList.[1]" value="true" type="checkbox">
<input name="MyList.[1]" value="false" type="hidden">
<input checked="checked" class="check-box" data-val="true" data-val-required="The Boolean field is required." id="MyList__2_" name="MyList.[2]" value="true" type="checkbox">
<input name="MyList.[2]" value="false" type="hidden"> </td> 

The result is basically the same, EXCEPT, that we have an additional "." between MyList and [x]. With this synthax the model binder cannot figure out how to bind the object.

I think this is basically what is also happening with our Dictionary before(we have tested with a list instead, same problem)

(I'm currently testing Steve Sanderson's begincollectionitem )

This link should help you . An oldie but a goodie.

I would not have a Dictionary in the viewmodel. You are right though, it should be some kind of list. You can use an array, list, collection, ienumerable, whatever.

public MyOtherMetaObject[] Attributions { get; set; }

MyOtherMetaObject should also contain the bool value you need. It's like a "brute force" dictionary.

You can then follow the guide in Haack's blog to make sure the input elements are named correctly. We use a HtmlHelper by Steve Sanderson for this, @Html.BeginCollectionItem .

Sometimes MVC can't automatically guess how to map the form data to a proper model. If that's the case you should really make sure it's not your fault :) You should double check whether there isn't a way it can be done automatically. If the problem is indeed difficult for the mapper you can generate a ModelBinder .

In your controller you have this:

[HttpPost]
public ActionResult Method([ModelBinder(typeof(YourModelBinder))]YourModel model)
{
}

Then you create a class YourModelBinder :

public class YourModelBinder : DefaultModelBinder
{
  public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
  {
    YourModel result = base.BindModel(controllerContext, bindingContext) as YourModel;

    // here you read all the form keys/values and stuff and build up your model

    return result;
  }
}

However I'm not sure how to map this to your MyObject stuff, since I have no idea what your model etc is.

Hi I know the question is slightly old but this might help someone. If you want an MVC3 tutorial for rendering and posting back a collection of check box values as part of a view model object and saving them to a db, then have a look at my answer to this question:

Saving many to many relationship data in MVC Create view

It details how to setup a data context using Entity Framework code first, along with the models, view models, Razor code, and controller actions to first render then save the posted back data to the db.

I recently wrote an article about how to implement an edit form for an entity with a sortable child collection. The code in the article uses async requests to add additional items to the collection and JQuery UI to sort the items:

http://blog.rsuter.com/asp-net-mvc-how-to-implement-an-edit-form-for-an-entity-with-a-sortable-child-collection/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM