Asp.net mvc 在控制器中注入HttpContextBase和IoC的目的是什么

Asp.net mvc 在控制器中注入HttpContextBase和IoC的目的是什么,asp.net-mvc,dependency-injection,inversion-of-control,castle-windsor,autofac,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()

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

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

// Again Autofac 
builder.RegisterModule(new AutofacWebTypesModule());
问题1: 您能解释一下包装HttpContextBase、HttpRequestBase等的原因吗

问题2: 注入的HttpContextBase与HttpContext(控制器属性)与System.Web.HttpContext.Current之间有什么区别

更新 问题3:
在代码中使用哪个HttpContext,注入的HttpContext,或者通过HttpContext和System.Web.HttpContext.Current调用它也很好?如果双向呼叫,是否有任何问题?

回答1

HttpContext
是一个臭名昭著的测试难题,因为它只存在于请求的上下文中。并有助于通过国际奥委会框架注入

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

从链接页面:

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

答案2

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

答案3


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

Hmm现在我知道这也是为了测试目的而做的。还有一个问题:如果有任何依赖的解决方案类库使用HttpContext.Current,那么我应该重构它们,以便从构造函数中使用HttpContextBase吗?是的,但您可以在将它们引入测试工具时逐步进行。只要您不尝试使用web堆栈外的类,问题就不存在,但一旦必须对它们进行测试,您就会遇到此问题,并且需要重构以解决此问题。下面是一个示例,使用StructureMap:
For()。使用(()=>new-HttpContextWrapper(HttpContext.Current))
// 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;
    }
    //....
}