Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs
Contact   •   Articles   •   Products   •   Support   •   Search
Ad-free experience sponsored by:
ASPOSE - the market leader of .NET and Java APIs for file formats – natively work with DOCX, XLSX, PPT, PDF, images and more

ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2


:P
On this page:
Edit this Post

ASP.NET Core 2.2 has been out for a while now and with it come some significant improvements to the hosting model if you plan on hosting in IIS. In previous versions you were required to host ASP.NET Core applications by proxying requests from IIS into the ASP.NET Core Kestrel server with IIS effectively as a Reverse Proxy. I wrote about this in a detailed blog post a while back.

In version 2.2 ASP.NET Core adds support for direct in-process hosting which improves throughput considerably using an easy mechanism that allows switching between in-process and out-of-process hosting.

In this post I'll focus on the new In Process hosting model since that's what's changed and is improved, but I'll review the basics of both models here so this post can stand on its own. I'll start with what's changed and then dig a little deeper into how the models work and how they differ.

ASP.NET Core 2.2 adds InProcess Hosting on IIS

The original versions of ASP.NET Core required you to host on IIS using an Out of Process model that proxies through IIS. Requests hit IIS and are forwarded to your ASP.NET Core app running the Kestrel Web Server.

Out of Process Hosting (pre v2.2 model)

IIS Out of Process Hosting

Figure 1 - Out of Process Hosting uses IIS as proxy to forward requests to your dotnet.exe hosted Console application.

With ASP.NET Core 2.2 there's now an In Process hosting model on IIS which hosts ASP.NET Core directly inside of an IIS Application pool without proxying to an external dotnet.exe instance running the .NET Core native Kestrel Web Server.

In Process Hosting (v2.2 and later)

Figure 2 - With In Process hosting your application runs nside of the IIS application pool and uses IIS's intrinsic processing pipeline.

The In Process model does not use Kestrel and instead uses a new Web Server implementation (IISHttpServer) that is hosted directly inside of the IIS Application Pool that is some ways similar to the way classic ASP.NET was plumbed into IIS.

This implementation accesses native IIS objects to build up the request data required for creating an HttpContext which is passed on to the ASP.NET Core middleware pipeline. As with the old version, the the Application Pool that hosts the ASP.NET Core Module does not have to be running .NET since the module hooks into the native code IIS pipeline.

Although this sounds like a fairly drastic change, from an application compatibility aspect I've not run into into any issues that have had any effect on my applications other than faster request throughput.

This feature improves throughput for ASP.NET Core requests on IIS significantly. In my off the cuff testing I see more than twice the throughput for small, do-nothing requests using IIS InProcess hosting. More on this later.

Microsoft has done a great job of introducing this hosting model with minimal impact on existing configuration: It's easy to switch between the old OutOfProcess and InProcess models via a simple project configuration switch that is propagated into the deployed web.config file.

OutOfProcess or InProcess? Use InProcess

For new applications that are deployed to IIS you almost certainly will want to use InProcess hosting because it provides better performance and is generally less resource intensive as it avoids the extra network hop between IIS and Kestrel and maintaining an additional process on the machine that needs to be monitored.

There are a few cases when OutOfProcess hosting might be desirable, such as for trouble shooting and debugging a failing server (you can run with console logging enabled for example) or if you want to be 100% compatible between different deployments of the same application, whether it's on Windows or Linux, since Kestrel is the primary mechanism used to handle HTTP requests on all platforms. With the InProcess model you're not using Kestrel, but rather a custom IISHttpServer implementation that directly interfaces with IIS's request pipeline.

But for most intents and purposes I think running InProcess on IIS is the way to go, unless you have a very specific need to require Kestrel and OutOfProcess hosting.

New ASP.NET Core projects automatically configure projects for InProcess hosting, but if you're coming from an older project you may have to update your project settings explicitly.

Settings Affected

Switching between hosting modes is very easy and requires only a configuration switch either inside of your .csproj file or in web.config.

Project Change - <AspnetCoreHostingModel>

The first change is in the project file where you can specify the hosting model by using the <AspNetCoreHostingModel> key.

To use InProcess hosting add the following to your Web project's .csproj file:

<PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>

