web-dev-qa-db-fra.com

Comment définir un itinéraire par défaut (vers une zone) dans MVC

Ok, cela a déjà été demandé, mais il n’existe pas de solution solide. Donc, dans un but personnel et pour ceux qui pourraient trouver cela utile.

Dans MVC2 (ASP.NET), je le souhaite. Ainsi, lorsque quelqu'un accède au site Web, une zone par défaut est spécifiée. Donc, la navigation sur mon site devrait vous envoyer à ControllerX ActionY dans AreaZ.

Utilisation de l'itinéraire suivant dans le fichier Global.asax

routes.MapRoute(
                "Area",
                "",
                new { area = "AreaZ", controller = "ControllerX ", action = "ActionY " }
            );

Maintenant, cela fonctionne comme dans il essaie de servir la page correcte. Cependant, MVC recherche la vue à la racine du site et non dans le dossier Zone.

Y a-il un moyen de résoudre cela?

MODIFIER

Il y a une 'solution' et c'est dans ControllerX, ActionY renvoie le chemin complet de la vue. Un peu de bidouille mais ça marche. Cependant, j'espère qu'il existe une meilleure solution.

         public ActionResult ActionY()
        {
            return View("~/Areas/AreaZ/views/ActionY.aspx");
        }

Modifier:

Cela devient également un problème lorsque vous avez un lien HTML ActionLink de la page. Si la zone n'est pas définie, le lien d'action est vide.

Est-ce tout cela par conception ou une faille?

119
LiamB

Celui-ci m'a intéressé et j'ai enfin eu l'occasion de l'examiner. Apparemment, d’autres personnes n’ont pas compris qu’il s’agissait d’un problème lié à recherche de la vue, pas d’un problème lié au routage lui-même - et c'est probablement parce que le titre de votre question indique qu'il s'agit du routage.

Dans tous les cas, puisqu'il s'agit d'un problème lié à View, le seul moyen d'obtenir ce que vous voulez est de remplacer le moteur de vue par défaut. Normalement, lorsque vous effectuez cette opération, il vous suffit de changer de moteur de vue (par exemple, Spark, NHaml, etc.). Dans ce cas, ce n'est pas la logique de création de vues que nous devons remplacer, mais les méthodes FindPartialView et FindView de la classe VirtualPathProviderViewEngine.

Vous pouvez remercier vos bonnes étoiles que ces méthodes sont en fait virtuelles, car tout le reste dans le VirtualPathProviderViewEngine n’est même pas accessible - c’est privé , et cela rend très ennuyeux de remplacer la logique de recherche, car vous devez fondamentalement réécrire la moitié du code déjà écrit si vous voulez le lire. Bien avec le cache de localisation et les formats de localisation. Après avoir creusé dans Reflector, j'ai finalement réussi à trouver une solution efficace.

Ce que j'ai fait ici est tout d'abord de créer un résumé AreaAwareViewEngine qui dérive directement de VirtualPathProviderViewEngine au lieu de WebFormViewEngine. J'ai fait cela pour que si vous voulez créer des vues Spark (ou autre)), vous pouvez toujours utiliser cette classe comme type de base.

Le code ci-dessous est assez long, donc pour vous donner un résumé rapide de ce qu'il fait réellement: Il vous permet de mettre un {2} dans le format d'emplacement, qui correspond au nom de la zone, de la même manière {1} correspond au nom du contrôleur. C'est ça! C'est pour cela que nous avons dû écrire tout ce code pour:

BaseAreaAwareViewEngine.cs

public abstract class BaseAreaAwareViewEngine : VirtualPathProviderViewEngine
{
    private static readonly string[] EmptyLocations = { };

