1

In my MVC project, I am having issue with binding MultiSelectLists with my Model properties. Although I can get the values through FormCollection object, but those are just the Selected IDs.

Following is my Model Class which represents a Post.

public class PostModel
{
    [Required(ErrorMessage = "Id is a required field")]
    public int Id { get; set; }

    [Required(ErrorMessage = "Post Title is required")]
    [StringLength(500)]
    public string Title { get; set; }

    .......

    public SelectList UnassignedTags { get; set; }
    public SelectList AssignedTags { get; set; }
}

Please note that this is just a Model class and has two additional properties (UnassignedTags and AssignedTags) only for the purpose of displaying them on screen and for keeping the values bound between calls.

A Single Post can be marked with multiple Tags. On my View, I want two multi select Lists. One to hold Unassigned Tags (Text and Value) and other to Hold Assigned Tags (Text and Value).

On My view, I show a Multi Select list for these lists using following code.

@Html.ListBox("UnassignedTagss", Model.UnassignedTags, new { @class = "form-control" })

@Html.ListBox("AssignedTagss", Model.AssignedTags, new { @class = "form-control" })

Everything is ok when I load the record on screen.

Once loaded, I let user move items between lists through javascript.

The problem comes when Form gets posted back for editions. I am unable to bind Listbox values with my model properties.

Following are my Action Methods for Showing / Editing Post record.

public ActionResult PostDtls(int postId)
{
    …..
}

[HttpPost]
public ActionResult PostDtls(PostModel post, FormCollection collection)
{
    …….
}

Is there any way I can bind ListBox items (regardless of selected or not) to my Model SelectList properties i.e. UnAssignedTags and AssignedTags ?

At the moment, I am selecting all items of ListBox through JQuery before posting the form back to the server. This way, I get comma separated Ids in FormCollection Object. However, the problem is that if I have to redisplay the view to the user because of an Invalid ModelState, I have to fetch the Tags from the database based on the Ids available in FormCollection object. I know the above solution is bad. And I need to know a good approach to implement this requirement.

1 Answer 1

6

I'm not sure why you are taking this approach. The first thing you need are 2 additional properties in your view model (I'm assuming the value type is int)

public int[] SelectedUnassignedTags { get; set; }
public int[] SelectedAssignedTags  { get; set; }

Then create the DropDownLists as follows

@Html.ListBoxFor(m => m.SelectedUnassignedTags, Model.UnassignedTags, ...)
@Html.ListBoxFor(m => m.SelectedUnassignedTags, Model.UnassignedTags, ...)

On postback, SelectedUnassignedTags and SelectedAssignedTags will contain the values that have been selected in the respective listboxes, so for example if you selected these 2 options

<option value="2">Item No 2</option>
<option value="4">Item No 4</option>

then SelectedUnassignedTags would be an array containing 2 and 4

In you post method (don't see any need for FormCollection)

public ActionResult PostDtls(PostModel post)
{
  if (!ModelState.IsValid())
  {
    // Repopulate you select lists (as you would have done in the get method)
    return View(post);
  }
}

To try and construct all the necessary option values, associated text and selected status in javascript and post back that much additional data, and then reconstruct them in the post method is likely to be more expensive than the database call (and of course, you could always cache them to avoid calling the database)

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your reply Stephen. As suggested, I am able to get the Ids through my model int[] properties. However, the thing that is disturbing me is that every time the form is submitted, I only have the Assigned / Unassigned IDs (which could be different from what was initially loaded) with me and do not have the option text. So based on these IDs I'll have to fetch the details (Tag display Text) from database every time form is submitted. Is that right ? or I am missing something here
Yes, that is the better way to go. While it would be possible to post back the ID value, Text value and Selected status for each option using javascript, this (apart from being very complex code) would likely be much slower than fetching from the database. Its only going to be applicable if your have validation errors, and with proper use of attributes, it can all be handled on the client side so the model should rarely be invalid anway. And if its fairly static data, the use MemoryCache or Session to avoid recalling the database.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.