One of the new features of ASP.NET Core 2.2 is support for hosting ASP.NET Core Web App with IIS using in-process or out-of-process hosting model. This article will cover steps needed to
- Host ASP.NET Core 2.2 Web API with IIS using in-process hosting model
- Host ASP.NET Core 2.2 Web API with IIS using out-of-process hosting model
- Host ASP.NET Core 2.2 Web API in Docker Windows containers (with IIS)
In ASP.NET Core 2.2, a new ASP.NET Core Module (AspNetCoreModuleV2) has been introduced which is a native IIS module that plugs into the IIS pipeline and provides in-process or out-of-process hosting capabilities. AspNetCoreModule used to be the module in previous version.
The dev tools used to develop these components are Visual Studio 2017 and Docker for Windows (Docker CE) and source code is available for download at GitHub.
ASP.NET Core 2.2 in-process hosting model with IIS
The main pointers about in-process hosting model with IIS are
- This is the default hosting model on creating a new ASP.NET Core 2.2 app where ASP.NET Core app is hosted within IIS worker process (w3wp.exe).
- When hosting in-process, ASP.NET Core module uses an in-process server implementation for IIS, called IIS HTTP Server (
IISHttpServer
) and avoids the additional cost of reverse-proxying requests over to a separate dotnet process. - You can specify in-process hosting model by
- Editing project file i.e.
<AspNetCoreHostingModel> InProcess </AspNetCoreHostingModel>
- Navigate to
Project Properties > Debug > Web Server Settings
and choose Hosting Model (you need to select IIS Express profile)
- Editing project file i.e.
- You need to use one app pool per app as sharing an app pool among apps isn’t supported.
- The new module is only capable of hosting .NET Core in the IIS process.
A sample web.config on publishing ASP.NET Core 2.2 Web App using in-process hosting model is displayed below
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\SampleWebAppForIIS.dll" stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout" hostingModel="InProcess" />
</system.webServer>
</location>
</configuration>
ASP.NET Core 2.2 out-of-process hosting model with IIS
The main pointers about out-of-process hosting model with IIS are
- Kestrel Server is used instead of IISHttpServer. The ASP.NET Core module forwards requests to ASP.NET Core app running Kestrel Server.
- When hosting out-of-process, the module only works with Kestrel. The module is incompatible with HTTP.sys.
- You can specify out-of-process hosting model by
- Editing project file i.e.
<AspNetCoreHostingModel>OutOfProcess </AspNetCoreHostingModel>
- Navigate to
Project Properties > Debug > Web Server Settings
and choose Hosting Model (you need to select IIS Express profile) - In case you do not specify
AspNetCoreHostingModel
in project file, it defaults to out-of-process hosting model.
- Editing project file i.e.
A sample web.config on publishing ASP.NET Core 2.2 Web App using out-of-process hosting model is displayed below
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\SampleWebAppForIIS.dll" stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout" hostingModel="OutOfProcess" />
</system.webServer>
</location>
</configuration>
Host ASP.NET Core 2.2 Web API in Docker Windows containers (with IIS)
Ensure that you have ASP.NET Core 2.2 installed on your developer machine. Create an ASP.NET Core Web App and select ASP.NET Core 2.2 version of .NET Core along with enabling Docker support (OS: Windows) as displayed below
I have updated the controller’s Get method to return the process name based on which we can identify in-process and out-of-process hosting model with IIS.
public ActionResult<ienumerable> Get()
{
return new string[] { Process.GetCurrentProcess().ProcessName };
}</ienumerable
Update the DockerFile as displayed below and main pointers about DockerFile are
- I have specified
microsoft/iis
as base image since I need to deploy Web API to windows containers having IIS. - Dotnet 2.2.0 hosting pack needs to be installed as
microsoft/iis
image doesn’t has ASP.NET Core 2.2 runtime installed which is needed to run the ASP.NET Core 2.2 Web App. microsoft/dotnet:2.2-sdk-nanoserver-1803
image is needed to build ASP.NET Core 2.2 Web Application project.- Docker multi-stage build optimizes image size by removing intermediate containers.
- Instead of using Default Web Site, I have created a new app pool and a web site. App pool name is ‘ap-samplewebapp’ and web site name is ‘samplewebapp’.
- Managed Runtime version of app pool is set to blank since ASP.NET Core runs in a separate process and manages the runtime. ASP.NET Core doesn’t rely on loading the desktop CLR. Setting the .NET CLR version to No Managed Code is optional.
- In case you need Integrated Windows authentication, you will need Group Managed Service Accounts(gMSA). You can read further about gMSA @ Active Directory Service Accounts for Windows Containers
# escape=`
FROM microsoft/iis as base
## Install dotnet 2.2.0 hosting pack
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"]
ADD https://download.visualstudio.microsoft.com/download/pr/48adfc75-bce7-4621-ae7a-5f3c4cf4fc1f/9a8e07173697581a6ada4bf04c845a05/dotnet-hosting-2.2.0-win.exe "C:/setup/dotnet-hosting-2.2.0-win.exe"
RUN start-process -Filepath "C:/setup/dotnet-hosting-2.2.0-win.exe" -ArgumentList @('/install', '/quiet', '/norestart') -Wait
RUN Remove-Item -Force "C:/setup/dotnet-hosting-2.2.0-win.exe"
## End Install dotnet 2.2.0 hosting pack
## Build and Publish Web App
FROM microsoft/dotnet:2.2-sdk-nanoserver-1803 AS build
WORKDIR /src
COPY ["SampleWebAppForIIS/SampleWebAppForIIS.csproj", "SampleWebAppForIIS/"]
RUN dotnet restore "SampleWebAppForIIS/SampleWebAppForIIS.csproj"
COPY . .
WORKDIR "/src/SampleWebAppForIIS"
RUN dotnet build "SampleWebAppForIIS.csproj" --no-restore --no-dependencies -c Release -o /app
FROM build AS publish
RUN dotnet publish "SampleWebAppForIIS.csproj" -c Release -o /publish
FROM base AS final
WORKDIR /inetpub/wwwroot/samplewebapp
## Create Web Site and Web Application
RUN Import-Module WebAdministration; `
Remove-Website -Name 'Default Web Site'; `
New-WebAppPool -Name 'ap-samplewebapp'; `
Set-ItemProperty IIS:\AppPools\ap-samplewebapp -Name managedRuntimeVersion -Value ''; `
Set-ItemProperty IIS:\AppPools\ap-samplewebapp -Name enable32BitAppOnWin64 -Value 0; `
Set-ItemProperty IIS:\AppPools\ap-samplewebapp -Name processModel.identityType -Value Service; `
New-Website -Name 'samplewebapp' `
-Port 80 -PhysicalPath 'C:\inetpub\wwwroot\samplewebapp' `
-ApplicationPool 'ap-samplewebapp' -force
COPY --from=publish /publish .
EXPOSE 80
Build and Publish Docker Image to Docker Hub
If you have Docker for Windows installed, you can run commands listed below to build and publish docker image to Docker Hub
- Build Docker Image:
docker build -t samplewebapp -f ./SampleWebApplicationforIIS/DockerFile .
- Tag Docker Image:
docker tag samplewebapp {YOUR_DOCKER_REPO}
- Publish Image to Docker Hub:
docker push {YOUR_DOCKER_REPO}
As an alternate option, you can also create Azure DevOps build pipeline to build and publish docker image to Docker Hub. The steps are
- Specify ‘Docker Container’ template during creating build pipeline
- Specify ‘Hosted Windows Container’ as Agent Pool
- Select a Docker registry service connection
- Specify DockerFile, Docker connection, Image Name etc. values in Build, Tag and Publish steps.
Create Windows Container from ASP.NET Core 2.2 Web API Docker image
After publishing Docker image, the next step is to create Windows container from ASP.NET Core 2.2 Web API Docker image. The Docker commands which are needed to create Windows container in ‘Docker for Windows’ are
- Create Docker Windows container by executing command
docker run -d -p 8000:80 --name samplewebappdemo {YOUR_DOCKER_REPO}
. This command will also display Container ID upon completion. - Get the IP Address of the container by running command
docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" samplewebappdemo
. This address is needed to browse to Web API URL. - If you want to connect to a running container using powershell, the command is
docker exec -t -i {YOUR_CONTAINER_ID} powershell
You can also install Kitematic which is used to manage Docker containers from GUI.
Demo
Navigate to the Web API URL after creating container(in-process), you will find that process name for in-process hosting model app is ‘w3wp’.
Similarly, if you navigate to the Web API URL after creating container (out-of-process), you will find that process name for out-of-process hosting model is ‘dotnet’.
Summary
This completes the article about hosting ASP.NET Core Web App with IIS using in-process or out-of-process hosting model along with deploying ASP.NET Core Web app to Windows Docker containers. You can download source code for this article from GitHub.