    public override ViewEngineResult FindView(
        ControllerContext controllerContext, string viewName,
        string masterName, bool useCache)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }
        if (string.IsNullOrEmpty(viewName))
        {
            throw new ArgumentNullException(viewName,
                "Value cannot be null or empty.");
        }

        string area = getArea(controllerContext);
        return FindAreaView(controllerContext, area, viewName,
            masterName, useCache);
    }

    public override ViewEngineResult FindPartialView(
        ControllerContext controllerContext, string partialViewName,
        bool useCache)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }
        if (string.IsNullOrEmpty(partialViewName))
        {
            throw new ArgumentNullException(partialViewName,
                "Value cannot be null or empty.");
        }

        string area = getArea(controllerContext);
        return FindAreaPartialView(controllerContext, area,
            partialViewName, useCache);
    }

    protected virtual ViewEngineResult FindAreaView(
        ControllerContext controllerContext, string areaName, string viewName,
        string masterName, bool useCache)
    {
        string controllerName =
            controllerContext.RouteData.GetRequiredString("controller");
        string[] searchedViewPaths;
        string viewPath = GetPath(controllerContext, ViewLocationFormats,
            "ViewLocationFormats", viewName, controllerName, areaName, "View",
            useCache, out searchedViewPaths);
        string[] searchedMasterPaths;
        string masterPath = GetPath(controllerContext, MasterLocationFormats,
            "MasterLocationFormats", masterName, controllerName, areaName,
            "Master", useCache, out searchedMasterPaths);
        if (!string.IsNullOrEmpty(viewPath) &&
            (!string.IsNullOrEmpty(masterPath) || 
              string.IsNullOrEmpty(masterName)))
        {
            return new ViewEngineResult(CreateView(controllerContext, viewPath,
                masterPath), this);
        }
        return new ViewEngineResult(
            searchedViewPaths.Union<string>(searchedMasterPaths));
    }

    protected virtual ViewEngineResult FindAreaPartialView(
        ControllerContext controllerContext, string areaName,
        string viewName, bool useCache)
    {
        string controllerName =
            controllerContext.RouteData.GetRequiredString("controller");
        string[] searchedViewPaths;
        string partialViewPath = GetPath(controllerContext,
            ViewLocationFormats, "PartialViewLocationFormats", viewName,
            controllerName, areaName, "Partial", useCache,
            out searchedViewPaths);
        if (!string.IsNullOrEmpty(partialViewPath))
        {
            return new ViewEngineResult(CreatePartialView(controllerContext,
                partialViewPath), this);
        }
        return new ViewEngineResult(searchedViewPaths);
    }

    protected string CreateCacheKey(string prefix, string name,
        string controller, string area)
    {
        return string.Format(CultureInfo.InvariantCulture,
            ":ViewCacheEntry:{0}:{1}:{2}:{3}:{4}:",
            base.GetType().AssemblyQualifiedName,
            prefix, name, controller, area);
    }

    protected string GetPath(ControllerContext controllerContext,
        string[] locations, string locationsPropertyName, string name,
        string controllerName, string areaName, string cacheKeyPrefix,
        bool useCache, out string[] searchedLocations)
    {
        searchedLocations = EmptyLocations;
        if (string.IsNullOrEmpty(name))
        {
            return string.Empty;
        }
        if ((locations == null) || (locations.Length == 0))
        {
            throw new InvalidOperationException(string.Format("The property " +
                "'{0}' cannot be null or empty.", locationsPropertyName));
        }
        bool isSpecificPath = IsSpecificPath(name);
        string key = CreateCacheKey(cacheKeyPrefix, name,
            isSpecificPath ? string.Empty : controllerName,
            isSpecificPath ? string.Empty : areaName);
        if (useCache)
        {
            string viewLocation = ViewLocationCache.GetViewLocation(
                controllerContext.HttpContext, key);
            if (viewLocation != null)
            {
                return viewLocation;
            }
        }
        if (!isSpecificPath)
        {
            return GetPathFromGeneralName(controllerContext, locations, name,
                controllerName, areaName, key, ref searchedLocations);
        }
        return GetPathFromSpecificName(controllerContext, name, key,
            ref searchedLocations);
    }

    protected string GetPathFromGeneralName(ControllerContext controllerContext,
        string[] locations, string name, string controllerName,
        string areaName, string cacheKey, ref string[] searchedLocations)
    {
        string virtualPath = string.Empty;
        searchedLocations = new string[locations.Length];
        for (int i = 0; i < locations.Length; i++)
        {
            if (string.IsNullOrEmpty(areaName) && locations[i].Contains("{2}"))
            {
                continue;
            }
            string testPath = string.Format(CultureInfo.InvariantCulture,
                locations[i], name, controllerName, areaName);
            if (FileExists(controllerContext, testPath))
            {
                searchedLocations = EmptyLocations;
                virtualPath = testPath;
                ViewLocationCache.InsertViewLocation(
                    controllerContext.HttpContext, cacheKey, virtualPath);
                return virtualPath;
            }
            searchedLocations[i] = testPath;
        }
        return virtualPath;
    }

    protected string GetPathFromSpecificName(
        ControllerContext controllerContext, string name, string cacheKey,
        ref string[] searchedLocations)
    {
        string virtualPath = name;
        if (!FileExists(controllerContext, name))
        {
            virtualPath = string.Empty;
            searchedLocations = new string[] { name };
        }
        ViewLocationCache.InsertViewLocation(controllerContext.HttpContext,
            cacheKey, virtualPath);
        return virtualPath;
    }


    protected string getArea(ControllerContext controllerContext)
    {
        // First try to get area from a RouteValue override, like one specified in the Defaults arg to a Route.
        object areaO;
        controllerContext.RouteData.Values.TryGetValue("area", out areaO);

        // If not specified, try to get it from the Controller's namespace
        if (areaO != null)
            return (string)areaO;

        string namespa = controllerContext.Controller.GetType().Namespace;
        int areaStart = namespa.IndexOf("Areas.");
        if (areaStart == -1)
            return null;

        areaStart += 6;
        int areaEnd = namespa.IndexOf('.', areaStart + 1);
        string area = namespa.Substring(areaStart, areaEnd - areaStart);
        return area;
    }

    protected static bool IsSpecificPath(string name)
    {
        char ch = name[0];
        if (ch != '~')
        {
            return (ch == '/');
        }
        return true;
    }
}

