【问题标题】:Why are my HttpApplication instance variables null?为什么我的 HttpApplication 实例变量为空?
【发布时间】:2011-11-22 17:20:36
【问题描述】:

我有一个 MVC3 应用程序,我在其中添加了几个简单的缓存变量作为属性。我在Application_Start 中添加我的数据,然后在控制器中尝试将HttpContext.ApplicationInstance 转换回我的类型以访问它。但是,该属性始终为空。这是一个例子:

编辑工作示例

public interface IMyMvcApp
{
    Hashtable Cache {get;set;}
}


public class MvcApplication: HttpApplication, IMyMvcApp
{

    public Hashtable Cache 
    {
        get { return Context.Cache["MyStuff"] as Hashtable; }
        set { Context.Cache["MyStuff"] = value}
    }

    public void Application_Start()
    {
        Cache = new Hashtable();
        Cache.Add("key", new object());
    }
}

public class AController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext context)
    {
        var myApp = context.HttpContext.ApplicationInstance as IMyMvcApp;

        Assert.IsNotNull(myApp.Cache);
    }
}

【问题讨论】:

    标签: c# asp.net-mvc-3 httpcontext


    【解决方案1】:

    框架创建的应用程序有多个实例。要验证这一点,请添加一个空构造函数并在其中放置一个断点。您将看到此构造函数将被多次命中,而 Application_Start 仅被命中一次。

    因此,您应该使用框架中已经内置的 Cache 对象,而不是重新发明轮子:

    protected void Application_Start()
    {
        ...
        Context.Cache["key"] = new object();
    }
    

    然后:

    protected override void OnActionExecuting(ActionExecutingContext context)
    {
        var value = context.HttpContext.Cache["key"];
    }
    

    【讨论】:

    • 我现在记得,我的 mvc 应用程序的实现只是访问了 get 访问器中的缓存。呵呵
    • 使用缓存通常不是应用程序长期对象的适当存储位置。任何类(如 Application 类)上的静态字段或属性可能更准确。
    【解决方案2】:

    除了 Darin 的正确答案推荐内置缓存之外,还有一个关于 Asp.Net 中Singletons的说明。

    MvcApplication 不是单例

    与非常普遍的看法相反,MvcApplication 不是全局单例。该类被实例化了多次,每个“管道”一个实例,因此性能计数器“管道实例计数”告诉您当前有多少 MvcApplication 实例被认为是活动的。添加一个默认 ctor 并自己证明这一点:

    public MvcApplication()
    {
        Trace.WriteLine(this.GetHashCode());
    }
    

    调试断线或查看 DebugViewer 中的各种哈希码。要强制增加管道实例计数,请使用 Thread.Sleep(5000) 创建一个方法,一旦您并行发出另一个 http 请求,Asp.Net 就会启动一个新实例。

    解决方案 - 如何在 Asp.Net 应用程序(MVC 或 WebForms)中实例化单例

    如果你的 MvcApplication 类有一个 Application_Start() 方法,那么这个方法实际上只被调用一次,进程范围。这允许将静态字段添加到 MvcApplication 并访问它们。

    这些字段然后被访问

    MvcApplication.MySingleValue
    
    • 显然。

    HttpApplication 怪异

    HttpApplication 类及其事件的设计非常奇怪,这可能是因为它对非常古老的基于 COM 的 ASP 页面的某种松散的向后设计兼容性。应用程序对象实际上只创建了一次,这肯定是与 Asp.Net 相关的错误信念的根源。 HttpApplication 奇怪的一个例子:

    protected void Application_Start()
    {
    }
    

    请注意,不涉及覆盖!

    总而言之,应用程序实例在大多数情况下可能并不重要,我认为没有任何情况可以与保持状态相关,因为它的状态将由处理的请求的任意子集共享。因此,可能不需要太频繁地以 Matt 提到的完全好的方式访问它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-23
      • 2012-08-17
      • 2015-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多