Asp.net web api 使用Ninject在Web API中捕获和注入HttpRequestMessage
我有一个类需要访问Web API服务中的HttpRequestMessage。目前,我有以下代码来捕获管道中的消息并将其保存以备将来使用(基于和):Asp.net web api 使用Ninject在Web API中捕获和注入HttpRequestMessage,asp.net-web-api,ninject,Asp.net Web Api,Ninject,我有一个类需要访问Web API服务中的HttpRequestMessage。目前,我有以下代码来捕获管道中的消息并将其保存以备将来使用(基于和): 公共类ContextCapturingControllerActivator:IHttpControllerActivator { 私有只读IKernel内核; 私有HttpRequestMessage请求消息; 公共上下文CapturingControllerActivator(IKernel内核) { this.kernel=内核; } 公共I
公共类ContextCapturingControllerActivator:IHttpControllerActivator
{
私有只读IKernel内核;
私有HttpRequestMessage请求消息;
公共上下文CapturingControllerActivator(IKernel内核)
{
this.kernel=内核;
}
公共IHTTP控制器创建(HttpRequestMessage requestMessage,
HttpControllerDescriptor控制器描述器,
类型控制器类型)
{
this.kernel.Rebind()
.ToConstant(请求消息);
var controller=(IHttpController)this.kernel.GetService(controllerType);
this.requestMessage=requestMessage;
requestMessage.RegisterForDispose(
新版本(()=>this.kernel.Release(controller));
返回控制器;
}
私有类发布:IDisposable
{
私人只读操作发布;
公开发布(行动发布)
{
这个。释放=释放;
}
公共空间处置()
{
这个。释放();
}
}
}
在我的composition根目录中,我配置了ControllerActivator
:
kernel.Bind()
.To();
最终结果是,从配置的角度来看,HttpRequestMessage
被“神奇地”注入到任何被请求的地方,因为它是在ControllerActivator
中为我们完成的。我无法从我的合成根注入消息。我也不喜欢重新绑定,因为它可以避免每次调用服务时添加新绑定。我怀疑这是由于WebAPI堆栈的单例特性造成的,但是我还没有弄清楚如何正确处理它
一般来说,由于报告的错误(并被忽略),我无法使用Ninject web api的最新不稳定Nuget包
有没有人能提出改进我的代码的正确方法,让代码更清晰,让未来的维护人员的生活更轻松(让我们面对现实吧——我可能会这么做)
谢谢。以下是我所做的,但我相信这取决于Web API 2.0+ 我创建了一个实例类,用于包装当前上下文的http请求:
public class HttpRequestMessageWrapper
{
private readonly HttpRequestMessage m_httpRequestMessage;
public HttpRequestMessageWrapper()
{
m_httpRequestMessage = HttpContext.Current.Items["MS_HttpRequestMessage"] as HttpRequestMessage;
}
public HttpRequestMessage RequestMessage
{
get
{
return m_httpRequestMessage;
}
}
}
然后,我使用请求范围中的ToMethod绑定将HttpRequestMessage绑定到属性
container.Bind<HttpRequestMessage>().ToMethod(ctx => new HttpRequestMessageWrapper().RequestMessage).InRequestScope();
container.Bind().ToMethod(ctx=>newhttprequestmessagewrapper().RequestMessage).InRequestScope();
我尝试了@Mackers提出的最干净的方法。。。。然而,在我的特定场景中,由于时间问题,它无法工作。在我的例子中,我需要将一个对象注入apicontroller ctor,该对象需要HttpRequestMessage。在构造并初始化控制器之前,HttpContext.Current.Items[“MS_HttpRequestMessage”]
不会被填充,我找不到任何其他方法来访问它。因此,我求助于创建一个定制的DelegatingHandler,并在当前请求消息传入时重新绑定它们
public class CurrentHttpRequestMessageHandler : DelegatingHandler
{
[SecuritySafeCritical]
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
UpdateScopeWithHttpRequestMessage(request);
return base.SendAsync(request, cancellationToken);
}
internal static void UpdateScopeWithHttpRequestMessage(HttpRequestMessage request)
{
NinjectConfig.GetConfiguredKernel().Rebind<HttpRequestMessage>().ToMethod(ctx => { return request; })
.InRequestScope();
}
}
然后将DelegatingHandler注册到HttpConfiguration:
config.MessageHandlers.Add(new CurrentHttpRequestMessageHandler());
基于Macker的答案,System.Web提供了一个可以使用并简化代码单元测试的工具。在代码中需要请求的任何地方,指定HttpRequestBase类型作为构造函数参数,并使用以下方法注册它: 例如:
Bind<HttpRequestBase>().ToMethod(context => new HttpRequestWrapper(HttpContext.Current.Request));
Bind().ToMethod(context=>newhttprequestwrapper(HttpContext.Current.Request));
统一示例:
container.RegisterType<HttpRequestBase>(new InjectionFactory(_ => new HttpRequestWrapper(HttpContext.Current.Request)));
container.RegisterType(newinjectionfactory(=>newhttprequestwrapper(HttpContext.Current.Request));
我最近也不得不对Ninject(以前也是对StructureMap)做同样的事情,但还没有找到更好的解决方案。@BenFoster我后来改用了Autofac(出于许多原因,不仅仅是这个问题),虽然它提供了一种更干净的方式将HttpRequestMessage注入到运行的代码中,我在内存集成测试中无法访问它。因此,每个DI框架似乎都有自己独特的权衡。有什么突破吗?我有同样的问题…我有同样的问题。使用上述解决方案会导致我的CPU峰值达到100,因为绑定存储在静态字典中。当多个请求通过时,由于每个线程都试图枚举字典,因此它们正在争用(有人找到别的方法吗?@Hudvoy?@BenFoster?
container.RegisterType<HttpRequestBase>(new InjectionFactory(_ => new HttpRequestWrapper(HttpContext.Current.Request)));