在ASP.net MVC中,控制器实例上的HttpContext为空

29

这可能不是使用控制器的正确方法,但我确实注意到了这个问题,而且还没有找到纠正它的方法。

public JsonResult SomeControllerAction() {

    //The current method has the HttpContext just fine
    bool currentIsNotNull = (this.HttpContext == null); //which is false    

    //creating a new instance of another controller
    SomeOtherController controller = new SomeOtherController();
    bool isNull = (controller.HttpContext == null); // which is true

    //The actual HttpContext is fine in both
    bool notNull = (System.Web.HttpContext.Current == null); // which is false        

}

我注意到控制器上的HttpContext并不是您在System.Web.HttpContext.Current中找到的“实际”HttpContext。

是否有一种方法可以手动填充控制器上的HttpContextBase?或者有更好的方法来创建控制器的实例吗?

5个回答

64

目前我将执行以下操作。这似乎是一个可接受的修复方案...

public new HttpContextBase HttpContext {
    get {
        HttpContextWrapper context = 
            new HttpContextWrapper(System.Web.HttpContext.Current);
        return (HttpContextBase)context;                
    }
}

当将此代码添加到控制器类中时,这些控制器将从中继承。

我不确定HttpContext为null是否是期望的行为,但目前这将为我解决问题。


非常感谢您解密了两种类型之间的新工作方式。我有一个旧类,我试图从MVC控制器中使用它来消耗HttpContext对象。现在我有一个类,它使用一个HttpContextBase对象,并具有一个构造函数重载,可以使用您提到的HttpContextWrapper构造函数在HttpContext和HttpContextBase之间进行转换。 - patridge
+1 这是一个很棒的代码片段!我稍微添加了一点内容。我用一个ContextHelper类包装了你的包装器,它只公开了我从你的底层HttpContext属性中所需的属性,以便我可以创建我的ContextHelper的模拟。StructureMap允许我交换我需要的内容。然后我创建了一个WebSite对象作为视图API,它在各种基类的视图、控制器等中都有暴露。如果您不介意的话,我会在我的书(ASP.NET MVC Cookbook)中提到这个:http://groups.google.com/group/aspnet-mvc-2-cookbook-review - Andrew Siemer
@Hugoware (HttpContextBase) 的转换是多余的,请将其删除。 - Andrus
这个怎么使用呢?我想从除了账户控制器之外的另一个控制器中将用户添加到角色中。 - Nathan McKaskle

25

控制器不是像你现在这样手动创建的。听起来你真正应该做的是将任何可重复使用的逻辑放到一个帮助类中。


1
Brad,你有没有什么地方可以帮助理解MVC设计和最佳实践?到目前为止,MVC一直很酷,但我找到的大多数示例都不是非常复杂。它们只涉及简单的情况,比如更新单个记录。 - hugoware
Brad,我遇到了同样的问题,这也是来自一个助手类,就像你推荐的一样。我尝试了Hugoware提供的修复方法(如下),并且它解决了我的问题。这样做是正确的方式吗? - Mark Kadlec

5
在ControllerContext中,HttpContext为空,因为在控制器创建时没有设置。控制器的构造函数没有分配这个属性,所以它将为空。通常,HttpContext被设置为ControllerBuilder类的HttpContext。控制器由ControllerBuilder类创建,然后是DefaultControllerFactory。当您想创建自己的控制器实例时,可以使用控制器的ExecuteMethod和自己的ControllerContext。在真实应用程序中不建议这样做。当您熟悉该框架并找到适当的方法时,您会发现想要的东西。在单元测试中需要ControllerContext时,可以使用模拟框架来模拟ControllerContext或者可以对其进行类伪造。
您可以在此博客上找到asp.net mvc请求流的模型:链接
当你刚接触Asp.net mvc时,值得花时间下载源代码并跟踪请求处理的路线。

0

你是想从控制器中使用某些功能吗?还是让控制器执行一个操作?

如果是前者,也许这段代码应该拆分成另一个类。如果是后者,你可以这样做,让控制器执行特定的操作:


return RedirectToAction("SomeAction", "SomeOtherController", new {param1 = "Something" });


0
你是否正在使用控制器工厂?如果是,那么你是如何注册组件的?
我遇到了一个问题,我不小心将基于HttpContext的依赖项添加为单例而不是Windsor中的瞬态。
HttpContext 对所有请求都为空,除了第一个请求。我花了一段时间才追踪到这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接