Отримати ім’я контролера та дії зсередини контролера?


173

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

Замість того, щоб просто дати собі ідентифікатор у кожній дії контролера (щоб використовувати його для деякого сортування виходів БД, залежного від перегляду), я подумав, що було б безпечніше і простіше створити цей ідентифікатор автоматично з контролера та методу дій, який він отримує дзвонив з.

Як я можу отримати ім'я контролера та дії з методу дії в контролері? Або мені для цього потрібні роздуми? Я здогадуюсь це досить легко, дякую заздалегідь!


1
Відображення дасть вам ім'я методу, який керує дією, але, імовірно, ви віддаєте перевагу ім'я дії, як повернене кодом Андрія.
citykid

Я в основному просто потребую однозначного ідентифікатора для кожної дії, що забезпечує перегляд, тож обидва способи справили б свою роботу. Але ти маєш рацію, відповідь Андрія, безумовно, більш елегантна.
Олексій

@citykid Чи бувають випадки, коли вони відрізняються за іншими способами, ніж регістр та суфікс "Контролер" для назв класів?
Іван

@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 ​​["контролер"]. ToString ();
Amogh Natu

Якщо ви збираєтесь це робити (вкажіть ім'я дії та контролера), чому б просто не призначити їх безпосередньо ???
MetalPhoenix

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

1
По-друге, чи можливо, я тут неправильно зрозумів фрагмент коду? ... Значення ["дія"], де "дія" є ключовим, а не ім'я дії, яку слід замінити (наприклад, "тип Pass123" без лапок "тип речі")? Тобто, чи все ще будуть Значення ["дія"] замість Значення ["Ваша Акція"]?
MetalPhoenix

@MetalPhoenix, саме "дія" буквально є ключовим, і Значення ["дія"] виведе "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 для дії та імені контролера.

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

string controllerName = this.ControllerContext.RouteData.Values ​​["контролер"]. 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.