Jak mogę zwrócić bieżące działanie w widoku ASP.NET MVC?

291

Chciałem ustawić klasę CSS na mojej stronie wzorcowej, która zależy od bieżącego kontrolera i akcji. Mogę dostać się do regulatora prądu poprzez ViewContext.Controller.GetType().Name, ale w jaki sposób mogę uzyskać aktualny działań (np Index, Showitd.)?

robale
źródło

Odpowiedzi:

83

Użyj ViewContexti spójrz na RouteDatakolekcję, aby wyodrębnić zarówno kontroler, jak i elementy akcji. Ale myślę, że ustawienie zmiennej danych wskazującej kontekst aplikacji (np. „Editmode” lub „error”) zamiast kontrolera / akcji zmniejsza sprzężenie między twoimi widokami a kontrolerami.

tvanfosson
źródło
możesz pobrać dane do kontrolera i przekazać je do przeglądania za pomocą DTO. stackoverflow.com/a/31749391/4293929
MstfAsan
5
to NIE MOŻE być zaakceptowana odpowiedź, zobacz zamiast tego najczęściej głosowaną odpowiedź.
Hakan Fıstık 28.04.16
1
@HakamFostok Nadal uważam, że porada dodawania informacji semantycznych do modelu jest lepszą metodą we wszystkich przypadkach niż poleganie na danych trasy (kontroler, akcja), nawet jeśli druga odpowiedź zawiera więcej szczegółów na temat uzyskiwania tych danych.
tvanfosson
467

W RC można także wyodrębnić dane trasy, takie jak nazwa metody akcji, jak ta

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

Aktualizacja do MVC 3

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

Aktualizacja do MVC 4

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

Aktualizacja do MVC 4.5

ViewContext.RouteData.Values["action"]
ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["id"]
Christian Dalager
źródło
20
Znam te wcześniejsze daty V2, ale teraz są to ViewContext.Controller.ValueProvider.GetValue("action").RawValue+ odmiany
Chris S
7
Ta składnia działa w wersji V4: (ciąg) ViewContext.RouteData.Values ​​["action"];
kiprainey
2
To rozwiązanie nie działa dla mnie (MVC4 + .NET Framework 4.5.1). Dla mnie działa odpowiedź Viacheslava Smityukha: ViewContext.RouteData.Values ​​[„akcja”], ViewContext.RouteData.Values ​​[„kontroler”], ViewContext.RouteData.Values ​​[„id”],
Tomas Kubes
@kiprainey W wersji V3.5: msdn.microsoft.com/en-us/library/…
Pluto
2
Spróbuj: (ciąg) HttpContext.Request.RequestContext.RouteData.Values ​​["action"];
Martin Dawson,
60

Aby uzyskać bieżący identyfikator w widoku:

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

Aby uzyskać bieżący kontroler:

ViewContext.RouteData.Values["controller"].ToString() 
tsquillario
źródło
1
ViewContext.RouteData.Values ​​[<key>] .ToString () zgłasza wyjątek, jeśli wartość nie istnieje w RouteData
Grizzly Peak Software
@ShaneLarson Po prostu porównaj z null lub sprawdź z ViewContext.RouteData.Values.ContainsKey(<key>)pierwszym.
Pluto,
40

Wiem, że to jest starsze pytanie, ale widziałem je i pomyślałem, że może zainteresuje Cię alternatywna wersja, niż pozwalanie twojemu widokowi obsługiwać pobieranie danych potrzebnych do wykonania zadania.

Moim zdaniem łatwiejszym sposobem byłoby zastąpienie metody OnActionExecuting . Przekazano Ci ActionExecutingContext, który zawiera członka ActionDescriptor, którego możesz użyć do uzyskania poszukiwanych informacji, którym jest ActionName, i możesz także uzyskać dostęp do ControllerDescriptor, który zawiera 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.
}

Mam nadzieję że to pomoże. Jeśli cokolwiek, to przynajmniej pokaże alternatywę dla każdego, kto przyjdzie na twoje pytanie.

Dale Ragan
źródło
fajna rekomendacja; pomógł mi inteligentnie wdrożyć wykrywanie kontrolera / działania. Dzięki!
effkay
Potrzebny mi był deskryptor akcji, nie mogłem znaleźć żadnego innego rozwiązania, więc po prostu robię to tutaj, a następnie wrzucam to, co chcę, do worka widokowego.
Chris Marisic
17

Widziałem różne odpowiedzi i wymyśliłem pomocnika klasy:

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

Tak więc w View (lub master / layout) możesz używać go w ten sposób (składnia 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>

Mam nadzieję, że to pomoże.

Michael Vashchinsky
źródło
15

Możesz pobrać te dane z RouteData obiektu ViewContext

ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["action"]
Wiaczesław Smityukh
źródło
9

W MVC powinieneś dostarczyć widokowi wszystkie dane, nie pozwalając widokowi zbierać własnych danych, więc możesz ustawić klasę CSS w akcji kontrolera.

ViewData["CssClass"] = "bold";

i wybierz tę wartość z ViewData w swoim widoku

terjetyl
źródło
Byłaby to również moja preferowana metoda, aby powstrzymać widoki od struktury kontrolera, ale można to zrobić inaczej.
tvanfosson,
1
Nie jestem pewien, czy nazwałbym to „CssClass”, ponieważ wydaje się to wskazywać, że logika wyświetlania wkrada się do twojego kontrolera.
tvanfosson,
Zgadzam się, zwykle robię coś takiego jak „Kontekst”, więc nie jest związany z warstwą prezentacji i nie psuje się, jeśli zmienisz nazwę widoku.
RedFilter,
6

Głosuję za tym 2:

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

i

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

Możesz pobrać zarówno nazwę fizyczną bieżącego widoku, jak i akcję, która go uruchomiła. Może być przydatny na częściowych stronach * .acmx do określenia kontenera hosta.


źródło
2

Używam ASP.NET MVC 4, a to, co zadziałało dla mnie:

ControllerContext.Controller.ValueProvider.GetValue("controller").RawValue
ControllerContext.Controller.ValueProvider.GetValue("action").RawValue
kiewic
źródło
0

Rozszerzając odpowiedź Dale Ragana , jego przykład do ponownego użycia, stwórz klasę ApplicationController, która wywodzi się z kontrolera, a z kolei wszystkie inne kontrolery wywodzą się z tej klasy ApplicationController, a nie z kontrolera.

Przykład:

public class MyCustomApplicationController : Controller {}

public class HomeController : MyCustomApplicationController {}

Na nowym ApplicationController utwórz właściwość o nazwie ExecutingAction z tym podpisem:

protected ActionDescriptor ExecutingAction { get; set; }

Następnie w metodzie OnActionExecuting (z odpowiedzi Dale'a Ragana) po prostu przypisz ActionDescriptor do tej właściwości, aby uzyskać do niej dostęp w dowolnym momencie na dowolnym kontrolerze.

string currentActionName = this.ExecutingAction.ActionName;
RunnerRick
źródło
0

Zastąp tę funkcję w swoim kontrolerze

protected override void HandleUnknownAction(string actionName) 
{  TempData["actionName"] = actionName;
   View("urViewName").ExecuteResult(this.ControllerContext);
}
Santosh Pandey
źródło