Maintenant, comme indiqué, ce n'est pas un moteur en béton, vous devez donc le créer également. Heureusement, cette partie est beaucoup plus facile, il suffit de définir les formats par défaut et de créer les vues:

AreaAwareViewEngine.cs

public class AreaAwareViewEngine : BaseAreaAwareViewEngine
{
    public AreaAwareViewEngine()
    {
        MasterLocationFormats = new string[]
        {
            "~/Areas/{2}/Views/{1}/{0}.master",
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.master",
            "~/Areas/{2}/Views/Shared/{0}.cshtml",
            "~/Views/{1}/{0}.master",
            "~/Views/{1}/{0}.cshtml",
            "~/Views/Shared/{0}.master"
            "~/Views/Shared/{0}.cshtml"
        };
        ViewLocationFormats = new string[]
        {
            "~/Areas/{2}/Views/{1}/{0}.aspx",
            "~/Areas/{2}/Views/{1}/{0}.ascx",
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.aspx",
            "~/Areas/{2}/Views/Shared/{0}.ascx",
            "~/Areas/{2}/Views/Shared/{0}.cshtml",
            "~/Views/{1}/{0}.aspx",
            "~/Views/{1}/{0}.ascx",
            "~/Views/{1}/{0}.cshtml",
            "~/Views/Shared/{0}.aspx"
            "~/Views/Shared/{0}.ascx"
            "~/Views/Shared/{0}.cshtml"
        };
        PartialViewLocationFormats = ViewLocationFormats;
    }

