装饰ASP.NET Web API IHttpController

Ste*_*ven 7 c# dependency-injection decorator asp.net-web-api

我试图总结的Web API控制器(IHttpController带装饰的实现),但我这样做的时候,网页API抛出一个异常,因为在某种程度上它期待的实际执行.

将装饰器应用于控制器是我成功应用于MVC控制器的一个技巧,我显然希望在Web API中也这样做.

我创建了一个IHttpControllerActivator允许解析修饰IHttpController实现的自定义.这是一个剥离的实现:

public class CrossCuttingConcernHttpControllerActivator : IHttpControllerActivator {
    private readonly Container container;
    public CrossCuttingConcernHttpControllerActivator(Container container) {
        this.container = container;
    }

    public IHttpController Create(HttpRequestMessage request, 
        HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        var controller = (IHttpController)this.container.GetInstance(controllerType);

        // Wrap the instance in one or multiple decorators. Note that in reality, the 
        // decorator is applied by the container, but that doesn't really matter here.
        return new MyHttpControllerDecorator(controller);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的装饰师看起来像这样:

public class MyHttpControllerDecorator : IHttpController {
    private readonly IHttpController decoratee;
    public MyHttpControllerDecorator(IHttpController decoratee) {
        this.decoratee = decoratee;
    }

    public Task<HttpResponseMessage> ExecuteAsync(
        HttpControllerContext controllerContext,
        CancellationToken cancellationToken)
    {
        // this decorator does not add any logic. Just the minimal amount of code to
        // reproduce the issue.
        return this.decoratee.ExecuteAsync(controllerContext, cancellationToken);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我运行我的应用程序并请求时ValuesController,Web API会抛出以下内容InvalidCastException:

无法将"WebApiTest.MyHttpControllerDecorator"类型的对象强制转换为"WebApiTest.Controllers.ValuesController".

堆栈跟踪:

at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass13.<GetExecutor>b__c(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c__DisplayClass5.<ExecuteAsync>b__4()
at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)
Run Code Online (Sandbox Code Playgroud)

就好像Web API为我们提供IHttpController抽象但跳过它仍然依赖于实现本身.这当然会严重违反依赖性倒置原则,并使抽象完全无用.所以我可能做错了.

我做错了什么?我怎样才能愉快地装饰我的API控制器?

Rad*_*ler 4

我想说,在 ASP.NET Web API 中实现此行为的自然、设计方法是使用自定义消息处理程序/委托处理程序

例如我确实有DelegationHandler这个

public class AuthenticationDelegationHandler : DelegatingHandler
{
    protected override System.Threading.Tasks.Task<HttpResponseMessage> 
        SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // I. do some stuff to create Custom Principal
        // e.g.
        var principal = CreatePrincipal();
        ...

        // II. return execution to the framework            
        return base.SendAsync(request, cancellationToken).ContinueWith(t =>
        {
            HttpResponseMessage resp = t.Result;
            // III. do some stuff once finished
            // e.g.:
            // SetHeaders(resp, principal);

            return resp;
        });
    }
Run Code Online (Sandbox Code Playgroud)

这是将其注入结构的方法:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MessageHandlers.Add(new AuthenticationDelegationHandler());
Run Code Online (Sandbox Code Playgroud)

  • 我确实理解你的观点。我只是想根据我的经验向您展示如何...。委托处理程序对于任何基本的东西(如 CORS、Auth)都工作得很好......其余的我们使用 AOP......但正如我所说......只是想向您展示另一种方法来做到这一点;) (2认同)