195

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?

4

13 回答 13

372
string actionName = this.ControllerContext.RouteData.Values["action"].ToString();
string controllerName = this.ControllerContext.RouteData.Values["controller"].ToString();
于 2013-08-15T08:06:51.243 回答
73

以下是一些用于获取该信息的扩展方法(它还包括 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;
    }
}

用法:

@Html.Controller();
@Html.Action();
@Html.Id();
于 2014-10-03T18:20:31.950 回答
24

可能有用。我需要控制器的构造函数中的操作,它出现在 MVC 生命周期的这一点上,this尚未初始化,并且ControllerContext = null. 我没有深入研究 MVC 生命周期并找到要覆盖的适当函数名称,而是在RequestContext.RouteData.

但为了这样做,与HttpContext构造函数中的任何相关用途一样,您必须指定完整的命名空间,因为this.HttpContext还没有被初始化。幸运的是,它看起来System.Web.HttpContext.Current是静态的。

// 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
}

注意:可能不是访问 HttpContext 中所有属性的最受支持的方式,但对于 RequestContext 和 Session 它似乎在我的应用程序中工作正常。

于 2013-10-24T15:58:42.213 回答
12
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();
    }
}
于 2014-02-05T18:52:49.727 回答
5
 @this.ViewContext.RouteData.Values["controller"].ToString();
于 2017-09-05T06:10:04.420 回答
4

这是我到目前为止所拥有的:

var actionName = filterContext.ActionDescriptor.ActionName;
var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
于 2015-11-09T22:30:46.990 回答
4

这是获得名称的最简单和最实用的答案:

var actionName = RouteData.Values["action"];
var controllerName = RouteData.Values["controller"];

或者

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

上面的代码使用 asp.net mvc 5 进行测试。

于 2017-06-26T14:15:33.257 回答
2

将此添加到 GetDefaults() 方法中的基本控制器

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
         GetDefaults();
         base.OnActionExecuting(filterContext);
    }

    private void GetDefaults()
    {
    var actionName = filterContext.ActionDescriptor.ActionName;
    var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
    }

将控制器实现到Basecontroller

添加部分视图 _Breadcrumb.cshtml 并使用 @Html.Partial("_Breadcrumb") 将其添加到所有需要的页面中

_面包屑.cshtml

<span>
    <a href="../@ViewData["controllerName"]">
        @ViewData["controllerName"]
    </a> > @ViewData["actionName"]
</span>
于 2017-02-21T19:22:08.630 回答
2

这对我来说似乎很有效(到目前为止),如果您使用属性路由也可以。

public class BaseController : Controller
{
    protected string CurrentAction { get; private set; }
    protected string CurrentController { get; private set; }

    protected override void Initialize(RequestContext requestContext)
    {
        this.PopulateControllerActionInfo(requestContext);
    }

    private void PopulateControllerActionInfo(RequestContext requestContext)
    {
        RouteData routedata = requestContext.RouteData;

        object routes;

        if (routedata.Values.TryGetValue("MS_DirectRouteMatches", out routes))
        {
            routedata = (routes as List<RouteData>)?.FirstOrDefault();
        }

        if (routedata == null)
            return;

        Func<string, string> getValue = (s) =>
        {
            object o;
            return routedata.Values.TryGetValue(s, out o) ? o.ToString() : String.Empty;
        };

        this.CurrentAction = getValue("action");
        this.CurrentController = getValue("controller");
    }
}
于 2016-01-16T02:50:14.107 回答
1

您可以像任何变量一样从操作中获取控制器名称或操作名称。它们只是特殊的(控制器和动作)并且已经定义,所以除了告诉你需要它们之外,你不需要做任何特别的事情来获得它们。

public string Index(string controller,string action)
   {
     var names=string.Format("Controller : {0}, Action: {1}",controller,action);
     return names;
   }

或者您可以在模型中包含控制器、操作以获取其中两个和您的自定义数据。

public class DtoModel
    {
        public string Action { get; set; }
        public string Controller { get; set; }
        public string Name { get; set; }
    }

public string Index(DtoModel baseModel)
    {
        var names=string.Format("Controller : {0}, Action: {1}",baseModel.Controller,baseModel.Action);
        return names;
    }
于 2015-07-31T15:02:05.070 回答
1

试试这个代码

将此覆盖方法添加到控制器

protected override void OnActionExecuting(ActionExecutingContext actionExecutingContext)
{
   var actionName = actionExecutingContext.ActionDescriptor.ActionName;
   var controllerName = actionExecutingContext.ActionDescriptor.ControllerDescriptor.ControllerName;
   base.OnActionExecuting(actionExecutingContext);
}
于 2021-01-22T06:37:27.683 回答
1

消除ToString()通话使用的需要

string actionName = ControllerContext.RouteData.GetRequiredString("action");
string controllerName = ControllerContext.RouteData.GetRequiredString("controller");
于 2017-01-29T19:32:22.957 回答
-8

为什么没有更简单的东西?

只需调用Request.Path,它将返回一个由“/”分隔的字符串

然后您可以使用.Split('/')[1]获取控制器名称。

在此处输入图像描述

于 2016-04-05T03:12:49.420 回答