IIS Deployment
Web API 2 apps live on IIS, Windows Server’s web server. Deploying means publishing the compiled site, configuring an application pool and a site, and swapping in production settings.
On this page · 5 min · Advanced
On this page
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Advanced
- Updated
- Oct 28, 2026
Related tutorials
Learning objectives#
- Prepare a Windows server with IIS and ASP.NET 4.8
- Publish the project with release settings
- Use Web.config transforms for environment settings
- Configure the app pool, HTTPS binding and database access
Explanation#
On the server, enable IIS with ASP.NET 4.8 (Server Manager → Web Server (IIS) → Application Development → ASP.NET 4.8). Install URL Rewrite and Dynamic Compression if you use them.
Publish from Visual Studio (Publish → Folder or Web Deploy) or from the command line with MSBuild. The output contains bin\, Global.asax and the transformed Web.config — no .cs files.
Web.config transforms (Web.Release.config) replace values at publish time: connection strings, app settings, debug="false". Keep real secrets out of Git by applying them on the build server or the server itself.
Create an application pool: .NET CLR Version v4.0, Managed Pipeline Integrated. Each API gets its own pool (and identity, IIS APPPOOL\ShopApi) so a crash or recycle affects only that app.
Create the site (or an application under an existing site), bind HTTPS with a certificate, and give the app pool identity read access to the folder and write access to App_Data if needed.
For SQL Server with Integrated Security, create a login for the app pool identity (or a domain service account) with least privilege.
Syntax#
# Build and publish to a folder (Developer Command Prompt for VS)
msbuild ShopApi.csproj /p:Configuration=Release /p:DeployOnBuild=true /p:PublishProfile=FolderProfile
# On the server: create the app pool and site with appcmd
%windir%\system32\inetsrv\appcmd add apppool /name:ShopApi /managedRuntimeVersion:v4.0 /managedPipelineMode:Integrated
%windir%\system32\inetsrv\appcmd add site /name:ShopApi /physicalPath:D:\sites\ShopApi /bindings:https/*:443:api.shop.com
%windir%\system32\inetsrv\appcmd set app "ShopApi/" /applicationPool:ShopApi
Code example: Web.Release.config — production values applied at publish#
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="ShopDb"
connectionString="Server=sql-prod01;Database=Shop;Integrated Security=True;"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</connectionStrings>
<appSettings>
<add key="Cors:Origins" value="https://shop.example.com"
xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
<add key="Environment" value="Production"
xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
</appSettings>
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
</system.web>
</configuration>
When publishing in Release, Visual Studio/MSBuild merges this file into Web.config: the ShopDb connection string points to sql-prod01, CORS allows only the production site, Environment becomes Production, and debug="true" is removed so IIS compiles optimised code and hides debug output.
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- xdt:Locator="Match(name)" finds the connection string with the same name in Web.config.
- xdt:Transform="SetAttributes" replaces only the attributes listed (connectionString, value).
- RemoveAttributes(debug) turns off debug compilation in production.
- appcmd creates an isolated application pool and an HTTPS site pointing at the published folder.
- The pool identity IIS APPPOOL\ShopApi is what SQL Server sees with Integrated Security.
Real-world use case#
A team deploys to two IIS servers behind a load balancer with Web Deploy from Azure DevOps. The pipeline applies Web.Release.config, injects the SQL password from a secret variable, takes one server out of rotation at a time, and runs smoke tests after each.
Common mistakes#
Debug compilation is slower, uses more memory and can leak details. Make sure the Release transform removes it.
.NET CLR “No Managed Code” or Classic pipeline breaks Web API. Use v4.0 and Integrated.
Usually a Web.config section that needs an IIS module (URL Rewrite, compression) not installed on the server. Install the module or remove the section.
Best practices#
- One application pool per API
- Publish Release builds only, with transforms
- HTTPS binding with a valid certificate
- Least-privilege identities for files and SQL
Remember this#
App pool: .NET CLR v4.0 + Integrated.
Web.Release.config: SetAttributes + Match(name/key).
IIS APPPOOL\YourPool is the identity SQL and the file system see.
Practice exercise#
Your task: Write a Web.Staging.config transform that sets the ShopDb connection string to Server=sql-staging;Database=Shop;Integrated Security=True; and Environment to Staging.
Need a hint?
Show solution
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="ShopDb" connectionString="Server=sql-staging;Database=Shop;Integrated Security=True;"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</connectionStrings>
<appSettings>
<add key="Environment" value="Staging" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
</appSettings>
</configuration>
Mini quiz#
Which application pool settings does Web API 2 need?
Want more? Practise all ASP.NET Web API MCQs · ASP.NET Web API interview questions
My notes#
Saved in this browser.