Get controller and action name from within controller?
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();
Rob
"I love deadlines. I like the whooshing sound they make as they fly by." Douglas Adams
Updated on July 22, 2022Comments
-
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 over 10 yearsReflection would give you the method name that handles the action, but presumably you prefer the action name as returned by Andrei's code.
-
Rob over 10 yearsI 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 over 9 years@citykid Are there cases where these differ in manners other than case and the "Controller" suffix for class names?
-
citykid over 9 years@John, ActionNameAttribute allows a c# method to have any action name: msdn.microsoft.com/en-us/library/…
-
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 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 over 9 yearssure 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 over 9 yearsIn 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 about 9 yearsIf you're going to do this (provide the action and controller name), why not just assign them directly???
-
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 about 9 yearsOn 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 about 9 years@MetalPhoenix, exactly, "action" literal is a key, and Values["action"] will output "CurrentActionName"
-
FuckStackoverflow about 9 yearsWell then it makes perfect sense! Thanks
-
Maksim Vi. almost 9 yearsNote that if you use
routes.LowercaseUrls = true;
your action names and contollers will be lowecased. I wonder if there's a workaround. -
Mustafa ASAN almost 9 yearscheck my answer for different approach
-
Umar Abbas over 8 yearsBest & Complete Solution, Thanks Jhon
-
Frédéric over 8 yearsThose 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 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 almost 7 yearsWhy to reinvent the wheel and furthermore, with a poor reinvension? this does not work for all cases.
-
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 withinGetDefaults()
? -
drzaus almost 6 yearsasides from subfolders, the real problem is that you can customize your routes so they won't always be
controller/action
-
Ben over 3 yearsDoesn't work in ASP.NET Core because HttpContext.Current doesn't exist anymore
-
Admin over 3 yearsThis was exactly what I was looking for. So simple, yet so powerful. Thanks.
-
Logarr almost 3 yearsI 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.