In-process hosting with IIS and ASP.NET Core

Note

This isn't the latest version of this article. For the current release, see the .NET 8 version of this article.

Warning

This version of ASP.NET Core is no longer supported. For more information, see .NET and .NET Core Support Policy. For the current release, see the .NET 8 version of this article.

Important

This information relates to a pre-release product that may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here.

For the current release, see the .NET 8 version of this article.

In-process hosting runs an ASP.NET Core app in the same process as its IIS worker process. In-process hosting provides improved performance over out-of-process hosting because requests aren't proxied over the loopback adapter, a network interface that returns outgoing network traffic back to the same machine.

The following diagram illustrates the relationship between IIS, the ASP.NET Core Module, and an app hosted in-process:

ASP.NET Core Module in the in-process hosting scenario

Enable in-process hosting

Since ASP.NET Core 3.0, in-process hosting has been enabled by default for all app deployed to IIS.

To explicitly configure an app for in-process hosting, set the value of the <AspNetCoreHostingModel> property to InProcess in the project file (.csproj):

<PropertyGroup>
  <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>

General architecture

The general flow of a request is as follows:

  1. A request arrives from the web to the kernel-mode HTTP.sys driver.
  2. The driver routes the native request to IIS on the website's configured port, usually 80 (HTTP) or 443 (HTTPS).
  3. The ASP.NET Core Module receives the native request and passes it to IIS HTTP Server (IISHttpServer). IIS HTTP Server is an in-process server implementation for IIS that converts the request from native to managed.

After the IIS HTTP Server processes the request:

  1. The request is sent to the ASP.NET Core middleware pipeline.
  2. The middleware pipeline handles the request and passes it on as an HttpContext instance to the app's logic.
  3. The app's response is passed back to IIS through IIS HTTP Server.
  4. IIS sends the response to the client that initiated the request.

CreateDefaultBuilder adds an IServer instance by calling the UseIIS method to boot the CoreCLR and host the app inside of the IIS worker process (w3wp.exe or iisexpress.exe). Performance tests indicate that hosting a .NET Core app in-process delivers significantly higher request throughput compared to hosting the app out-of-process and proxying requests to Kestrel.

Apps published as a single file executable can't be loaded by the in-process hosting model.

Application configuration

To configure IIS options, include a service configuration for IISServerOptions in Program.cs. The following example disables AutomaticAuthentication:

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Server.IIS;
using Microsoft.EntityFrameworkCore;
using RPauth.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.Configure<IISServerOptions>(options =>
{
    options.AutomaticAuthentication = false;
});

builder.Services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();
builder.Services.AddAuthentication(IISServerDefaults.AuthenticationScheme);

builder.Services.AddRazorPages();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.Run();
Option Default Setting
AutomaticAuthentication true If true, IIS Server sets the HttpContext.User authenticated by Windows Authentication. If false, the server only provides an identity for HttpContext.User and responds to challenges when explicitly requested by the AuthenticationScheme. Windows Authentication must be enabled in IIS for AutomaticAuthentication to function. For more information, see Windows Authentication.
AuthenticationDisplayName null Sets the display name shown to users on login pages.
AllowSynchronousIO false Whether synchronous I/O is allowed for the HttpContext.Request and the HttpContext.Response.
MaxRequestBodySize 30000000 Gets or sets the max request body size for the HttpRequest. Note that IIS itself has the limit maxAllowedContentLength which will be processed before the MaxRequestBodySize set in the IISServerOptions. Changing the MaxRequestBodySize won't affect the maxAllowedContentLength. To increase maxAllowedContentLength, add an entry in the web.config to set maxAllowedContentLength to a higher value. For more details, see Configuration.

Differences between in-process and out-of-process hosting

The following characteristics apply when hosting in-process:

  • IIS HTTP Server (IISHttpServer) is used instead of Kestrel server. For in-process, CreateDefaultBuilder calls UseIIS to:

    • Register the IISHttpServer.
    • Configure the port and base path the server should listen on when running behind the ASP.NET Core Module.
    • Configure the host to capture startup errors.
  • The requestTimeout attribute doesn't apply to in-process hosting.

  • Sharing an app pool among apps isn't supported. Use one app pool per app.

  • The architecture (bitness) of the app and installed runtime (x64 or x86) must match the architecture of the app pool. For example, apps published for 32-bit (x86) must have 32-bit enabled for their IIS Application Pools. For more information, see the Create the IIS site section.

  • Client disconnects are detected. The HttpContext.RequestAborted cancellation token is cancelled when the client disconnects.

  • When hosting in-process, AuthenticateAsync isn't called internally to initialize a user. Therefore, an IClaimsTransformation implementation used to transform claims after every authentication isn't activated by default. When transforming claims with an IClaimsTransformation implementation, call AddAuthentication to add authentication services:

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Server.IIS;
using Microsoft.EntityFrameworkCore;
using RPauth.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.Configure<IISServerOptions>(options =>
{
    options.AutomaticAuthentication = false;
});

