【问题标题】:Using HttpContext outside of a Controller - Bad practice?在控制器之外使用 HttpContext - 不好的做法?
【发布时间】:2017-04-02 08:08:51
【问题描述】:

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

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

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

所以我的问题是 - 在控制器外部使用 HttpContext 真的是一种糟糕的做法吗 - 例如在中间件内部?
如果是这样 - 还有什么选择?

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

谢谢。

【问题讨论】:

  • 视情况而定。如果您在域层(=域服务)中引用它,那么这绝对是您能做的最糟糕的事情之一,因为域不能对基础设施(db、webservice、asp.net、wpf、uwp 等主机)有任何依赖关系.)。如果它用在应用层(=应用服务)上没关系。不同之处在于,应用程序级别与应用程序相关联,几乎或根本不可移植(即访问 httpcontext 信息,它无法在 WPF 上工作,因为没有 httpcontext)
  • @Tseng,是的,我是这么想的。这就是为什么我问是否可以在顶级控制器和中间件中使用它——这意味着任何必须存在于 ASP.Net 范围内的代码

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


【解决方案1】:

在控制器之外的 ASP.NET 核心中使用 HttpContext 类的实例是完全可以的。尤其是如果没有代表当前请求的HttpContext 实例,编写中间件将毫无用处。

主要区别在于您不应该在 ASP.NET System.Web 类型的思维中使用像 HttpContext.Current 这样的静态访问器。如果您的大部分现有代码都依赖于此,您引用的博客文章是关于如何在 ASP.NET Core 中模仿这一点。在 ASP.NET Core 术语中,上下文的实例被传递给中间件的 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);
    }
}

【讨论】:

  • 如你所说,我注意到HttpContext 参数被传递给中间件,这就是我能够获取客户端远程IP 地址的方式。我没有注意到使用HttpContext 的实例和使用静态HttpContext.Current 之间的细微差别。所以谢谢你让我放心。
猜你喜欢
  • 1970-01-01
  • 2010-12-27
  • 1970-01-01
  • 1970-01-01
  • 2010-09-26
  • 1970-01-01
  • 2011-06-19
  • 2019-06-15
  • 2016-12-16
相关资源
最近更新 更多