The relevant project setting is the AspNetCoreHostingModel which can be InProcess or OutOfProcess. When missing it defaults to the old OutOfProcess mode that uses an external Kestrel server with IIS acting as a proxy.

This affects how dotnet publish creates your configuration when you publish your project and what it generates into the web.config file when the project is published.

web.config Change

The <AspnetCoreHostingModel> project setting affects the generated build output by writing configuration data into the web.config file for the project. Specifically it sets the the hostingModel attribute on the <aspNetCore> element that is generated:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" />
      </handlers>
      
      <!-- hostingModel is the new property here -->
      <aspNetCore processPath="dotnet" arguments=".\WebApplication1.dll"	
			      stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout"
			      hostingModel="InProcess" />
			      
    </system.webServer>
  </location>
</configuration>

If the <AspNetCoreHostingModel> key in the project is set to OutOfProcess or is missing, the hostingModel attribute is not generated and the application defaults to OutOfProcess.

Refresh web.config on Publish

I found that unlike the rest of the files in the publish output folder the web.config file was not updated on a new publish unless I deleted the file (or the entire publish folder). If you make changes that affect the IIS configuration I recommend to nuke the publish folder and doing a clean publish.

Note that you can easily switch between modes after publishing by simply changing the value between InProcess and OutOfProcess in the web.config in the Publish folder. This can be useful for debugging if you want to log output on a failing application with verbose log settings enabled for example.

Just remember that if you change publish output it will be overwritten next time you publish again.

Cool - this single setting is all you need to change to take advantage of InProcess hosting and you'll gain a bit of extra speed connecting to your application.

More Detail: Reviewing IIS Hosting

To understand how InProcess hosting for IIS is a nice improvement, lets review how ASP.NET Core applications are hosted on Windows with IIS.

What is an ASP.NET Core Application?

When you create an ASP.NET Core application you typically create a standalone Console application that is launched with dotnet .\MyApplication.dll. When you run the Console application, ASP.NET Core hosts its own internal Kestrel Web Server inside of the application. Kestrel handles the incoming HTTP traffic and a Kestrel connector hands of an HttpContext to the ASP.NET Core request middleware pipeline for processing.

When you build an ASP.NET Web application you essentially create a fully self contained Web Server that runs ASP.NET Core on top of it.

Why do I need a Web Server for my Web Server?

For live applications hosted on Windows you typically use IIS as the front end server for your ASP.NET Core application rather than letting your ASP.NET Core running the .NET Kestrel Web Server be accessed directly.

In a nutshell, the built in Kestrel Web server in ASP.NET core is not meant to be an Internet facing Web server, but rather act as an application server or Edge Server that handles very specific data processing tasks. Kestrel is optimized for application scenarios, but it's not optimized for other things like static file serving or managing the server's lifetime

For this reason you generally do not want to run Kestrel directly in a Web application. This is true on Windows with IIS and also on Linux where you tend to use a Web server nginx or ha-proxy to handle non-application concerns. I wrote about how to set up IIS rewrite rules to route common static files rather than letting Kestrel handle them. This is not only about speed but it lets your Web application focus on doing the dynamic things that it's designed to do, letting IIS do the work it was designed for.

Here are a few of many arguments on why you want to use a full Web Server rather than running your application directly connected to the Web:

  • Port Sharing
    Kestrel currently can't do port sharing in the same way that IIS and http.sys can do on Windows. Currently that functionality is supported only through IIS on Windows. (AFAIK you can't even using the HttpSys Server to do this). Additionally although it's possible to use host header routing in ASP.NET Core, it's not exactly easy or maintainable to set this up currently.

  • Lifetime Management
    If you run your app without any support infrastructure any crash or failure will shut down the application and take your site offline. No matter what, you need some sort of host monitor to ensure your app continues to run if it fails and IIS provides that out of the box. ASP.NET Core with the ASP.NET Core Module benefits directly by being able to restart application pools that can relaunch your application on failures.

  • Static File Serving
    Kestrel is not very good with static file handling currently and compared to IIS's optimized static file caching and compression infrastructure, Kestrel is comparitively slow. IIS takes full advantage of Kernel mode caching, and built in compression infrastructure that is much more efficient than today's ASP.NET StaticFile handler (".UseStaticFiles()").

