Comment puis-je retourner l'action en cours dans une vue ASP.NET MVC?


291

Je voulais définir une classe CSS dans ma page maître, qui dépend du contrôleur et de l'action actuels. Je peux accéder au contrôleur actuel via ViewContext.Controller.GetType().Name, mais comment puis-je obtenir l'action en cours (par exemple Index, Showetc.)?

Réponses:


83

Utilisez le ViewContextet regardez la RouteDatacollection pour extraire à la fois le contrôleur et les éléments d'action. Mais je pense que la définition d'une variable de données qui indique le contexte de l'application (par exemple, "mode d'édition" ou "erreur") plutôt que contrôleur / action réduit le couplage entre vos vues et les contrôleurs.


vous pouvez obtenir des données dans le contrôleur et les transmettre à DTO. stackoverflow.com/a/31749391/4293929
MstfAsan

5
cela ne doit PAS être la réponse acceptée, voir la réponse la plus votée à la place.
Hakan Fıstık

1
@HakamFostok Je pense toujours que le conseil d'ajouter des informations sémantiques au modèle est une meilleure méthode dans tous les cas que de s'appuyer sur les données de route (contrôleur, action) à votre avis même si l'autre réponse fournit plus de détails sur la façon d'obtenir ces données.
tvanfosson

467

Dans le RC, vous pouvez également extraire des données d'itinéraire comme le nom de la méthode d'action comme ceci

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

Mise à jour pour MVC 3

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

Mise à jour pour MVC 4

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

Mise à jour pour MVC 4.5

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

20
Je connais cette pré-date V2, mais c'est maintenant ViewContext.Controller.ValueProvider.GetValue("action").RawValue+ variations
Chris S

7
Cette syntaxe fonctionne en V4: (chaîne) ViewContext.RouteData.Values ​​["action"];
kiprainey

2
Cette solution ne fonctionne pas pour moi (MVC4 + .NET Framework 4.5.1). Pour moi, cela fonctionne la réponse de Viacheslav Smityukh: ViewContext.RouteData.Values ​​["action"], ViewContext.RouteData.Values ​​["controller"], ViewContext.RouteData.Values ​​["id"],
Tomas Kubes

@kiprainey Dans V3.5 aussi: msdn.microsoft.com/en-us/library/…
Pluton

2
Essayez: (chaîne) HttpContext.Request.RequestContext.RouteData.Values ​​["action"];
Martin Dawson

60

Pour obtenir l'ID actuel sur une vue:

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

Pour obtenir le contrôleur actuel:

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

1
ViewContext.RouteData.Values ​​[<key>] .ToString () lève une exception si la valeur n'existe pas dans RouteData
Grizzly Peak Software

@ShaneLarson Il suffit de comparer avec null ou de vérifier en ViewContext.RouteData.Values.ContainsKey(<key>)premier.
Pluton

40

Je sais que c'est une question plus ancienne, mais je l'ai vue et j'ai pensé que vous pourriez être intéressé par une version alternative que de laisser votre vue gérer la récupération des données dont elle a besoin pour faire son travail.

Un moyen plus simple à mon avis serait de remplacer la méthode OnActionExecuting . Vous passez le ActionExecutingContext qui contient le membre ActionDescriptor que vous pouvez utiliser pour obtenir les informations que vous recherchez, qui est le ActionName et vous pouvez également atteindre le ControllerDescriptor et il contient le 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.
}

J'espère que cela t'aides. Si quoi que ce soit, au moins cela montrera une alternative pour toute autre personne qui vient par votre question.


belle recommandation; m'a aidé à implémenter intelligemment le contrôleur / la détection d'action. Merci!
effkay

Obtenir le descripteur d'action était ce dont j'avais besoin, je ne pouvais pas vraiment trouver d'autre solution, alors je le fais ici et je mets ce que je veux dans le sac de vision.
Chris Marisic

17

J'ai vu différentes réponses et j'ai trouvé un assistant de 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;
        }
    }
}

Donc, dans View (ou master / layout), vous pouvez l'utiliser comme ça (syntaxe 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>

J'espère que ça aide.


15

Vous pouvez obtenir ces données de RouteData d'un ViewContext

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

9

Dans MVC, vous devez fournir à la vue toutes les données, ne pas laisser la vue collecter ses propres données, vous pouvez donc définir la classe CSS dans l'action de votre contrôleur.

ViewData["CssClass"] = "bold";

et sélectionnez cette valeur de vos ViewData dans votre vue


Ce serait également ma méthode préférée pour empêcher les vues de dépendre de la structure du contrôleur, mais cela peut être fait autrement.
tvanfosson

1
Je ne suis pas sûr de le nommer "CssClass" car cela semble indiquer que la logique d'affichage se glisse dans votre contrôleur.
tvanfosson

D'accord, je fais généralement quelque chose comme "Context", donc il n'est pas lié à la couche de présentation et ne se casse pas si vous renommez la vue non plus.
RedFilter

6

Je vote pour ce 2:

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

et

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

Vous pouvez récupérer le nom physique de la vue actuelle et l'action qui l'a déclenchée. Il peut être utile dans les pages partielles * .acmx pour déterminer le conteneur hôte.


2

J'utilise ASP.NET MVC 4, et c'est ce qui a fonctionné pour moi:

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

0

Prolonger la réponse de Dale Ragan , son exemple de réutilisation, créez une classe ApplicationController qui dérive de Controller, et à votre tour, tous vos autres contrôleurs dérivent de cette classe ApplicationController plutôt que Controller.

Exemple:

public class MyCustomApplicationController : Controller {}

public class HomeController : MyCustomApplicationController {}

Sur votre nouveau ApplicationController, créez une propriété nommée ExecutingAction avec cette signature:

protected ActionDescriptor ExecutingAction { get; set; }

Et puis dans la méthode OnActionExecuting (d'après la réponse de Dale Ragan), affectez simplement l'ActionDescriptor à cette propriété et vous pouvez y accéder chaque fois que vous en avez besoin dans l'un de vos contrôleurs.

string currentActionName = this.ExecutingAction.ActionName;

0

Remplacez cette fonction dans votre contrôleur

protected override void HandleUnknownAction(string actionName) 
{  TempData["actionName"] = actionName;
   View("urViewName").ExecuteResult(this.ControllerContext);
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.