2009-10-20 6 views
4

Quelqu'un pourrait-il expliquer comment les routes sont associées aux contrôleurs dans MVC 2? Actuellement, j'ai un contrôleur dans /Controllers/HomeController.cs et une vue /Home/Index.aspx.ASP.NET MVC 2 Comment sont les urls/routes, les vues liées aux contrôleurs?

méthode d'enregistrement

Mon itinéraire ressemble à ceci:

public static void RegisterRoutes(RouteCollection routes) 
     { 
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
      routes.IgnoreRoute("{resource}.aspx/{*pathInfo}"); 
      routes.MapRoute(
       "Default", 
       // Route name 
       "{controller}/{action}/{id}", 
       // URL with parameters 
       new { controller = "Home", action = "Index", id = "" } 
       // Parameter defaults 
      ); 
     } 

Si je demande l'URL: http://localhost/Home/Index, la demande est traitée correctement par HomeController.Index().

Cependant, pour la vie de moi, je ne peux pas comprendre comment l'URL/Home/Index est pointé vers HomeController. La vue aspx ne fait pas référence, pour autant que je sache, à HomeController, HomeController ne fait pas référence à la vue, et la table de routage ne mentionne pas explicitement HomeController. Comment cela se passe-t-il magiquement? Il me manque sûrement quelque chose d'évident.

puis

Répondre

5

Le moteur de vues par défaut qui est livré avec ASP.NET MVC fonctionne sur les conventions suivantes:

Vous avez une structure de dossiers comme celui-ci:

- Controllers\ 
|- HomeController.cs 
- Views\ 
|- Home\ 
|-- Index.aspx 
|- Shared\ 

Lorsqu'une demande arrive, et correspond à un itinéraire défini dans la méthode RegisterRoutes (voir les choses comme URL routing pour plus de détails que), le régulateur d'adaptation est appelé:

routes.MapRoute(
    "Default", // Route name, allows you to call this route elsewhere 
    "{controller}/{action}/{id}", // URL with parameters 
    new { controller = "Home", action = "Index", id = "" } // Parameter defaults 
); 

dans la route par défaut, vous spécifiez également un contrôleur par défaut (sans le suffixe "Controller") - le moteur de routage ajoutera automatiquement Controller sur le nom du contrôleur pour vous - et une action par défaut.

Dans votre contrôleur, vous appelez la méthode simple:

public ActionResult Index(){ 
    return View(); 
} 

Le moteur d'affichage par défaut recherche alors un fichier ASPX appelé Index (le même que l'action) dans un dossier appelé « Home » (le même en tant que contrôleur) dans le dossier "Vues" (convention).Si elle n'en trouve pas, elle recherchera également une page d'index dans le dossier partagé.

Des ASP.NET MVC Nerd Dinner sample chapter

applications ASP.NET MVC par défaut utilisent une structure de nommage des répertoires fondée sur les conventions lors de la résolution des modèles de vue. Cela permet aux développeurs d'éviter d'avoir à qualifier complètement un chemin de localisation lors du référencement de vues depuis une classe Controller. Par défaut, ASP.NET MVC recherchera le fichier de modèle d'affichage dans le répertoire \Views\[ControllerName]\ situé sous l'application. Le sous-répertoire \Views\Shared permet de stocker des modèles d'affichage qui sont réutilisés sur plusieurs contrôleurs de l'application. Lorsque ASP.NET MVC tente de résoudre un modèle de vue, il vérifie d'abord dans le répertoire spécifique \Views\[Controller], et s'il ne trouve pas le modèle de vue, il regarde dans le répertoire \Views\Shared. Lorsqu'il s'agit de nommer des modèles d'affichage individuels, il est recommandé de faire en sorte que le modèle d'affichage partage le même nom que la méthode d'action à l'origine du rendu. Par exemple, au-dessus de notre méthode d'action "Index" utilise la vue "Index" pour afficher le résultat de la vue, et la méthode d'action "Détails" utilise la vue "Détails" pour afficher ses résultats. Cela permet de voir rapidement quel modèle est associé à chaque action.

Les développeurs n'ont pas besoin de spécifier explicitement le nom du modèle de vue lorsque le modèle de vue a le même nom que la méthode d'action appelée sur le contrôleur. Nous pouvons simplement passer l'objet modèle à la méthode d'assistance View() (sans spécifier le nom de la vue), et ASP.NET MVC déduira automatiquement que nous voulons utiliser le modèle de vue \Views\[ControllerName]\[ActionName] sur le disque pour le rendre.


