c# – 装饰ASP.NET Web API IHttpController

前端之家收集整理的这篇文章主要介绍了c# – 装饰ASP.NET Web API IHttpController前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试使用装饰器来包装Web API控制器(IHttpController实现),但是当我这样做时,Web 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);
    }
}

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

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);
    }
}

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

Unable to cast object of type ‘WebApiTest.MyHttpControllerDecorator’
to type ‘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)

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

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

解决方法

我会说,如何在ASP.NET Web API中实现此行为的自然设计方式是使用 Custom Message Handlers / Delegation Handlers

例如,我确实有这个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;
        });
    }

这就是如何将其注入结构:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MessageHandlers.Add(new AuthenticationDelegationHandler());

猜你在找的C#相关文章