    protected override IView CreatePartialView(
        ControllerContext controllerContext, string partialPath)
    {
        if (partialPath.EndsWith(".cshtml"))
            return new System.Web.Mvc.RazorView(controllerContext, partialPath, null, false, null);
        else
            return new WebFormView(controllerContext, partialPath);
    }

    protected override IView CreateView(ControllerContext controllerContext,
        string viewPath, string masterPath)
    {
        if (viewPath.EndsWith(".cshtml"))
            return new RazorView(controllerContext, viewPath, masterPath, false, null);
        else
            return new WebFormView(controllerContext, viewPath, masterPath);
    }
}

Notez que nous avons ajouté quelques entrées à la norme ViewLocationFormats. Ce sont les nouvelles entrées {2}, où le {2} sera mappé sur le area que nous avons mis dans le RouteData. J'ai laissé le MasterLocationFormats seul, mais vous pouvez évidemment changer cela si vous le souhaitez.

Maintenant modifiez votre global.asax pour enregistrer ce moteur de vue:

Global.asax.cs

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new AreaAwareViewEngine());
}

... et enregistrez la route par défaut:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapRoute(
        "Area",
        "",
        new { area = "AreaZ", controller = "Default", action = "ActionY" }
    );
    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = "" }
    );
}

Maintenant, créez le AreaController que nous venons de référencer:

DefaultController.cs (dans ~/Controllers /)

public class DefaultController : Controller
{
    public ActionResult ActionY()
    {
        return View("TestView");
    }
}

Évidemment, nous avons besoin de la structure de répertoires et de la vue correspondante - nous allons garder cela très simple:

TestView.aspx (dans ~/Zones/ZoneZ/Vues/Par défaut/ou ~/Zones/ZoneZ/Vues/Partagées /)

<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<h2>TestView</h2>
This is a test view in AreaZ.

Et c'est tout. Enfin, nous avons terminé.

Dans la plupart des cas, vous devriez pouvoir simplement prendre les commandes BaseAreaAwareViewEngine et AreaAwareViewEngine et les insérer dans n’importe quel projet MVC. Ainsi, même s’il a fallu beaucoup de code pour que cela soit fait, dois l'écrire une fois. Ensuite, il vous suffit de modifier quelques lignes dans global.asax.cs et de créer la structure de votre site.

98
Aaronaught

Voici comment je l'ai fait. Je ne sais pas pourquoi MapRoute () ne vous permet pas de définir la zone, mais renvoie l'objet route afin que vous puissiez continuer à apporter les modifications supplémentaires souhaitées. J'utilise ceci parce que j'ai un site MVC modulaire vendu aux entreprises et que ces derniers doivent pouvoir déposer des DLL dans le dossier bin pour ajouter de nouveaux modules. Je leur permets de changer le "HomeArea" dans la config AppSettings.

var route = routes.MapRoute(
                "Home_Default", 
                "", 
                new {controller = "Home", action = "index" },
                new[] { "IPC.Web.Core.Controllers" }
               );
route.DataTokens["area"] = area;

Edit: Vous pouvez également essayer ceci dans votre AreaRegistration.RegisterArea pour la zone dans laquelle vous voulez que l'utilisateur aille par défaut. Je ne l'ai pas testé, mais AreaRegistrationContext.MapRoute définit la valeur route.DataTokens["area"] = this.AreaName; pour toi.

context.MapRoute(
                    "Home_Default", 
                    "", 
                    new {controller = "Home", action = "index" },
                    new[] { "IPC.Web.Core.Controllers" }
                   );
97
Chris Alderson

même la réponse a déjà été donnée - voici la syntaxe courte (ASP.net 3, 4, 5):

routes.MapRoute("redirect all other requests", "{*url}",
    new {
        controller = "UnderConstruction",
        action = "Index"
        }).DataTokens = new RouteValueDictionary(new { area = "Shop" });
55
SeriousM

Merci à Aaron d’avoir fait remarquer que c’est pour localiser les points de vue, j’ai mal compris.