There are additional reasons: Security and server hardening, administration features, managing SSL certificates, full logging and Http Request tracing facilities and the list goes on. All good reasons to sit behind a dedicated Web server platform rather than running and managing a self-hosted server instance.

Out of Process Hosting

Prior to ASP.NET Core 2.2 the only way to host ASP.NET Core on IIS was through out of process, proxy mode hosting. In this model IIS is acting like a Web Server Frontend/Proxy that passes requests through to a separately executing instance of the .NET Core Console application that runs Kestrel and your ASP.NET Core application. Each request first hits IIS and the AspNetCoreModule packages up all the request headers and data and essentially forwards it from port 80/443 (or whatever your port is) to the dedicated port(s) that Kestrel is listening on.

Figure 3 - Out of Process ASP.NET Core IIS Hosting

As you can see the out of process model makes an additional http call to the self-contained running dotnet core application. As you can imagine there's some overhead involved in this extra HTTP call and the packaging of the data along the way. It's pretty quick, because it all happens over a loopback connection, but it's still a lot of overhead compared to directly accessing request data from IIS.

Once on the ASP.NET Core side the request is picked up by Kestrel, which then passes on processing to the ASP.NET Core pipeline.

Figure 4 - Once requests are forwarded via HTTP, they are picked up by the Kestrel Web Server

In Process Hosting

Figure 5 - IIS In Process Hosting routes requests directly into the application pipeline via the IISHttpServer implementation.

In-process hosting does not use the Kestrel Web Server and instead uses an IISHttpServer implementation. This implementation receives incoming requests from the standard IIS http.sys driver and the built-in IIS native pipeline. Requests are routed to the Web site's port and host name through IIS and the request is then routed to IISHttpServer into ASP.NET Core.

Figure 5.1 - In Process hosting uses the IISHttpServer component to handle the Web Server interface

IISHttpServer then packages up request data for passing on to the ASP.NET Core pipeline to provide the HttpContext required to process the current request through the ASP.NET Core pipeline. Input is retrieved through native interfaces that talk to the IIS intrinisic objects and output is routed into the IIS output stream.

In Process Differences

Keep in mind that In Process Hosting does not use Kestrel and because you are using a different Web Server there might be some subtle differences in some settings that are picked up from the Web Server to create the HttpContext. One advantage of running Out of Process with Kestrel you get the same Web Server on all platforms regardless of whether you run standalone, on IIS, on Linux or even in Docker.

That said I haven't run into any issues with any of my (small to medium sized) applications where I've noticed anything that affected my application, but it's a possibility to watch out for.

One ASP.NET Core Application per Application Pool

The ASP.NET Core module V2 running in InProcess mode has to run in its own dedicated Application Pool. According to the documentation you cannot run multiple sites or virtual directories (Web Applications) using the the ASP.NET Core Module in a single Application Pool. Make sure each ASP.NET Core app on IIS gets its own Application Pool.

Checking for InProcess or OutOfProcess Hosting

Once an application is in production you might want to ensure that you're using the appropriate hosting mechanism. You can check in a couple of ways.

Check for the dotnet process

You can check for a dotnet process that runs your application's dll. If you're running out of process you should have a dotnet process that's running your application's dll as shown in Figure 5:

Figure 6 - OutOfProcess uses dotnet.exe to run your application in proxy forwarding mode when using IIS and you can see that separate process in the Process list.

If the dotnet.exe process is running with your application's specific command line, you know your app is running Out Of Process.

Check the Response Server Header

You can also check the HTTP response for the server and check for either Kestrel or Microsoft IIS as the Web Server for OutOfProcess and Inprocess modes respectively :

OutOfProcess

Figure 7 - Out of Process IIS Hosting forwards requests to an externally hosted ASP.Core application running Kestrel.

InProcess

Figure 8 - In Process IIS Hosting implements the Web server host inside of the Asp.Net Core Module using IIS infrastructure. The Server reads Microsoft-IIS/10.0.

Performance

So the obvious reason to use the new In Process model is that it's faster and uses less resources as it's running directly in process of the IIS Application Pool. There is no internal HTTP traffic and overhead and requests are processed immediately.

