IIS7 Integrated mode: Request is not available in this context exception in Application_Start

The “Request is not available in this context” exception is one of the more common errors you may receive on when moving ASP.NET applications to Integrated mode on IIS 7.0.  This exception happens in your implementation of the Application_Start method in the global.asax file if you attempt to access the HttpContext of the request that started the application. 


Update: We recently launched a service that significantly helps you understand, troubleshoot, and improve IIS and ASP.NET web applications. If you regularly troubleshoot IIS errors, manage Windows Servers, or tune ASP.NET performance, definitely check out the demo at www.leansentry.com.


The error looks something like this:

Server Error in ‘/’ Application.


Request is not available in this context

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.HttpException: Request is not available in this context

Source Error:

Line 3:  {
Line 4:      HttpContext context = HttpContext.Current;
Line 5:      String appPath = context.Request.ApplicationPath;
Line 6:  }
Line 7:  </script>


Source File: c:inetpubwwwrootglobal.asax    Line: 5

Stack Trace:

[HttpException (0x80004005): Request is not available in this context]
   System.Web.HttpContext.get_Request() +3467061
   ASP.global_asax.Application_Start(Object source, EventArgs e) in c:inetpubwwwrootglobal.asax:5

[HttpException (0x80004005): Request is not available in this context]
   System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) +3388766 …

This error is due to a design change in the IIS7 Integrated pipeline that makes the request context unavailable in Application_Start event.  When using the Classic mode (the only mode when running on previous versions of IIS), the request context used to be available, even though the Application_Start event has always been intended as a global and request-agnostic event in the application lifetime.  Despite this, because ASP.NET applications were always started by the first request to the app, it used to be possible to get to the request context through the static HttpContext.Current field.

Applications have taken a dependency on this behavior become broken in Integrated mode, which officially decouples Application_Start from the request that starts the application.  In the future, we may introduce changes that will further break the assumption that applications start because of requests – for example, by introducing a warmup mechanism that can start ASP.NET applications based on a specific schedule.

So, what does this mean to you?

Basically, if you happen to be accessing the request context in Application_Start, you have two choices:

  1. Change your application code to not use the request context (recommended).
  2. Move the application to Classic mode (NOT recommended).

In fact, most of the customers I have spoken to realize that they do not need to access the request context in Application_Start.  Because this event is intended for global initialization activities, any logic that references a specific request is typically a design oversight.

In these cases, it should be trivial to remove any reference to HttpContext.Current from the Application_Start method. 

A common example of this is using the HttpContext.Current.Request.ApplicationPath to get to the application’s root virtual path.  This should become HttpRuntime.AppDomainAppVirtualPath.  Voila, no need to use the request!

In the cases where you do need to access the request information for the first request to the application (I have seen VERY few applications where this is the case), you can use a workaround that moves your first-request initialization from Application_Start to BeginRequest and performs the request-specific initialization on the first request.

Here is an example of how to do that in your global.asax (you can also do it in a module):

void Application_BeginRequest(Object source, EventArgs e)

{

    HttpApplication app = (HttpApplication)source;

    HttpContext context = app.Context;

    // Attempt to peform first request initialization

    FirstRequestInitialization.Initialize(context);

}


class
FirstRequestInitialization

{

    privatestaticbool s_InitializedAlready = false;

    privatestaticObject s_lock = newObject();

    // Initialize only on the first request

    publicstaticvoid Initialize(HttpContext context)

    {

        if (s_InitializedAlready)

        {

            return;

        }

        lock (s_lock)

        {

            if (s_InitializedAlready)

            {

                return;

            }

            // Perform first-request initialization here …

            s_InitializedAlready = true;

        }

    }

}

This code attempts to initialize at the beginning of each request, with only the first request performing the initialization (hence, first request initialization J). Note that the lock is necessary to insure correct behavior in the case where multiple requests arrive to your application near simultaneously (don’t lock around type objects, since this may lock multiple appdomains – see Rico’s post).

