asp.net mvc place les contrôleurs dans un projet séparé

107

J'apprends juste asp.net mvc et j'essaye de comprendre comment déplacer mes contrôleurs dans un projet séparé. Généralement, lorsque j'ai déjà conçu des applications Web asp.net, j'ai créé un projet pour mes modèles, un autre pour ma logique, puis il y avait le Web.

Maintenant que j'apprends asp.net mvc, j'espérais suivre un modèle similaire et placer les modèles et les contrôleurs chacun dans leurs propres projets séparés, et laisser simplement les vues / scripts / css sur le Web. La partie modèles était facile, mais ce que je ne comprends pas, c'est comment «trouver» mes contrôleurs dans un projet séparé. Aussi, je voudrais savoir si cela est souhaitable. Merci!

Aaron Palmer
la source

Réponses:

92

Tout d'abord, c'est certainement une bonne idée de placer votre modèle dans un projet séparé. Comme vous l'avez découvert, c'est trivial.

En ce qui concerne les contrôleurs et les vues, je ne vois aucun avantage évident à les séparer pour la plupart des projets de base, bien que vous puissiez avoir un besoin particulier de le faire dans une application particulière.

Si vous choisissez de le faire, vous devrez indiquer au framework comment trouver vos contrôleurs. Le moyen de base pour ce faire est de fournir votre propre ControllerFactory. Vous pouvez consulter le code source de DefaultControllerFactory pour avoir une idée de la façon dont cela est fait. Sous-typer cette classe et remplacer la méthode GetControllerType (string controllerName) peut suffire à accomplir ce que vous demandez.

Une fois que vous avez créé votre propre ControllerFactory personnalisé, vous ajoutez la ligne suivante à Application_Start dans global.asax pour indiquer au framework où le trouver:

ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());

Mise à jour: lisez cet article et les articles auxquels il renvoie pour plus d'informations. Voir aussi le commentaire de Phil Haack sur ce post sur:

ControllerBuilder.Current.DefaultNamespaces.Add(
    "ExternalAssembly.Controllers");

... ce qui n'est pas une solution complète, mais peut-être suffisante pour des cas simples.

Craig Stuntz
la source
2
Merci Craig! C'est exactement ce que je cherchais. Cette information existe-t-elle même sur le Web? J'ai cherché partout sur Google avec peu de chance. StackOverflow revient!
Aaron Palmer
11
Je suis d'accord, les contrôleurs gèrent les entrées de l'utilisateur, manipulent le modèle, puis transmettent les données à la vue. Ils sont généralement très spécifiques à une application. Toute logique qui n'est pas spécifique à l'application pourrait être mieux dans une bibliothèque ou le modèle. Mais les contrôleurs en général devraient être avec le projet Web.
Haacked
2
J'ai un contrôleur d'erreur et des vues identiques entre deux applications. Il est logique pour moi de les avoir dans un seul assemblage que les deux applications peuvent utiliser.
Sailing Judo
3
N'est-il pas plus facile de tester les contrôleurs et d'utiliser l'IoC lorsque les contrôleurs sont dans un projet séparé - ce serait la raison principale
Samuel Goldenbaum
1
@Chev, je ne pense pas que cela fasse de différence là-bas. La testabilité de vos contrôleurs a plus à voir avec la façon dont vous les codez , pas avec l' endroit où ils vivent.
Craig Stuntz
19

Bien qu'il soit raisonnable de créer votre propre ControllerFactory, j'ai trouvé plus pratique de définir tous mes contrôleurs dans chaque projet, mais de les dériver des contrôleurs de mon projet partagé:

namespace MyProject1.Controllers
{
   public class MyController : MySharedProject.Controllers.MyController
   {
      // nothing much to do here...
   }
}

namespace MySharedProject.Controllers
{
   public abstract class MyController : System.Web.Mvc.Controller
   {
      // all (or most) of my controller logic here...
   }
}

Cela présente l'avantage supplémentaire de disposer d'un emplacement pour placer votre logique de contrôleur qui diffère d'un projet à l'autre. En outre, il est plus facile pour les autres développeurs de trouver rapidement la logique de votre contrôleur car les contrôleurs existent à l'emplacement standard.

Quant à savoir si cela est souhaitable, je pense que oui. J'ai créé une logique de gestion de compte commune que je souhaite partager entre des projets qui ont autrement une logique métier très différente. Je partage donc mon compte et mes contrôleurs d'administration, mais les autres contrôleurs sont spécifiques à leurs projets respectifs.

ThisGuy
la source
1
Cela a très bien fonctionné, mais j'ai dû éliminer du code redondant pour éviter une erreur de routage
Ken Mc
Bonjour, Comment puis-je gérer le routage dans ce type de projet? Je veux utiliser le routage d'attributs ...
محمد
Vous pouvez utiliser le routage d'attributs comme vous le feriez normalement.
ThisGuy
2
Je ne sais pas pourquoi cela n'a pas plus de votes positifs ... beaucoup plus élégant que la réponse acceptée, je pense. Merci!
jleach
Cela ne fonctionne pas pour moi. Pourriez-vous dire est-ce .Net Core ou .Net Framework?
Homayoun Behzadian le
4
  • Ajoutez la bibliothèque de classes pour votre projet mvc.
  • Dans la classe, ajoutez le code suivant (For u'r Controller Code)

    namespace ContactController
    {
    public class ContactController : Controller
    {
        public ActionResult Call()
        {
            ViewBag.Title = "Inside MyFirst Controller.";
            return View();
        }
    }

    }

  • Dans le dossier d'affichage de projet mvc, ajoutez le dossier pour Contact et créez un fichier Call.cshtml. Voir le dossier

  • Ajoutez la référence de projet de bibliothèque de classes dans votre projet MVC principal.

Référence

  • Enfin pour faire référence à l'espace de noms du contrôleur de contact dans Route Config.

RouteConfig

RandyMohan
la source
3
C'est un peu dommage que vous ayez un espace de noms avec le même nom que le contrôleur.
Mariusz Jamro
3

Mon problème a été résolu après la mise à jour System.Web.Mvc référence NuGet afin que MvcWebsite et la bibliothèque de classes utilisent la même System.Web.Mvcversion

Pas besoin d'ajouter des espaces de noms par défaut

Homayoun Behzadian
la source
Le problème était que MvcWebsite n'a pas levé d'exception alors que l'assembly mvc actuel a une version inférieure à l'assembly mvc référencé par la bibliothèque de classes
Homayoun Behzadian
1

La forme la plus simple de séparation que j'utilise est de conserver les vues "telles quelles" dans le projet MVC d'origine mais de supprimer les contrôleurs. Ensuite, dans un nouveau projet ClassLibrary, ajoutez les classes Controller et assurez-vous qu'elles héritent de Controller.

Le moteur de routage MVC acheminera automatiquement vers les contrôleurs de la ClassLibrary et les contrôleurs construiront automatiquement les vues à partir du projet MVC d'origine, à condition que vous ayez correctement mis en place vos références et vos utilisations.

J'utilise cette architecture pour implémenter un module Rapports Html qui peut être compilé et déployé séparément de la solution principale. Enfin, je suis libre de SSRS!

Jamie
la source