C# 为什么我的HttpApplication实例变量为空?

C# 为什么我的HttpApplication实例变量为空?,c#,asp.net-mvc-3,httpcontext,C#,Asp.net Mvc 3,Httpcontext,我有一个MVC3应用程序,其中添加了两个简单的缓存变量作为属性。我在Application\u Start中添加数据,然后在控制器中尝试将HttpContext.ApplicationInstance转换回我的类型以访问它。但是,属性总是空的。下面是一个例子: 编辑为工作示例 public interface IMyMvcApp { Hashtable Cache {get;set;} } public class MvcApplication: HttpApplication, I

我有一个MVC3应用程序,其中添加了两个简单的缓存变量作为属性。我在
Application\u 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);
    }
}

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

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

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

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

除了Darin推荐内置缓存的正确答案之外,还有一个关于Asp.Net中的单例的注释

mvcapapplication不是单例应用程序

与人们普遍认为的相反,MVCapapplication并不是一个全局单例。该类被实例化多次,每个“管道”一个实例,因此性能计数器“管道实例计数”告诉您当前有多少MVCAPApplication实例处于活动状态。添加一个默认的ctor并亲自证明:

public MvcApplication()
{
    Trace.WriteLine(this.GetHashCode());
}
调试中断行或在DebugViewer中查看各种哈希代码。为了强制管道实例计数上升,请使用Thread.Sleep(5000)创建一个方法,然后,当您并行发出另一个http请求时,Asp.Net将启动一个新实例

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

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

然后,用户可以访问这些字段

MvcApplication.MySingleValue
  • 很明显
HttpApplication怪诞

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

protected void Application_Start()
{
}
请注意,没有涉及覆盖


总之,应用程序实例在大多数情况下可能是次要的,我看不到任何场景,如果它与保持状态相关,因为它的状态将由处理的请求的任意子集共享。因此,以Matt提到的完全好的方式访问它可能不需要太多时间。

我现在记得,我的mvc应用程序实现只是命中了get accessor中的缓存。缓存通常不是应用程序长寿命对象的合适存储位置。任何类(如应用程序类)上的静态字段或属性可能更准确。