views:

57

answers:

1

I have entries for an enumeration stored inside a database table with only the following fields: ID and Name. I want to show the values stored inside this table inside a DropDownList on a form. The user then chooses a value and submits the form.

I found a way to easily create a DropDownList from an enumeration (although it would probably be best to just populate the DropDownList with the Name fields of all the records in the table). However, I haven't found a way to later bind the DropDownList in the form submission to an integer value to put into the database (FK - PK) with the other form values.

Can you provide some sample code that illustrates how to do such binding?

UPDATE: Thanks for the awesome answer. I have one more question: is it possible to fetch DropDownList content via AJAX and have it be put into the DropDownList and into the SelectList in the ViewModel (with both the ID and Name parameters)? I want to selectively fetch content based on an input the user makes and I want the ViewModel to then be filled with that fetched data.

+2  A: 

As always start by defining a model:

public class MyViewModel
{
    public int SelectedValue { get; set; }
    public IEnumerable<SelectListItem> Items { get; set; }
}

Then the controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel
        {
            // TODO: Fetch from the database some enumerable collection 
            // containing Id and Name
            Items = new SelectList(new[]
            {
                new { Id = 1, Name = "item 1" },
                new { Id = 2, Name = "item 2" },
            }, "Id", "Name")
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        // TODO: Do something with model.SelectedValue
        return RedirectToAction("index");
    }
}

and finally the strongly typed view:

<% using (Html.BeginForm()) { %>
    <%: Html.DropDownListFor(x => x.SelectedValue, Model.Items) %>
    <input type="submit" value="OK" />
<% } %>
Darin Dimitrov
Is it *that* easy? That's called a View Model, right? I've run across such a term, but never knew what it meant and that it was as easy to use as that. It's nice that ASP.NET MVC has such a good model binder.
Maxim Zaslavsky
View Model is a class that you provide to reflect the View (data that will be shown/edited), so it is tightly coupled to the view. The Model on the other hand represents your business logic. It could be a class that represent business entities and contain much more fields that are shown to the view. Your repositories usually work with models. So in your controller you would use a repository to fetch a model object, map it to a view model and pass this view model to the view. On another controller action you could fetch the same model but map it to a different view model.
Darin Dimitrov
Thanks so much for your help! One more quick question: if I decorate the properties in my ViewModel with validation attributes (such as RequiredAttributes), do they only apply when the form is submitted and the ViewModel is returned to the Controller or will they break my code when I first create the ViewModel instance in the HttpGet part?
Maxim Zaslavsky
In my above comment, I'm assuming that it's better to have the validation in the ViewModel, so that I can have both server-side and client-side validation without any pain. Is that not the case?
Maxim Zaslavsky
Yes, you can decorate the properties of you view model with validation attributes. They will be applied by the default model binder when this view model appears as an argument of a controller action you are posting to.
Darin Dimitrov
@Darin awesome. Sorry to bother you again, but I have one more question. Is it possible to fetch DropDownList content via AJAX and have it be put into the DropDownList and into the SelectList in the ViewModel (with both the ID and Name parameters)? I want to selectively fetch content based on an input the user makes and I want the ViewModel to then be filled with that fetched data.
Maxim Zaslavsky