[UPDATE] Je viens de créer un projet qui envoie l'utilisateur par défaut à une zone sans modifier les chemins de code ou de recherche:

Dans global.asax, enregistrez comme d'habitude:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = ""}  // Parameter defaults,
        );
    }

dans Application_Start(), veillez à utiliser l'ordre suivant;

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        RegisterRoutes(RouteTable.Routes);
    }

dans votre zone d'enregistrement, utilisez

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "ShopArea_default",
            "{controller}/{action}/{id}",
            new { action = "Index", id = "", controller = "MyRoute" },
            new { controller = "MyRoute" }
        );
    }

Vous trouverez un exemple à l'adresse http://www.emphess.net/2010/01/31/areas-routes-and-defaults-in-mvc-2-rc/

J'espère vraiment que c'est ce que vous demandiez ...

////

Je ne pense pas qu'écrire un pseudo ViewEngine soit la meilleure solution dans ce cas. (Manquant de réputation, je ne peux pas commenter). Le WebFormsViewEngine est sensible à la zone et contient AreaViewLocationFormats qui est défini par défaut comme

AreaViewLocationFormats = new[] {
        "~/Areas/{2}/Views/{1}/{0}.aspx",
        "~/Areas/{2}/Views/{1}/{0}.ascx",
        "~/Areas/{2}/Views/Shared/{0}.aspx",
        "~/Areas/{2}/Views/Shared/{0}.ascx",
    };

Je crois que vous n'adhérez pas à cette convention. Vous avez posté

public ActionResult ActionY() 
{ 
    return View("~/Areas/AreaZ/views/ActionY.aspx"); 
} 

comme un hack de travail, mais cela devrait être

   return View("~/Areas/AreaZ/views/ControllerX/ActionY.aspx"); 

Cependant, si vous ne souhaitez pas suivre la convention, vous pouvez choisir un chemin court en dérivant du WebFormViewEngine (effectué dans MvcContrib, par exemple) dans lequel vous pouvez définir les chemins de recherche. le constructeur, ou -un peu de hacky- en spécifiant votre convention comme ceci sur Application_Start:

((VirtualPathProviderViewEngine)ViewEngines.Engines[0]).AreaViewLocationFormats = ...;

Cela devrait être effectué avec un peu plus de soin, bien sûr, mais je pense que cela montre l'idée. Ces champs sont public dans VirtualPathProviderViewEngine dans MVC 2 RC.

16
mnemosyn

Je suppose que vous voulez que l'utilisateur soit redirigé vers ~/AreaZ URL une fois qu'il a visité ~/ URL. Je réaliserais avec le code suivant dans votre racine HomeController.

public class HomeController
{
    public ActionResult Index()
    {
        return RedirectToAction("ActionY", "ControllerX", new { Area = "AreaZ" });
    }
}

Et la route suivante dans Global.asax.

routes.MapRoute(
    "Redirection to AreaZ",
    String.Empty,
    new { controller = "Home ", action = "Index" }
);
6
Anthony Serdyukov

Ajouter ce qui suit à Application_Start fonctionne pour moi, même si je ne suis pas sûr que vous ayez ce paramètre dans RC:

var engine = (WebFormViewEngine)ViewEngines.Engines.First();

// These additions allow me to route default requests for "/" to the home area
engine.ViewLocationFormats = new string[] { 
    "~/Views/{1}/{0}.aspx",
    "~/Views/{1}/{0}.ascx",
    "~/Areas/{1}/Views/{1}/{0}.aspx", // new
    "~/Areas/{1}/Views/{1}/{0}.ascx", // new
    "~/Areas/{1}/Views/{0}.aspx", // new
    "~/Areas/{1}/Views/{0}.ascx", // new
    "~/Views/{1}/{0}.ascx",
    "~/Views/Shared/{0}.aspx",
    "~/Views/Shared/{0}.ascx"
};
2
Derek Hunziker

