API web en solución MVC en proyecto separado

88

Estoy creando un nuevo proyecto MVC4 y la investigación me ha llevado a creer que la comunicación desde javascript al lado del servidor se logra mejor ahora a través del marco de la API web en lugar de las acciones del controlador. ¿Es correcto mi entendimiento sobre esto?

Supongo que puedo compartir todos mis atributos, etc.entre la API web y los controladores MVC, por lo que, a primera vista, no parece un cambio masivo para mí.

Cuando estoy configurando aplicaciones, me gusta dividir componentes en proyectos. Mi plan era tener un proyecto MVC y un proyecto de API web. Pero me he encontrado con problemas. Por ejemplo, terminé con 2 aplicaciones como tales, configuración de enrutamiento separada, etc., etc.

Entonces, mi pregunta es, en una aplicación MVC, ¿el marco de la API web debería ubicarse dentro del mismo proyecto, o la API web debería separarse en un proyecto propio y solucionar los problemas?

aficionado
fuente

Respuestas:

110

Desafortunadamente, se equivoca al respecto: supongo que puedo compartir todos mis atributos, etc.entre los controladores web api y mvc, por lo que, a primera vista, no parece un cambio masivo para mí.

Muchos de los conceptos utilizados por Web API y MVC, aunque similares a primera vista, en realidad no son compatibles. Por ejemplo, los atributos de la API web son System.Web.Http.Filters.Filtery los atributos de MVC son System.Web.Mvc.Filter, y no son intercambiables.

Lo mismo se aplica a muchos otros conceptos: enlace de modelos (mecanismos completamente diferentes), rutas (la API web usa HTTPRoutes no Routes, aunque ambos operan en la misma RouteTable subyacente), resolución de dependencias (no compatible) y más, aunque similar en el superficie, son muy diferentes en la práctica. Además, Web API no tiene un concepto de áreas.

En última instancia, si todo lo que está tratando de lograr es tener una forma "nueva y moderna" de ofrecer contenido JSON, piénselo dos veces antes de seguir ese camino. Ciertamente, no recomendaría refactorizar ningún código existente a menos que realmente esté buscando adoptar HTTP y construir su aplicación de una manera REST.

Realmente todo depende de lo que estés construyendo. Si está comenzando un nuevo proyecto, y todo lo que necesita es ofrecer algo de JSON para facilitar su aplicación web, siempre que esté dispuesto a vivir con algún código potencialmente duplicado (como el que mencioné anteriormente), la API web podría alojarse fácilmente en el mismo proyecto que ASP.NET MVC.

Solo separaría la API web en un proyecto separado si va a crear una API adecuada para su servicio en línea, tal vez para ser consumida por clientes externos o por varios dispositivos, como alimentar sus aplicaciones móviles.

Filip W
fuente
2
+1 Excelente respuesta. Al principio pensé que tanto MVC como WebAPI pueden compartir parte del código, especialmente en el caso de filtros, enlace de modelos, etc. pero son totalmente diferentes.
VJAI
5
Sí, en tal escenario, simplemente inicie un nuevo proyecto MVC4 en Visual Studio, y cuando se le solicite una plantilla de proyecto (segunda pantalla) simplemente seleccione Web API. Eso instalará la API web de Nuget y, en el caso que describiste, debería estar perfectamente bien. Lo que obtiene es un archivo de configuración de API web separado conectado a Global.asax. Además, es posible que desee separar los controladores API en una carpeta separada (de forma predeterminada, están junto con los controladores MVC). Finalmente, las rutas predeterminadas obviamente se configuran por separado y no interfieren entre sí
Filip W
9
Ojalá mi líder hubiera leído esta publicación antes de diseñar nuestro proyecto actual.
Billdr
2
@FilipW Gracias por las buenas explicaciones. También tengo una aplicación MVC y usaré WebAPI2 para usar el servicio para aplicaciones de Android. Por otro lado, como dice David Peden a continuación, la seguridad, el mantenimiento y la implementación también son muy importantes cuando se decide crear un nuevo proyecto separado para WebAPI. En ese caso, teniéndolos en cuenta, ¿qué sugeriría? ¿Para crear un nuevo proyecto separado para WebAPI o usar el proyecto MVC actual? Gracias por adelantado.
Jack
1
Muy bien "Solo separaría la API web en un proyecto separado si va a crear una API adecuada para su servicio en línea, tal vez para ser consumida por clientes externos o por varios dispositivos, como alimentar sus aplicaciones móviles". Golpea el clavo en la cabeza y hace que sea fácil determinar de qué manera hacerlo.
ozzy432836
27

