asp.net mvc coloca los controladores en un proyecto separado

107

Estoy aprendiendo asp.net mvc y estoy tratando de averiguar cómo mover mis controladores a un proyecto separado. Normalmente, cuando he diseñado aplicaciones web asp.net antes, creé un proyecto para mis modelos, otro para mi lógica, y luego estaba la web.

Ahora que estoy aprendiendo asp.net mvc, esperaba seguir un patrón similar y poner los modelos y controladores en sus propios proyectos separados, y dejar las vistas / scripts / css en la web. La parte de los modelos fue fácil, pero lo que no entiendo es cómo "encontrar" mis controladores en un proyecto separado. Además, me gustaría saber si esto es aconsejable. ¡Gracias!

Aaron Palmer
fuente

Respuestas:

92

En primer lugar, ciertamente es una buena idea poner su modelo en un proyecto separado. Como ha descubierto, esto es trivial.

Con respecto a los controladores y las vistas, no veo ninguna ventaja obvia en separarlos para la mayoría de los proyectos básicos, aunque es posible que tenga una necesidad particular de hacerlo en una aplicación en particular.

Si elige hacer esto, deberá indicarle al marco cómo encontrar sus controladores. La forma básica de hacer esto es proporcionando su propio ControllerFactory. Puede echar un vistazo al código fuente de DefaultControllerFactory para tener una idea de cómo se hace esto. Subescribir esta clase y anular el método GetControllerType (string controllerName) puede ser suficiente para lograr lo que está pidiendo.

Una vez que haya creado su propio ControllerFactory personalizado, agregue la siguiente línea a Application_Start en global.asax para indicarle al marco dónde encontrarlo:

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

Actualización: lea esta publicación y las publicaciones a las que se vincula para obtener más información. Vea también el comentario de Phil Haack en esa publicación sobre:

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

... que no es una solución completa, pero posiblemente lo suficientemente buena para casos simples.

Craig Stuntz
fuente
2
¡Gracias Craig! Esto es exactamente lo que estaba buscando. ¿Existe esta información en la web? Lo he estado buscando en Google sin mucha suerte. ¡StackOverflow llega de nuevo!
Aaron Palmer
11
Estoy de acuerdo, los controladores manejan la entrada del usuario, manipulan el modelo y luego pasan los datos a la vista. Por lo general, son muy específicos de una aplicación. Cualquier lógica que no sea específica de la aplicación podría estar mejor en una biblioteca o en el modelo. Pero los controladores en general deberían estar con el proyecto web.
Pirateado el
2
Tengo un controlador de errores y vistas idénticas entre dos aplicaciones. Para mí tiene sentido tenerlos en un solo ensamblaje que ambas aplicaciones puedan usar.
Judo de vela
3
¿No es más fácil probar los controladores y usar IoC cuando los controladores están en un proyecto separado? Esa sería la razón principal
Samuel G
1
@Chev, no creo que haya ninguna diferencia allí. La capacidad de prueba de sus controladores tiene más que ver con cómo los codifica , no con dónde viven.
Craig Stuntz
19

Si bien es razonable crear su propia ControllerFactory, me pareció más conveniente definir todos mis Controllers en cada proyecto, pero derivarlos de Controllers en mi proyecto compartido:

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...
   }
}

Esto tiene el beneficio adicional de que tiene un lugar para colocar su lógica de controlador que difiere de un proyecto a otro. Además, es más fácil para otros desarrolladores encontrar rápidamente la lógica de su controlador porque los controladores existen en el lugar estándar.

En cuanto a si esto es aconsejable, creo que absolutamente lo es. Creé una lógica común de administración de cuentas que quiero compartir entre proyectos que de otra manera tienen una lógica comercial muy diferente. Así que estoy compartiendo mi cuenta y mis controladores administrativos, pero los otros controladores son específicos de sus respectivos proyectos.

Este chico
fuente
1
Esto funcionó muy bien, pero tuve que eliminar algunos códigos redundantes para evitar un error de enrutamiento
Ken Mc
Hola, ¿Cómo puedo gestionar el enrutamiento en este tipo de proyecto? Quiero usar el enrutamiento de atributos ...
محمد
Puede utilizar el enrutamiento de atributos como lo haría normalmente.
ThisGuy
2
No estoy seguro de por qué esto no tiene más votos a favor ... mucho más elegante que la respuesta aceptada, creo. ¡Gracias!
jleach
Esto no funciona para mi. ¿Podrías decir si esto es .Net Core o .Net Framework?
Homayoun Behzadian
4
  • Agregue la biblioteca de clases para su proyecto mvc.
  • En la clase agregue el siguiente código (para u'r Controller Code)

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

    }

  • En la carpeta de vista del proyecto mvc, agregue la carpeta para Contacto y cree un archivo Call.cshtml. Ver folder

  • Agregue la referencia del proyecto de la biblioteca de clases a su proyecto MVC principal.

Referencia

  • Finalmente, para referir el espacio de nombres del controlador de contacto a Route Config.

RouteConfig

RandyMohan
fuente
3
Es un poco desafortunado que tenga un espacio de nombres con el mismo nombre que el controlador.
Mariusz Jamro
3

Mi problema se resolvió después de actualizar la System.Web.Mvcreferencia de NuGet, por lo que MvcWebsite y Class Library usan la misma System.Web.Mvcversión

No es necesario agregar espacios de nombres predeterminados

Homayoun Behzadian
fuente
El problema fue que MvcWebsite no arrojó una excepción mientras el ensamblado de mvc actual tiene una versión más baja que el ensamblado de
mvc
1

La forma más simple de separación que utilizo es retener las Vistas "tal cual" en el proyecto MVC original pero eliminar los Controladores. Luego, en un nuevo proyecto de ClassLibrary, agregue las clases Controller y asegúrese de que hereden de Controller.

El motor de enrutamiento MVC se enrutará automáticamente a los controladores en ClassLibrary y los controladores construirán automáticamente las vistas del proyecto MVC original, siempre que tenga sus referencias y usos correctamente en su lugar.

Estoy usando esta arquitectura para implementar un módulo de Informes Html que se puede compilar e implementar por separado de la solución principal. ¡Por fin estoy libre de SSRS!

Jamie
fuente