有很多关于使用 IHttpContextAccessor 在 DI 服务中注入用户信息的信息。不过该界面有警告,建议谨慎使用。
该接口需谨慎使用。它依赖于 AsyncLocal,这可能会对异步调用产生负面性能影响。它还创建了对“环境状态”的依赖,这会使测试变得更加困难。
我认为有人要告诉我的是,注入用户信息是一种代码味道,我应该硬着头皮将其从控制器传递下来?或者我可以在中间件中做一些事情吗?
非常感谢,
詹姆斯
在 .NET(Core)的当前实现中,关于
AsyncLocal
(默认 IHttpContextAccessor
实现背后的机制)的使用,需要考虑一些事项:
AsyncLocal
的状态,导致 IHttpContextAccessor
失去对当前 HttpContext
对象的引用。过去三年我一直在跟踪这个问题。我和许多其他人一直在敦促微软解决这个问题,但到目前为止,微软还没有可用的解决方案。甚至没有 CaptureExecutionContextOnAsyncEnumeration=true
配置开关,或者如果他们喜欢 CaptureExecutionContextOnAsyncEnumerationAndYesIUnderstandThePerformanceImpact=true
。请注意,虽然文档确实说明了负面性能影响,但实际上没有警告更重要的正确性问题。
不幸的是,文档还指出:
它还会产生对“环境状态”的依赖,这会使测试变得更加困难。
然而,在我看来,这种说法是错误的。虽然
HttpContextAccessor
实现依赖于 AsyncLocal
以及“环境状态”,但类依赖于 IHttpContextAccessor
抽象,并且这个抽象可以被替换(这是 DI 的承诺),这不会限制测试以任何有意义的方式。我不确定这个声明是如何泄漏到文档中的。我怀疑这源自 .NET 的一位首席架构师的意见。早在 2017 年,我就与那位架构师进行了一次关于环境状态和可测试性主题的“讨论”。在那次讨论中,您可以看到我们支持和反对的论点。阅读讨论并表达您自己的意见。
我什至会更进一步说,你的 application 组件无论如何都不应该依赖于 IHttpContextAccessor
,因为它将它们耦合到
HttpContext
。相反,它们应该依赖于应用程序定制的抽象。在应用程序的启动路径中,您可以为那些依赖于 HttpContextAccessor
的应用程序定制抽象提供适配器实现。