tags:

views:

46

answers:

3

I'm working on an ASP.NET MVC controller with several action methods, all of which need the same bit of data. This data requires a lookup that can only be done with the route values (so, I can't do the lookup in the constructor). I'm sure this has been discussed at length, but I've yet to find a satisfactory recommendation.

What's the best way to get this data without repeating myself in each action method? I'm working through:

  • Create an Action Filter, this seems like the best bet, but where do I store the object, in the action parameters? Is it appropriate to create a ViewModel object in an action filter and pass it directly to the action methods, for them to fill out the rest of the ViewModel object?

  • Create a child action (Html.RenderAction) to render this data, but this requires a second set of lookups since the child action requires another full cycle of instantiating the controller.

  • Helper method/property called in each action method.

Thought or opinions on a best approach here?

+1  A: 

A filter is probably your best bet and you can store the object in ViewData.

Another option (not a better one) is to create your own controller base class that overrides the ExecuteCore method and does the lookup there.

I did this for logging since I want to log each page view and I didn't want to have to add a filter to each and every controller I made. In mvc 3 there will be a way to declare global filters which can fix this as well.

Sruly
I was heading down this road, seems like a good way to do it. But, then I ended up having to pull the object out of ViewData in each action method, again repeating myself, and doing something that may be easier and more readable in a simple helper method, so I'm souring a bit on the filter idea right now.
RyanW
You can use master pages and create a helper method to pull the data from ViewData to save you some repetitiveness.
Sruly
A: 

You could override the OnActionExecuting() method in your controller and get the data there.

M4N
Thanks for the tip. This would be equivalent to adding a filter at the controller level right? Since it would be called for every action.
RyanW
The down side here is that testability decreases (as it does with filters) since the code is further apart and dependent on the mvc runtime. Binders and helper method have an advantage in this regard.
RyanW
+1  A: 

Ok, so given what you've told me, I would suggest using a custom ModelBinder.

It's the best fit for the situation. I would argue that using a filter is the wrong approach because a filter's job isn't to bind data - that's a job for a ModelBinder.

HTHs,
Charles

EDIT: I've just been thinking about it and I'm a little bit torn if you should use a model binder or not.

The general rule of thumb I just came up with is that if you need the ProjectDetails inside the action itself, use a ModelBinder but if you don't need the ProjectDetails inside the action, use an ActionFilter to just add it to your model / viewdata.

Maybe someone else could throw their 2c in.

Charlino
Interesting, I hadn't even thought about a ModelBinder. I'll explore that a bit too. Thanks.
RyanW
From your other comment on @Sruly's answer, it sounds like you are using the ProjectDetails inside the action method... If that's the case, I'd definitely use the ModelBinder approach, no question about it.
Charlino
It's used, but only in that the action method would pull ProjectDetails out of ViewData and load it into the ViewModel.
RyanW
In that case, could you define an simple interface which has a ProjectDetails property, make sure all your viewmodels inherit from that interface, then inside your action filter (OnActionExecuted) cast the viewmodel to that interface and set the ProjectDetails there so you don't have to do it in the Action method...?
Charlino