Congratulations to all monthly winners of May 2013 !!! They have won INR 2900 cash and INR 27497 worth prize.
DotNetFunda.Com Logo
Twitter TwitterLinkedIn
YouTubeGoogle
 Online : 33294 |  Welcome, Guest!   Register  Login
 Home > Blogs > ASP.NET > Using DropdownList in MVC ...
Vikash

Using DropdownList in MVC

 Blog author: Vikash | Posted on: 9/22/2012 | Category: ASP.NET Blogs | Views: 960 | Status: [Member] | Points: 75 | Alert Moderator   
Ads

Working with drop-down lists in ASP.NET MVC has some confusing aspects,

and here we can see with some example.

Imagine the goal is to edit a song (not the music and lyrics of a song - just the boring data pieces). Each song is associated with an album, and each song has a title and track number. With this description, you can imagine an edit view using the following code:

<%= Html.DropDownList("AlbumId", Model.Albums)%>
  ...
<%= Html.TextBox("Title", Model.Title) %>
   ...
<%= Html.TextBox("TrackNumber", Model.TrackNumber) %>

The Html.DropDownList helper method likes to work with SelectListItem objects, so a view model you can pair with this view looks like the following:

public class EditSongViewModel
{        
    public string Title { get; set; }                
    public int TrackNumber { get; set; }
    public IEnumerable<SelectListItem> Albums { get; set; }
}

Some people don't like to use SelectListItem types in their view models. Instead, they'll convert to them in the view. I think it's entirely reasonable to use SelectListItem in a view model, because the view model is supposed to make the view easier to write. Having the view model perfectly aligned with the needs of the view means you need to think less (and write less code) when creating the view.

Creating SelectListItems

There are a couple approaches you can take when creating a sequence of SelectListItem objects. I think the cleanest approach is to have an extension method that knows how to take a collection of objects in your software (like Album objects), and map them into SelectListItem objects.

public static IEnumerable<SelectListItem> ToSelectListItems(
              this IEnumerable<Album> albums, int selectedId)
{
    return 
        albums.OrderBy(album => album.Name)
              .Select(album => 
                  new SelectListItem
                  {
                    Selected = (album.ID == selectedId),
                    Text = album.Name,
                    Value = album.ID.ToString()
                   });
}

You can use the method like this:

model.Albums = _repository.FindAllAlbums().ToSelectItems(selectedId);

That code works, because Html.DropDownList will happily work with IEnumerable of SelectListItem.

The class you need to be careful with is the SelectList class. I've seen quite a few people make the mistake of wrapping their SelectListItem objects in a SelectList without setting the DataTextField and DataValueField properties. This does not work:

model.Albums = new SelectList(
                _repository.FindAllAlbums().ToSelectListItems(1)
                );

You'd think the SelectList class would know how to work with a collection of SelectListItem objects - but it doesn't. The following doesn't work either (the drop-down list will display "System.Web.Mvc.SelectListItem" for every entry):

model.Albums = 
    new SelectList(_repository.FindAllAlbums()
                              .ToSelectItems(selectedID));

The SelectList class is really designed to perform the conversion we did earlier (with the extension method), but it uses late binding reflection. The following would work, because we tell the SelectList where to find the text and value fields:

model.Albums = new SelectList(
                _repository.FindAllAlbums(), "ID", "Name"
                );

Reading the Selection

If you are using the same model to accept input from the edit view during a postback, you might think the default model binder will repopulate the Albums collection with all the album information and set the selected album. Unfortunately - the web doesn't work this way and the Albums collection will be empty.

The only album related information the browser will post is the value of the selected item. If you want this value bound to a model, you'll need to provide an AlbumId property (to match the name we gave the DropDownList in the view - "AlbumId").

public class EditSongViewModel
{
    public int AlbumId { get; set; }
    public string Title { get; set; }                
    public int TrackNumber { get; set; }
    public IEnumerable<SelectListItem> Albums { get; set; }
}

Some people will create two separate view models in this case. One view model is designed to carry information to the view, and will have an Albums property (but no AlbumId property). The second view model is designed to accept user input during postback and will have an AlbumId propery (but no Albums property). This approach adds the overhead of an extra class, but the view models are perfectly aligned with their duties and no properties go unused. You'll have to decide which approach is best for you.

Summary

  • Don't use a SelectList without telling it the DataTextField and DataValueField properties to use.
  • Don't expect to see a collection for a drop-down list repopulated on a postback.
  • Extension methods make it easy to create a sequence of SelectListItem objects in strongly-typed code.
  • Html.DropDownList doesn't require a SelectList - it's happy working with any sequence of SelectListItem objects.



Regards,
Vikash Pathak
Found interesting? Add this to:


Experience:1 year(s)
Home page:http://www.dotnetfunda.com/profile/vikash.aspx
Member since:Monday, June 18, 2012
Level:Starter
Status: [Member]
Biography:1+ yrs exp in .Net & MCP(70-526) paper completed.

 Responses

Vinay13mar
Posted by: Vinay13mar | Posted on: 11/3/2012 | Level: Starter | Status: [Member] | Points: 15 | Alert Moderator 
>> Write Response - Respond to this post and get points

More Blogs

About Us | Contact Us | The Team | Advertise | Software Development | Write for us | Testimonials | Privacy Policy | Terms of Use | Link Exchange | Members | Go Top
General Notice: If you find plagiarised (copied) contents on this page, please let us know the original source along with your correct email id (to communicate) for further action.
Copyright © DotNetFunda.Com. All Rights Reserved. Copying or mimicking the site design and layout is prohibited. Logos, company names used here if any are only for reference purposes and they may be respective owner's right or trademarks. | 6/19/2013 7:24:29 AM