Before I show a few simplistic requests here, keep in mind that these tests are not representative of typical application traffic. Running simple do-nothing requests only demonstrates that potential throughput is drastically improved, but for longer running request the request overhead is far overshadowed by application level processing in comparison to the request access times.

Still it's always a good idea to eek out extra performance and the improved throughput means less latency in requests, slightly faster response times and less overhead on the server potential more load that can be processed.

How I set up the Test

For this test I used a standard ASP.NET Core API project and then created a small custom class that has a few basically do nothing HelloWorld style methods in it:

public class TestController : Controller
{

    [Route("api/helloworld")]
    public string HelloWorld()
    {
        return "Hello World. Time is: " + DateTime.Now.ToString();
    }
    
    [Route("api/helloworldjson")]
    public object HelloWorldJson()
    {
        return new
        {
            Message = "Hello World. Time is: " + DateTime.Now.ToString(),
            Time = DateTime.Now
        };
    }
    
    [HttpPost]        
    [Route("api/helloworldpost")]
    public object HelloWorldPost(string name)
    {
        return $"Hello {name}. Time is: " + DateTime.Now.ToString();
    }
    
    ... informational requests removed
}

How Much of a Difference?

OutOfProcess

The out of process test result looks something like this:

Figure 9 - IIS Out of Process processing results with Proxying

This is on my local i7 - 12 core laptop. As you can see I get ~8.2k requests a second using out of process hosting.

InProcess Running that same test with InProcess hosting - ie. only adding the hostingModel="InProcess" to web.config (or via the AspNetCoreHosting project setting) I get this:

Figure 10 - IIS In Process processing results

This produces 19k+ requests a second. That's more than twice as many requests!

This is not exactly surprising given that you are removing an extra HTTP request and all the parsing that goes along the for ride in that process. But still it's quite a significant difference.

But again keep this in perspective. This doesn't mean that your app will now run twice as fast, but simply that you get slightly faster connect and response times for each request that runs through IIS which is a welcome addition, especially given that you have to do nothing to take advantage of this improvement except upgrade and set a configuration switch in your project.

Just for reference, if I hit an IIS static Web site using tiny plain static pages I can generate about ~50k requests/second on this same setup.

Raw Kestrel

Just for argument's sake I also wanted to test that same process using just raw Kestrel (on Windows) without IIS in the middle.

Figure 11 - Out of Process processing results with direct Kestrel access

Direct Kestrel access lands somewhere in the middle between In and Out of Process hosting.

I was a bit surprised by this - I would have expected raw Kestrel to perform on par or better than IIS for dynamic requests. Given all the performance stats we've heard how well ASP.NET Core performance on various benchmarks and many of the fastest benchmarks use raw Kestrel access.

I would expect IIS to have a big edge for static files (with Kernel caching), but for dynamic requests I expected Kestrel to beat IIS. But apparently that's not the case at least not on Windows. Even for dynamic requests the IIS Inprocess throughput is better than Kestrel's.

Summary

While IIS is getting marginalized in favor of hosting on Linux and Docker, remember that IIS is still Azure's default ASP.NET Core deployment model if you publish to an AppService and don't explicit specify platform. This means IIS is still in use in more scenarios than just self-hosted IIS applications, so it's not going away anytime soon. And Microsoft just backed that up with the new in processing hosting features that provide much better performance.

You now have two options for hosting on IIS using either the now classic Out of Processing that proxies requests through IIS and uses a completely self-contained ASP.NET Core console application using the .NET Based Kestrel Web Server, or you can use the In Process Hosting model which is more similar to the way classic ASP.NET used to interface with IIS through its own native APIs.

The new In Process model is considerably faster in terms of request throughput so in almost all cases when hosting on IIS you'll want to choose the InProcess model.

The key setting to remember is to set:

<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>

in your project and remove it or set it to OutOfProcess to use the old mode. The setting will generate the required hostingModel attribute in web.config which can also be explictly set in this file to make runtime changes to the host behavior.

This is a great improvement that gets you a decent performance bump for literally setting a switch.

Switch it on and go burn some rubber…

Resources

this post created and published with Markdown Monster
Posted in ASP.NET Core  IIS  

The Voices of Reason


 

Milan
March 18, 2019

# re: ASP.NET Core InProcess Hosting on IIS with ASP.NET Core 2.2

