views:

78

answers:

3

What's the most practical way to add custom properties to a side wide ViewDataDictionary?

Let's assume a simple case:

public ActionResult Index()
{
  // ViewData["Title"] = "Home";
  ViewData.Title = "Home";
  return View();
}

The first thing that comes to mind is a custom class and using "new" in a application base controller:

public class CustomDataDictionary : ViewDataDictionary
{
  public string Title { get; set; }
}

public class ApplicationController : Controller
{
    public new CustomDataDictionary ViewData { get; set;} 
}

I'm assuming you would also have to also make a corresponding CustomViewPage with the same property to use the custom view data dictionary in the views as well.

The second thing that comes to mind is to create a ViewDataDictionaryExtensions class.

Thirdly, use a "View Model". My beef with View Models are that always creating one and passing it into View seems like repeating yourself over and over in controller code, at least compared to the previous two options.

The real goal is that each application might have a core set of properties in the ViewData that make sense for that apps purpose. I tend to shy away from relying on dictionary keys, and it would be nice to have real properties for other developers to rely one to know what data to set. Plus, keys can easily be misspelled.

All three methods get the job done. What have others done?

A: 

Re the problem with names getting misspelt - that is what constants are for.

For ViewData to be typed appropriately, you'd need to inherit etc; so by the time you've done that, I wonder if you couldn't just as easily add some common code into the controller that sets a key.

Using a key seems, to me at least, the least complex answer - that also works in the widest number of cases (i.e. where certain code only knows about a basic IDictionary<string,object>).

You may also be interested in this related question.

Marc Gravell
"that is what constants are for."That sounds great, until you have about 50 of them. It get's old really quick when you start using constants for hash key names.Extensions would be gret... if only we had extension properties. Get/Set ala SmartBag doesn't tell the non familiar coder much about the problem being solved.Controller methods would be ok, but you're implying they're properties of the controller, which isn't true. They're properties of the actions viewdata.
claco
A: 

All of those sound like they would work. I figure which one you choose depends what your requirements/needs are. (Really unique and informative answer, huh?)

Your question was "What have others done?" though. So, if you're polling, I have used the constants approach for smaller applications recently. I haven't done an enterprise MVC app yet, but I figure I would probably make a base class that inherits Controller and defines those extra properties. And if I wanted to pass those consistently to the view I would similarly have a base class for my models. However, this would have to be used judiciously--even if you formally type them, they still act a lot like globals. So you have to be careful of course.

Mufasa
A: 

In the end, at least for this app, I went with having a a base AppViewModel class. Controller.OnActionExecute/ed looks to see of ViewData.Model is set and if it isn't, an instance of AppViewModel is put in it's place so all pages have a consistent Model to work with (Model.Title, Model.IsAuthenticated, Model.User, etc)

Then more detailed controller actions have a subclass of AppModelView that gets set to ViewData.Model either manually in the action itself, or set in the OnExecute/ed via an attribute.

Not very much code at all, but it keeps from repeating the same old create/set code in all the controller actions. And for me, it keeps the view data as a package rather than cluttering up the Controller api.

claco