Come posso restituire l'azione corrente in una vista MVC ASP.NET?


291

Volevo impostare una classe CSS nella mia pagina principale, che dipende dal controller e dall'azione correnti. Posso accedere al controller corrente tramite ViewContext.Controller.GetType().Name, ma come posso ottenere l'azione corrente (ad es . Index, ShowEcc.)?

Risposte:


83

Utilizzare ViewContexte guardare la RouteDataraccolta per estrarre sia il controller che gli elementi di azione. Ma penso che l'impostazione di una variabile di dati che indichi il contesto dell'applicazione (ad es. "Editmode" o "error") anziché il controller / azione riduce l'accoppiamento tra le visualizzazioni e i controller.


puoi ottenere i dati nel controller e passarli per visualizzarli con DTO. stackoverflow.com/a/31749391/4293929
MstfAsan

5
questa NON deve essere la risposta accettata, vedi invece la risposta più votata.
Hakan Fıstık,

1
@HakamFostok Penso ancora che il consiglio di aggiungere informazioni semantiche al modello sia un metodo migliore in tutti i casi piuttosto che fare affidamento sui dati del percorso (controllore, azione) nella vista anche se l'altra risposta fornisce maggiori dettagli su come ottenere tali dati.
tvanfosson,

467

In RC è anche possibile estrarre i dati del percorso come il nome del metodo di azione in questo modo

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

Aggiornamento per MVC 3

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

Aggiornamento per MVC 4

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

Aggiornamento per MVC 4.5

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

20
Conosco questo V2 precedente, ma ora sono ViewContext.Controller.ValueProvider.GetValue("action").RawValue+ variazioni
Chris S,

7
Questa sintassi funziona in V4: (stringa) ViewContext.RouteData.Values ​​["azione"];
Kiprainey,

2
Questa soluzione non funziona per me (MVC4 + .NET Framework 4.5.1). Per me, funziona la risposta di Viacheslav Smityukh: ViewContext.RouteData.Values ​​["azione"], ViewContext.RouteData.Values ​​["controller"], ViewContext.RouteData.Values ​​["id"],
Tomas Kubes

@kiprainey Anche nella V3.5: msdn.microsoft.com/en-us/library/…
Plutone

2
Prova: (stringa) HttpContext.Request.RequestContext.RouteData.Values ​​["azione"];
Martin Dawson,

60

Per ottenere l'ID corrente in una vista:

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

Per ottenere il controller corrente:

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

1
ViewContext.RouteData.Values ​​[<key>] .ToString () genera un'eccezione se il valore non esiste in RouteData
Grizzly Peak Software

@ShaneLarson Basta confrontare con null o verificare ViewContext.RouteData.Values.ContainsKey(<key>)prima.
Plutone,

40

So che questa è una domanda più vecchia, ma l'ho vista e ho pensato che potresti essere interessato a una versione alternativa piuttosto che lasciare che la tua vista gestisca il recupero dei dati necessari per fare il suo lavoro.

Un modo più semplice secondo me sarebbe quello di sovrascrivere il metodo OnActionExecuting . Si è passati ad ActionExecutingContext che contiene il membro ActionDescriptor che è possibile utilizzare per ottenere le informazioni che si stanno cercando, ovvero ActionName e si può anche raggiungere ControllerDescriptor e contiene 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.
}

Spero che questo ti aiuti. Semmai, almeno mostrerà un'alternativa per chiunque altro venga dalla tua domanda.


bella raccomandazione; mi ha aiutato a implementare intelligentemente il controller / il rilevamento dell'azione. Grazie!
Effkay,

Ottenere l'azione desrciptor è ciò di cui avevo bisogno, non riuscivo a trovare davvero nessuna altra soluzione, quindi lo faccio solo qui e poi inserisco ciò che voglio nel viewbag.
Chris Marisic,

17

Ho visto risposte diverse e ho trovato un aiutante di classe:

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

Quindi in View (o master / layout) puoi usarlo in questo modo (sintassi 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>

Spero che sia d'aiuto.


15

È possibile ottenere questi dati da RouteData di un ViewContext

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

9

In MVC è necessario fornire a View tutti i dati, non consentire a View di raccogliere i propri dati, pertanto è possibile impostare la classe CSS nell'azione del controller.

ViewData["CssClass"] = "bold";

e scegli questo valore dal tuo ViewData nella tua vista


Questo sarebbe anche il mio metodo preferito per evitare che le visualizzazioni dipendano dalla struttura del controller, ma si può fare diversamente.
tvanfosson,

1
Non sono sicuro che lo chiamerei "CssClass" in quanto sembra indicare che la logica di visualizzazione si insinua nel controller.
tvanfosson,

D'accordo, di solito faccio qualcosa come "Contesto", quindi non è legato al livello di presentazione e non si rompe se si rinomina la vista.
RedFilter

6

Voto per questo 2:

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

e

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

È possibile recuperare sia il nome fisico della vista corrente sia l'azione che lo ha attivato. Può essere utile in pagine * .acmx parziali per determinare il contenitore host.


2

Sto usando ASP.NET MVC 4, e questo è ciò che ha funzionato per me:

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

0

Estensione della risposta di Dale Ragan , il suo esempio di riutilizzo, crea una classe ApplicationController che deriva dal controller e, a sua volta, tutti gli altri controller derivano da quella classe ApplicationController anziché dal controller.

Esempio:

public class MyCustomApplicationController : Controller {}

public class HomeController : MyCustomApplicationController {}

Sul tuo nuovo ApplicationController crea una proprietà denominata ExecutingAction con questa firma:

protected ActionDescriptor ExecutingAction { get; set; }

E poi nel metodo OnActionExecuting (dalla risposta di Dale Ragan), è sufficiente assegnare ActionDescriptor a questa proprietà e puoi accedervi ogni volta che ne hai bisogno in uno dei tuoi controller.

string currentActionName = this.ExecutingAction.ActionName;

0

Sostituisci questa funzione nel tuo controller

protected override void HandleUnknownAction(string actionName) 
{  TempData["actionName"] = actionName;
   View("urViewName").ExecuteResult(this.ControllerContext);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.