Very well explained. You covered pretty much all questions that I would normally have for such a feature. Seeing the call stacks, your tests results, and everything else makes this very valuable article. I will definitely feature this post in my next newsletter.

Thank you.


Rick
March 18, 2019

# re: ASP.NET Core InProcess Hosting on IIS with ASP.NET Core 2.2

The one problem I've seen with this is in development the environment is detected as "Development;Production", which matches nothing. ASPNETCORE_ENVIRONMENT was set to "Development" in all the places the documentation says it's possible to set it, but I couldn't find where that "Production" value was coming from. Switching back to out of process made it work as described, reporting just the value of ASPNETCORE_ENVIRONMENT.


Kyriakos Sidiropoulos
March 21, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Thanks a billion for such an insightful post. This blog is a true goldmine. I experimented with setting IIS to point at the source-code directory of my .Web project (which contains Web.config and /bin with all dlls). The solution runs in in-process mode (following all of your instructions):

  • So far so good, everything seems to work fine (debugging, breakpoints and everything else)
  • To sweeten the deal I also tweaked the pre/post build events of the .csproj to have it spawn and remove an 'App_Offline.htm' right next to the Web.config and inside the /bin folder so as to enable VS to overwrite dlls upon recompilation (no more "dll has been locked by process XYZ").

Just a quick question: Is there something obviously wrong with this approach that is bound to byte us back if we employ it to develop our solution like this?

Thank you in advance, keep up the good work and may Winds be under your Radiant Wings, always.


Hugo
March 22, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

I believe that may not be so easy, but, do not support sharing memory between applications it's what stopping me to move to .NET Core and I consider .NET Core an incomplete framework.

The old ASP.NET provides at least to ways to share memory resources:

  1. Share the application pool
  2. Thru aspnet_intern: https://visualstudiomagazine.com/articles/2017/11/29/improve-startup-time.aspx

I awaited for .NET Core 2.2 because of In-Process (that was supposed to be released on 2.1) and faced this issue.


Rick Strahl
March 22, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Rick - make sure that you build a Production build when you publish. If you're using the command line:

dotnet publish -c Release

which should by default set everything up for production.

You can specify environment variables as part of the web.config (from the docs):

<aspNetCore processPath="dotnet"
      arguments=".\MyApp.dll"
      stdoutLogEnabled="false"
      stdoutLogFile="\\?\%home%\LogFiles\stdout"
      hostingModel="InProcess">
  <environmentVariables>
    <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
    <environmentVariable name="CONFIG_DIR" value="f:\application_config" />
  </environmentVariables>
</aspNetCore>

You know I've railed against this everything default is Development in .NET Core for a while publically and I absolutely hate that! For the reasons you outline every application I build (HTML or API) has a request in it that shows me some stats about the application and one of those settings is the environment that shows me environment and release/debug state.


Rick Strahl
March 22, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Kyriakos - So far I haven't seen or heard of any issues. The beauty of all of this is that it is easily interchangable. If you are relying on a specific process model, then I would argue there's a much bigger problem in the application that is too tightly coupled to its environment. Unless there's a very good reason to do this, I think that's the first thing that should probably be addressed.

Other than that it seems like a Win-Win, but time will tell. This is a new feature and only time will tell what breaks.

It's also important to point out that .NET Core 2.2 is not an LTS Release meaning it's not considered a full release. According to MS we'll have to wait quite a while for full LTS status with .NET Core 3.1 which looks to be out quite a bit (late this year, more likely early next).


Naveed Zafar
March 26, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

We are running multiple NET CORE 2.1.5 applications under one app Pool, who all are sharing one ISAPI filter too, as per your article , each NET core app will have its own POOL, so then how we can implement this new IN-Process to our situation where we must have to use ISAPI filter and all APPs (some are using core and some are not) in one pool.

Thanks Naveed


Rick Strahl
March 26, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Naveed - if you need to really share an AppPool then you can still use out of process hosting and that should continue to work the same as it did before.

Not sure what your filter is doing that it needs to be shared in the same hosting process - some shared state I presume? Maybe there's a better way to do this than an ISAPI filter?


Michael B Birnholz
March 28, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Rick your papers are truly badass. I am pretty sure MSFT should run all release candidates by you and have you write their docs!


