简体   繁体   English

从控制器内获取控制器和动作名称?

[英]Get controller and action name from within controller?

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).对于我们的 Web 应用程序,我需要根据视图保存获取和显示的项目的顺序 - 或者准确地说 - 生成视图的控制器和操作(当然还有用户 ID,但这不是这里的重点)。

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.与其只是在每个控制器操作中自己提供一个标识符(以便将其用于某些与视图相关的 DB 输出排序),我认为从控制器和它获取的操作方法自动创建此标识符会更安全、更容易叫自。

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?或者我需要反思吗?

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

Here are some extension methods for getting that information (it also includes the ID):以下是获取该信息的一些扩展方法(它还包括 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();

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 .我需要在控制器的构造函数的动作,看来在这一点上MVC生命周期的, this还没有初始化, 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 .我没有深入研究 MVC 生命周期并找到要覆盖的适当函数名称,而是在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.但是为了做到这一点,与构造函数中任何与HttpContext相关的用途一样,您必须指定完整的命名空间,因为this.HttpContext还没有被初始化。 Luckily, it appears System.Web.HttpContext.Current is static.幸运的是, 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
}

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

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();
    }
}
 @this.ViewContext.RouteData.Values["controller"].ToString();

This is what I have so far:这是我到目前为止:

var actionName = filterContext.ActionDescriptor.ActionName;
var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;

Here is the simplest and most practical answer to getting a name:这是获得名字的最简单和最实用的答案:

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

Or要么

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

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

Add this to your base controller inside GetDefaults() method将此添加到 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;
    }

Implement your controllers to Basecontroller将您的控制器实现到Basecontroller

Add a partial view _Breadcrumb.cshtml and add it in all required pages with @Html.Partial("_Breadcrumb")添加局部视图 _Breadcrumb.cshtml 并使用 @Html.Partial("_Breadcrumb") 将其添加到所有必需的页面中

_Breadcrumb.cshtml _Breadcrumb.cshtml

<span>
    <a href="../@ViewData["controllerName"]">
        @ViewData["controllerName"]
    </a> > @ViewData["actionName"]
</span>

You can get controller name or action name from action like any variable.您可以像任何变量一样从操作中获取控制器名称或操作名称。 They are just special (controller and action) and already defined so you do not need to do anything special to get them except telling you need them.它们只是特殊的(控制器和动作)并且已经定义,所以你不需要做任何特殊的事情来获得它们,除非告诉你需要它们。

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

Or you can include controller , action in your models to get two of them and your custom data.或者您可以在模型中包含 controller 、 action 以获取其中两个和您的自定义数据。

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

This seems to work nicely for me (so far), also works if you are using attribute routing.这对我来说似乎很好用(到目前为止),如果您使用属性路由也适用。

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

To remove need for ToString() call use消除对ToString()调用的需要

string actionName = ControllerContext.RouteData.GetRequiredString("action");
string controllerName = ControllerContext.RouteData.GetRequiredString("controller");

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).对于我们的Web应用程序,我需要保存获取和显示的项目的顺序,具体取决于视图-确切地说,是生成视图的控制器和操作(当然还有用户ID,但这不是重点)。

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?如何从控制器的action方法中获取控制器的名称和动作? Or do I need reflection for that?还是我需要为此反思?

Try this code试试这个代码

add this override method to controller将此覆盖方法添加到控制器

protected override void OnActionExecuting(ActionExecutingContext actionExecutingContext)
{
   var actionName = actionExecutingContext.ActionDescriptor.ActionName;
   var controllerName = actionExecutingContext.ActionDescriptor.ControllerDescriptor.ControllerName;
   base.OnActionExecuting(actionExecutingContext);
}

Why not having something simpler?为什么不做一些更简单的事情?

Just call Request.Path , it will return a String Separated by the "/"只需调用Request.Path ,它将返回一个由“/”分隔的字符串

and then you can use .Split('/')[1] to get the Controller Name.然后你可以使用.Split('/')[1]来获取控制器名称。

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM