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


173

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

我认为不仅要在每个控制器动作中自己给出一个标识符(以便将其用于与视图有关的数据库输出排序),我还认为,从其获取的控制器和动作方法中自动创建该标识符会更安全,更轻松。从。

如何从控制器的action方法中获取控制器的名称和动作?还是我需要反思?我想这很容易,谢谢您!


1
反射将为您提供处理操作的方法名称,但是大概您希望使用Andrei代码返回的操作名称。
13年

对于提供视图的每个动作,我基本上只需要一个明确的标识符,因此两种方式都可以完成工作。但是您是对的,Andrei的回答肯定更优雅。
亚历克斯

@citykid是否存在除案例和类名的“ Controller”后缀以外的其他方式?
约翰

@约翰,ActionNameAttribute允许交流#方法有任何动作名称:msdn.microsoft.com/en-us/library/...
citykid

@citykid哦,好的。鉴于您可以Route在我收集的操作方法上使用属性指定路由,这是一种过时的功能?此外,是否也可以重命名控制器?
John

Answers:


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

13
在某些情况下,您可能希望在View文件中包含控制器的名称,则可以只使用this.ViewContext.RouteData.Values [“ controller”]。ToString();。
Amogh Natu 2014年

如果要执行此操作(提供操作和控制器名称),为什么不直接分配它们呢???
MetalPhoenix 2015年

1
@MetalPhoenix,您能否澄清一下您在说什么用例?OP不需要分配控制器或动作-他们只需要以一般方式了解当前正在处理的控制器和动作是什么。
Andrei 2015年

1
再读一遍,是否有可能我误解了这里的代码片段?... Values [“ action”]其中“ action”是键而不是要替换的动作的名称(例如“'Pass123'不带引号”类型的事物)?也就是说:仍然是Values [“ action”]而不是Values [“ yourAction”]?
MetalPhoenix

@MetalPhoenix,确切地说,“操作”字面量是一个键,并且Values [“ action”]将输出“ CurrentActionName”
Andrei

62

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

1
最佳和完整的解决方案,感谢Jhon
Umar Abbas

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,它似乎在我的应用程序中可以正常工作。


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


4

这是我到目前为止的内容:

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

3

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

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进行测试。


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”)将其添加到所有必需的页面中

_Breadcrumb.cshtml

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

(1):这仍然是MVC5中最常用的方法之一吗?(2)您filterContext从哪里得到变量GetDefaults()
chriszo111

1

您可以像任何变量一样从操作中获取控制器名称或操作名称。它们只是特殊的(控制器和动作),并且已经定义,因此您无需做任何特殊的操作即可获得它们,除非告诉您需要它们。

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

或者,您可以在模型中包括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;
    }

1

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

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


1

在OnActionExecuting中使用给定的行作为操作和控制器名称。

字符串actionName = this.ControllerContext.RouteData.Values [“ action”]。ToString();

字符串controllerName = this.ControllerContext.RouteData.Values [“ controller”]。ToString();


-8

为什么不拥有更简单的东西?

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

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

在此处输入图片说明


1
-1:使用您的代码,子级应用程序将被忽略(例如:)http://www.example.com/sites/site1/controllerA/actionB/。MVC提供了一堆用于路由的API,那么为什么需要解析(再次)URL?
T-moty '16

为什么要重新发明轮子,而且重新发明不善?这并不适用于所有情况。
jstuardo

子文件夹的旁边,真正的问题是您可以自定义路线,这样它们就不会永远都是controller/action
drzaus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.