ASP.NET Core is running on Kestrel, ASP.NET Core’s internal web server. Although really fast Kestrel is not a full blown web server. The idea is that you put another web server(on Windows typically IIS) in front of it that acts as a proxy and forwards the requests to Kestrel.
To get this working in IIS, an AspNetCoreModule exists that achieves this goal. Here is the web.config that configures all of this:
<?xml version="1.0" encoding="utf-8"?> | |
<configuration> | |
<!-- | |
Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380 | |
--> | |
<system.webServer> | |
<handlers> | |
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/> | |
</handlers> | |
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/> | |
<httpProtocol> | |
<customHeaders> | |
<!--Is set in startup.cs with services.addcors, so we can't set it here also (Xavier)--> | |
<!--<add name="Access-Control-Allow-Origin" value="*" />--> | |
<!--<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />--> | |
<!--<add name="Access-Control-Allow-Headers" value="*" />--> | |
</customHeaders> | |
</httpProtocol> | |
</system.webServer> | |
</configuration> |
If you look at the configuration, you see that by default all request(path="*" verb="*") are forwarded to Kestrel. This isn't ideal because Kestrel is a lot slower in handling static files than IIS.
A better solution is to only forward the requests that should be handled by ASP.NET Core(by example; path="api/*" verb="*") and let other requests be served by IIS.
The magic trick is to use IIS URL Rewrite rules to forward requests to the wwwroot folder of your ASP.NET Core app:
<system.webServer> | |
<rewrite> | |
<rules> | |
<rule name="wwwroot-static"> | |
<match url="([\S]+[.](html|htm|js|css))" /> | |
<action type="Rewrite" url="wwwroot/{R:1}" /> | |
</rule> | |
</rules> | |
</rewrite> | |
<handlers> | |
<add name="StaticFileModuleHtml" path="*.htm*" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" /> | |
<add name="StaticFileModuleJs" path="*.js" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" /> | |
<add name="StaticFileModuleCss" path="*.css" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" /> | |
<add name="aspNetCore" path="api/*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" /> | |
</handlers> | |
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" | |
stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/> | |
</system.webServer> |
UPDATE: Rick Strahl did a more complete blog post where he took this approach a few steps further: https://weblog.west-wind.com/posts/2017/Apr/27/IIS-and-ASPNET-Core-Rewrite-Rules-for-AspNetCoreModule