调用HttpContext.Request时如何避免HttpException?

Sim*_*mon 13 c# asp.net httpcontext

因此,如果在全局启动内调用,则抛出HttpContext.Request

public HttpRequest get_Request()
{
    if (this.HideRequestResponse)
    {
        throw new HttpException(SR.GetString("Request_not_available"));
    }
    return this._request;
}
Run Code Online (Sandbox Code Playgroud)

这实际上已记录在案

如果在HttpRequest对象不可用时尝试使用此属性,ASP.NET将引发异常.例如,在Global.asax文件的Application_Start方法中或在从Application_Start方法调用的方法中都是如此.那时还没有创建HTTP请求.

有没有办法检查HttpContext.Request是否处于可以检索而不抛出异常的状态?实际上我想写一个TryGetRequest帮助方法.

  • 反思不是一种选择.它需要是一个公共API.
  • 我无法访问应用程序上下文.这是通用的日志记录代码.因此,在启动完成时设置一些标志不是一种选择

Joe*_*son 5

正如deostroll观察到的那样,这是合理的,实际上可能有必要依靠ASP.NET应用程序生命周期来确定当前HttpRequest何时可用。通用日志记录代码至少在HttpContext.Current某种程度上取决于当前HttpContext实例。如果该假设成立,则HttpModule可以实现,HttpContext.ItemsBeginRequest事件触发时在集合中存储一个标志。静态TryGetRequest辅助方法可以测试该标志的存在,以确定是否可以安全使用HttpContext.Request

也许像这样:

public class HttpRequestHelper : IHttpModule
{
    private const string HttpRequestIsAvailable = "HttpRequestIsAvailable";

    public static bool TryGetRequest(HttpContext context, out HttpRequest request)
    {
        request = null;
        if (context != null)
        {
            if (context.Items.Contains(HttpRequestIsAvailable))
                request = context.Request;
        }
        return (request != null);
    }

    #region IHttpModule

    public void Dispose()
    {
    }

    public void Init(HttpApplication context)
    {
        context.BeginRequest += context_BeginRequest;
    }

    private void context_BeginRequest(object sender, EventArgs e)
    {
        ((HttpApplication)sender).Context.Items.Add(HttpRequestIsAvailable, true);
    }

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

该模块必须在web.config中注册(假设IIS 7.0集成管道):

  <system.webServer>
    <modules>
      <add name="HttpRequestHelper" type="Utility.HttpRequestHelper" />
    </modules>
  </system.webServer>
Run Code Online (Sandbox Code Playgroud)

日志记录代码将使用如下的helper方法:

HttpRequest request;
if (HttpRequestHelper.TryGetRequest(HttpContext.Current, out request))
    LogWithRequest(request, message);
else
    LogWithoutRequest(message);
Run Code Online (Sandbox Code Playgroud)

该实现不依赖于私有API或反射。它依赖于标志,但是状态信息保留在HttpContext实例中,并且封装得很好。


Sim*_*mon 1

不使用反射是不可能的