如何初始化自定义HTTP上下文或HttpContextBase

时间:2012-01-02 13:31:48

标签: c# asp.net httpcontext

我正在尝试创建自己的自定义HTTP上下文:

CustomHttpContext : HttpContextBase
{
    public override HttpRequestBase Request { }
}

我无法弄清楚的一件事是如何使用

初始化基类
System.Web.HttpContext.Current

有没有人有任何想法我如何首先使用Current Http初始化自定义上下文然后覆盖某些方法/属性以达到我自己的目的?

2 个答案:

答案 0 :(得分:8)

简单的答案是否定的,这是不可能的。另请注意,HttpContext不会从HttpContextBase继承,相反,它们都实现了IServiceProvider。最后,HttpContext被封存,表明作者不希望别人做任何事情而不是消费这个类。

毫无疑问,你被HttpContextBase所困扰,它有一个无参数构造函数,所以甚至不能让你从当前的请求和响应中实例化它,就像HttpContext一样!

让我们用'decompiler'来看看HttpContext.Current的实现:

// System.Web.HttpContext
/// <summary>Gets or sets the <see cref="T:System.Web.HttpContext" /> object for the current HTTP request.</summary>
/// <returns>The <see cref="T:System.Web.HttpContext" /> for the current HTTP request.</returns>
public static HttpContext Current
{
    get
    {
        return ContextBase.Current as HttpContext;
    }
    set
    {
        ContextBase.Current = value;
    }
}

如果我们看看ContextBase.Current(来自System.Web.Hosting.ContextBase):

// System.Web.Hosting.ContextBase
internal static object Current
{
    get
    {
        return CallContext.HostContext;
    }
    [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
    set
    {
        CallContext.HostContext = value;
    }
}

和CallContext(在System.Runtime.Messaging中):

// System.Runtime.Remoting.Messaging.CallContext
/// <summary>Gets or sets the host context associated with the current thread.</summary>
/// <returns>The host context associated with the current thread.</returns>
/// <exception cref="T:System.Security.SecurityException">The immediate caller does not have infrastructure permission. </exception>
public static object HostContext
{
    [SecurityCritical]
    get
    {
        IllogicalCallContext illogicalCallContext = Thread.CurrentThread.GetIllogicalCallContext();
        object hostContext = illogicalCallContext.HostContext;
        if (hostContext == null)
        {
            LogicalCallContext logicalCallContext = CallContext.GetLogicalCallContext();
            hostContext = logicalCallContext.HostContext;
        }
        return hostContext;
    }
    [SecurityCritical]
    set
    {
        if (value is ILogicalThreadAffinative)
        {
            IllogicalCallContext illogicalCallContext = Thread.CurrentThread.GetIllogicalCallContext();
            illogicalCallContext.HostContext = null;
            LogicalCallContext logicalCallContext = CallContext.GetLogicalCallContext();
            logicalCallContext.HostContext = value;
            return;
        }
        LogicalCallContext logicalCallContext2 = CallContext.GetLogicalCallContext();
        logicalCallContext2.HostContext = null;
        IllogicalCallContext illogicalCallContext2 = Thread.CurrentThread.GetIllogicalCallContext();
        illogicalCallContext2.HostContext = value;
    }
}

我们开始了解如何检索HttpContext。它正在打包当前用户访问网站时开始的线程(这非常有意义!)。进一步研究我们可以看到它也会根据请求重新创建(见下文)。

我们还可以看到,在接口层,HttpContext.Current无法更改为指向您自己的HttpContext,因为该属性不是虚拟的。它还使用了许多私有或内部的BCL类,因此您不能简单地复制大部分实现。

使用自己的CustomContext对象简单地包装HttpContext会更容易,也更不容易出现任何其他问题。您可以简单地将HttpContext.Current包装在BaseContext属性中,然后在类上拥有您自己的属性(并使用您要存储和检索自己的属性的任何基于会话,数据库或请求的状态存储机制)。

就个人而言,我会使用自己的类来存储我自己的信息,因为它属于我的应用程序和用户等,并且与http管道或请求/响应处理没有任何关系。

另见:

答案 1 :(得分:0)

只需在dash的答案中添加一些内容,您也可以将[ThreadStatic]属性与一些静态属性一起使用。在BeginRequest上初始化它,可以使用global.cs,也可以编写自己的HttpModule / HttpHandler。

如何创建网络模块: http://msdn.microsoft.com/en-us/library/ms227673(v=vs.100).aspx

线程静态: http://msdn.microsoft.com/en-us/library/system.threadstaticattribute.aspx