Carlos Estrada
March 28, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Hi Rick, I have a question. Does this apply for my application (running InProcess)if I have a Asp.Net Core App relying on .Net Framework(is a requirement for me do to a 3rd party Component). I said my app is a Asp.NEt Core with .Net Framework 4.6


Gary Gary
April 24, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Ive struggled to find good ASP .NET Core hosting which is why I'm going to try and start my own! Im starting a managed hosting service. hosting.garygary.uk (the website is WIP)

  • IIS ASP (.NET Core) hosting with publishing through FTP or Web deploy from £5 per month
  • Small MSSQL Database hosting from £5 per month.
  • Cheaper than azure and direct customer support.

Sumit
May 11, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Hi Rick, thanks for such a nice post. Everything is very well explained. Just want to ask you that, as we all know that CreateWebHostBuilder method internally calls UserKesteral method so my question is that do we need that method when we use InProcess hosting?


Rick Strahl
May 11, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Sumit - Yes you'll want it so you can still run out of process or during development if you don't want to use IIS or IIS Express or you run on a non-windows platform.

ASP.NET Core will do the right thing once the server starts to figure out which server it needs to run. Those references are included in the runtime dependencies anyway so you're not gaining anything by removing them.


Andrew Robinson
May 13, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Rick, I have inprocess working fine but when running this way, I am unable to debug my app. Simple breakpoints fail to break. If I turn the hosting model settings under the project debug settings to "Out of Process" then my breakpoints start working. It wasn't clear to me from your write up that this is the behavior everyone should be seeing. Any help or pointer in the right direction would be appreciated. Thanks for the write up.


Rick Strahl
May 13, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Andrew - I haven't checked that and not actually sure whether that is supported. I suspect it isn't. Is that really necessary though? Do you really need to run in process while debugging?


William McGray
May 14, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Rick, very well explained and thank you for this article. Actually, I just want to test this new .net core project on my hosting provider. I use .net 4.5 on my site. On new project, I plan to use new .net core on my hosting since my provider has support .net core. So, this article really helpful.

@Gary, With your budget around £5 per month, just use my hosting provider, asphostportal.com. So far, they are good and really stable. Or second option for you is hostforlife.eu, it is also worth for money. Hope it helps!


Justin
May 22, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Great article, however in your previous article from 2016 about ASP.NET Core you recommended NOT to use IIS hosting in the development environment. I was interested in this updated one if you'd recommend it now, but you didn't mention it one way or another.

At our company, it's been a nightmare trying to develop ASP.NET Core apps under IIS, here are some of the issues:

  1. Any changes you make to the web.config are constantly overwritten, as this is an auto-generated file.
  2. The default web.config settings won't work if your app pool is in 32-bit compatibility mode, because it chooses the wrong dotnet.exe. You can't just change it though, because of issue #1.
  3. When the app is launched, if you try to make a change and rebuild, you get build errors about the dll's being locked / in use.
  4. The IIS website's app pool is constantly tampered with by ASP.NET Core. I have a binding set up for SSL on mine, and yet every few hours that binding is getting deleted.
  5. When things go wrong with the IIS configuration, you get a generic ANCM error page rather than a useful error message. You have to dig through event logs and try running dotnet.exe manually command line to figure out the issue.

The fact that you didn't mention any of these tells me that you're still not using IIS for local dev, that you only use it for server hosting. Is that still your recommendation then, to use IIS express locally?


Jason
June 04, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Good article - very clear. One thing I've noticed is that I've not been able to Use Forwarded Headers despite following the simple steps here: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.2 Maybe I'm missing something obvious, but still searching for an answer... Is this something you've noticed or have an explanation for pls? Thanks.


Rick Strahl
June 04, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Justin - I don't use IIS for development. There simply is not much reason to do so because unlike on IIS where there were lots of differences between IIS and IIS Express due to the hosting and security setup as well as the tight IIS pipeline integration, with .NET Core you're running the internal Web Server which exhibits the same behavior regardless of what front end Web server you are using.

That said there are a few differences, and if you happen to be using those (ie. Windows Auth and passthrough security for example) then yes you may have to run IIS for dev.

