Problem with databinding (?) in [HttpPost] Edit ActionMethod
I have a viewmodel called ArticleAdmin that includes a lis开发者_如何学JAVAt of checkboxes:
public class ArticleAdmin
{
public ArticleAdmin()
{
TopicCheckboxes = new List<TopicCheckbox>();
}
...
public IList<TopicCheckbox> TopicCheckboxes { get; set; }
...
}
ToopicCheckbox has its own viewmodel class, defined in a separate file:
public class TopicCheckbox
{
public bool IsAssociated { get; set; }
public string TopicName { get; set; }
public int TopicId { get; set; }
}
This works well for passing the model into the view:
(UPDATE: this Action method is newly included for some clarity) public ActionResult Edit(int id)
{
//Get the Article entity by id:
var articleEntity = Repository.Articles.Get<Article>(id);
//Map the entity to the viewmodel:
Mapper.CreateMap<Article, ArticleAdmin>();
// 2nd mapping to populate the article's relations to topics:
Mapper.CreateMap<TopicArticle, TopicArticleAdmin>();
var articleData = Mapper.Map<Article, ArticleAdmin>(articleEntity);
//Generate checkboxes (models) to manage associations with topics:
foreach (var topic in Repository.Topics.List())
{
var topicCheckbox = new TopicCheckbox { TopicId = topic.Id, TopicName = topic.Title };
if (Repository.TopicArticles.FindList(x => x.TopicId == topic.Id && x.ArticleId == id).Count() > 0)
topicCheckbox.IsAssociated = true;
//and add them to the viewmodel:
articleData.TopicCheckboxes.Add(topicCheckbox);
}
return View(articleData);
}
...all the checkboxes I expect appear in the form:
But apparently this list isn't model-binding back to the [HttpPost] "Edit" ActionMethod.
Even though the TopicCheckboxes list was populated in the form, the list is empty in the ActionMethod.
[HttpPost]
public ActionResult Edit(ArticleAdmin articleData)
... the count of articleData.TopicCheckboxes is 0.
So how do I get model-binding to work properly so that this list of checkboxes back in the ActionMethod is populated correctly on post-back?
You have initialized TopicCheckBoxes
, but you didn't add elements to it.
Check out this question which was answered by Haacked's article and this answer, which has a custom ModelBinder to attach lists.
OK, I've figured it out based largely on this Question: Custom Model Binder for Complex composite objects HELP
As I now feel this is probably a duplicate question, I'll delete it, unless someone comes in over the next day or so and comments that it is otherwise useful.
The key is in setting up an array structure in the input name attributes of the checkboxes. In my case, that means each checkbox needs a series of hidden values:
<div>
<input type = "checkbox" name="TopicCheckboxes[1].IsAssociated" value = "true"id="topic_1" checked />
<input type = "hidden" name = "TopicCheckboxes.Index" value = "1" />
<input type = "hidden" name="TopicCheckboxes[1].IsAssociated" value = "false" />
<input type = "hidden" name = "TopicCheckboxes[1].TopicName" value = "test" />
<input type = "hidden" name = "TopicCheckboxes[1].TopicId" value = "1" />
<label for='topic_1'> test </label>
</div>
The really, really important field is the first hidden field: TopicCheckboxes.Index "which the default binder looks at for it's own use", and needs to be repeated with a different value for each checkbox.
精彩评论