Premièrement, quelle version de MVC2 utilisez-vous? Il y a eu des changements significatifs de preview2 à RC.

En supposant que vous utilisiez la télécommande, je pense que votre carte de route devrait avoir une apparence différente. Dans le AreaRegistration.cs _ dans votre région, vous pouvez enregistrer une sorte de route par défaut, par exemple.

        context.MapRoute(
            "ShopArea_default",
            "{controller}/{action}/{id}",
            new { action = "Index", id = "", controller="MyRoute" }
        );

Le code ci-dessus enverra l'utilisateur au MyRouteController de notre ShopArea par défaut.

L'utilisation d'une chaîne vide en tant que second paramètre devrait générer une exception, car un contrôleur doit être spécifié.

Bien sûr, vous devrez changer la route par défaut dans Global.asax afin qu’il n’interfère pas avec cette route par défaut, par exemple. en utilisant un préfixe pour le site principal.

Voir également ce fil et la réponse de Haack: Ordre des itinéraires d'enregistrement de zone MVC 2

J'espère que cela t'aides.

2
mnemosyn

Ce que j'ai fait pour que cela fonctionne est la suivante:

  1. J'ai créé un contrôleur par défaut dans le dossier racine/contrôleurs. J'ai nommé mon contrôleur DefaultController.
  2. Dans le contrôleur, j'ai ajouté le code suivant:

    namespace MyNameSpace.Controllers {
    public class DefaultController : Controller {
        // GET: Default
        public ActionResult Index() {
            return RedirectToAction("Index", "ControllerName", new {area = "FolderName"});
        }
    } }
    
  3. Dans mon RouterConfig.cs, j'ai ajouté ce qui suit:

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new {controller = "Default", action = "Index", id = UrlParameter.Optional});
    

L'astuce derrière tout cela est que j'ai créé un constructeur par défaut qui sera toujours le contrôleur de démarrage à chaque démarrage de mon application. Lorsqu'il atteint ce contrôleur par défaut, il sera redirigé vers tout contrôleur que je spécifie dans l'action d'index par défaut. Qui dans mon cas est

www.myurl.com/FolderName/ControllerName

.

1
JEuvin

La localisation des différents blocs de construction est effectuée dans le cycle de vie de la demande. L'une des premières étapes du cycle de vie d'une demande ASP.NET MVC consiste à mapper l'URL demandée sur la méthode d'action appropriée du contrôleur. Ce processus est appelé routage. Une route par défaut est initialisée dans le fichier Global.asax et explique au framework ASP.NET MVC comment gérer une demande. Double-cliquez sur le fichier Global.asax dans le projet MvcApplication1 pour afficher le code suivant:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing;

namespace MvcApplication1 {

   public class GlobalApplication : System.Web.HttpApplication
   {
       public static void RegisterRoutes(RouteCollection routes)
       {
           routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

           routes.MapRoute(
               "Default",                                          // Route name
               "{controller}/{action}/{id}",                       // URL with parameters
               new { controller = "Home", action = "Index",
                     id = "" }  // Parameter defaults
           );

       }

       protected void Application_Start()
       {
           RegisterRoutes(RouteTable.Routes);
       }
   }

}

Dans le gestionnaire d'événements Application_Start (), qui est déclenché chaque fois que l'application est compilée ou que le serveur Web est redémarré, une table de routage est enregistrée. La route par défaut est nommée Par défaut et répond à une URL sous la forme http://www.example.com/ {controller}/{action}/{id}. Les variables entre {et} sont renseignées avec les valeurs réelles de l'URL de la demande ou avec les valeurs par défaut si aucune substitution n'est présente dans l'URL. Cette route par défaut mappera le contrôleur principal et la méthode d’action Index en fonction des paramètres de routage par défaut. Nous n'aurons aucune autre action avec cette carte de routage.

