【问题标题】:How do I get an HttpContext object from HttpContextBase in ASP.NET MVC 1?如何从 ASP.NET MVC 1 中的 HttpContextBase 获取 HttpContext 对象?
【发布时间】:2010-12-31 19:38:47
【问题描述】:

我正在使用一些与 WebForms/MVC 无关的工具,并且我需要在给定 HttpContextBase 对象的引用的情况下获取 HttpContext 的实例。我不能使用HttpContext.Current,因为我也需要它以异步方式工作(HttpContext.Current 在异步请求期间返回null)。我知道HttpContextWrapper,但走错路了。

【问题讨论】:

    标签: asp.net-mvc httpcontext


    【解决方案1】:

    你不能。

    HttpContextBase 的全部目的是抽象出对具体 HttpContext 类的依赖。虽然它可能包含一个具体的HttpContext(例如httpContextWrapper的情况),但其他实现可能与HttpContext完全无关。 p>

    您最好的选择是定义一个可以为您获取HttpContextBase 的自定义抽象工厂,因为您始终可以将具体的HttpContext 包装在HttpContextWrapper 中。

    【讨论】:

    • 顺便说一句,这做得很糟糕——我知道想要为单元测试设置一个设置,而且我理解抽象层——但是当你想使用现有的 ASP 时你应该这样做.NET 类需要 HttpContext? (如msdn.microsoft.com/en-us/library/…
    • 是的,要测试 IHttpHandler 实现,您最终不得不在(响应包装器)中放置大量抽象来进行单元测试,这感觉不对,但最终成为唯一的选择.
    【解决方案2】:

    你可以,

    var abstractContext = new System.Web.HttpContextWrapper(System.Web.HttpContext.Current);
    

    【讨论】:

    • -1 这是错误的方式,当你有上下文时,这会给你基础,而不是相反。
    【解决方案3】:

    最简单的方法是获取应用程序ApplicationInstance,并使用其Context 属性:

    // httpContextBase is of type HttpContextBase
    HttpContext context = httpContextBase.ApplicationInstance.Context;
    

    (感谢Ishmael Smyrnow 在 cmets 中注意到这一点)

    原答案:

    您可以,尤其是当您收到的HttpContextBase 实例在运行时是HttpContextWrapper 类型时。以下示例说明了如何执行此操作。它假设您有一个名为Foo 的方法,它接受上下文为HttpContextBase,但随后需要调用第三方程序集(您可能没有好运来修改)中的一个方法,该方法期望输入上下文作为HttpContext

    void Foo(HttpContextBase context) 
    {
        var app = (HttpApplication) context.GetService(typeof(HttpApplication));
        ThirdParty.Bar.Baz(app.Context);
    }
    
    // Somewhere in assembly and namespace ThirdParty,
    // in a class called Bar, there is Baz expecting HttpContext:
    
    static void Baz(HttpContext context) { /* ... */ }
    

    HttpContextBase 有一个名为GetService 的方法,因为它支持IServiceProviderGetService 覆盖 HttpContextWrapper 代表包装 HttpContext 实例的 GetService 实现。 GetServiceHttpContext 实现允许您查询常见的嫌疑人,如 HttpApplicationHttpRequestHttpResponse 等。碰巧HttpApplication 有一个名为Context 的属性,它返回一个HttpContext 的实例。因此,通过GetServiceHttpContextBase 询问HttpApplication,然后读取返回的HttpApplication 实例的Context 属性,即可获得包装好的HttpContext 实例。

    HttpContextBase 不同,GetService 不会作为HttpContext 的公共成员出现,但这是因为HttpContext 明确实现了IServiceProvider.GetServiceHttpContextBase 没有。

    请记住,Foo 不再是可测试的,因为它依赖于能够在测试期间解开底层的HttpContext,而这几乎是不可能伪造/存根的。然而,这个答案的重点是解决这个问题,“我如何从 HttpContextBase 获取 HttpContext 对象?”,字面意思。当您发现自己被夹在您不一定有权修改的组件之间时,图示的技术非常有用。

    【讨论】:

    • 非常有趣的答案,我自己在 MVC 中使用它来将 HttpContext 从错误过滤器传递给 ELMAH 进行日志记录。
    • 不错的答案,打赌这需要一些挖掘? :)
    • 很好的答案!我特别在我的 Elmah 到 MVC 控制器中使用了它github.com/alexanderbeletsky/elmah.mvc.controller/blob/master/…
    • 有了HttpContextBase,你不能打电话给context.ApplicationInstance.Context吗?
    • @IshmaelSmyrnow 该死,在HttpContextBase 返回的所有Http*Base 变体中,不要错过了。 :P 我会更新答案。
    猜你喜欢
    • 2018-02-14
    • 1970-01-01
    • 2020-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多