Skip to main content

How to Deploy ASP.NET Core to IIS & Troubleshoot 502 / 500.30 Startup Errors

Production guide for configuring IIS, the ASP.NET Core Hosting Bundle, In-Process hosting, AppPool permissions, and diagnosing 502 / 500.30 startup errors.

· 12 min read · Intermediate to Advanced

Key takeaways

  • Understand the architectural difference between In-Process and Out-of-Process hosting in IIS.
  • Configure Application Pool identities and directory security ACLs correctly.
  • Enable stdout logging and capture Event Viewer error codes to fix HTTP 500.30 & 502.5 failures instantly.
  • Enforce HTTPS redirection, HSTS headers, and reverse-proxy forwarded headers.

Most enterprise environments still put ASP.NET Core behind IIS on Windows Server, even though modern .NET runs perfectly well on Kestrel by itself. There's a reason for that. IIS handles the reverse-proxy work, SSL termination, request filtering, and process lifecycle management that you'd otherwise have to build yourself.

1. In-Process vs Out-of-Process Hosting Models

Set hostingModel="inprocess" and your compiled app runs directly inside the IIS worker process, w3wp.exe. No loopback HTTP adapter in between. That one change is why In-Process hosting consistently outperforms Out-of-Process on both throughput and memory latency — it's been the default across ASP.NET Core 3.x through .NET 8/9/10 for good reason.

<!-- web.config for In-Process Hosting -->
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet"
                  arguments=".\YourApp.dll"
                  stdoutLogEnabled="true"
                  stdoutLogFile=".\logs\stdout"
                  hostingModel="inprocess">
        <environmentVariables>
          <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
        </environmentVariables>
      </aspNetCore>
    </system.webServer>
  </location>
</configuration>

2. Common Failure: HTTP 500.30 — ASP.NET Core In-Process Startup Failure

This one means w3wp.exe successfully started AspNetCoreModuleV2, but the .NET CLR threw an unhandled exception somewhere during Program.cs initialization. Usually it's a Dependency Injection resolution failure, an invalid connection string, or a missing appsettings.Production.json — rarely anything more exotic than that.

3. Application Pool Permissions & Identity ACLs

IIS Application Pools run under a virtual identity by default — "IIS AppPool\<AppPoolName>". That works fine until your app needs to write logs to disk, generate dynamic PDFs, or buffer temp files, at which point you need to grant write access explicitly. PowerShell handles this in a few lines:

# PowerShell: Grant AppPool Read & Write permissions to deployment folder
$path = "C:\inetpub\wwwroot\arahimx-api"
$appPool = "IIS AppPool\ArahimxAppPool"

$acl = Get-Acl $path
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($appPool, "ReadAndExecute, Write", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
Set-Acl $path $acl

4. Forwarded Headers & HTTPS Configuration

IIS terminates SSL and proxies the request on to Kestrel. That means Kestrel never sees the original HTTPS scheme or the real client IP unless you tell ASP.NET Core to read them off the forwarded headers instead:

// Program.cs
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    // Trust the local reverse proxy
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

var app = builder.Build();
app.UseForwardedHeaders();
app.UseHsts();
app.UseHttpsRedirection();

Summary & Key Takeaway

Enable stdout logging before you need it, not after. Keep In-Process hosting on for the performance win, and put the whole configuration behind CI/CD so it doesn't quietly drift between environments over time.

← All guides