我一直在为ASP.NET Core API编写一些日志服务 我写了一个中间件,它将记录每个被调用的动作(交叉关注,似乎合乎逻辑)。
我想记录的一件事是用户的IP(例如)。
我能想到获取数据的唯一方法是HttpContext.Connection
它按预期工作。
But lately I've been reading更多关于它的信息,我理解在控制器外部访问HttpContext
被认为是一种不好的做法。
它使代码无法测试,因为它很难模仿和模仿
此外,代码不能移植到其他.NET应用程序,并且必须存在于ASP.NET应用程序的上下文中。
所以我的问题是 - 在控制器之外使用HttpContext真是太糟糕了吗 - 例如在中间件中? 如果是这样的话 - 还有什么选择?
或者在ASP.NET中使用的组件(例如TOP级控制器或中间件)中使用HttpContext
是合法的。
感谢。
答案 0 :(得分:3)
在控制器之外的ASP.NET核心中使用HttpContext类的实例是完全没问题的。特别是在没有表示当前请求的HttpContext
实例的情况下编写中间件将毫无用处。
主要区别在于您不应该在ASP.NET HttpContext.Current
类型的思维中使用像System.Web
这样的静态访问器。您引用的博客文章是关于如何在ASP.NET Core中模仿这个,如果您现有的大部分代码依赖于此。在ASP.NET核心术语中,上下文的实例将传递给中间件的Invoke方法,或者您可以使用依赖注入来访问IHttpContextAccessor
对象。
在ASP.NET Core Docs中查看此示例。 HttpContext
作为参数名context
注入,因此无需依赖HttpContext.Current
之类的静态访问器。特别是这更容易测试,因为您可以在单元测试中创建自己的HttpContext
实例,并将其传递给Invoke
方法。
public class RequestCultureMiddleware
{
private readonly RequestDelegate _next;
public RequestCultureMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
// Call the next delegate/middleware in the pipeline
return this._next(context);
}
}