En mi opinión, la seguridad y la implementación deben impulsar su decisión. Por ejemplo, si su aplicación MVC usa autenticación de formularios pero está interesado en usar la autenticación básica (con SSL) para su API, los proyectos separados le facilitarán la vida. Si desea alojar su sitio en www.example.com pero alojar su API como api.example.com (frente a www.example.com/api), los proyectos separados le facilitarán la vida. Si separa sus proyectos y los subdominios en consecuencia y tiene la intención de aprovechar su propia API desde su aplicación MVC, tendrá que averiguar cómo tratar el problema de la Política del mismo origen para las llamadas del lado del cliente a su API. Las soluciones comunes a esto son aprovechar jsonp o CORS (preferiblemente si puede).

Actualización (26/3/2013): Se acerca el soporte oficial de CORS: http://aspnetwebstack.codeplex.com/wikipage?title=CORS%20support%20for%20ASP.NET%20Web%20API

David Peden
fuente
Estoy tratando de entender los problemas relacionados con la decisión de integrar la API web con mi aplicación MVC o tenerla como un proyecto separado. Pude implementar con éxito una aplicación Web API HelloWorld en un subdominio en mi servidor web. Desde este proyecto separado, probablemente usaré el modelo de mi aplicación web MVC y llamaré el código en ese proyecto separado. Parece que podría ser más fácil seguir esta ruta de un proyecto separado, pero ¿qué problemas crees que podría encontrar con este enfoque?
Ciaran Gallagher
2
Personalmente, no usaría su modelo de vista como su DTO para su API. Espero que esa decisión le cause serios problemas en el futuro, ya que sus modelos de vista y firmas de API divergen. SoC ( en.wikipedia.org/wiki/Separation_of_concerns ) es muy importante.
David Peden
@DavidPeden Sugieres crear un nuevo proyecto separado para WebAPI. ¿Es eso cierto? Por otro lado, crearé un nuevo proyecto separado para WebAPI (actualmente tengo una capa de interfaz de usuario (MVC) y una capa de datos (biblioteca de clases) en mi aplicación. Entonces, también uso DI, pero me pregunto si puedo usar las mismas Entidades, Repositorios, Interfaces y Clases Abstractas en la Capa de Datos para el proyecto WebAPI recién creado y lo único que tengo que hacer es crear Controladores WebAPI? O también los creo todos (Entidades, Repositorios, Interfaces y Resumen clases) otra vez para la WebAPI? ¿Alguna ayuda por favor?
Jack
1
@ H.Johnson Es difícil dar un consejo general que sea significativo, pero parece que se beneficiaría de tener una capa de servicio de aplicaciones que encapsule sus entidades y repositorios que puedan ser aprovechadas por sus dos UI (MVC y API).
David Peden
9

Después de cierto grado de experiencia (creando API para aplicaciones y para mvc). Principalmente hago ambas cosas.

Creo un proyecto separado para las llamadas a la API que provienen de otros clientes u otros dispositivos (aplicaciones Android / IOS). Una de las razones es que la autenticación es diferente, se basa en tokens (para mantenerla sin estado). No quiero mezclar esto dentro de mi aplicación MVC.

Para mis llamadas de API javascript / jquery a mi aplicación MVC, me gusta simplificar las cosas, así que incluyo una API web dentro de mi aplicación MVC. No tengo la intención de tener una autenticación basada en tokens con mis llamadas a la API de JavaScript, porque bueno, está en la misma aplicación. Solo puedo usar el [authorize]atributo en un punto final de API, cuando un usuario no está conectado, no obtendrá los datos.

Además, cuando se trata de carritos de compras y desea almacenar un carrito de compras de usuarios en una sesión (mientras no está conectado), también debe tener esto en su API si agrega / elimina productos a través de su código javascript. Esto seguramente hará que su API tenga estado, pero también reducirá la complejidad en su MVC-API.

CularBytes
fuente
4
Bueno @Dimi, esa es una edición inútil para conseguir algunos votos ... ¿Cómo puedo rechazarlos?
CularBytes
Haz lo que quieras. No edito por votos, pero supongo que para obtener el mejor aspecto posible. Adelante.
DmitryBoyko
3
@CularBytes No puede rechazar las ediciones, pero puede editarlas nuevamente y deshacer los cambios. Esto requiere un proceso de revisión por pares de menos de 2000 representantes, pero tiene suficiente representante para hacerlo al instante. Estoy de acuerdo en que la edición no agregó ningún valor y la he revertido para ti.
Dan Bechard
5

Recientemente hice casi lo mismo: comencé con un nuevo proyecto de aplicación web MVC 4 eligiendo la plantilla de API web en VS2012.

Esto creará una API web alojada en la misma aplicación que MVC.

Quería mover ApiControllers a un proyecto de biblioteca de clases separado. Esto fue bastante fácil pero la solución estaba un poco oculta.

En AssemblyInfo.cs del proyecto MVC 4, agregue una línea de código similar

[assembly: PreApplicationStartMethod(typeof(LibraryRegistrator), "Register")]

Ahora necesita la clase LibraryRegistrator (no dude en nombrarla como sea)

public class LibraryRegistrator
    {
        public static void Register()
        {
            BuildManager.AddReferencedAssembly(Assembly.LoadFrom(HostingEnvironment.MapPath("~/bin/yourown.dll")));
        }
    }

En el proyecto MVC 4 también agregue una referencia a la biblioteca Api.

Ahora puede agregar controladores Api a su propia biblioteca de clases separada (yourown.dll).

fanvabra
fuente
2

Incluso si su proyecto es tan complejo como para justificar dos "interfaces", entonces solo consideraría dividir webapi en un proyecto separado como último recurso. Tendrá dolores de cabeza de implementación y sería difícil para un novato comprender la estructura de su solución. Sin mencionar los problemas de enrutamiento.

Mi objetivo es mantener el espacio de nombres system.web aislado en una "capa de presentación". A pesar de que webapi no es de presentación , sigue siendo parte de la interfaz de su aplicación. Siempre que mantenga la lógica en su dominio y no en sus controladores, no debería tener demasiados problemas. Además, no olvide hacer uso de las áreas.

Mella
fuente
1
Mi principal razonamiento para querer proyectos separados es que la API no es realmente una interfaz. Es de nivel medio.
lordcheeto
6
"Sería difícil de entender para un novato" no es una buena razón para elegir un enfoque sobre el otro. Mantenlo simple cuando sea posible, claro, pero las necesidades complejas a menudo requieren soluciones complejas. En lugar de escribir código tonto para atender a los novatos, deberíamos entrenar a los novatos para que comprendan y escriban código inteligente.
Dan Bechard
0

Además de configurar la DLL separada para Web.Api.

Sólo una sugerencia:

  1. Crea el proyecto
  2. Nugget WebActivatorEx
  3. Cree un método de clase para ser llamado en app_start

    [ensamblado: WebActivatorEx.PostApplicationStartMethod (typeof (API.AppWebActivator), "Start")]

    [ensamblado: WebActivatorEx.ApplicationShutdownMethod (typeof (API.AppWebActivator), "Shutdown")]

  4. Registrar una ruta web.api dentro del método de inicio

    public static void Start () {GlobalConfiguration.Configure (WebApiConfig.Register); }

  5. Haga referencia al proyecto al proyecto web. para activar el método de inicio.

Espero que esto ayude.

jayson.centeno
fuente
0

Intenté dividir los controladores de API en un nuevo proyecto. Todo lo que he hecho es crear un nuevo proyecto de biblioteca, moví los controladores dentro de la carpeta llamada API. Luego agregó la referencia del proyecto de la biblioteca al proyecto MVC.

La configuración de webAPI se deja en el propio proyecto MVC. Funciona bien.

jaicind
fuente