views:

8236

answers:

7

I wanted to set a css class in my master page depending on the current controller and action. I can get to the current controller via ViewContext.Controller.GetType().Name, but how do I get the current action? (ie Index, Show etc)

+6  A: 

In MVC you should provide the View with all data, not let the View collect its own data so what you can do is to set the CSS class in your controller action.

ViewData["CssClass"] = "bold";

and pick out this value from your ViewData in your View

TT
This would be my preferred method as well to keep the views from depending on the controller structure, but it can be done otherwise.
tvanfosson
Not sure I would name it "CssClass" as that seems to indicate that display logic is creeping into your controller.
tvanfosson
Agreed, I usually do something like "Context", so it is not tied to presentation layer, and does not break if you rename the view either.
RedFilter
+9  A: 

Use the ViewContext and look at the RouteData collection to extract both the controller and action elements. But I think setting some data variable that indicates the application context (e.g., "editmode" or "error") rather than controller/action reduces the coupling between your views and controllers.

tvanfosson
+11  A: 

To get the current Id on a View:

ViewContext.RouteData.Values["id"].ToString()

To get the current controller:

ViewContext.RouteData.Values["controller"].ToString()
tsquillario
+18  A: 

In the RC you can also extract route data like the action method name like this

ViewContext.Controller.ValueProvider["action"].RawValue
ViewContext.Controller.ValueProvider["controller"].RawValue
ViewContext.Controller.ValueProvider["id"].RawValue
Christian Dalager
I know this pre-dates V2, but it's now `ViewContext.Controller.ValueProvider.GetValue("action").RawValue` + variations
Chris S
+6  A: 

I know this is an older question, but I saw it and I thought you might be interested in an alternative version than letting your view handle retrieving the data it needs to do it's job.

An easier way in my opinion would be to override the OnActionExecuting method. You are passed the ActionExecutingContext that contains the ActionDescriptor member which you can use to obtain the information you are looking for, which is the ActionName and you can also reach the ControllerDescriptor and it contains the ControllerName.

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    ActionDescriptor actionDescriptor = filterContext.ActionDescriptor;
    string actionName = actionDescriptor.ActionName;
    string controllerName = actionDescriptor.ControllerDescriptor.ControllerName;
    // Now that you have the values, set them somewhere and pass them down with your ViewModel
    // This will keep your view cleaner and the controller will take care of everything that the view needs to do it's job.
}

Hope this helps. If anything, at least it will show an alternative for anybody else that comes by your question.

Dale Ragan
nice recommendation; helped me in implementing controller/action sensing intelligently. Thanks!
effkay
+3  A: 

I vote for this 2:

string currentActionName = ViewContext.RouteData.GetRequiredString("action");

and

string currentViewName = ((WebFormView)ViewContext.View).ViewPath;

You can retrive both physical name of current view and action that triggered it. It can be usefull in partial *.acmx pages to determine host container.

A: 

How? When I try the above way I get an error NullReferenceException

Welcome to Stack Overflow! This site is a question and answer site, and not a forum, so it may work a little differently than you are used to. After reading the FAQ (http://stackoverflow.com/faq) may I suggest that you ask your question as a new question. You can link back to this one to provide context to those people who will answer.
Jason Berkan