Получить контроллер и имя действия из контроллера?


173

Для нашего веб-приложения мне нужно сохранить порядок выбранных и отображаемых элементов в зависимости от представления - или, если быть точным, контроллера и действия, которые сгенерировали представление (и, конечно, идентификатор пользователя, но здесь дело не в этом).

Вместо того, чтобы просто указывать свой идентификатор в каждом действии контроллера (чтобы использовать его для некоторой зависящей от вида сортировки выходов БД), я подумал, что будет безопаснее и проще создать этот идентификатор автоматически из контроллера и метода действия, который он получает. звонил из.

Как я могу получить имя контроллера и действие из метода действия в контроллере? Или мне нужно размышление для этого? Я думаю, это довольно легко, спасибо заранее!


1
Reflection даст вам имя метода, который обрабатывает действие, но, вероятно, вы предпочитаете имя действия, возвращаемое кодом Андрея.
— citykid

Мне просто нужен однозначный идентификатор для каждого действия, которое предоставляет представление, так что оба способа справятся со своей задачей. Но ты прав, ответ Андрея определенно более элегантный.
— Алекс

@citykid Существуют ли случаи, когда они отличаются по манере, отличной от case и суффикса «Controller» для имен классов?
— Джон

@John, ActionNameAttribute позволяет ac # методу иметь любое имя действия: msdn.microsoft.com/en-us/library/…
— citykid

@citykid О, хорошо. Это своего рода устаревшая функция, учитывая, что вы можете указать маршруты с Routeатрибутом в методе действия, который я собираю? Кроме того, возможно ли переименовать контроллеры?
— Джон

Ответы:


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

Если вы собираетесь это сделать (укажите действие и имя контроллера), почему бы просто не назначить их напрямую ???
— MetalPhoenix

1
@ MetalPhoenix, не могли бы вы уточнить, о каком сценарии использования вы говорите? OP не нужно назначать контроллер или действие - они просто должны в общих чертах понять, какой контроллер и какое действие в настоящее время обрабатываются.
— Андрей

1
При втором чтении, возможно, что я неправильно понял фрагмент кода здесь? ... Значения ["action"] где "action" - это ключ, а не имя заменяемого действия (например, "Pass123" без кавычек ")? То есть: все равно будут Values ​​["action"] вместо Values ​​["yourAction"]?
— MetalPhoenix

@MetalPhoenix, точнее, литерал «action» является ключевым, и Values ​​[«action»] выведет «CurrentActionName»
— Андрей

62

Вот несколько методов расширения для получения этой информации (включая идентификатор):

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
Лучшее и полное решение, спасибо Джону
— Умар Аббас

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

Или вы можете включить контроллер, действие в ваших моделях, чтобы получить два из них и ваши пользовательские данные.

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

Убрать необходимость ToString()использования звонка

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

1

Используйте данные строки в OnActionExecuting для Action и Controller name.

строка actionName = this.ControllerContext.RouteData.Values ​​["action"]. ToString ();

string 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

Зачем изобретать велосипед, а тем более при плохой реинвенции? это не работает для всех случаев.
— jstuardo

Помимо подпапок, реальная проблема заключается в том, что вы можете настроить свои маршруты, чтобы они не всегда былиcontroller/action
— drzaus
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.