Personally for development I only run Kestrel ever with dotnet watch run. This is the most productive environment that allows for making changes and those changes being applied immediately without restarts.

Wrong Runtime (not 32 bit)

This is more of a general problem with .NET Core unfortunately in that it can't resolve the differences between 32 bit and 64 bit, and by default uses the version that was last installed and is on the Windows path. You can however provide the specific runtime in the IIS command arguments for the .NET startup file.

IIS website's app pool is constantly tampered with by ASP.NET Core

I don't think so. There's something else going on. .NET Core does nothing with configuration. You deploy your app and once it's installed, it's just an application - it doesn't change server configuration and has no access to server level features like APplication Pool configuration unless your app is writing into web.config and mucking with settings itself.

When things go wrong with the IIS configuration

Yeah that's difficult but somewhat understandable. IIS knows nothing about .NET Core and .NET Core has no specific IIS features either so if something goes wrong before the server is hoisted there's currently no error info.

The best way to work though that in my experience is to test run the application with Kestrel and see if that works first. In most cases there's a problem during the Asp.net core startup that causes the application to not connect to IIS properly and if you run with Development you should see the failures during startup. If Kestrel runs most likely the IIS app will also run. If you start in Debug mode you also getting logging info from the Kestrel app and you can hook up debug file logging to get more info written out.

There's no doubt this is more complex than classic ASP.NET hosting which was fully integrated into IIS and ASP.NET Core is more of a bolt on via a native module and the hand off during startup between the two can be rocky if something goes wrong there. But once ASP.NET Core is up and running you have access to all the tools and logging to troubleshoot.


Tim
June 06, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Great post as always. We have a .net core 2.2 web api we are hosting in an azure app service. We are getting an HTTP Error 500.30 - ANCM In-Process Start Failure error when navigating to our url. When we look at the event log we see this D:\home\site\wwwroot' hit unexpected managed exception, exception code = '0xe0434352'. Last 4KB characters of captured stdout and stderr logs: fail: Microsoft.AspNetCore.Server.HttpSys.HttpSysListener[0] .Ctor Microsoft.AspNetCore.Server.HttpSys.HttpSysException (5): Access is denied at Microsoft.AspNetCore.Server.HttpSys.ServerSession..ctor() at Microsoft.AspNetCore.Server.HttpSys.HttpSysListener..ctor

Searched for days and cannot figure out the issue. Any thoughts?


Rick Strahl
June 07, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Check and make sure your target platform matches what you compiled to in your Azure settings. Specifically 64bit vs 32 bit.

Also looks to me like you're not ussing IIS hosting but HttpSys hosting - those are not the same thing AFAIK. Check your program.cs and make sure IIS hosting is in there rather than HttpSys hosting.


Tim
June 07, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Thanks Rick. Yes we did every flavor of 64bit and 32bit in the app and on the Azure App Service. The app service is reporting Microsoft-IIS/10.0.

We want to do HttpSys (InProcess) under IIS because we are using windows auth. Here is my program.cs...

        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseHttpSys(options =>
            {
                options.Authentication.Schemes = AuthenticationSchemes.NTLM | AuthenticationSchemes.Negotiate;
                options.Authentication.AllowAnonymous = false;
            });

Rick Strahl
June 07, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Using useHttpSys() doesn't use IIS, but it uses a raw HTTP Sys handler inside of the Console applicaiton - it's a standalone host similar to running raw Kestrel but instead of Kestrel it uses HttpSys as the Web interface. It's not IIS though.

HttpSys won't work on Azure because the way the ports need to be exposed and registered on Windows. Even on client Windows this is a pain to set up. Likely that's why you are getting the Access Denied errors.

I think what you want is UseIIS() and if you use inprocess hosting Windows Auth should still work.


Bron Davies
June 25, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

This is all well and good and really is a straight-forward configuration, but what about setting up SSL on IIS with an InProcess ASP.NET CORE app. I have a very simple site that works fine over HTTP but once I applied a certificate binding to port 443 on the IIS website, Chrome won't load the page with an error of my.web.site sent an invalid response. ERR_SSL_PROTOCOL_ERROR


Rick Strahl
June 25, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Bron - that's probably unrelated to the .NET Core hosting and sounds like an invalid or badly configured certifiate.

