使用IoC在Controller中注入HttpContextBase的目的是什么?

时间:2014-09-19 14:23:08

标签: asp.net-mvc dependency-injection inversion-of-control castle-windsor autofac

我见过很多使用IoC容器的代码示例,其注册如下:

// Autofac
builder.Register(c => new HttpContextWrapper(HttpContext.Current))
            .As<HttpContextBase>()
            .InstancePerRequest();

// Again Autofac 
builder.RegisterModule(new AutofacWebTypesModule());

(参见src for AutofacWebTypesModule HERE

// Castle Windsor
container.Register(Component.For<HttpContextBase()
                  .LifeStyle.PerWebRequest
                  .UsingFactoryMethod(() => new HttpContextWrapper(HttpContext.Current)));

与使用构造函数注入的控制器一起:

public class HomeController : Controller
{
    private readonly HttpContextBase _httpContext;

    public HomeController(HttpContextBase httpContext)
    {
        _httpContext = httpContext;
    }
    //....
}

问题1:

请解释一下包装HttpContextBase,HttpRequestBase等的原因..?

问题2:

注入的HttpContextBase HttpContext (Controller的属性)vs System.Web.HttpContext.Current

更新

问题3:

在代码中使用哪个HttpContext,注入一个,或者通过 HttpContext System.Web.HttpContext.Current ?如果双向调用会有任何问题吗?

1 个答案:

答案 0 :(得分:4)

回答1

HttpContext在测试方面是一个臭名昭着的痛苦,因为它只存在于请求的上下文中。 Since .net 3.5 HttpContextBase is an abstraction of HttpContext并且有助于通过IOC框架注入

通过让IOC容器处理它,您可以注册在测试时注入组件的不同/确定性实例。在普通代码中,您将注入HttpContextWrapper,这是默认实现

从链接页面:

  

HttpContextBase类是一个包含相同内容的抽象类   成员作为HttpContext类。 HttpContextBase类启用   你可以创建类似于HttpContext类的派生类,但是   您可以自定义并在ASP.NET管道外工作。   执行单元测试时,通常使用派生类   实现具有满足方案的自定义行为的成员   你正在测试。

回答2

注入的HttpContextBase将返回测试成功所需的数据:特定的查询字符串,特定的查询等。通常注入的实现只包含测试所需的方法,忽略所有其他的,例如上下文.User.Identity.Name属性,以便测试身份验证。

回答3

在代码中,您必须始终使用注入的HttpContextBase,因为您不希望依赖于在测试时可能失败的具体实现。如果同时调用两种方式,您可能会遇到问题,尤其是在测试中,因为HttpContext.Current将返回null。