Modifier pour ajouter:

Quelques exemples des itinéraires que j'ai mis en place, qui a mis explicitement le contrôleur sont:

routes.MapRoute(
    "PhotoDetailsSlug", 
    "Albums/{albumId}/{photoId}/{slug}", 
    new {controller = "Albums", action = "PhotoDetails"}, 
    new {albumId = @"\d{1,4}", photoId = @"\d{1,8}"} 
); 

Ici, je suis en indiquant explicitement que je suis en utilisant le contrôleur Albums, et l'action PhotoDetails sur cela, et en passant dans les différents ids, etc à l'action.

+0

La plupart de cela est logique. Toutefois, l'objet par défaut transmis à .MapRoute dans votre second extrait de code fait référence à un contrôleur appelé "Accueil".Ma classe de contrôleur est appelée "HomeController". Comment puis-je spécifier explicitement le contrôleur utilisé pour une route/url particulière? –

+0

Vous devrez ajouter une règle explicite pour ces routes, et lui indiquer dans les paramètres par défaut quel contrôleur (moins le suffixe "Controller") à utiliser. –

+0

Merci - Je vais marquer cela comme accepté. Cependant, dois-je comprendre que dans l'exemple ci-dessus, "Albums" doit avoir une classe de contrôleur correspondante nommée "AlbumsController"? –

2

il y a une déclaration return View() A l'intérieur de l'indice d'action. Lorsqu'une vue vide est renvoyée, DefaultViewEngine recherche dans plusieurs dossiers par défaut le nom de la méthode Controller (en particulier dans la méthode FindView). L'un d'eux est le répertoire Views/Home car Home est le nom du contrôleur. Là, il trouve le fichier d'index, et l'utilise pour afficher le résultat.

+0

Cela explique comment la vue correcte est trouvée, mais comment la méthode de contrôleur correcte à exécuter est trouvée? –

6

Ceci est la convention dans ASP.NET MVC. Lorsque vous utilisez DefaultControllerFactory, cette convention est enterrée dans la classe interne scellée System.Web.Mvc.ControllerTypeCache (typique pour Microsoft pour écrire des classes scellées internes). A l'intérieur, vous trouverez une méthode appelée EnsureInitialized qui ressemble à ceci:

public void EnsureInitialized(IBuildManager buildManager) 
{ 
    if (this._cache == null) 
    { 
     lock (this._lockObj) 
     { 
      if (this._cache == null) 
      { 
       this._cache = GetAllControllerTypes(buildManager).GroupBy<Type, string>(delegate (Type t) { 
        return t.Name.Substring(0, t.Name.Length - "Controller".Length); 
       }, StringComparer.OrdinalIgnoreCase).ToDictionary<IGrouping<string, Type>, string, ILookup<string, Type>>(delegate (IGrouping<string, Type> g) { 
        return g.Key; 
       }, delegate (IGrouping<string, Type> g) { 
        return g.ToLookup<Type, string>(t => t.Namespace ?? string.Empty, StringComparer.OrdinalIgnoreCase); 
       }, StringComparer.OrdinalIgnoreCase); 
      } 
     } 
    } 
} 

Faites attention la façon dont le regroupement est fait. Donc, en gros, DefaultControllerFactory cherchera à l'intérieur de tous les assemblys référencés pour les types implémentant la classe de base Controller et supprimera le "Controller" du nom.

Si vous voulez vraiment disséquer dans les détails ASP.NET MVC pipeline je vous recommande ce excellent article.

+0

C'est bizarre. Le nom de la classe de contrôleur doit être lié à l'URL ?! Et si je voulais utiliser le même contrôleur pour une url qui n'avait pas le nom du contrôleur? –

+1

Puis vous le spécifiez dans votre table de routage: 'routes.MapRoute (" MyRoute "," someSpecialUrl/blabla ", nouveau {controller =" Accueil ", action =" Index ", id =" "});' mais vous avez toujours devez spécifier le contrôleur à utiliser. –

+0

En outre, avec l'ensemble d'indicateurs StringComparer.OrdinalIgnoreCase, cela ne signifie-t-il pas que le framework ne pourra pas faire la différence entre HomeController et homecontroller? –

Questions connexes