Як я можу повернути поточну дію у вигляді ASP.NET MVC?


291

Я хотів встановити клас CSS на своїй головній сторінці, що залежить від поточного контролера та дії. Я можу дістатись до поточного контролера через ViewContext.Controller.GetType().Name, але як мені отримати поточну дію (наприклад Index, Showтощо)?

Відповіді:


83

Використовуйте колекцію ViewContextта перегляньте RouteDataколекцію, щоб витягти як контролер, так і елементи дії. Але я думаю, що встановлення певної змінної даних, яка вказує на контекст програми (наприклад, "editmode" або "помилка"), а не контролер / дія, зменшує зв'язок між вашими переглядами та контролерами.


ви можете отримати дані в контролері і передати їх для перегляду за допомогою DTO. stackoverflow.com/a/31749391/4293929
MstfAsan

5
це НЕ повинно бути прийнятою відповіддю, дивіться натомість найбільш проголосовану відповідь.
Hakan Fıstık

1
@HakamFostok Я все-таки вважаю, що порада додати семантичну інформацію до моделі є кращим методом у всіх випадках, ніж покладатися на дані маршруту (контролер, дія) на ваш погляд, навіть якщо інша відповідь надає більш детальну інформацію про те, як отримати ці дані.
tvanfosson

467

У RC ви також можете витягти дані маршруту, такі як назва методу дії, як це

ViewContext.Controller.ValueProvider["action"].RawValue
ViewContext.Controller.ValueProvider["controller"].RawValue
ViewContext.Controller.ValueProvider["id"].RawValue

Оновлення для MVC 3

ViewContext.Controller.ValueProvider.GetValue("action").RawValue
ViewContext.Controller.ValueProvider.GetValue("controller").RawValue
ViewContext.Controller.ValueProvider.GetValue("id").RawValue

Оновлення для MVC 4

ViewContext.Controller.RouteData.Values["action"]
ViewContext.Controller.RouteData.Values["controller"]
ViewContext.Controller.RouteData.Values["id"]

Оновлення для MVC 4.5

ViewContext.RouteData.Values["action"]
ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["id"]

20
Я знаю цю дату V2, але зараз ViewContext.Controller.ValueProvider.GetValue("action").RawValue+ варіації
Chris S

7
Цей синтаксис працює у V4: (рядок) ViewContext.RouteData.Values ​​["дія"];
kiprainey

2
Це рішення для мене не працює (MVC4 + .NET Framework 4.5.1). Для мене це працює відповідь В’ячеслава Смітюха: ViewContext.RouteData.Values ​​["дія"], ViewContext.RouteData.Values ​​["контролер"], ViewContext.RouteData.Values ​​["id"],
Томаш Кубес,


2
Спробуйте: (рядок) HttpContext.Request.RequestContext.RouteData.Values ​​["дія"];
Мартін Доусон

60

Щоб отримати поточний ідентифікатор на перегляді:

ViewContext.RouteData.Values["id"].ToString()

Щоб отримати поточний контролер:

ViewContext.RouteData.Values["controller"].ToString() 

1
ViewContext.RouteData.Values ​​[<key>] .ToString () кидає виняток, якщо значення не існує в RouteData
Grizzly Peak Software

@ShaneLarson Просто порівняйте з null або перевірте ViewContext.RouteData.Values.ContainsKey(<key>)спочатку.
Плутон

40

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

На мій погляд, простішим способом було б перекриття методу OnActionExecuting . Вам передається ActionExecutingContext, який містить члена ActionDescriptor, який ви можете використовувати для отримання потрібної інформації, яка є іменем ActionName, і ви також можете дістатися до ControllerDescriptor, і він містить ім'я ControllerName.

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    ActionDescriptor actionDescriptor = filterContext.ActionDescriptor;
    string actionName = actionDescriptor.ActionName;
    string controllerName = actionDescriptor.ControllerDescriptor.ControllerName;
    // Now that you have the values, set them somewhere and pass them down with your ViewModel
    // This will keep your view cleaner and the controller will take care of everything that the view needs to do it's job.
}

