Wednesday, 13 November 2013

http://codeoverload.wordpress.com/2011/05/22/dropdown-lists-in-mvc-3/

Dropdown Lists in MVC 3

I’ve been lucky enough to work full-time with ASP.NET MVC 3 for the past couple of months, and I’ve completely fallen in love. It’s quite a change from WebForms, and it took a while to ‘click’ so I’m putting together a few examples both as a personal reference, but also to help anyone looking to take the leap from WebForms.
The first thing I struggled with was how to implement dropdown lists, so this post will walk through the steps required to make a simple form:
The first step is to build a model for the form. We need two properties for the dropdown, one to hold the list of options and the other for the ID of the selected option:
public class CreditCardModel
{
    public List<SelectListItem> CardTypeOptions { get; set; }

    [Display(Name = "Card Type")]
    public string CardTypeID { get; set; }

    [Display(Name = "Card Number")]
    [Required(ErrorMessage = "Please provide your card number")]
    public string CardNumber { get; set; }
}
The controller class requires two action methods, one to show the initial form (the GET request) and one to handle the form submission (the POST request):
public class CreditCardController : Controller
{
    public ActionResult AddCard()
    {
        var model = new CreditCardModel();
        
        // Populate the dropdown options
        model.CardTypeOptions = GetCardTypes("MS"); // Set the default to American Express
        return View(model);
    }
    
    [HttpPost]
    public ActionResult AddCard(CreditCardModel model)
    {
        // TODO - Handle the form submit

        // Populate the dropdown options
        model.CardTypeOptions = GetCardTypes("MS"); // Set the default to American Express
        return View(model);
    }
    
    // TODO - AddCardComplete goes here
    
    // TODO - GetCardTypes goes here
}
I’ve hard-coded the dropdown values inside the controller to keep things simple:
private List<SelectListItem> GetCardTypes(string defaultValue)
{
    List<SelectListItem> items = new List<SelectListItem>();
    items.Add(new SelectListItem { Text = "American Express", Value = "AE", Selected = (defaultValue == "AE") });
    items.Add(new SelectListItem { Text = "Mastercard", Value = "MS", Selected = (defaultValue == "MS") });
    items.Add(new SelectListItem { Text = "Visa", Value = "VS", Selected = (defaultValue == "VS") });
    return items;
}
The view needs the ‘@model’ directive at the top to bind to the CreditCardModel. I’m using Razor as my view engine of choice – quite simply, it rocks! Note the use of ValidationSummary, any validation errors will automatically appear here:
@model Demo.Models.CreditCardModel
@{
    ViewBag.Title = "Add Card";
}
<h2>Add Card</h2>
@using (Html.BeginForm())
{
    @Html.ValidationSummary()
<table>
    <tr>
        <td>@Html.LabelFor(x => x.CardTypeID)</td>
        <td>@Html.DropDownListFor(x => x.CardTypeID, Model.CardTypeOptions)</td>
    </tr>
    <tr>
        <td>@Html.LabelFor(x => x.CardNumber)</td>
        <td>@Html.EditorFor(x => x.CardNumber)</td>
    </tr>
</table>
<input type="submit" value="Add Card" />
}
Inside the AddCard POST action we need a check that the model is valid before we save the card details. This can be checked by calling ModelState.IsValid which is available to all action methods.
Something to watch out for – it’s a recommended practice to redirect the user to an action following a post. The reason for this is to prevent the user accidentally re-submitting the form by refreshing the page. This is done by returning a call to RedirectToAction(), passing in the action name.
if (ModelState.IsValid)
{
    // TODO - Save the data to your database...

    // Prevent the user resubmitting the card by asking their
    // browser to request a different page using a GET request
    return RedirectToAction("addcardcomplete");
}
Create a new view called AddCardComplete:
@{
    ViewBag.Title = "Add Card Complete";
}
<h2>Add Card Complete</h2>
<p>Your card has been added</p>
Create an action method for the view inside the controller:
public ActionResult AddCardComplete()
{
    return View();
}
All done! The selected value of the dropdown will be automatically bound to the CardTypeID property of the CreditCardModel instance.