Par défaut, toutes les URL possibles peuvent être mappées via cette route par défaut. Il est également possible de créer nos propres itinéraires. Par exemple, mappons l'URL http://www.example.com/Employee/Maarten vers le contrôleur d'employé, l'action Show et le paramètre prenom. L'extrait de code suivant peut être inséré dans le fichier Global.asax que nous venons d'ouvrir. Etant donné que l'infrastructure ASP.NET MVC utilise le premier itinéraire correspondant, cet extrait de code doit être inséré au-dessus de l'itinéraire par défaut. sinon la route ne sera jamais utilisée.

routes.MapRoute(

   "EmployeeShow",                    // Route name
   "Employee/{firstname}",            // URL with parameters
    new {                             // Parameter defaults
       controller = "Employee",
       action = "Show", 
       firstname = "" 
   }  

);

Ajoutons maintenant les composants nécessaires pour cette route. Tout d’abord, créez une classe nommée EmployeeController dans le dossier Controllers. Vous pouvez le faire en ajoutant un nouvel élément au projet et en sélectionnant le modèle de classe de contrôleur MVC situé sous l'onglet Web | Catégorie MVC. Supprimez la méthode d'action Index et remplacez-la par une méthode ou une action nommée Afficher. Cette méthode accepte un paramètre firstname et transmet les données au dictionnaire ViewData. Ce dictionnaire sera utilisé par la vue pour afficher des données.

La classe EmployeeController passera un objet Employee à la vue. Cette classe Employé doit être ajoutée au dossier Modèles (cliquez avec le bouton droit de la souris sur ce dossier, puis sélectionnez Ajouter | Classe dans le menu contextuel). Voici le code de la classe Employee:

namespace MvcApplication1.Models {

   public class Employee
   {
       public string FirstName { get; set; }
       public string LastName { get; set; }
       public string Email { get; set; }
   }

} 
0
Sanju

La solution acceptée à cette question est, bien que résumant correctement comment créer un moteur de vue personnalisé, ne répond pas correctement à la question. Le problème ici est que Pino ne spécifie pas correctement son itinéraire par défaut. En particulier, sa définition de "zone" est incorrecte. "Zone" est vérifié via la collection DataTokens et doit être ajouté en tant que tel:

var defaultRoute = new Route("",new RouteValueDictionary(){{"controller","Default"},{"action","Index"}},null/*constraints*/,new RouteValueDictionary(){{"area","Admin"}},new MvcRouteHandler());
defaultRoute.DataTokens.Add("Namespaces","MyProject.Web.Admin.Controller"); 
routes.Add(defaultRoute);

les "zones" spécifiées dans l'objet par défaut seront ignorées. Le code ci-dessus crée un itinéraire par défaut, qui intercepte les demandes adressées à la racine de votre site, puis appelle Contrôleur par défaut, action d'indexation dans la zone d'administration. Veuillez également noter que la clé "Namespaces" étant ajoutée à DataTokens, cela n'est requis que si vous avez plusieurs contrôleurs portant le même nom. Cette solution est vérifiée avec Mvc2 et Mvc3 .NET 3.5/4.0

0
nuhusky2003

Bien que la création d'un moteur de vue personnalisé puisse fonctionner pour cela, vous pouvez toujours avoir une alternative:

  • Décidez ce que vous devez afficher par défaut.
  • Ce quelque chose a contrôleur et action (et zone), non?
  • Ouvrez l'enregistrement de cette zone et ajoutez quelque chose comme ceci:
public override void RegisterArea(AreaRegistrationContext context)
{
    //this makes it work for the empty url (just domain) to act as current Area.
    context.MapRoute(
        "Area_empty",
        "",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        namespaces: new string[] { "Area controller namespace" }
    );
        //other routes of the area
}

À votre santé!

0
Tengiz
routes.MapRoute(
                "Area",
                "{area}/",
                new { area = "AreaZ", controller = "ControlerX ", action = "ActionY " }
            );

Avez-vous essayé ça?

0
Barbaros Alp