3

I'm working with MVC 5 for a few months read a lot of articles, forums and documentation but always wondering what is better in the view;

1) binding data using static method of model like here

2) binding the same data using ViewData[index] which is set in Controller that with previous example will look like this

@Html.DropDownListFor(n => n.MyColorId, ViewData[index])
Community
  • 1
  • 1
DespeiL
  • 993
  • 9
  • 28
  • 1
    Honestly, I'd go for the option that lets the compiler cry foul if you refactor the model. `ViewData[index]` is more brittle in this case. – Berin Loritsch Jun 14 '16 at 18:00
  • One thing ViewBag/ViewData have going for them though is that you don't have to reference System.Web.Mvc in your model class (for SelectListItem). You might like to keep your model classes separate as a bridge between DAL and repository, with no requirement to know anything about ASP.NET MVC. You could always meet halfway by making 'AvailableColors' a Dictionary instead and Select-ing to a List on the page itself, but that's not particularly attractive either. – oflahero Oct 14 '16 at 10:43

2 Answers2

8

You want to use option 1, mainly because you want to use Strongly Type as much as possible, and fix the error at compile time.

In contrast, ViewData and ViewBag are dynamic, and compile could not catch error until run-time.

Here is the sample code I used in many applications -

Model

public class SampleModel
{
    public string SelectedColorId { get; set; }
    public IList<SelectListItem> AvailableColors { get; set; }

    public SampleModel()
    {
        AvailableColors = new List<SelectListItem>();
    }
}

View

@model DemoMvc.Models.SampleModel
@using (Html.BeginForm("Index", "Home"))
{
    @Html.DropDownListFor(m => m.SelectedColorId, Model.AvailableColors)
    <input type="submit" value="Submit"/>

}

Controller

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new SampleModel
        {
            AvailableColors = GetColorListItems()
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(SampleModel model)
    {
        if (ModelState.IsValid)
        {
            var colorId = model.SelectedColorId;
            return View("Success");
        }
        // If we got this far, something failed, redisplay form
        // ** IMPORTANT : Fill AvailableColors again; otherwise, DropDownList will be blank. **
        model.AvailableColors = GetColorListItems();
        return View(model);
    }

    private IList<SelectListItem> GetColorListItems()
    {
        // This could be from database.
        return new List<SelectListItem>
        {
            new SelectListItem {Text = "Orange", Value = "1"},
            new SelectListItem {Text = "Red", Value = "2"}
        };
    }
}
Win
  • 61,100
  • 13
  • 102
  • 181
2

I would say, completely separate dropdown items from ViewData. Have your model contain a property for dropdown. Fill that in your controller and just bind it in the view like

ViewModel

class MyModel
{
    public IEnumerable<SelectListItem> dropdowndata {get; set;}
}

Controller

public Actionresult MyAction(string id)
{
     IEnumerable<data> mydata = callDALmethodtogetit();
     Mymodel model = new MyModel 
                     {
                        dropdowndata = mydata.Select(c => new SelectListItem 
                                                       { 
                                                          Value = c.Id.ToString(), 
                                                          Text = c.Name 
                                                       });
                     }
 }

View

@Html.DropDownListFor(model => model.dropdowndata, Model.dropdowndata)
Luiso
  • 4,173
  • 2
  • 37
  • 60
Rahul
  • 76,197
  • 13
  • 71
  • 125
  • If in model 'A' I only need ID of model 'B' why I sould keep collection of all models 'B'? – DespeiL Jun 14 '16 at 18:06
  • @DespeiL, I given a sample code to show what I am saying. intention is to get the dropdown data as part of controller action and in view you should just bind it and nothing more than that. – Rahul Jun 14 '16 at 18:09
  • You cannot bind a ` –  Jun 14 '16 at 23:06