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

Cri*_* E. 5 asp.net-mvc dependency-injection castle-windsor inversion-of-control autofac

我已经看到许多使用IoC容器的代码示例,注册如下:

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

// Again Autofac 
builder.RegisterModule(new AutofacWebTypesModule());
Run Code Online (Sandbox Code Playgroud)

(请参阅此处的AutofacWebTypesModule的src )

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

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

public class HomeController : Controller
{
    private readonly HttpContextBase _httpContext;

    public HomeController(HttpContextBase httpContext)
    {
        _httpContext = httpContext;
    }
    //....
}
Run Code Online (Sandbox Code Playgroud)

问题1:

你能解释一下包装HttpContextBase,HttpRequestBase等的原因吗?

问题2:

注入的HttpContextBaseHttpContext(Controller的属性)与System.Web.HttpContext.Current之间的区别是什么?

更新

问题3:

在代码中使用哪个HttpContext,Injected One或者它也可以通过HttpContextSystem.Web.HttpContext.Current调用它?如果两种方式都有问题吗?

sam*_*amy 4

答案1

HttpContext在测试方面这是众所周知的痛苦,因为它只存在于请求的上下文中。由于 .net 3.5HttpContextBase是 IOC 框架的抽象HttpContext并适合通过 IOC 框架注入

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

从链接页面:

HttpContextBase 类是一个抽象类,包含与 HttpContext 类相同的成员。HttpContextBase 类使您能够创建类似于 HttpContext 类的派生类,但您可以自定义该类,并且该类在 ASP.NET 管道之外工作。执行单元测试时,通常使用派生类来实现具有自定义行为的成员,以满足您正在测试的场景。

答案2

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

答案3

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