在Controller之外使用HttpContext - 不好的做法?

时间:2017-04-02 08:08:51

标签: c# asp.net asp.net-web-api asp.net-core httpcontext

我一直在为ASP.NET Core API编写一些日志服务 我写了一个中间件,它将记录每个被调用的动作(交叉关注,似乎合乎逻辑)。

我想记录的一件事是用户的IP(例如)。 我能想到获取数据的唯一方法是HttpContext.Connection 它按预期工作。

But lately I've been reading更多关于它的信息,我理解在控制器外部访问HttpContext被认为是一种不好的做法。 它使代码无法测试,因为它很难模仿和模仿 此外,代码不能移植到其他.NET应用程序,并且必须存在于ASP.NET应用程序的上下文中。

所以我的问题是 - 在控制器之外使用HttpContext真是太糟糕了吗 - 例如在中间件中? 如果是这样的话 - 还有什么选择?

或者在ASP.NET中使用的组件(例如TOP级控制器或中间件)中使用HttpContext是合法的。

感谢。

1 个答案:

答案 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);
    }
}