在 Controller 之外使用 HttpContext - 不好的做法?
Using HttpContext outside of a Controller - Bad practice?
我一直在为我的 ASP.NET Core API 编写一些日志记录服务。
我写了一个 middleware 来记录每个被调用的动作(横切关注点,看起来合乎逻辑)。
我想记录的其中一件事是用户的 IP(例如)。
我能想到的获取数据的唯一方法是通过 HttpContext.Connection
.
它按预期工作。
But lately I've been reading 更多关于它的信息,我知道在控制器外部访问 HttpContext
被认为是一种不好的做法。
它使代码不可测试,因为它很难模拟和模仿。
此外,代码不可移植到 other.NET 应用程序,必须存在于 ASP.NET 应用程序的上下文中。
所以我的问题是 - 在控制器外部使用 HttpContext 真的是一种糟糕的做法 - 例如在中间件内部吗?
如果是这样 - 还有什么选择?
或者在 ASP.NET(例如顶级控制器或中间件)中使用的组件内部使用 HttpContext
是合法的。
谢谢。
在控制器外部的 ASP.NET 核心中使用 HttpContext class 的实例完全没问题。特别是如果没有代表当前请求的 HttpContext
实例,编写中间件将毫无用处。
主要区别是您不应该在 ASP.NET System.Web
的思路中使用 静态访问器 ,如 HttpContext.Current
。您引用的博客 post 是关于如何在 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);
}
}
我一直在为我的 ASP.NET Core API 编写一些日志记录服务。
我写了一个 middleware 来记录每个被调用的动作(横切关注点,看起来合乎逻辑)。
我想记录的其中一件事是用户的 IP(例如)。
我能想到的获取数据的唯一方法是通过 HttpContext.Connection
.
它按预期工作。
But lately I've been reading 更多关于它的信息,我知道在控制器外部访问 HttpContext
被认为是一种不好的做法。
它使代码不可测试,因为它很难模拟和模仿。
此外,代码不可移植到 other.NET 应用程序,必须存在于 ASP.NET 应用程序的上下文中。
所以我的问题是 - 在控制器外部使用 HttpContext 真的是一种糟糕的做法 - 例如在中间件内部吗?
如果是这样 - 还有什么选择?
或者在 ASP.NET(例如顶级控制器或中间件)中使用的组件内部使用 HttpContext
是合法的。
谢谢。
在控制器外部的 ASP.NET 核心中使用 HttpContext class 的实例完全没问题。特别是如果没有代表当前请求的 HttpContext
实例,编写中间件将毫无用处。
主要区别是您不应该在 ASP.NET System.Web
的思路中使用 静态访问器 ,如 HttpContext.Current
。您引用的博客 post 是关于如何在 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);
}
}