I use standard IIS certificates with my site without issues works no different than other IIS sites.


Aravinda
July 01, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Does In Process hosting work with ASP .NET Core Apps targeting .NET Framework (v4.7.1 to be more specific)?


Jose Rodriguez
July 04, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Rick Thank you for your great post. It is really helpful for me. I struggled to test this .net core on my hosting provider. Now, everything is working fine.

@Bron If you have problem with your https, it is not related with .net Core. Are you using your own server or you use hosting provider? If you deploy your .net site with hosting provider, you might need to contact their support how to enable SSL on your site. For example, I use asphostportal here and I can just enable SSL directly via their control panel. Each hosting providers have their own configuration.


Santiago
July 11, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Excellent post! I used your first post on hosting an app in .Net Core and now you update it with this incredibly detail post on .Net Core 2.2 and IIS. Awesome!

Thank you!


Dean
July 24, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Hello, still not real sure what is best for hosting .net core 2.2 on linux? Can one use the In-Process on linux? Kestral does not even seem to be working on linux with 2.2. Any help would be appreciated......Thanks,


Menahem
September 03, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Rick this post is miles better than the info on MSDN/ms.docs, and they get paid to do it (maybe that`s the problem). Thank you for the double distilled much needed explanation on hosting Core.


Rick Strahl
September 04, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Menahem - thank you, but to be fair to the Microsoft Docs, they are documentation/reference material, rather than detailed articles, so while this in-depth content here is very useful it's also densely packed and has a lot more information than you need at a glance. Credit where Credit is due - the docs do a pretty good job for most topics to get you up and running. For more detail, you can search out articles like this that hit the edge cases and more nuanced scenarios.


Tom Hare
September 06, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Hi Rick, excellent post as always. Having a problem with an inProcess .NetCore 2.2 app trying to call another .NetCore 2.2 webservice, both configured with Windows authentication and running on the same physical server. The call returns a 401 not authorized. Any thoughts?


Victor
September 08, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Dean Not too sure if you can use In-Process on Linux server. I also curious about that configuration. But if you use it on Windows server, I can make sure it is working fine. I have tested to deploy it on asphostportal shared hosting plan. It work smoothly.


Rick Strahl
September 08, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

@Dean - Linux hosting is a completely different beast, and frankly I don't know enough about that to even write about it. Basically you typically will use a separate front end Web Server like nginx or Apache that proxies back to Kestrel just like the IIS out of process hosting setup.

Kestrel most definitely works on Linux with .NET Core 2.2 but there may be security issues in directly exposing a port directly (just as there are on Windows). Again not qualified to help with that.

FWIW, if you look at the recent benchmarks for TechemPower it turns out that IIS is actually making a pretty good showing for performance and in some cases is faster than Linux when serving .NET Core code which I found surprising. While Linux can be cheaper, Windows is still a viable option if that's what you're familiar with, especially on Azure which actually defaults to Windows hosting for ASP.NET Core.


Adi
September 15, 2019

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Hi Rick

Not something directly related to this post. I'm running a dotnet core Web API in a production and I'm struggling a big problem with unhandled exceptions crashing the whole system. I'm trying to gather logs to try fixing those problems but in the same time I want my system automatically recover meanwhile. Only IIS restart helps for now which requires me watching the system 24x7. Is there any service you can help me with that does that automatically (watch system and restart when it fails) ?

Please note that I'm now migrating to In-Process model and I'm not sure if that helps.

Thanks


Rick Strahl
Monday

# re: ASP.NET Core In Process Hosting on IIS with ASP.NET Core 2.2

Not sure - exceptions should stay localized to Kestrel if you are running out of process. When things 'lock up' you should check if IIS itself is dead (or the application - does it still serve static pages) or whether it's indeed the Kestrel server that's crashed and somehow hung.

IIS is supposed to detect hung Kestrel instances and automatically restart them. Other than that you can only resort to using some sort of monitoring application. I have an old application West Wind Web Monitor that I use for this sort of thing - it runs on the live server, checks URLs and when they fail notify you and also have the option of running a script or executable that can restart IIS (ie. run IISRESET). It's pretty old and looks it, but I've been using it on my servers as long as I can remember and it works great.


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2019