API Web dans la solution MVC dans un projet distinct

88

Je crée un nouveau projet MVC4, et les recherches m'ont amené à croire que la communication de javascript vers le serveur est mieux réalisée maintenant grâce au cadre d'API Web plutôt que par les actions du contrôleur. Ma compréhension est-elle correcte à ce sujet?

Je suppose que je peux partager tous mes attributs, etc. entre l'API Web et les contrôleurs MVC, donc à première vue, cela ne me semble pas un changement massif.

Lorsque je mets en place des applications, j'aime diviser les composants en projets. Mon plan était d'avoir un projet MVC et un projet d'API Web. Mais j'ai rencontré des problèmes. Par exemple, j'ai fini avec 2 applications en tant que telles, une configuration de routage séparée, etc.

Ma question est donc la suivante: dans une application MVC, le cadre de l'API Web devrait-il se trouver dans le même projet ou l'API Web devrait-elle être séparée en un projet propre et contourner les problèmes?

amateur
la source

Réponses:

110

Malheureusement, vous vous trompez à ce sujet - je présume que je peux partager tous mes attributs, etc. entre les contrôleurs Web api et mvc, donc à première vue, cela ne me semble pas un changement massif.

De nombreux concepts utilisés par l'API Web et MVC, même s'ils sont similaires à première vue, ne sont en fait pas compatibles. Par exemple, les attributs de l'API Web sont System.Web.Http.Filters.Filteret les attributs MVC le sont System.Web.Mvc.Filter- et ils ne sont pas interchangeables.

