Share via


WCF Http And Non-Http Calls hosted in the same Asp.Net Application (IIS7)

You may want to consider the following issue if you plan on hosting your WCF endpoints in IIS. Consider an ASP.NET application which makes both http and non-http (netNamedPipeBinding or netTcpBinding) WCF calls. If the ASP.NET application is restarted, then a 500.21 error will occur if the very first call is a non-http call.

Why does this happen? ASP.Net is heavily dependent on IIS7 where IIS7 calls into ASP.Net and gives ASP.Net the chance to initialize its applications in either Classic or Integrated mode.  There is no way for ASP.Net to know which mode it is in, other than which entry point IIS7 calls into.  So when applications use non-HTTP WAS methods to start app domains and do things without giving IIS7 a chance to initialize ASP.Net, then ASP.Net has to guess.  When ASP.Net knows it is hosted by IIS7, it uses that knowledge to assume it should do Integrated mode initialization.  In other places ASP.Net doesn't know if it is hosted by IIS7 and decides to initialize a 'classic' runtime.  There's just no way for ASP.Net to know for sure what to do when it is being non-HTTP activated.

In this particular case, the WCF web service executes and then raises a web event on a background thread.  When the configured web event providers try to process the event, the TemplatedMailWebEventProvider creates an internal HttpRequest and tries to execute it and use the output as the email template.  Of course, without having gone through HTTP activation yet, ASP.Net isn't quite initialized.  When it goes through init code, it initializes the HttpRuntime in a 'Classic' style, and it stays that way for the lifetime of the application.  When later HTTP requests come through, the requests are processed by the integrated pipeline, but with a classic StepManager, which results in confusion and failed requests and AV's.

Unfortunately, ASP.Net can do nothing here since Webhost/WAS doesn't notify ASP.Net to start an application unless the request is over HTTP. (Thanks to Steve Molloy for his insights)

RESOLUTION

In the specific case:

If you use TemplatedMailWebEventProvider.  use SimpleMailWebEventProvider instead if you must have email alerts for events.

Or, if you need to make the email pretty or fit a special format, you can extend System.Web.Management.MailWebEventProvider to provide that functionality without too much extra effort.

In the general case, you can resolve this issue with the following:

Split the application in two so that http calls are in one and non-http calls are in the other application.

Create a secondary application that can be called from the main application. This requires .NET 4.0 where the location tag can be used in the following scenario. Create two web applications where all the http calls are in the main application and the non-http calls are in the secondary application. In the main application's web.config file, use a location tag to locate the second application that houses non-http endpoints.

An article based on this issue can be found at this link: https://support.microsoft.com/?kbid=2018968