7
votes

Décorer ASP.NET Web API IHTTPCONTROLLER

J'essaie d'envelopper les contrôleurs d'API Web ( IHTTPCONTROLLER Mises en œuvre) avec des décorateurs, mais lorsque je le fais, Web API jette une exception, car il s'agit en quelque sorte à la mise en œuvre réelle.

Appliquer des décorateurs aux contrôleurs est une astuce que j'applique avec succès aux contrôleurs MVC et j'aime évidemment faire la même chose dans l'API Web.

J'ai créé une personnalisation ihttpcontrolleractivator qui permet de résoudre la décoration IHTTPCONTROLLER Mises en œuvre. Voici une implémentation dépourvée: xxx

Mon décorateur ressemble à ceci: xxx

Toutefois, quand j'exécute mon application et demande Le ValeursController , Web API me jette le suivant InvalidCastException :

Impossible de lancer l'objet de type 'webapitest.myhttpcontrollerdecorator' Tapez 'webapitest.controls.valuescontroller'.

stacktrace: xxx

C'est comme si Web API nous fournit avec le iHttpcontroller abstraction mais dépend toujours de la mise en œuvre elle-même. Cela serait bien sûr une violation grave du principe d'inversion de dépendance et de rendre l'abstraction totalement inutile. Donc, je fais probablement quelque chose de mal à la place.

Qu'est-ce que je fais mal? Comment puis-je décorer avec plaisir de mes contrôleurs API?


0 commentaires

3 Réponses :


4
votes

Je dirais que la voie naturelle et conçue comment réaliser ce comportement dans ASP.NET Web API est avec le gestionnaires de messages personnalisés / gestionnaires de délégation

Par exemple, j'ai ce délégationHandler en place < Pré> xxx

et c'est comment injecter cela dans la structure: xxx


6 commentaires

Merci pour votre réponse. Je suis toujours un peu ennuyé que je ne puisse pas décorer ihttpcontroller , mais votre solution satisfera probablement mes besoins :-). Le seul problème avec cette approche est que les gestionnaires de délégation sont des singletons et que certains ne peuvent pas dépendre d'un service avec une durée de vie plus courte. Existe-t-il un moyen de laisser les API Web les résoudre sur chaque demande?


Eh bien, parce que nous travaillons avec des services externes (pourraient être des singletons aussi) mais définir les valeurs dans le contexte (demande, httpcontext utilisateur) ... Nous n'avons pas besoin de l'instance par "demande". Le décorateur IHTTPCONTROLLER ne peut pas fonctionner, je dirais, car à la fin, nous ne travaillons pas avec cette interface. Le cadre examine (réflexion) le contrôleur "réel" et basé sur ses méthodes / paramètres / attributs décide quelle méthode sur l'instance à appeler. Donc, le motif de décorateur ne fonctionnerait pas ici. De toute façon ... le gestionnaire de délégation devrait résoudre le problème


Une délégationHandler pourrait dépendre (par l'intermédiaire d'une injection constructrice) sur d'autres services qui pourraient être (ou doivent être) définis avec un style de vie par demande (ou plus court). Lorsque cela se produit, la délégationHandler devrait avoir une vie aussi courte (ou plus courte) que le style de vie le plus court de ses dépendances.


Une chose drôle est que l'API Web est très similaire à MVC, mais avec MVC icontroller S peut être décoré sans problème, car il s'agit du contrôleur contrôleur de la classe de base qui fait toute la réflexion arriver à la bonne action. L'infrastructure appelle simplement l'interface icontroller . N'est-ce pas bizar que Web API nous fournit avec un IHTTPCONTROLLER abstraction, mais dépend toujours de la mise en œuvre réelle?


Je comprends ton point. J'ai juste essayé de vous montrer comment .. basé sur mon expérience. Les gestionnaires de délégation travaillent assez bien pour toute chose fondamentale en tant que Cors, auth ... pour le reste que nous utilisons l'AOP ... mais comme je l'ai dit ... je voulais juste vous montrer une autre façon de faire ça;)


Et je vous remercie pour votre aide. Merci.



1
votes

Vous pouvez contourner cela en implémentant ihttpactioninvoker et "convertir" le décorateur dans l'instance décorée au point que le ihttpcontroller abstraction n'est plus pertinent.

Cela se fait facilement en héritant à partir de apicontrolleractioninvoker .

(j'ai codé dur l'exemple et s'attendre à ce que toute mise en œuvre du monde réel soit plus flexible.) xxx

ceci a été enregistré dans global.asax.cs xxx

si vous " D effectivement veux faire cela est une autre question - qui connaît les ramifications de modification de actionContext ?


2 commentaires

Dans votre exemple, vous extrayez la décorée du décorateur. Cela ne serait-il pas supprimer le comportement que le décorateur a ajouté? Est-ce que ce comportement sera-t-il encore appelé?


@Steven Oui, je suis sûr que cela contournerait les appels décorés - une solution complète aurait besoin de gérer appelant les méthodes dans la personnalisation ihttpactioninvoker et contourner la mise en œuvre par défaut.



1
votes

Vous pouvez fournir une implémentation personnalisée de ihttpcontrollerselector code> pour modifier le type instancié pour un contrôleur particulier. (Veuillez noter que je n'ai pas testé cela à l'épuisement)

Mettre à jour le décorateur pour être générique p> xxx pré>

Définir la mise en oeuvre personnalisée de ihttpcontrollerselector code> p> xxx pré>

Lorsque vous enregistrez les contrôleurs, ajoutez l'enregistrement d'une version décorée du type de contrôleur p> xxx pré>

enregistrer l'implémentation de IHTTPCONTROLLORSELLector CODE> P>

private MyHttpControllerDecorator<T> DecoratorBuilder<T>(T instance)
    where T : IHttpController
{
    return new MyHttpControllerDecorator<T>(instance);
}


0 commentaires