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


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.