i trying implement check box list in mvc many-to-many relationship (article - category). have tried this, not work. know different , approach it.
in domain model:
public class article { public int id { get; set; } [required] [stringlength(255)] public string title { get; set; } [required] public string body { get; set; } [required] public datetime datecreated { get; set; } [required] [stringlength(255)] public string author { get; set; } public icollection<articlecomment> comments { get; set; } public icollection<category> categories { get; set; } }
in view model:
public class articlescategoriesviewmodel { public int id { get; set; } [required] public string title { get; set; } [required] [uihint("tinymce_jquery_full"), allowhtml] public string body { get; set; } [required] [datatype(datatype.date)] [display(name = "publication date")] public datetime datecreated { get; set; } [required] public string author { get; set; } public ienumerable<categoriesviewmodel> categories { get; set; } public ienumerable<categoriesviewmodel> allcategories { get; set; } public string[] postedcategories { get; set; } }
in controller:
public actionresult edit(int id) { //return article categories article articletoedit = _repo.getarticlecategories(id); mapper.createmap<article, articlescategoriesviewmodel>(); mapper.createmap<category, categoriesviewmodel>(); articlescategoriesviewmodel article = mapper.map<article, articlescategoriesviewmodel>(articletoedit); //return categories ienumerable<category> allcategories = _repo.getallcategories(); ienumerable<categoriesviewmodel> allcategories = mapper.map <ienumerable<category>, ienumerable<categoriesviewmodel>>(allcategories); article.allcategories = allcategories; if (articletoedit == null) { return httpnotfound(); } return view(article); }
in view model:
<ul> @foreach (var g in model.allcategories) { <li> <input type="checkbox" name="postedcategories" value="@g.id" id="@g.id" @{if (model.categories.firstordefault(h => h.id == g.id) != null) { <text> checked='checked' </text> } } /> <label for="@g.id">@g.name</label> </li> } </ul>
it works show categories of article, when submit post new categories selected, model not valid.
this post method:
[httppost] [validateantiforgerytoken] public actionresult edit([bind(include = "id,title,body,datecreated,author,postedcategories")]articlescategoriesviewmodel articletoedit) { if (modelstate.isvalid) { mapper.createmap<articlescategoriesviewmodel, article>(); article article = mapper.map<articlescategoriesviewmodel, article>(articletoedit); if (_repo.editarticle(article) && _repo.save()) { return redirecttoaction("index"); } else { modelstate.addmodelerror("", "one or more erros found. operation not valid."); return view(articletoedit); } } modelstate.addmodelerror("", "one or more erros found. model-binding operation not valid."); return view(articletoedit); }
i have got null references error when mvc model-data-binding try match data, apparently happens when matching collections "allcategories", "categories" of model view. appreciate help.
you should use view model category
has properties describe want display/edit in view
public class categoryvm { public int id { get; set; } public string name { get; set; } public bool isselected { get; set; } } public class articlescategoriesviewmodel { public int id { get; set; } .... public string author { get; set; } list<categoryvm> categories { get; set; } }
view
for(int = 0; < model.categories.count; i++) { @html.checkboxfor(m => m.categories[i].isselected) @html.labelfor(m => m.categories[i].isselected, model.categories[i].name) @html.hiddenfor(m => m.categories[i].id) @html.hiddenfor(m => m.categories[i].name) }
in method, initialize articlescategoriesviewmodel
based on id, , add categoryvm each available category , set isselected property based on categories assigned article. in post method, can selected categories var selectedcategories = articletoedit.categories.where(c => c.isselected)
.
you should remove [bind(include="..")]
attribute. view model represents display/edit in view unnecessary since should not excluding properties.