Coder Perfect

Is it possible to get the controller and action names from within the controller?

Problem

I need to save the order of the fetched and displayed items based on the view – or, to be more accurate, the controller and action that generated the view (and, of course, the user id, but that’s not the point here).

Instead of manually providing an identifier in each controller action (to be used for some view-dependent sorting of DB outputs), I decided that it would be safer and easier to generate one automatically from the controller and action method it is called from.

How do I extract the name of the controller and action from a controller’s action method? Or do I need to think about it?

Asked by Rob

Solution #1

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

Answered by Andrei

Solution #2

Here are some extension methods for retrieving that data (including 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();

Answered by John B

Solution #3

It could be handy. I needed the action in the controller’s constructor, and it appears that this hasn’t been initialized at this point in the MVC lifecycle, as ControllerContext = null. I located the action in RequestContext.RouteData rather than going into the MVC lifecycle and looking for the relevant function name to override.

However, like with any HttpContext-related use in the constructor, you must supply the whole namespace in order to do so. HttpContext hasn’t been set up yet, either. Fortunately, System.Web.HttpContext.Current looks to be 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: This is probably not the best technique to access all properties in HttpContext, but it appears to work fine in my application for RequestContext and Session.

Answered by sonjz

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();
    }
}

Answered by Chris Ballance

Solution #5

 @this.ViewContext.RouteData.Values["controller"].ToString();

Answered by Hossein Hajizadeh

Post is based on https://stackoverflow.com/questions/18248547/get-controller-and-action-name-from-within-controller