Get controller and action name from within controller?

241,631

Solution 1

string actionName = this.ControllerContext.RouteData.Values["action"].ToString();
string controllerName = this.ControllerContext.RouteData.Values["controller"].ToString();

Solution 2

Here are some extension methods for getting that information (it also includes the ID):

public static class HtmlRequestHelper
{
    public static string Id(this HtmlHelper htmlHelper)
    {
        var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;

        if (routeValues.ContainsKey("id"))
            return (string)routeValues["id"];
        else if (HttpContext.Current.Request.QueryString.AllKeys.Contains("id"))
            return HttpContext.Current.Request.QueryString["id"];

        return string.Empty;
    }

    public static string Controller(this HtmlHelper htmlHelper)
    {
        var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;

        if (routeValues.ContainsKey("controller"))
            return (string)routeValues["controller"];

        return string.Empty;
    }

    public static string Action(this HtmlHelper htmlHelper)
    {
        var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;

        if (routeValues.ContainsKey("action"))
            return (string)routeValues["action"];

        return string.Empty;
    }
}

Usage:

@Html.Controller();
@Html.Action();
@Html.Id();

Solution 3

Might be useful. I needed the action in the constructor of the controller, and it appears at this point of the MVC lifecycle, this hasn't initialized, and ControllerContext = null. Instead of delving into the MVC lifecycle and finding the appropriate function name to override, I just found the action in the RequestContext.RouteData.

But in order to do so, as with any HttpContext related uses in the constructor, you have to specify the full namespace, because this.HttpContext also hasn't been initialized. Luckily, it appears System.Web.HttpContext.Current is static.

// controller constructor
public MyController() {
    // grab action from RequestContext
    string action = System.Web.HttpContext.Current.Request.RequestContext.RouteData.GetRequiredString("action");

    // grab session (another example of using System.Web.HttpContext static reference)
    string sessionTest = System.Web.HttpContext.Current.Session["test"] as string
}

NOTE: likely not the most supported way to access all properties in HttpContext, but for RequestContext and Session it appears to work fine in my application.

Solution 4

var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;
if (routeValues != null) 
{
    if (routeValues.ContainsKey("action"))
    {
        var actionName = routeValues["action"].ToString();
                }
    if (routeValues.ContainsKey("controller"))
    {
        var controllerName = routeValues["controller"].ToString();
    }
}

Solution 5

 @this.ViewContext.RouteData.Values["controller"].ToString();
Share:
241,631
Rob
Author by

Rob

"I love deadlines. I like the whooshing sound they make as they fly by." Douglas Adams

Updated on July 22, 2022

Comments

  • Rob
    Rob almost 2 years

    For our web application I need to save the order of the fetched and displayed items depending on the view - or to be precise - the controller and action that generated the view (and the user id of course, but that's not the point here).

    Instead of just giving an identifier myself in each controller action (in order to use it for some view-dependant sorting of DB outputs), I thought that it would be safer and easier to create this identifier automatically from the controller and action method it gets called from.

    How can I get the name of the controller and action from within the action method in a controller? Or do I need reflection for that?

    • citykid
      citykid over 10 years
      Reflection would give you the method name that handles the action, but presumably you prefer the action name as returned by Andrei's code.
    • Rob
      Rob over 10 years
      I basically just need an unambiguous identifier for every action that delivers a view, so both ways would do the job. But you're right, Andrei's answer is definitely more elegant.
    • John
      John over 9 years
      @citykid Are there cases where these differ in manners other than case and the "Controller" suffix for class names?
    • citykid
      citykid over 9 years
      @John, ActionNameAttribute allows a c# method to have any action name: msdn.microsoft.com/en-us/library/…
    • John
      John over 9 years
      @citykid Oh, ok. That's kind of an obsolete feature given that you can specify the routes with a Route attribute on the action method I gather? Also, is it also possible to rename controllers?
    • John
      John over 9 years
      @citykid (Addition to last comment after some more research: It appears that the "Route" attribute is newer and probably obsoletes the "Action" attribute somewhat. Also, the renaming the controllers would be more unusual but can by creating a custom controller factory. It appears that you can't then get the name from the class anymore though.)
    • citykid
      citykid over 9 years
      sure sure, the Actionname attribute is however still there, working and not marked as obsolete. in the common case the marked answer is the best way to do it anyway.
  • Amogh Natu
    Amogh Natu over 9 years
    In some case where you might want to have the name of the controller in the View file, then you can just use this.ViewContext.RouteData.Values["controller"].ToString();
  • FuckStackoverflow
    FuckStackoverflow about 9 years
    If you're going to do this (provide the action and controller name), why not just assign them directly???
  • Andrei
    Andrei about 9 years
    @MetalPhoenix, can you clarify a bit what use case you are talking about? OP does not need to assign controller or action - they just need to understand, in generic way, what are the controller and action currently being processed.
  • FuckStackoverflow
    FuckStackoverflow about 9 years
    On a second read, is it possible that I misunderstood the code snippit here? ...Values["action"] where "action" is a key and not the name of the action to be substituted (like "'Pass123' without the quotes" type of thing)? That is to say: would still be Values["action"] instead of Values["yourAction"]?
  • Andrei
    Andrei about 9 years
    @MetalPhoenix, exactly, "action" literal is a key, and Values["action"] will output "CurrentActionName"
  • FuckStackoverflow
    FuckStackoverflow about 9 years
    Well then it makes perfect sense! Thanks
  • Maksim Vi.
    Maksim Vi. almost 9 years
    Note that if you use routes.LowercaseUrls = true; your action names and contollers will be lowecased. I wonder if there's a workaround.
  • Mustafa ASAN
    Mustafa ASAN almost 9 years
    check my answer for different approach
  • Umar Abbas
    Umar Abbas over 8 years
    Best & Complete Solution, Thanks Jhon
  • Frédéric
    Frédéric over 8 years
    Those names will reflect the casing of request url. What you do with them should not be case-sensitive. (I fell in that trap.)
  • T-moty
    T-moty about 8 years
    -1: with your code, sub-level applications are simply ignored (eg: http://www.example.com/sites/site1/controllerA/actionB/). MVC provides a bunch of API's for routing, so why you need to parse (again) URLs?.
  • jstuardo
    jstuardo almost 7 years
    Why to reinvent the wheel and furthermore, with a poor reinvension? this does not work for all cases.
  • chriszo111
    chriszo111 over 6 years
    (1): Is this still one of the most common ways within MVC5? (2) Where do you get your filterContext variable from within GetDefaults()?
  • drzaus
    drzaus almost 6 years
    asides from subfolders, the real problem is that you can customize your routes so they won't always be controller/action
  • Ben
    Ben over 3 years
    Doesn't work in ASP.NET Core because HttpContext.Current doesn't exist anymore
  • Admin
    Admin over 3 years
    This was exactly what I was looking for. So simple, yet so powerful. Thanks.
  • Logarr
    Logarr almost 3 years
    I just tried overriding the ControllerFactory methods in MVC 5 to try and execute a common method after construction, because I needed to get at the HttpContext and Session and it wasn't working in the constructor. Even after it has been constructed, the values are not set where the factory can do anything with them, so they must be set after the controller factory is done doing its thing.