With this issue out of the way, you should be able to enjoy the benefits of Integrated mode on IIS7 without much other grief.  For more info on ASP.NET Integrated mode and how to take advantage of it, be sure to check out http://www.iis.net/articles/view.aspx/IIS7/Extending-IIS7/Getting-Started/How-to-Take-Advantage-of-the-IIS7-Integrated-Pipel.

Thanks,

Mike

79 Comments

  1. Anonymous

    ASP.NET 2.0 applications on IIS 7.0 are hosted using the ASP.NET Integrated mode by default. This post lists the changes in behavior that you may encounter when deploying your ASP.NET applications on IIS 7.0 on Windows Vista and Windows Server 2008.

  2. Anonymous

  3. Anonymous

    Hi maybe this could help someone. I installed VS2008 and .NET 3.5 and my nice CMS stopped working with this error. All I did to get going was change the DefaultAppPool setting to Classic App Pool settings and bingo all fixed

  4. Mike Volodarsky

    Hi Mike,

    As I mentioned in this post, this breaking change is specific to Integrated mode (like most other breaking changes), and so you can work around it by placing the application in Classic mode.

    However, we recommend that if possible, you try to fix the underlying error and remain in Integrated mode as it provides a better migration path long term. For more on this, see http://mvolo.com/blogs/serverside/archive/2007/12/08/IIS-7.0-Breaking-Changes-ASP.NET-2.0-applications-Integrated-mode.aspx.

    Thanks,

    Mike

  5. Anonymous

    I just ran into this problem in trying to move to IIS 7. My problem is that the HttpContext.Request property is throwing an exception instead of just returning null. We are doing logging in this method and our logging framework looks at the HttpContext.Current.Request property for info to log. If this is null, nothing is logged. Throwing an exception makes us have to wrap this code in a try/catch block. Definitely not ideal. Is there a way to check to see if accessing the Request property will thrown an exception before accessing it?

  6. Mike Volodarsky

    Bob,

    The reason we throw this exception is specifically so that you dont try to access the Request in App_Start, because the request is not available there. The idea is that you just shouldnt do it – there is no reason to check it for null since you know it is not available there.

    Now, in other pipeline events, the request is always available, so you shouldnt need to check it for being null.

    Thanks,

    Mike

  7. Anonymous

    If I am not mistaken the actual corresponding property for HttpContext.Current.Request.ApplicationPath would be HttpRuntime.AppDomainAppVirtualPath

  8. Mike Volodarsky

    Hi Alexander,

    You are right, it is AppDomainAppVirtualPath, AppDomainAppPath returns a physical path corresponding to the app’s root vdir. Thanks for pointing out the typo!

    Mike

  9. Anonymous

    Enquanto preparava as demonstraões para minha sessão no TechDays Portugal 2008 , reparei que a Web Client

  10. Anonymous

    Hi,

    If I understand well, some guy modified the way the HttpContext.Current works in order to make sure people do not use it while within the application_start event.

    Yes. Right. I could understand that, from the design point of view.

    I have a problem, however, with the way this was implemented, ie. by throwing an exception.

    I have an example of how people might really get impacted by this.

    I have a logging component, which was designed years ago from now, and which is used in a dozen applications, either desktop or web based.

    This component outputs the logs in a standardised format for all products sold by the company I used to work with.

    One of the strengths of this logging component is that it was able to detect whether specific contexts were available or not. For example, if the httpcontext was available, the logging facility would extract the IP address from which the request originated. The same applied to the referrer and user-agent information.

    The check was rather simple and clearly understandable to the other developers who used this component. The code looked like this, in a very simplified view:

    if(ComesFromWebApp())
    {
    if(HttpContext.Current != null)
    {
    ExtractContextInformation();
    }
    }

    What was actually done is preventing developers from writing a transparent way of finding context related information when it becomes available.

    Developers can’t use a simple but effective “if not null” check anymore, just because some guy simply decided that no one should ever ask this question.

    I am not questioning the skills, experience or ability required to take such decisions. However, I would appreciate understanding how exactly they could came to deciding that asking if “something” exists before actually using it should trigger an exception.

    If I follow that vision, I should somehow expect that the excerpt below:

    int a = 12;
    if(a != null)
    {
    say(“hello world!”);
    }

    might someday trigger an exception “Integers not available in this context” because some guy decided that no one should ask the existence of Integers within the main() method.

    I understand and agree with what they meant by giving no context while in the ApplicationStart phase.

    However, many developers didn’t wait for them to understand this, and already implemented the necessary tests long ago. That decision broke these developers work.

    Let’s hope these people are not working on the Reflection classes…a lot of things might get hurt :)

    (thanks for your post anyway, I got an answer to what I was looking for!)

  11. Anonymous

    Finally someone who knows what they’re talking about. Using Context.Request is exactly what caused the problem. I had to trawl through so many bogus posts before finding this gem. Thanks for the help!

  12. Anonymous

    Thanks for this article Mike,

    How would I get the current URL? I’m getting this error after migrating to IIS7. The failure is in this particular line of code:

    Uri url = HttpRuntime.Current.Request.Url;

    I need to access the URL. Again, this was executed from the Application_OnStart() event.

    thanks

  13. Anonymous

    I experienced this problem.

    All I had to do is change the application pool the application was in to the classic application pool. Thats it

  14. Mike Volodarsky

    Oscar,

    If you need request information, you’d need to use the first request initialization pattern I show in this post.

    Thanks,

    Mike

  15. Mike Volodarsky

    Srinivas,

    As I mention in this post, moving to Classic mode is an option – but not a recommended one. Classic mode is a backwards compatibility mode that does not take advantage of current and future capabilities in the Integrated mode platform, and may be deprecated in a future release.

    If at all possible, developers should take advantage of the Integrated mode by making the appropriate changes to their application.

    Thanks,

    Mike

  16. Mike Volodarsky

    Antonio,

    I understand your concern. Unfortunately, from working with many customers and applications we saw that returning nul had the unintended effect, causing applications to behave incorrectly without a clear way to discover the problem.

    When building platform software, it is often necessary to make tradeoffs between backwards compatible behavior and moving developers to new behavior. In IIS 7.0, we did both – we offer Classic mode for applications that are unwilling or unable to take the changes needed to move to Integrated mode, and Integrated mode for those that are willing to use the new patterns (minimal) to receive the benefit.

    Precisely because of this, we were able to avoid compromising the Integrated mode platform with backward compatibility hacks. Instead, we offer a platform that is 99% compatible and that makes the right changes needed to provide the correct experience going forward. If you are in that 1%, go with Classic mode.

    Thanks,

    Mike

  17. Anonymous

    can't we make use of wcsf to fix up this issue, without changing the architecture of the project developed in vs2005.

  18. Anonymous

    Hi,

    I had this exact problem and changed as per the recommendation to use (Web.HttpRuntime.AppDomainAppVirtualPath). But since doing so I now get and ‘Access Denied’ error and I’m not 100% sure why when it worked just fine previously. The only change that has happened is that I’m now using a vista 64bit machine with IIS7 on it, but the same code with VS2008.

    Any ideas?
    thx.

  19. Mike Volodarsky

    Hi Frost,

    The issues you are having most likely have nothing to do with the code change, and everything with being deployed in a new environment.

    I would recommend getting the full exception details and looking at what is causing the access denied error – most likely incorrectly configured permissions for the application.

    Thanks,

    Mike

  20. Anonymous

    Thanks for the response and you were right. The issue was with IIS7 and the configuration of it. I had to set the Authentication to “windows authentication” enabled. That solved the issue.

  21. Anonymous

    Hi Mike,

    We have a web application that is deployed in multiple environments, and web.config contains several configuration elements that are keyed on the host name of where the instance is deployed (e.g. “dev.company.com”, “prod.company.com”, etc).

    The settings need to be read at application start time, and previously we just called “HttpContext.Current.Request.Url.Host” to get the host name where the running app is deployed.

    Any idea how to get the URL on application startup without using HttpContext? Or do I need to start rethinking the configuration design?

    Thanks,
    Vlad

  22. Mike Volodarsky

    Hi Vlad,

    You’ll need to move to the “first request initialization” pattern, see this post for details/code sample.

    Thanks,

    Mike

  23. Anonymous

    Great article, I was wondering what you would do in the situation where need to kick start the sqldependency cache which is in Application_Start:
    System.Data.SqlClient.SqlDependency.Start(“connectionstring”);

    The SQL server may be down or something thus this will cause an exception, so to catch it you would use Application_Error but now you have the problem where you can’t use Response.Redirect or Server.Transfer because they aren’t available so how would you handle the error?

    Regards DotnetShadow

  24. Anonymous

    刚刚将一台服务器升级到IIS7,经典模式没有任何问题。换成集成模式碰到以下问题问题一:状况:程序启动报“Requestisnotavailableinthiscontext”错误。原因:在…

  25. Anonymous

    Mike –

    Great work.

    Wonder if the System.Web.Management.WebErrorEvent type can be updated. When you WebErrorEvent.Raise during Application_Start, you get HttpException out of WebErrorEvent.InitRequestInformation.

    There are cases where we need to use Health Monitoring to raise Errors in our Application Start code. Our application has no code that assumes it has a Request during Application_Start, but System.Web.Management does!

    As it stands, we have to trick it by assigning null to HttpContext.Current prior to triggering an Event-Raising condition.

    Seems to me that it’s a defect in System.Web.Management. I do not see a way, though, to tell that you are inside Application_Start. Perhaps that ‘state’ does exist on some internal class; certainly you can leverage HttpRuntime.UsingIntegratedPipeline.

    Any hope of System.Web.Management being updated?

  26. Mike Volodarsky

    Hi Howard,

    I’ll forward the request over to the ASP.NET team, although you might want to create a bug report on the connect website. I agree that it is a bug.

    In the meantime, you can try a workaround of creating a custom event that derives from WebBaseEvent that carries your error information, without attempting to capture request information (you can also manually do this yourself if the context is available, if you want).

    You can then add health monitoring rules for your custom event to route to the same source as the request errors.

    Thanks,

    Mike

  27. Anonymous

    Is there a chance this behavior will be changed?  There are several disadvantages, currently, and a much better alternative.

    You suggest that one simply shouldn't use .Request in Application_Start, however, this isn't actually that easy.  Howard mentions a case where System.Web.Management uses the property.  However, any other code could just as easily trigger this problem – should everything else be updated?

    You also suggest that in all other cases, Request is just available, so you shouldn't need to "check" whether it's there or not – but the point is, code reuse is nice, and the current approach means that there can be no code sharing between Start and other events even if the Request related code is trivial.  If, rather than throwing an exception, null were returned, this problem wouldn't exist: checking for null is much cleaner (and cheaper) than catching an exception and ignoring it.

    Right now, any application logging I do consists of many try..catch statements surrounding just one statement where the caught exception is ignored.  This isn't in good style; in particular it teaches people that it's good practice to ignore exceptions, when in fact doing so involves significant performance penalty (which in other contexts may be problematic), and worse, ignores the fact that in a truly exceptional situation, the object throwing the exception may well not be in a valid state.

    The current approach is also inconsistent with the rest of the API.  Whereas HttpContext.Current returns null when there is no current HttpContext, .Request throws an exception?

    There's simply no good reason to throw an exception rather than return null in this case.  If you return null, sane code which does rely on HttpContext being present at all (as would be required for the code to work during Session_End) might just work, and logging code could reasonably check wether the request is present.  Code which truly uses .Request in an invalid state will cause a nullreference exception.

    But whatever you do, please document it:

    http://msdn.microsoft.com/en-us/library/system.web.httpcontext.request.aspx

    The current behaviour isn't ideal, but the worst of it is that it's undocumented – that makes code using HttpContext generally less reliable.

  28. Mike Volodarsky

    Hi Eamon,

    I understand your perspective – however, at the time our priority was to clearly identify any breaking changes in Integrated mode to help its adoption. Its more discoverable for most people to receive this exception message than track down a NullRef or a code behavior chage.

    I agree that this is not ideal for code that is called from other request events.

    Also agree that it should be documented, and suprised it not. I am not at Microsoft anymore, but you can get a response from the IIS team by posting on forums.iis.net or filing a bug on connect.

    Thanks,

    Mike

  29. Anonymous

    Thanks Mike. I can honestly say that I love you for fixing this problem I’ve been battling for what felt like forever!

  30. Anonymous

    Hi mike,

    First of all thank you for this article ;

    While applying you solution I have some problems again..

    i need Htppcontext.Curent at Application_Start(object sender, EventArgs e) .  

    Here the sender has type httpapplicationfactory, so i am not able to cast it to httpapllication type and call your method. So what do  you suggest ?

    thank you .

  31. Mike Volodarsky

    Yaya,

    The context is not available in Application_Start in Integrated mode. That is the subject of this workaround – moving context accesses to a first-request init pattern using request events, such as BeginRequest.

    Thanks,
    Mike

  32. Anonymous

    1.下载了一个C#版本的DNN,编译源码,本来想监视一下install的过程,结果一下子就碰到了第一个麻烦。程序运行的时候会报错错误内容为:Requestisnotavailablein…

  33. Anonymous

    Is there a way to find out the http:// address and port of the server that hosts the site? I know this sounds odd, but I am running WCF services and they run on multiple sites. I dont want to configure this in the web.config but rather initialize the WCF service with the server and its port its published on. The HttpRuntime does not provide any information about this. I was using Context.Request.Url.Authority …what is the integrated pipeline equivalent?

  34. Anonymous

    Nice work around, I wonder why many of ASP.NET apps stills causing this error and that where your work help me alot 😉

  35. Anonymous

    I’ve change the call in Application_Start to HttpRuntime.AppDomainAppPath and this still fails with error “Request is not available in this context”. Any ideas why?

  36. Anonymous

    Wouldn’t it make more sense to put your code workaround for accessing the HttpContext.Current.Request object in the first request into the void Session_Start(object sender, EventArgs e)?

    You do your same check to initialize whatever you’re initializing only once, but being in the session start, it will be checked less frequently than the begin request. Or is this simple check negligible to be in either?

  37. Anonymous

    Thanks for posting this! Had the issue where I needed to get to the physical path, your workaround worked a treat.

  38. Anonymous

    This helped great for many of the issues we ran into. However one particular one I am stuck at. What if we need to actually get the request object itself. :/

    Fixing the mapping to the path was fine but in one case I have something like

    If tContext IsNot Nothing Then
    Dim tRequest As HttpRequest = tContext.Request

    tClient = tRequest.UserHostAddress
    tUrl = tRequest.RawUrl
    End If

    How can I get the UserHostAddress and RaUrl without the request :(

  39. Anonymous

    Hi Mike,

    Thanks for the workaround provided. Reading through the comments above, however, I must admit, I liked antonio’s opinion. HttpContext.Request was returning null and it was an expected behavior for ages.

    Anyway, if I’m gonna support both modes, if it’s a good idea to perform checking the following way, rather than using try-catch?

    if (sender is HttpApplication) // IIS7 Integrated mode (?)
    {
    // use the workaround provided
    }
    else // IIS5/6 or IIS7 Classic mode (?)
    {
    // go “classic” way
    }

  40. Anonymous

    When I try to access the passed context variable in FirstRequestInitialization.Initialize() I get this error:

    “‘System.Web.HttpContext.Current.get’ cannot be accessed with an instance reference; qualify it with a type name instead.”

  41. Anonymous

    למה פתאום התחלנו לקבל את השגיאה Request is not available in this context אם ניגשים אליו מתוך ה – Application_Start

  42. Anonymous

    Hi, and thanks for the explanation.
    I am one of those getting this error (though not via Application_Start)
    I understand that Request is not always available in an Application event, but here is my problem:
    What I really need is to collect ApplicationPath.
    I need it in my LogWriter class which logs (does tracing) for an HttpModule and is called from all event handlers including Init handler.

    My first complaint is that ApplicationPath is not available in neither Application nor ApplicationInstance.
    You have to reach for the Request to get it and as you pointed out it is not always there.

    My second complaint is that you did not provide a way to check if the Request is there or not.
    Sure I can do a try catch, but that seems excessive and I have this in a pretty sensitive part of the code performance wise.
    I think a much more sensible strategy would be to return null.

  43. Anonymous

    Recently while we were performing the migration of a blog engine in ASP.NET to Azure we had to deal with

  44. Anonymous

    When I try to access the passed context variable in FirstRequestInitialization.Initialize() I get this error: “‘System.Web.HttpContext.Current.get’ cannot be accessed with an instance reference; qualify it with a type name instead.

  45. Anonymous

    Recently while we were performing the migration of a blog engine in ASP.NET to Azure we had to deal with

  46. Anonymous

    Thanks for making such a cool project. I’ve been checking the site for the Windows version, but I never left a comment about it. I know you are working hard

  47. Anonymous

    “# Mike Volodarsky : The reason we throw this exception is specifically so that you dont try to access the Request in App_Start, because the request is not available there. The idea is that you just shouldnt do it – there is no reason to check it for null since you know it is not available there.”
    Yes, I know it’s not there … if I’m directly in the Application_Start. NOT IF I AM SEVERAL LEVELS DEEP IN METHOD CALLS!

    Anyway thanks a lot for such a bright design decision … instead of checking whether a property is null (hey, not Request is available hence you don’t get any) I have to wrap something in a try{} block, check whether the exception is this brainless one or something else … T H A N K S

  48. Anonymous

    s_InitializedAlready = true;
    // Perform first-request initialization here …

    setting initializedAlready before code seems more natural

  49. Anonymous

    quick question. is there any way to get the website host header in the application start or would i need to use FirstRequestInitialization.
    code currently sends an email when the web-site is restarted, and I’d like to have it pass the http://www.MyFancyWebsite.com name. Request.ServerVariables[“SERVER_NAME”]. for now i just changed it to use Environment.MachineName + @”” + HttpRuntime.AppDomainAppPath. I can figure it out from here, but it be nicer if i could pass the default host header…. I can’t think of a good way to do this, without going in and reading IIS configs, which is way too impractical for my uses.

  50. Chinh

    I have same issue, but I need Response at Application_Start(object sender, EventArgs e).
    when I run code below:

    Response.Clear();
    Response.Cache.SetCacheability(HttpCacheability.Private);
    Response.Expires = -1;
    Response.Buffer = true;

    then threw error “Response is not available in this context”.
    Please help me fix it!

  51. Armand

    Hi Mike,

    Currently im trying to migrate my application from iis 6 to iis7, i dont change any configuratio on web.config. Since the web.config already had addtional configuration to running on iis7 which generated by Visual Studio.

    The web site load smoothly but when i navigated to a page with a User Control, the IE is freeze, and on another page which contain User Control the IE load it repeatly but showing same page.

    can you help me to solve this problem?

    i really appreciated your help

  52. Steve

    I know there’s nothing you can do about it now. But, thanks for giving me a place to complain. “Just don’t attempt to use Request in Application_Start” is not trivial if you’re in code that doesn’t know it’s in Application_Start. Mutli-situation logging code is my example. too, but it’s not the only time I’ve encountered this since we switched to integrated mode. “null” is the value you use for not available, not throwing an exception. I can’t believe you didn’t implement any way whatsoever to check availability of Request.

Leave a Reply

Your email address will not be published. Required fields are marked *