ASP.NET Core Behind IIS: ANCM Hosting Models and 500.30 / 502.5 / 500.19 Fixes

ASP.NET Core does not run inside IIS. It runs as a separate out-of-process dotnet worker, and IIS sits in front of it as a reverse proxy using the ASP.NET Core Module (ANCM). Understanding that one sentence explains almost every deployment failure administrators hit on Windows: the 500.30, the 502.5, the app that works with dotnet run but not through a site binding, and the HTTPS redirect loop. This article covers the install order, the module configuration that matters, and the diagnostic path for each of the common failures.

The Two Hosting Models and Which One You Are Using

In-process hosting (<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel> in the project file, and the default since .NET Core 3.0) loads the application inside w3wp.exe via a modified ANCM. Out-of-process hosting runs dotnet MyApp.dll as a child process and proxies HTTP over a loopback port. In-process is faster — no extra hop, no port, less memory — and it is the right default on Windows Server. Out-of-process remains useful when you need a different runtime version than the server’s or when you want the worker isolated from IIS.

The distinction matters for troubleshooting because the log locations and error codes differ. Both ultimately surface in the Windows Application event log under source IIS AspNetCore Module V2, but in-process failures usually appear as a request-level 500 with a stack trace in the app’s own logging, while out-of-process failures often appear as a proxy error before the app has produced any output.

Install Order: Runtime, Hosting Bundle, IIS Feature

StepComponentWhy order matters
1IIS role with Static Content, Request Filtering, WebSocket ProtocolANCM installer registers handlers against an existing IIS
2ASP.NET Core Hosting Bundle (.NET 8 or later)Installs ANCM V2 plus the shared runtime and dotnet CLI
3Verify dotnet --list-runtimesConfirms the runtime matches the app’s target framework
4Publish output to the site folderweb.config is generated by the SDK at publish time
5Restart IIS (iisreset)Picks up module registration changes

The most common install mistake is installing the runtime (the lightweight installer) rather than the Hosting Bundle. The runtime includes dotnet and the shared frameworks but not ANCM, so IIS has no handler for the application and returns a static 404 or 500.19. If %ProgramFiles%\IIS\Asp.Net Core Module\V2\aspnetcorev2.dll is missing, this is your problem.

After installing the bundle, iisreset. The ANCM installer registers the module at the server level, but a running worker process will not see the new module until it restarts. Skipping this step produces a “module handler not found” error on an otherwise correct installation.

Reading the web.config the SDK Generates

Publishing an ASP.NET Core project emits a web.config whose relevant section looks like this for in-process hosting:

<aspNetCore processPath="dotnet" arguments=".\MyApp.dll" hostingModel="inprocess" stdoutLogEnabled="false" />

Three edits are worth making. First, set stdoutLogEnabled="true" and stdoutLogFile=".\logs\stdout" during initial deployment — this is the only place startup exceptions are written before the app’s own logger is configured. Turn it back off once stable, or the log directory will fill. Second, add hostingModel="inprocess" explicitly if you are migrating from an older publish profile that assumes out-of-process. Third, for out-of-process, set the processPath to the absolute path of dotnet.exe if the PATH is ambiguous.

Remember that web.config in the publish folder is the effective one. Editing the project-level file does nothing at runtime, and editing the deployed copy gets overwritten on the next publish unless you have configured the build to preserve changes. Keep a transform or a post-publish step instead.

Application Pool and Identity Settings

Two application pool settings cause more ASP.NET Core support tickets than any others. The first is “No Managed Code”: the pool’s .NET CLR Version must be set to No Managed Code, because IIS is only proxying — leaving it on v4.0 loads the legacy CLR for no reason and can cause odd module conflicts. The second is the identity: the default ApplicationPoolIdentity works fine for reading the publish folder, but any file writes (logs, uploads, data protection keys) need an explicit ACL grant on those folders.

Data protection keys deserve a specific mention. ASP.NET Core encrypts cookies and antiforgery tokens using keys stored under the user profile by default. Under ApplicationPoolIdentity those keys live in a profile that may be recycled or recreated, which manifests as users being logged out at random. Persist the keys to a folder with an explicit ACL, or to a shared location if you run multiple nodes.

Diagnosing 500.30, 502.5, and 500.19

HTTP Error 500.30 – ANCM In-Process Start Failure means the app started and then exited. The app’s stdout log is the place to look. Typical causes: a missing appsettings section, a connection string the app cannot reach at startup, a Program.cs exception in top-level statements, or a target framework mismatch between the publish output and the installed runtime.

HTTP Error 502.5 – Process Failure is the out-of-process analogue: ANCM launched dotnet app.dll and the process exited before binding a port. Read the stdout log for the exception. If there is no log at all, the process failed before the app’s logger initialised — usually a missing runtime version or a bad path in processPath.

HTTP Error 500.19 with “cannot read configuration file because it contains invalid XML” or “this configuration section cannot be used at this path” is an IIS-level problem, not an app problem. It is usually a missing IIS feature (AspNetCoreModuleV2 section locked), a 32-bit/64-bit mismatch in the handler, or a duplicated <aspNetCore> element from a copied web.config. Check the “Config Error” block on the error page — it names the exact file and line.

For anything intermittent, enable Failed Request Tracing at the site level with a rule scoped to status codes 400–599. The trace will show how far the request got through the module chain, which cleanly separates an ANCM problem from an application problem. Our walkthrough on tracing .NET startup failures in IIS has the step-by-step setup.

HTTPS, Forwarded Headers, and the Redirect Loop

The classic symptom is an infinite redirect on an HTTPS site that works over HTTP. IIS terminates TLS and forwards a plain HTTP request to the app; the app sees HttpContext.Request.Scheme == "http" and its UseHttpsRedirection middleware redirects to HTTPS, which IIS terminates again, and the cycle repeats. The fix is the Forwarded Headers middleware, configured to trust the loopback proxy and to honour X-Forwarded-Proto:

app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto });

This must be registered before UseHttpsRedirection and before authentication. In .NET 8 and later the default known-networks list excludes the loopback address, so you must either add KnownNetworks/KnownProxies for 127.0.0.1 and ::1, or clear the lists if IIS is the only ingress. Also configure ASPNETCORE_FORWARDEDHEADERS_ENABLED=true on hosts where you cannot change code.

A Deployment Checklist

  • Hosting Bundle installed, not just the runtime; ANCM V2 DLL present; iisreset run afterwards.
  • App pool set to No Managed Code, 64-bit, and an identity with explicit ACLs on log and key folders.
  • web.config hosting model set deliberately; stdout logging on for first deploy, off once stable.
  • Data protection keys persisted outside the user profile.
  • Forwarded headers configured before HTTPS redirection; known proxies include the loopback address.
  • Failed Request Tracing enabled temporarily for any startup or redirect issue.
  • Publish artifact tested on the same runtime version as the server, not the dev machine.

Get those seven items right and ASP.NET Core on IIS is a quiet, reliable deployment. Most of the pain people attribute to IIS comes from the mismatch between what the SDK publishes and what the server actually has installed. If you are provisioning a new host for this kind of workload, the Windows VPS plans for .NET and IIS hosting list the instance shapes that include the memory headroom a hosting bundle plus a worker process needs, and the support team can confirm which .NET runtimes are preinstalled on your chosen image.

Leave a Comment