[c#] How can I return the current action in an ASP.NET MVC view?

I wanted to set a CSS class in my master page, which depends 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 (e.g. Index, Show etc.)?

This question is related to c# asp.net-mvc

The answer is


To get the current Id on a View:

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

To get the current controller:

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

You can get these data from RouteData of a ViewContext

ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["action"]

I am using ASP.NET MVC 4, and this what worked for me:

ControllerContext.Controller.ValueProvider.GetValue("controller").RawValue
ControllerContext.Controller.ValueProvider.GetValue("action").RawValue

Extending Dale Ragan's answer, his example for reuse, create an ApplicationController class which derives from Controller, and in turn have all your other controllers derive from that ApplicationController class rather than Controller.

Example:

public class MyCustomApplicationController : Controller {}

public class HomeController : MyCustomApplicationController {}

On your new ApplicationController create a property named ExecutingAction with this signature:

protected ActionDescriptor ExecutingAction { get; set; }

And then in the OnActionExecuting method (from Dale Ragan's answer), simply assign the ActionDescriptor to this property and you can access it whenever you need it in any of your controllers.

string currentActionName = this.ExecutingAction.ActionName;

I am using ASP.NET MVC 4, and this what worked for me:

ControllerContext.Controller.ValueProvider.GetValue("controller").RawValue
ControllerContext.Controller.ValueProvider.GetValue("action").RawValue

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


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.


You can get these data from RouteData of a ViewContext

ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["action"]

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

Update for MVC 3

ViewContext.Controller.ValueProvider.GetValue("action").RawValue
ViewContext.Controller.ValueProvider.GetValue("controller").RawValue
ViewContext.Controller.ValueProvider.GetValue("id").RawValue

Update for MVC 4

ViewContext.Controller.RouteData.Values["action"]
ViewContext.Controller.RouteData.Values["controller"]
ViewContext.Controller.RouteData.Values["id"]

Update for MVC 4.5

ViewContext.RouteData.Values["action"]
ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["id"]

Extending Dale Ragan's answer, his example for reuse, create an ApplicationController class which derives from Controller, and in turn have all your other controllers derive from that ApplicationController class rather than Controller.

Example:

public class MyCustomApplicationController : Controller {}

public class HomeController : MyCustomApplicationController {}

On your new ApplicationController create a property named ExecutingAction with this signature:

protected ActionDescriptor ExecutingAction { get; set; }

And then in the OnActionExecuting method (from Dale Ragan's answer), simply assign the ActionDescriptor to this property and you can access it whenever you need it in any of your controllers.

string currentActionName = this.ExecutingAction.ActionName;

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.


Override this function in your controller

protected override void HandleUnknownAction(string actionName) 
{  TempData["actionName"] = actionName;
   View("urViewName").ExecuteResult(this.ControllerContext);
}

To get the current Id on a View:

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

To get the current controller:

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

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


I saw different answers and came up with a class helper:

using System;
using System.Web.Mvc;

namespace MyMvcApp.Helpers {
    public class LocationHelper {
        public static bool IsCurrentControllerAndAction(string controllerName, string actionName, ViewContext viewContext) {
            bool result = false;
            string normalizedControllerName = controllerName.EndsWith("Controller") ? controllerName : String.Format("{0}Controller", controllerName);

            if(viewContext == null) return false;
            if(String.IsNullOrEmpty(actionName)) return false;

            if (viewContext.Controller.GetType().Name.Equals(normalizedControllerName, StringComparison.InvariantCultureIgnoreCase) &&
                viewContext.Controller.ValueProvider.GetValue("action").AttemptedValue.Equals(actionName, StringComparison.InvariantCultureIgnoreCase)) {
                result = true;
            }

            return result;
        }
    }
}

So in View (or master/layout) you can use it like so (Razor syntax):

            <div id="menucontainer">

                <ul id="menu">
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("home", "index", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("account","logon", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("Logon", "Logon", "Account")</li>
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("home","about", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("About", "About", "Home")</li>
                </ul>

            </div>

Hope it helps.


To get the current Id on a View:

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

To get the current controller:

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

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.


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.


To get the current Id on a View:

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

To get the current controller:

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

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


Override this function in your controller

protected override void HandleUnknownAction(string actionName) 
{  TempData["actionName"] = actionName;
   View("urViewName").ExecuteResult(this.ControllerContext);
}

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

Update for MVC 3

ViewContext.Controller.ValueProvider.GetValue("action").RawValue
ViewContext.Controller.ValueProvider.GetValue("controller").RawValue
ViewContext.Controller.ValueProvider.GetValue("id").RawValue

Update for MVC 4

ViewContext.Controller.RouteData.Values["action"]
ViewContext.Controller.RouteData.Values["controller"]
ViewContext.Controller.RouteData.Values["id"]

Update for MVC 4.5

ViewContext.RouteData.Values["action"]
ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["id"]

I saw different answers and came up with a class helper:

using System;
using System.Web.Mvc;

namespace MyMvcApp.Helpers {
    public class LocationHelper {
        public static bool IsCurrentControllerAndAction(string controllerName, string actionName, ViewContext viewContext) {
            bool result = false;
            string normalizedControllerName = controllerName.EndsWith("Controller") ? controllerName : String.Format("{0}Controller", controllerName);

            if(viewContext == null) return false;
            if(String.IsNullOrEmpty(actionName)) return false;

            if (viewContext.Controller.GetType().Name.Equals(normalizedControllerName, StringComparison.InvariantCultureIgnoreCase) &&
                viewContext.Controller.ValueProvider.GetValue("action").AttemptedValue.Equals(actionName, StringComparison.InvariantCultureIgnoreCase)) {
                result = true;
            }

            return result;
        }
    }
}

So in View (or master/layout) you can use it like so (Razor syntax):

            <div id="menucontainer">

                <ul id="menu">
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("home", "index", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("account","logon", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("Logon", "Logon", "Account")</li>
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("home","about", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("About", "About", "Home")</li>
                </ul>

            </div>

Hope it helps.