— Kiaasa Dhanori Pune

To deploy an ASP.NET web service to IIS you create a target folder, grant the right NTFS permissions to an Active Directory service account, build a dedicated application pool that runs as that account, import the Web Deploy package, fix the database connection string, set authentication, and finally test a web method. Done correctly, the service authenticates to SQL Server with Windows integrated security instead of a password buried in web.config.
This guide walks the entire process on Windows Server with IIS 7+ and the .NET Framework, using neutral placeholder names so you can map each step to your own environment. Wherever the original runbook had a rough edge, the corrected, modern approach is called out so the result is secure and repeatable.
Why deploy an ASP.NET web service this way
The core design decision is to deploy an ASP.NET web service to IIS under a custom application pool whose identity is a domain service account. That single choice solves a recurring security problem: it removes the SQL username and password from the connection string entirely.
Instead of storing credentials in clear text, the application pool's worker process runs as a managed AD account, and SQL Server trusts that Windows identity. The benefits are concrete:
- No plaintext SQL passwords in
web.config— onlyTrusted_Connection=Yes. - Centralized credential rotation — the password is managed in Active Directory, not edited across servers.
- Least privilege — the service account is granted exactly the database and file rights it needs.
- Cleaner auditing — SQL and file access trace back to a named identity, not a shared local account.
The example assumes a folder layout under the IIS site such as D:\inetpub\wwwroot\WS\, where WS is a parent application that holds one or more individual web-service applications. We will add a new application called SampleData.
Prerequisites before you begin
Confirm these are in place on the web server, or the later steps will fail in confusing ways:
- IIS with the matching ASP.NET version registered. For a .NET Framework 4.x app, the ASP.NET 4.x role feature must be installed and the framework registered (
aspnet_regiis -ion legacy boxes, or the Web Server role's ASP.NET 4.x feature on Windows Server 2012+). - Web Deploy (msdeploy) installed if you plan to use Import Application from a
.zippackage. Without it, IIS will not show the Deploy menu. - The AD service account and group already created in your domain (for example a service account and an authorization role group).
- SQL Server logins created for that service account on the target database, with the needed
db_datareader/db_datawriteror stored-procedure execute rights. - The Web Deploy package built from the project (Visual Studio's Publish > Web Deploy Package, or MSBuild) and copied to the server.
Modern note: classic .asmx SOAP web services and the .NET Framework are legacy. New work should target ASP.NET Core Web API hosted in IIS via the ASP.NET Core Module, or a Windows/Linux container. The IIS-plus-app-pool-identity pattern below still applies almost unchanged for ASP.NET Core, so the steps remain useful even as you modernize the runtime.
Step-by-step: deploy an ASP.NET web service to IIS
-
Create the target directory. In File Explorer (or PowerShell) create the folder that will hold the new application:
New-Item -ItemType Directory -Path 'D:\inetpub\wwwroot\WS\SampleData' -Force -
Grant NTFS permissions to the service account and role group. Right-click the new folder, choose Properties > Security > Edit > Add. Use the Locations button to select the correct domain, type the service account name (for example
SVC.WEBAPP), and click Check Names to resolve it to the fullaccount@your.domainform. Grant the minimum read rights: Read & execute, List folder contents, and Read. Repeat for the authorization role group (for exampleROL-WEBAPP_PROD).The same thing from an elevated prompt:
icacls "D:\inetpub\wwwroot\WS\SampleData" /grant "YOURDOMAIN\SVC.WEBAPP:(OI)(CI)RX"icacls "D:\inetpub\wwwroot\WS\SampleData" /grant "YOURDOMAIN\ROL-WEBAPP_PROD:(OI)(CI)RX"Here
(OI)(CI)makes the grant inherit to files and subfolders andRXis read-and-execute. Grant Modify only if the app must write to disk (logs, temp uploads); a read-only deployment should stay read-only. -
Create a dedicated application pool. Open IIS Manager, select Application Pools, and click Add Application Pool. Name it
SampleData, choose .NET CLR version v4.0, and set the managed pipeline mode to Integrated. Click OK.Note: the IIS dialog is labelled "Add Application Pool," not "Add Application" — the original runbook's wording is a common slip. For an ASP.NET Core app you would instead pick No Managed Code here.
-
Set the pool identity to the AD service account. Select the new pool, open Advanced Settings, find Identity under Process Model, click the ... button, choose Custom account > Set, and enter the service account and password. Click OK back to the main screen. This is the identity that SQL Server will trust.
PowerShell equivalent:
Import-Module WebAdministrationSet-ItemProperty 'IIS:\AppPools\SampleData' -Name processModel.identityType -Value SpecificUserSet-ItemProperty 'IIS:\AppPools\SampleData' -Name processModel.userName -Value 'YOURDOMAIN\SVC.WEBAPP'Set-ItemProperty 'IIS:\AppPools\SampleData' -Name processModel.password -Value 'YourStrongPassword' -
Copy the Web Deploy package to the server. Transfer the built package (for example
SampleData_Release_YYYYMMDD.zip) from your release share to a staging folder on the web server. Always prefer a secure transfer (a UNC share over SMB, or SFTP) rather than plain unencrypted FTP, which exposes credentials and contents on the wire. -
Import the application from the package. In IIS Manager, expand the site, right-click the parent WS application (or the Default Web Site), and choose Deploy > Import Application. Browse to the
.zipfrom the previous step and click Next. Keep the contents selected, click Next, then set the Application Path toSampleDataand finish. IIS unpacks the package into your target folder and registers the application.If you prefer the command line:
msdeploy -verb:sync -source:package="C:\Staging\SampleData_Release_YYYYMMDD.zip" -dest:auto -setParam:name="IIS Web Application Name",value="Default Web Site/WS/SampleData" -
Correct the database connection string. Open the deployed
web.configand set the right server and database for the environment. Using Windows integrated security keeps secrets out of the file:<appSettings><add key="ConnectionString" value="Server=SQLPROD01.your.domain;Trusted_Connection=Yes;Database=SampleDb" /></appSettings>Keep a per-environment value so DEV, QA, and PROD point at the correct SQL instance and database. A cleaner pattern is the standard
<connectionStrings>section withIntegrated Security=SSPI, but if the application reads fromappSettingsas above, match what the code expects. -
Set authentication on the application. Select the
SampleDataapplication, open the Authentication feature, then Enable Anonymous Authentication and Disable Windows Authentication if the service is meant to be reached without per-user Windows challenge. With anonymous enabled, requests run under the application pool identity, which is exactly the AD account you configured — that is what lets the trusted SQL connection work end to end.If instead the API must authenticate each caller, leave Windows Authentication on and plan for Kerberos delegation, which is a larger topic.
-
Point the application at your custom pool. Select the
SampleDataapplication, click Basic Settings, click Select, and choose theSampleDataapplication pool from the dropdown. Click OK. The application now runs under the AD service account identity. -
Recycle the pool and reload the site. Recycling the specific app pool is safer than restarting the whole web server, which affects every site on the box:
Restart-WebAppPool -Name 'SampleData'
Verify the deployment works
Verification is the step teams skip and regret. Confirm each layer before declaring success.
- Service endpoint loads. Browse to the service URL, for example
http://localhost/WS/SampleData/Service.asmx(classic) or the API's base route. You should see the service description page or a valid response rather than a 500. - Invoke a web method. On a classic
.asmxpage, click a method such asGetItemsById, supply a known test input, and click Invoke. A second window returns the XML result. For a Web API, call the route withcurl:
curl -i http://localhost/WS/SampleData/api/items/123
- Confirm the running identity. Check that the worker process runs as your service account:
Get-WmiObject Win32_Process -Filter "name='w3wp.exe'" | ForEach-Object { $_.GetOwner().User }
- Check the SQL connection. A successful data-returning call proves the trusted connection works. If it fails, run SQL Server Profiler or query
sys.dm_exec_sessionsto confirm the service account login is connecting.
A clean response from a real web method that reads live data is the true sign the deployment succeeded.
Common pitfalls when you deploy an ASP.NET web service to IIS
Most failed deployments trace back to a short list of mistakes. Watch for these:
| Symptom | Likely cause | Fix |
| HTTP 503 / pool stops instantly | Wrong service-account password or "Log on as a batch job" right missing | Re-enter the password in the pool identity; grant the logon right via Group Policy / Local Security Policy |
| HTTP 500.19 config error | Web Deploy / required IIS module not installed | Install Web Deploy and the matching ASP.NET role feature |
| HTTP 401.3 access denied | Service account lacks NTFS read on the app folder | Grant Read & execute with icacls (inherited) |
| SQL login failed for the pool account | No SQL login/role for the service account | Create the login and grant database role membership |
| Wrong data in QA/PROD | Connection string left at DEV value after import | Update Server= and Database= per environment |
| App still uses old pool | Basic Settings not pointed at the new pool | Reassign the pool, then recycle |
Two more that bite people: the application pool's .NET version must match the app (a v4 app under a v2 pool throws cryptic errors), and the service account needs the "Log on as a service" / batch job right, which is granted automatically when you set the identity through IIS Manager but not always when you script it — verify it after a PowerShell-driven setup.
Hardening and good practice
Once the service runs, tighten it:
- Use HTTPS with a real certificate and bind port 443; redirect HTTP to HTTPS.
- Scope NTFS rights to read-only unless the app genuinely writes files.
- Use a Group Managed Service Account (gMSA) where possible — Windows rotates its password automatically, removing the stored secret entirely.
- Keep environment-specific config out of the package using Web.config transforms or parameterized Web Deploy so the same artifact promotes from DEV to PROD safely.
- Replace plain FTP with SMB over the LAN or SFTP for moving packages.
Key Takeaways
- Running the application pool as an AD service account lets you use
Trusted_Connection=Yesand keep SQL passwords out ofweb.config. - The reliable order is: folder → NTFS permissions → app pool + identity → import package → connection string → authentication → assign pool → recycle → test.
- Enable Anonymous Authentication so requests run under the pool identity, which is what makes the trusted SQL connection work.
- Most failures are a missing logon right, wrong .NET pool version, missing NTFS read, or a stale connection string — check those first.
- Classic
.asmxon .NET Framework is legacy; the same IIS-and-app-pool pattern carries straight over to ASP.NET Core Web API, so modernize the runtime while keeping this deployment model.
Frequently Asked Questions
How do I make an IIS application pool run as a domain account?
Select the pool in IIS Manager, open Advanced Settings, edit Identity, choose Custom account, and enter the domain account and password. IIS grants the account the needed logon rights for you. The worker process (w3wp.exe) then runs under that identity.
Why use a service account instead of a SQL username and password?
A trusted Windows connection means no credentials are stored in plaintext, the password is rotated centrally in Active Directory, access is audited under a named identity, and you can apply least-privilege database roles to the account.
What is the difference between Import Application and just copying files?
Import Application uses Web Deploy to unpack a package, register the IIS application, and apply parameters such as the connection string in one consistent step. Copying files by hand skips that registration and parameterization, which is where manual deployments drift between environments.
The app pool keeps stopping after I set the identity. Why?
Almost always a bad password or a missing "Log on as a service / batch job" right for the account. Re-enter the password, confirm the account is not locked or expired, and verify the logon right in Local Security Policy, then start the pool again.
For more Windows Server, IIS, and sysadmin walkthroughs, subscribe on YouTube at @explorenystream.