builder.Services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();
builder.Services.AddAuthentication(IISServerDefaults.AuthenticationScheme);

builder.Services.AddRazorPages();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.Run();

In-process hosting runs an ASP.NET Core app in the same process as its IIS worker process. In-process hosting provides improved performance over out-of-process hosting because requests aren't proxied over the loopback adapter, a network interface that returns outgoing network traffic back to the same machine.

The following diagram illustrates the relationship between IIS, the ASP.NET Core Module, and an app hosted in-process:

ASP.NET Core Module in the in-process hosting scenario

Enable in-process hosting

Since ASP.NET Core 3.0, in-process hosting has been enabled by default for all app deployed to IIS.

To explicitly configure an app for in-process hosting, set the value of the <AspNetCoreHostingModel> property to InProcess in the project file (.csproj):

<PropertyGroup>
  <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>

General architecture

The general flow of a request is as follows:

  1. A request arrives from the web to the kernel-mode HTTP.sys driver.
  2. The driver routes the native request to IIS on the website's configured port, usually 80 (HTTP) or 443 (HTTPS).
  3. The ASP.NET Core Module receives the native request and passes it to IIS HTTP Server (IISHttpServer). IIS HTTP Server is an in-process server implementation for IIS that converts the request from native to managed.

After the IIS HTTP Server processes the request:

  1. The request is sent to the ASP.NET Core middleware pipeline.
  2. The middleware pipeline handles the request and passes it on as an HttpContext instance to the app's logic.
  3. The app's response is passed back to IIS through IIS HTTP Server.
  4. IIS sends the response to the client that initiated the request.

CreateDefaultBuilder adds an IServer instance by calling the UseIIS method to boot the CoreCLR and host the app inside of the IIS worker process (w3wp.exe or iisexpress.exe). Performance tests indicate that hosting a .NET Core app in-process delivers significantly higher request throughput compared to hosting the app out-of-process and proxying requests to Kestrel.

Apps published as a single file executable can't be loaded by the in-process hosting model.

Application configuration

To configure IIS options, include a service configuration for IISServerOptions in ConfigureServices. The following example disables AutomaticAuthentication:

services.Configure<IISServerOptions>(options => 
{
    options.AutomaticAuthentication = false;
});
Option Default Setting
AutomaticAuthentication true If true, IIS Server sets the HttpContext.User authenticated by Windows Authentication. If false, the server only provides an identity for HttpContext.User and responds to challenges when explicitly requested by the AuthenticationScheme. Windows Authentication must be enabled in IIS for AutomaticAuthentication to function. For more information, see Windows Authentication.
AuthenticationDisplayName null Sets the display name shown to users on login pages.
AllowSynchronousIO false Whether synchronous I/O is allowed for the HttpContext.Request and the HttpContext.Response.
MaxRequestBodySize 30000000 Gets or sets the max request body size for the HttpRequest. Note that IIS itself has the limit maxAllowedContentLength which will be processed before the MaxRequestBodySize set in the IISServerOptions. Changing the MaxRequestBodySize won't affect the maxAllowedContentLength. To increase maxAllowedContentLength, add an entry in the web.config to set maxAllowedContentLength to a higher value. For more details, see Configuration.

Differences between in-process and out-of-process hosting

The following characteristics apply when hosting in-process:

  • IIS HTTP Server (IISHttpServer) is used instead of Kestrel server. For in-process, CreateDefaultBuilder calls UseIIS to:

    • Register the IISHttpServer.
    • Configure the port and base path the server should listen on when running behind the ASP.NET Core Module.
    • Configure the host to capture startup errors.
  • The requestTimeout attribute doesn't apply to in-process hosting.

  • Sharing an app pool among apps isn't supported. Use one app pool per app.

  • The architecture (bitness) of the app and installed runtime (x64 or x86) must match the architecture of the app pool. For example, apps published for 32-bit (x86) must have 32-bit enabled for their IIS Application Pools. For more information, see the Create the IIS site section.

  • Client disconnects are detected. The HttpContext.RequestAborted cancellation token is cancelled when the client disconnects.

  • When hosting in-process, AuthenticateAsync isn't called internally to initialize a user. Therefore, an IClaimsTransformation implementation used to transform claims after every authentication isn't activated by default. When transforming claims with an IClaimsTransformation implementation, call AddAuthentication to add authentication services:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<IClaimsTransformation, ClaimsTransformer>();
        services.AddAuthentication(IISServerDefaults.AuthenticationScheme);
    }
    
    public void Configure(IApplicationBuilder app)
    {
        app.UseAuthentication();
    }
    
  • Web Package (single-file) deployments aren't supported.