Dheeraj Palagiri Dheeraj Palagiri - 15 days ago 4
C# Question

ListBox not posting to MVC controller

I have a form which have some text Area's and ListBox. All the other fields in the form are being posted to controller but not ListBox?

Here is Razor code:

<form method="post" action="/Admin/AddPost">
@Html.ValidationSummary(true)
<div class="form-group">
<label>Title</label>
<input type="text" class="form-control" name="BlogTitle" placeholder="Title" value="@Model.BlogTitle" required>
</div>
<div class="form-group">
<label>Image</label>
<input type="text" class="form-control" name="BlogImage" value="@Model.BlogImage" placeholder="Image">
</div>
<div class="form-group">
<label>Description</label>
<textarea name="BlogDescription">@Model.BlogDescription</textarea>
</div>
<div class="form-group">
<label>Tags</label>
@Html.ListBox("Tags", Model.Tags, new { @class = "form-control", @name = "Tags", @multiple = "multiple" })
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>


Here is GET and POST from controller:

public ActionResult AddPost()
{
var model = new BlogModel
{
BlogTitle = string.Empty,
BlogDescription = string.Empty,
BlogImage = string.Empty,
Tags = new TagQueries().GetAllTags().Select(x => new SelectListItem
{
Text = x.TagName,
Value = x.TagId.ToString(),
Selected = false
})
};
return View(model);
}
[HttpPost]
public ActionResult AddPost(BlogModel model)
{
TransferBlogDetailsToDbModel addToDb = new TransferBlogDetailsToDbModel();
if (ModelState.IsValid && model != null)
{
try
{
addToDb.TransferBlogDetails(model);
return RedirectToAction("Index", "Admin");
}
catch (Exception)
{
ModelState.AddModelError("", "Invalid data,Please try again");
}
}
return View(model);
}


Here is the Model:

public class BlogModel
{
[HiddenInput]
public int BlogId { get; set; }

[Required(ErrorMessage = "Blog Title is required")]
public string BlogTitle { get; set; }
[Required(ErrorMessage = "Blog description is required")]
public string BlogDescription { get; set; }
public string BlogImage { get; set; }

public IEnumerable<SelectListItem> Tags { get; set; }
}


Any suggestions are appreciated.

Answer

Your property Tags is typeof IEnumerable<SelectListItem> and you cannot bind a <select multiple> to a collection of complex objects. A <select> posts back an array of simple values (the values of the selected options).

Your model needs a property to bind to, say

public IEnumerable<int> SelectedTags { get; set; }

assuming that the TagId of Tag is typeof int. Then the code in the view is

 @Html.ListBoxFor(m => m.SelectedTags , Model.Tags, new { @class = "form-control" })

Side notes:

  1. Do not use new { @name = "..." } - fortunately it does nothing, and never attempt to override the name attribute generated by the HtmlHelper methods
  2. Do not use new { @multiple = "multiple" } - the ListBox() and ListBoxFor() methods already generate that
  3. Use the TextBoxFor() andTextAreaFor()` methods to generate your other form controls so that you get correct 2-way model binding
  4. Remove the Selected = false code in the SelectListItem constructor (not only is it false by default, the value is ignored anyway - its the value of SelectedTags which determines what is selected)
Comments