Comment enregistrer un Controller dans ASP.NET MVC lorsque la classe controller est dans un assemblage différent?

mon but est de modifier asp.net MVC controller registry de sorte que je puisse créer des controllers et des vues dans une assemblée (enfant) séparée, et juste copier les fichiers de vue et les DLLs à L'application MVC hôte et les nouveaux controllers sont effectivement "connectés" à l'application hôte.

évidemment, je vais avoir besoin d'une sorte de schéma du CIO, mais je suis perdu.

mon idée était d'avoir un montage enfant avec système.Web.mvc référencé et ensuite seulement construire des classes de controller héritées de Controller :

Montage Séparé:

using System.Web;
using System.Web.Mvc;

namespace ChildApp
{
    public class ChildController : Controller
    {
        ActionResult Index()
        {
            return View();
        }
    }
}

Yay toute fine et dandy. Mais ensuite j'ai cherché à modifier le Registre du contrôleur de l'application hôte pour charger mon nouveau contrôleur enfant à l'exécution, et j'ai été confus. Peut-être parce que j'ai besoin d'une meilleure compréhension de C#.

quoi qu'il en soit, j'ai pensé que j'avais besoin de créer une classe CustomControllerFactory . Alors j'ai commencé à écrire un cours qui CA annulerait la méthode GetControllerInstance() . Pendant que je tapais, intellisence a soulevé ceci:

application MVC hôte:

public class CustomControllerFactory : DefaultControllerFactory 
{
    protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
    {
        return base.GetControllerInstance(requestContext, controllerType);
    }
}

maintenant, à ce point je suis perdu. Je ne sais pas ce que cela fait. À l'origine, j'allais écrire une classe "contrôleur Loader" comme un Localisateur de Service comme celui-ci:

application MVC hôte:

public class ControllerLoader
{
    public static IList<IController> Load(string folder)
    {
        IList<IController> controllers = new List<IController>();

        // Get files in folder
        string[] files = Directory.GetFiles(folder, "*.plug.dll");
        foreach(string file in files)
        {
            Assembly assembly = Assembly.LoadFile(file);
            var types = assembly.GetExportedTypes();
            foreach (Type type in types)
            {
                if (type.GetInterfaces().Contains(typeof(IController)))
                {
                    object instance = Activator.CreateInstance(type);
                    controllers.Add(instance as IController);
                }
            }
        }
        return controllers;
    }
}

et puis j'avais l'intention d'utiliser ma liste de contrôleurs pour enregistrer dans le contrôleur de l'usine. Mais. .. comment? Je sens que je suis sur le bord d'essayer de le comprendre. Je suppose que tout se résume à cette question: Comment puis-je me connecter dans return base.GetControllerInstance(requestContext, controllerType); ? Ou devrais-je utiliser une approche totalement différente?

25
demandé sur ΩmegaMan 2011-09-26 23:07:35

4 réponses

référence à l'autre assemblage de la "racine" ASP.NET projet MVC. Si les controllers sont dans un autre namespace, vous devrez modifier les routes dans global.asax, comme ceci:

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

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        namespaces: new[] { typeof(HomeController).Namespace }
    );

}

notez l'argument additionnel namespaces à la méthode MapRoute .

26
répondu Mark Seemann 2011-09-26 19:14:50

un autre projet devrait être mis en place comme une zone et vous obtiendrez le résultat souhaité. La classe d'inscription de zone mettra votre projet de zone dans le mix. Ensuite, vous pouvez simplement déposer la dll dans une application en cours d'exécution et il fonctionnera sans construire l'application entière et en la redéployant.

la façon la plus simple de le faire est d'ajouter un nouveau projet mvc à votre solution et de demander à Visual Studio de créer le nouveau projet inside /areas/mynewprog/. Supprimer tous les fichiers que vous n'avez pas besoin et ajoutez une classe d'enregistrement de zone pour la relier.

construire le projet, saisir il est dll et le déposer dans votre exécution sites bin répertoire et que son..

vous avez alors juste à traiter les vues et les trucs, soit les compiler dans la dll ou les copier sur le serveur dans les domaines/mynewproj/ dossier.

2
répondu JBeckton 2013-09-21 00:42:33

mon expérience avec les contrôleurs est que cela fonctionne. Copiez l'assemblée dans le répertoire bin (ou ajoutez une référence à l'assemblée et elle y sera copiée pour vous)

Je n'ai pas essayé avec des vues

0
répondu pm100 2011-09-26 19:11:00

créer un module séparé comme montré structure du projet de Plugin:

Plugin Project structure

notent que certains dossiers ont été exclus du projet.

Le Contrôleur De Messagerie.le fichier cs est le suivant:

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

namespace MessagingModule.Controllers
{
    public class MessagingController : Controller
    {
        //
        // GET: /Messaging/

        public ActionResult Index()
        {
          var appName = Session["appName"]; // Get some value from another module
            return Content("Yep Messaging module @"+ appName);
        }

    }
}

le fichier de Messagingaregistration est le suivant:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace MessagingModule
{
  public class MessagingAreaRegistration : AreaRegistration
  {
    public override string AreaName
    {
      get
      {
        return "Messaging";
      }
    }

    public override void RegisterArea( AreaRegistrationContext context )
    {
      context.MapRoute(
          "Messaging_default",
          "Messaging/{controller}/{action}/{id}",
          new { action = "Index", id = UrlParameter.Optional }
        //new[] { "MessagingModule.Controllers" }
      );
    }

  }
}

à La potion de la Mondiale.asax.cs fichier

[Charger le module externe (contrôleurs, contrôleurs d'api de la bibliothèque) dans le domaine de l'application. Après cela asp.net mvc fait le reste pour vous (Enregistrement de zone et la découverte de contrôleurs) [3]

   using System;
   using System.Collections.Generic;
   using System.Linq;
   using System.Web;
   using System.Web.Http;
   using System.Web.Mvc;
   using System.Web.Optimization;
   using System.Web.Routing;
   using System.Reflection;
   using System.Web.Configuration;
   using System.Text.RegularExpressions;

   namespace mvcapp
   {
     // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
     // visit http://go.microsoft.com/?LinkId=9394801

     public class MvcApplication : System.Web.HttpApplication
     {
       protected void Application_Start()
       {
         var domain = AppDomain.CurrentDomain;

         domain.Load("MessagingModule, Version=1.0.0.0, Culture=neutral,   PublicKeyToken=null");
0
répondu RorvikSam 2018-09-24 18:04:48