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

而不是仅仅在每个控制器动作中给自己一个标识符(为了将它用于一些依赖于视图的DB输出排序),我认为从控制器和它被调用的动作方法中自动创建这个标识符会更安全更容易。

如何从控制器中的动作方法中获得控制器和动作的名称?还是说我需要反思一下?


当前回答

这对我来说似乎工作得很好(到目前为止),如果您使用属性路由也同样有效。

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

其他回答

下面是取名字最简单、最实用的方法:

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

Or

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

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

删除对ToString()调用的需求

string actionName = ControllerContext.RouteData.GetRequiredString("action");
string controllerName = ControllerContext.RouteData.GetRequiredString("controller");
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();
    }
}

可能会有用。我需要控制器的构造函数中的动作,它出现在MVC生命周期的这一点上,这还没有初始化,ControllerContext = null。我没有深入研究MVC生命周期,也没有找到要重写的适当函数名,而是在RequestContext.RouteData中找到了动作。

但是为了这样做,就像构造函数中任何与HttpContext相关的用法一样,你必须指定完整的命名空间,因为这。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,它似乎在我的应用程序中工作得很好。

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