4

This is taken from VS Add New Scaffolded Item... when creating a new controller.

In the controller:

// GET: Drivers/Create
public ActionResult Create()
{
    ViewBag.Tenant = new SelectList(db.Tenants, "TenantID", "TenantName");
    return View();
}

The view then renders a drop-down list:

@Html.DropDownListFor(model => model.Tenant, null, htmlAttributes: new { @class = "form-control" })

The relevant model information:

public partial class Driver
{
    public int DriverID { get; set; }
    public int Tenant { get; set; }
    public virtual Tenant Tenant1 { get; set; }
}

public partial class Tenant
{
    public Tenant()
    {
        this.Drivers = new HashSet<Driver>();
    }

    public int TenantID { get; set; }
    public string TenantName { get; set; }
    public virtual ICollection<Driver> Drivers { get; set; }
}

Can someone explain why this works?

I looked at other questions and documentation and couldn't find the answer. I suspect it is something along the lines of "convention over configuration" and it is pulling from the ViewBag using the name of the property. In fact, I changed the ViewBag property to Tenantz and got the following exception:

There is no ViewData item of type 'IEnumerable' that has the key 'Tenant'.

So is setting the property name of the ViewBag the same as the model property you want to update a good practice? It seems ok but I always hear how you should avoid ViewBag and dynamic types.

2
  • what is the model of your view? Commented Mar 30, 2016 at 20:01
  • @SOfanatic added to question Commented Mar 30, 2016 at 20:06

1 Answer 1

7

As you have already discovered there's a convention. The following line in your view:

@Html.DropDownListFor(model => model.Tenant, null, htmlAttributes: new { @class = "form-control" })

is exactly the same as this line:

@Html.DropDownList("Tenant", null, htmlAttributes: new { @class = "form-control" })

Now if you look at how the DropDownList helper is implemented in the source code you will notice that it simply does that:

object obj = htmlHelper.ViewData.Eval(name) as IEnumerable<SelectListItem>;

where name is the first argument passed to the DropDownList helper. And guess what? It discovers the corresponding value that you have set in your controller: ViewBag.Tenant = ....

This being said using ViewBag is an absolutely, disastrously, terribly bad practice. You've already find out why. It can bite you like a dog without you even knowing what's going on. The best way to protect against those dogs (ViewBag) is to search them inside your solution and give them poison. Simply get rid of absolutely any ViewBag calls in your code and use view models. Then you will not get bad surprises and everything will have a reasonable explanation and questions like this wouldn't be necessary on StackOverflow.

Like for example you could write a normal view model:

public class DriverViewModel
{
    public int? SelectedTenantID { get; set; }

    public IEnumerable<SelectListItem> Tenants { get; set; }
}

and a normal controller action that will query your datastore for the required information and project your entity model to the view model:

// GET: Drivers/Create
public ActionResult Create()
{
    var viewModel = new DriverViewModel();
    viewModel.Tenants = new SelectList(db.Tenants, "TenantID", "TenantName");
    return View(viewModel);
}

and finally the corresponding strongly typed view:

@model DriverViewModel
...
@Html.DropDownListFor(
    model => model.SelectedTenantID, 
    Model.Tenants, 
    htmlAttributes: new { @class = "form-control" }
)

In this case you are using a strongly typed view, with a strongly typed view model and a helper. There are no longer any doubts (and dogs that bite). The code is readable and you cannot ask, why this convention over configuration is doing this or that. So as long as there's no trace of ViewBag in your application there will be no such questions.

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

4 Comments

dogs and poison :) Nice!
Yeah, it's incredible that people continue to insist on using ViewBag. Even after it has bitten the crap out of them.
Based on your answer, is there any scenario at all where utilizing the ViewBag would be appropriate?
I will add that the scaffolding actually added the second line listed, which is even worse than the first because it uses a hard-coded string.

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.