Il en va de même pour de nombreux autres concepts - liaison de modèle (mécanismes complètement différents), routes (l'API Web utilise HTTPRoutes et non Routes, même si elles fonctionnent toutes les deux sur la même RouteTable sous-jacente), résolveur de dépendances (non compatible) et plus encore - même si similaire sur le surface, sont très différents dans la pratique. De plus, l'API Web n'a pas de concept de zones.

En fin de compte, si tout ce que vous essayez de faire est d'avoir une façon «nouvelle et tendance» de diffuser du contenu JSON - réfléchissez à deux fois avant de vous engager dans cette voie. Je ne recommanderais certainement pas de refactoriser un code existant à moins que vous ne cherchiez vraiment à adopter HTTP et à créer votre application de manière REST.

Tout dépend vraiment de ce que vous construisez. Si vous démarrez un nouveau projet et que tout ce dont vous avez besoin est de servir du JSON pour faciliter votre application Web - à condition que vous soyez prêt à vivre avec du code potentiellement dupliqué (comme ce que j'ai mentionné ci-dessus), l'API Web pourrait facilement être hébergée dans le même projet que ASP.NET MVC.

Je ne séparerais l'API Web en un projet distinct que si vous envisagez de créer une API appropriée pour votre service en ligne - peut-être à utiliser par des clients externes ou par divers appareils - tels que l'alimentation de vos applications mobiles.

Filip W
la source
2
+1 Excellente réponse. Je pensais au départ que MVC et WebAPI pouvaient partager une partie du code, en particulier dans le cas des filtres, de la liaison de modèle, etc., mais ils sont totalement différents.
VJAI
5
Oui, dans un tel scénario, démarrez simplement un nouveau projet MVC4 dans Visual Studio et, lorsque vous êtes invité à indiquer un modèle de projet (deuxième écran), sélectionnez simplement API Web. Cela installera l'API Web de Nuget et dans le cas que vous avez décrit, cela devrait parfaitement fonctionner. Ce que vous obtenez est un fichier de configuration de l'API Web séparé branché sur Global.asax. En outre, vous souhaiterez peut-être séparer les contrôleurs API dans un dossier séparé (par défaut, ils sont avec les contrôleurs MVC). Enfin, les routes par défaut sont évidemment configurées séparément et n'interfèrent pas les unes avec les autres
Filip W
9
J'aurais aimé que mon responsable ait lu cet article avant de concevoir notre projet actuel.
Billdr
2
@FilipW Merci pour les bonnes explications. J'ai également une application MVC et j'utiliserai WebAPI2 pour utiliser le service pour les applications Android. D'autre part, comme le dit David Peden ci-dessous, la sécurité, la maintenance et le déploiement sont également très importants au moment de décider de créer un nouveau projet distinct pour WebAPI. Dans ce cas, en les gardant à l'esprit, que proposez-vous? Pour créer un nouveau projet distinct pour WebAPI ou utiliser le projet MVC actuel? Merci d'avance.
Jack
1
Très bien "Je ne séparerais l'API Web en un projet distinct que si vous envisagez de créer une API appropriée pour votre service en ligne - peut-être à utiliser par des clients externes ou par divers appareils - comme alimenter vos applications mobiles." frappez le clou sur la tête et permet de déterminer facilement de quelle manière le faire.
ozzy432836
27

L'OMI, la sécurité et le déploiement devraient guider votre décision. Par exemple, si votre application MVC utilise l'authentification par formulaire mais que vous souhaitez utiliser l'authentification de base (avec SSL) pour votre API, des projets distincts vous faciliteront la vie. Si vous souhaitez héberger votre site sur www.example.com mais hébergez votre API sous api.example.com (par rapport à www.example.com/api), des projets séparés vous faciliteront la vie. Si vous séparez vos projets et les sous-domaines en conséquence et que vous avez l'intention d'exploiter votre propre API à partir de votre application MVC, vous devrez trouver comment gérer le problème de la même politique d'origine pour les appels côté client à votre API. Solutions communes à ce levier sont jsonp ou CORS ( de préférence si vous le pouvez).

Mise à jour (26/03/2013): le support officiel CORS arrive: http://aspnetwebstack.codeplex.com/wikipage?title=CORS%20support%20for%20ASP.NET%20Web%20API

David Peden
la source
J'essaie de comprendre les problèmes liés à la décision d'intégrer l'API Web à mon application MVC ou de l'avoir en tant que projet distinct. J'ai pu déployer avec succès une application Web API HelloWorld dans un sous-domaine de mon hôte Web. À partir de ce projet séparé, j'utiliserai probablement le modèle de mon application Web MVC et j'appellerai du code dans ce projet distinct. Il semble qu'il serait peut-être plus facile de suivre cette voie d'un projet séparé, mais quels problèmes pensez-vous que je pourrais rencontrer avec cette approche?
Ciaran Gallagher
2
Personnellement, je n'utiliserais pas votre modèle de vue comme votre DTO pour votre API. Je m'attendrais à ce que cette décision vous cause de graves problèmes à mesure que vos modèles de vue et vos signatures d'API divergent. SoC ( en.wikipedia.org/wiki/Separation_of_concerns ) est très important.
David Peden
@DavidPeden Vous suggérez de créer un nouveau projet séparé pour WebAPI. Est-ce vrai? D'autre part, je vais créer un nouveau projet séparé pour WebAPI (j'ai actuellement une couche d'interface utilisateur (MVC) et une couche de données (bibliothèque de classes) dans mon application. Donc, j'utilise également DI, mais je me demande si je peux utiliser les mêmes entités, référentiels, interfaces et classes abstraites dans la couche de données pour le projet WebAPI nouvellement créé et la seule chose que je dois faire est de créer des contrôleurs WebAPI ou est-ce que je les crée également tous (entités, référentiels, interfaces et résumé classes) à nouveau pour le WebAPI? Avez-vous de l'aide s'il vous plaît?
Jack
1
@ H.Johnson Il est difficile de donner des conseils généraux qui soient significatifs, mais il semble que vous auriez intérêt à disposer d'une couche de service d'application qui encapsule vos entités et référentiels qui peuvent être exploités par vos deux interfaces utilisateur (MVC et API).
David Peden
9

Après un certain degré d'expérience (création d'API pour les applications et pour mvc). Je fais principalement les deux.

Je crée un projet séparé pour les appels d'API provenant d'autres clients ou d'autres appareils (applications Android / IOS). L'une des raisons est que l'authentification est différente, elle est basée sur des jetons (pour la garder sans état). Je ne veux pas mélanger cela dans mon application MVC.

Pour mes appels javascript / jquery api à mon application mvc, j'aime garder les choses simples afin d'inclure une API Web dans mon application MVC. Je n'ai pas l'intention d'avoir une authentification basée sur des jetons avec mes appels API javascript, car bon, c'est dans la même application. Je peux simplement utiliser l' [authorize]attribut sur un point de terminaison d'API, lorsqu'un utilisateur n'est pas connecté, il n'obtiendra pas les données.

De plus, lorsque vous traitez avec des paniers d'achat et que vous souhaitez stocker le panier d'un utilisateur dans une session (sans être connecté), vous devez également l'avoir dans votre API si vous ajoutez / supprimez des produits via votre code javascript. Cela rendra votre API avec état à coup sûr, mais réduira également la complexité de votre MVC-API.

CularBytes
la source
4
Eh bien @Dimi, c'est une modification inutile pour obtenir des votes ... Comment puis-je les rejeter?
CularBytes
Faites ce que vous voulez. Je n'édite pas par votes mais pour le meilleur look que je suppose. Aller de l'avant.
Développeur
3
@CularBytes Vous ne pouvez pas rejeter les modifications, mais vous pouvez les modifier à nouveau et annuler les modifications. Cela nécessite un processus d'examen par les pairs de moins de 2000 représentants, mais vous avez suffisamment de représentants pour le faire instantanément. Je reconnais que la modification n'a ajouté aucune valeur et je l'ai annulée pour vous.
Dan Bechard
5

J'ai récemment fait presque la même chose: j'ai commencé avec un nouveau projet d'application Web MVC 4 en choisissant le modèle d'API Web dans VS2012.

Cela créera une API Web hébergée dans la même application que MVC.

Je voulais déplacer les ApiControllers dans un projet de bibliothèque de classes distinct. C'était assez simple mais la solution était un peu cachée.

Dans AssemblyInfo.cs du projet MVC 4, ajoutez une ligne de code similaire

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

Vous avez maintenant besoin de la classe LibraryRegistrator (n'hésitez pas à la nommer comme vous le souhaitez)

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

Dans le projet MVC 4, ajoutez également une référence à la bibliothèque Api.

Vous pouvez maintenant ajouter des contrôleurs Api à votre propre bibliothèque de classes distincte (yourown.dll).

fanvabra
la source
2

Même si votre projet est si complexe qu'il justifie deux "frontaux", je n'envisagerais toujours de diviser webapi en un projet distinct qu'en dernier recours. Vous aurez des maux de tête de déploiement et il serait difficile pour un débutant de comprendre la structure de votre solution. Sans parler des problèmes de routage.

Je viserais à garder l'espace de noms system.web isolé dans la seule "couche de présentation". Bien que le webapi ne soit pas de présentation, il fait toujours partie de l'interface de votre application. Tant que vous conservez la logique dans votre domaine et non dans vos contrôleurs, vous ne devriez pas rencontrer trop de problèmes. N'oubliez pas non plus d'utiliser les zones.

pseudo
la source
1
Ma principale raison de vouloir des projets séparés est que l'API n'est pas vraiment frontale. C'est de niveau intermédiaire.
lordcheeto
6
«Il serait difficile pour un débutant de comprendre» n'est pas une bonne raison de choisir une approche plutôt qu'une autre. Restez simple lorsque cela est possible, bien sûr, mais les besoins complexes nécessitent souvent des solutions complexes. Plutôt que d'écrire du code stupide pour répondre aux besoins des débutants, nous devrions former les débutants à comprendre et à écrire du code intelligent.
Dan Bechard
0

En plus de configurer la DLL distincte pour Web.Api.

Juste une suggestion:

  1. Créer le projet
  2. Nugget WebActivatorEx
  3. Créer une méthode de classe à appeler sur app_start

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

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

  4. Enregistrer des routes web.api dans la méthode de démarrage

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

  5. Référencez le projet au projet Web. pour activer la méthode de démarrage.

J'espère que cela t'aides.

jayson.centeno
la source
0

J'ai essayé de diviser les contrôleurs d'API en un nouveau projet. Tout ce que j'ai fait est de créer un nouveau projet de bibliothèque, de déplacer les contrôleurs dans un dossier nommé API. Puis ajouté la référence du projet de bibliothèque au projet MVC.

La configuration webAPI est laissée dans le projet MVC lui-même. Ça fonctionne bien.

jaicind
la source