Сподіваюсь, це допомагає. Якщо що-небудь, принаймні, це покаже альтернативу для будь-кого іншого, що стосується вашого питання.


приємна рекомендація; допоміг мені інтелектуально реалізувати контролер / дії. Дякую!
effkay

Отримати дескриптор дій - це те, що мені було потрібно, я не міг знайти дійсно будь-якого іншого рішення, тому я просто роблю це тут, а потім заношу те, що мені хочеться, у вікно перегляду.
Кріс Марісіч

17

Я побачив різні відповіді і придумав класного помічника:

using System;
using System.Web.Mvc;

namespace MyMvcApp.Helpers {
    public class LocationHelper {
        public static bool IsCurrentControllerAndAction(string controllerName, string actionName, ViewContext viewContext) {
            bool result = false;
            string normalizedControllerName = controllerName.EndsWith("Controller") ? controllerName : String.Format("{0}Controller", controllerName);

            if(viewContext == null) return false;
            if(String.IsNullOrEmpty(actionName)) return false;

            if (viewContext.Controller.GetType().Name.Equals(normalizedControllerName, StringComparison.InvariantCultureIgnoreCase) &&
                viewContext.Controller.ValueProvider.GetValue("action").AttemptedValue.Equals(actionName, StringComparison.InvariantCultureIgnoreCase)) {
                result = true;
            }

            return result;
        }
    }
}

Тож у View (або master / layout) ви можете використовувати його так (синтаксис Razor):

            <div id="menucontainer">

                <ul id="menu">
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("home", "index", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("account","logon", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("Logon", "Logon", "Account")</li>
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("home","about", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("About", "About", "Home")</li>
                </ul>

            </div>

Сподіваюся, це допомагає.



9

У MVC ви повинні надавати Перегляду всі дані, а не дозволяти Перегляду збирати власні дані, тому ви можете встановити клас CSS у дії контролера.

ViewData["CssClass"] = "bold";

і виберіть це значення у ViewData у своєму представленні


Це був би мій кращий метод, щоб утримати види не залежно від структури контролера, але це можна зробити інакше.
tvanfosson

1
Не впевнений, що я назвав би це "CssClass", оскільки це, здається, вказує на те, що логіка дисплея прокрадається у ваш контролер.
tvanfosson

Погоджено, я зазвичай роблю щось на кшталт "Контексту", тому воно не прив'язане до шару презентації і не порушується, якщо ви перейменовуєте представлення даних.
RedFilter

6

Я голосую за це 2:

string currentActionName = ViewContext.RouteData.GetRequiredString("action");

і

string currentViewName = ((WebFormView)ViewContext.View).ViewPath;

Ви можете отримати як фізичну назву поточного перегляду, так і дію, яка її викликала. Визначити контейнер хоста може бути корисним на часткових * .acmx сторінках.


2

Я використовую ASP.NET MVC 4, і це те, що працювало для мене:

ControllerContext.Controller.ValueProvider.GetValue("controller").RawValue
ControllerContext.Controller.ValueProvider.GetValue("action").RawValue

0

Розширюючи відповідь Дейла Рагана , його приклад для повторного використання, створіть клас ApplicationController, який походить від Controller, і, в свою чергу, всі ваші інші контролери виходять із цього класу ApplicationController, а не Controller.

Приклад:

public class MyCustomApplicationController : Controller {}

public class HomeController : MyCustomApplicationController {}

У новому ApplicationController створіть властивість під назвою ExecutingAction з цим підписом:

protected ActionDescriptor ExecutingAction { get; set; }

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

string currentActionName = this.ExecutingAction.ActionName;

0

Замініть цю функцію у контролері

protected override void HandleUnknownAction(string actionName) 
{  TempData["actionName"] = actionName;
   View("urViewName").ExecuteResult(this.ControllerContext);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.