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.  It 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:\inetpub\wwwroot\global.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:\inetpub\wwwroot\global.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

{

    private static bool s_InitializedAlready = false;

    private static Object s_lock = new Object();

    // Initialize only on the first request

    public static void 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

Published 10 November 07 09:41 by Mike Volodarsky
Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# MVolo's Blog said on November 10, 2007 10:23 PM:

The “Request is not available in this context” exception is one of the more common errors you may receive

# MVolo's Blog said on November 10, 2007 10:23 PM:

The “Request is not available in this context” exception is one of the more common errors you may receive

# Mike Volodarsky's WebLog said on November 10, 2007 10:24 PM:

The “Request is not available in this context” exception is one of the more common errors you may receive

# Noticias externas said on November 10, 2007 11:11 PM:

The “Request is not available in this context” exception is one of the more common errors you may receive

# Mark said on November 21, 2007 11:27 AM:
You could even move this into an HttpModule - say a LoadApplicationModule, which repoints through to any error pages
# Mike Volodarsky's ServerSide said on December 8, 2007 8:55 PM:

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.

# Edward Ashley said on December 14, 2007 11:54 AM:
Mike, have a question on this "Server Error in '/' Application" You posted an example that is written in C# but I use VB can you also either post a example in VB or send me and example? My E-mail is eahosting@gmail.com I hope that this will take care of my problems. Thanks, Edward
# Mike Wheelaghan said on January 16, 2008 7:30 AM:
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
# Mike Volodarsky said on January 16, 2008 11:00 PM:

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

# Bob Vandehey said on February 18, 2008 2:54 PM:
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?
# Mike Volodarsky said on February 18, 2008 5:30 PM:

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

# Alexander said on March 9, 2008 12:00 PM:
If I am not mistaken the actual corresponding property for HttpContext.Current.Request.ApplicationPath would be HttpRuntime.AppDomainAppVirtualPath
# Mike Volodarsky said on March 9, 2008 6:55 PM:

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

# Paulo Morgado said on March 11, 2008 6:06 AM:

While preparing the demos for my session at TechDays Portugal 2008 , I've noticed that the Web Client

# Paulo Morgado said on March 11, 2008 6:07 AM:

While preparing the demos for my session at TechDays Portugal 2008 , I&#39;ve noticed that the Web Client

# Paulo Morgado said on March 11, 2008 6:20 AM:

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

# Paulo Morgado said on March 11, 2008 6:20 AM:
# antonio said on March 29, 2008 1:11 PM:
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!)
# Werner said on April 2, 2008 5:22 AM:
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!
# Chistopher Yang said on May 19, 2008 9:56 AM:

症状:在iis7在使用集成模式的Pool可能出现HttpException,而程序在经典模式下能正常运行.

解决方法:http://mvolo.com/blogs/serverside/archiv...

# Oscar said on June 5, 2008 11:54 AM:
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
# Srinivas Madabushi said on June 5, 2008 2:59 PM:

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

# Mike Volodarsky said on June 5, 2008 7:50 PM:

Oscar,

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

Thanks,

Mike

# Mike Volodarsky said on June 5, 2008 7:53 PM:

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

# Mike Volodarsky said on June 5, 2008 7:57 PM:

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

# Rory Becker said on June 10, 2008 7:43 AM:
Thanks for the tip... I did not know about Web.HttpRuntime.AppDomainAppVirtualPath
# Shriyan said on June 30, 2008 8:40 AM:

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

# Frost said on July 28, 2008 4:15 PM:
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.
# Mike Volodarsky said on July 28, 2008 5:03 PM:

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

# Frost said on July 29, 2008 4:57 PM:
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.
# Vlad said on August 20, 2008 6:53 PM:
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
# Mike Volodarsky said on August 21, 2008 4:59 PM:

Hi Vlad,

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

Thanks,

Mike

# Alex said on September 18, 2008 1:27 PM:
What's the equivalent property for Context.Request.Url ?
# DotnetShadow said on September 24, 2008 8:32 AM:
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
# Goodspeed said on December 1, 2008 2:57 AM:

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

# Howard Hoffman said on December 3, 2008 4:02 PM:
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?
# Mike Volodarsky said on December 4, 2008 11:14 PM:

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

Leave a Comment

(required) 
(optional)
(required) 
Enter the code you see below


About Mike Volodarsky

For the past 5 years, I was the core Program Manager for Microsoft ASP.NET 2.0 and IIS 7.0 products. I drove the design and development of the IIS 7.0 web server core, the IIS FastCGI support, the AppCmd command line tool, the ASP.NET Integrated pipeline, and other special projects around server security, performance, and scalability. Now, I am working on my own on cutting edge web server tech on top of the Microsoft IIS platform, and continue blogging about it here.

About me



For the past 5 years, I was the core server Program Manager for the IIS 7.0 and ASP.NET 2.0 products at Microsoft.
Now, I work on advanced web server tech using IIS 7.0, .NET, and Windows Server 2008 and write about it in this blog.

View Michael Volodarsky's profile on LinkedIn

Writings



TechNet Magazine
>Top 10 Performance Improvements in IIS 7.0

MSDN Magazine
>IIS 7.0: Build Web Server Solutions with End-To-End Extensibility
>IIS 7.0: Enhance Your Apps with the Integrated ASP.NET Pipeline
>IIS 7.0: Explore The Web Server For Windows Vista And Beyond
>Design and Deploy Secure Web Apps with ASP.NET 2.0 and IIS 6.0
>Fast, Scalable, and Secure Session State Management for Your Web Applications


Tools and Modules

LeechGuard
IconHandler 2.0
DirectoryListing
HttpRedirection
IIS Auth for Wordpress
iisschema.exe
PortCheck.exe v2.0

Popular Posts

- ASP.NET 2.0 Breaking Changes on IIS 7.0
- Develop IIS7 modules and handlers with .NET
- Troubleshoot IIS7 errors like a pro
- Troubleshooting 503 / "service unavailable" errors
- Troubleshooting "server not found" errors
- Create IIS7 sites, applications, and virtual directories
- Run Ruby on Rails with IIS FastCGI
- VS Debugging of ASP.NET applications on Windows Vista
- Stop hot-linking with IIS and ASP.NET

Tags

Search

Go

This Blog

Archives

Good IIS Blogs

Disclaimer

These postings are provided as is with no warranties, and confer no rights. The views expressed in this blog are entirely my own.

Syndication