Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid a HttpException when calling HttpContext.Request?

So HttpContext.Request throws if called within a global start

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

This is actually documented

ASP.NET will throw an exception if you try to use this property when the HttpRequest object is not available. For example, this would be true in the Application_Start method of the Global.asax file, or in a method that is called from the Application_Start method. At that time no HTTP request has been created yet.

Is there a way of checking if a HttpContext.Request is in a state that it can be retrieved without throwing the exception? Effectively I want to write a TryGetRequest helper method.

  • Reflection is not an option. It needs to be a public API.
  • I dont have access to the application context. this is generic logging code. So setting some flag when startup has finished is not an option
like image 589
Simon Avatar asked Apr 18 '14 01:04

Simon


People also ask

What is HttpContext request?

HTTPContext. Current is a static property. This property is a static property of the HttpContext class. The property stores the HttpContext instance that applies to the current request. The properties of this instance are the non-static properties of the HttpContext class.

Is HttpContext current items thread safe?

The HttpContext is NOT thread safe, accessing it from multiple threads can result in exceptions, data corruption and generally unpredictable results.

How does HttpContext current work?

From ASP.NET 4.5 and after, Current HttpContext is passed through CallContext instead of [ThreadStatic] , so context remains available through out async calls in single logical context instead of current thread as each async call may end up on different threads.

How is HttpContext created?

When an HTTP request arrives at the server, the server processes the request and builds an HttpContext object. This object represents the request which your application code can use to create the response.


2 Answers

As deostroll observed, it is reasonable and may in fact be necessary to rely on the ASP.NET application lifecycle to determine when the current HttpRequest has become available. The generic logging code is presumably dependent at the very least on HttpContext.Current or some other reference to the current HttpContext instance. If that assumption holds true, then an HttpModule can be implemented that stores a flag in the HttpContext.Items collection when the BeginRequest event fires. The static TryGetRequest helper method can test for the presence of that flag to determine whether it is safe to use HttpContext.Request.

Perhaps like this:

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
}

The module must be registered in web.config (assuming IIS 7.0 integrated pipeline):

  <system.webServer>
    <modules>
      <add name="HttpRequestHelper" type="Utility.HttpRequestHelper" />
    </modules>
  </system.webServer>

The logging code would use the helper method like this:

HttpRequest request;
if (HttpRequestHelper.TryGetRequest(HttpContext.Current, out request))
    LogWithRequest(request, message);
else
    LogWithoutRequest(message);

The implementation does not rely on private API's or reflection. It relies on a flag, but the state information remains with the HttpContext instance and is well encapsulated.

like image 191
Joel Allison Avatar answered Sep 20 '22 06:09

Joel Allison


Why not wrap the call to HttpContext.Request with a try, catch block then you can catch the exception and modify your behaviour accordingly.

like image 45
phuzi Avatar answered Sep 18 '22 06:09

phuzi