- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我试图用装饰器包装 Web API Controller (IHttpController
实现),但是当我这样做时,Web API 抛出异常,因为不知何故它期待实际的实现。
将装饰器应用于 Controller 是我成功应用于 MVC Controller 的一个技巧,显然我喜欢在 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 Controller ?
最佳答案
我想说的是,如何在 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;
});
}
这是将其注入(inject)结构的方法:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new AuthenticationDelegationHandler());
关于c# - 装饰 ASP.NET Web API IHttpController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20444059/
虽然我已经使用 Microsoft .NET Framework 多年,但对于 ASP.NET,尤其是 ASP.NET WebAPI Framework,我还是个新手。我正在考虑为一个小项目使用 AS
我试图用装饰器包装 Web API Controller (IHttpController 实现),但是当我这样做时,Web API 抛出异常,因为不知何故它期待实际的实现。 将装饰器应用于 Cont
我是一名优秀的程序员,十分优秀!