We have an ASP.NET Core site running on our test server that we would like to auto-deploy by XCopy to our IIS web server as we do our current apps, where I already have the site running. I've added a publish profile that packages the site to a "publish-local" directory within the solution. Whenever I try to copy over the existing site, all DLLs are being used by another process, presumably Kestrel, so I am forced to deploy to a sibling directory and re-map IIS to look at the sibling. How does one update a running ASP.NET Core site without having to manually intervene and stop either the Kestrel or IIS web servers?
4 Answers
When running with IIS you can drop a file called app_offline.htm
(case sensitive) to your application folder. IIS will stop your application and will serve the contents of the app_offline.html
file. Now you can copy your application. Once finished remove the app_offline.htm and IIS will start your app. This is described in the docs and also in my post on running Asp.NET Core apps with IIS.

- 64,141
- 14
- 108
- 120

- 31,342
- 4
- 73
- 104
-
2Even with app_offline.htm, yourwebsite.exe is still in use and you can't copy the new version. With app_offline.htm and an application pool reset _then_ it looks like you can copy yourwebsite.exe, but just putting app_offline.htm isn't enough. – J. Allen Dec 21 '16 at 18:01
-
My understanding is that putting app_offline.html should be enough. IIS tries stopping your application gracefully so if there are pending requests stopping the application process might not be immediate. If you don't see the application being stopped after just putting app_offline.html I suggest opening an issue in this repo: https://github.com/aspnet/AspNetCoreModule – Pawel Dec 21 '16 at 18:15
-
1I would think the same, but it's an issue I'm bumping up against right now. In my TFS build I have a powershell script that puts in app_offline.htm, it waits a few seconds, it submits a request to IIS and gets back a 503 error showing the application is offline...yet mywebsite.exe is _still_ locked for editing and dotnet publish fails. :( I guess I'll submit an issue to the repo you suggested, because I agree - app_offline.htm should be good enough. – J. Allen Dec 21 '16 at 19:30
-
1This worked for me. Putting app_offline.html allowed me to finally publish my app using passive ftp without having to stop the IIS-Server first. – FerX32 Mar 19 '17 at 00:35
-
Perfect! :-) Works here too. .NET Core 2, IIS 8.5 – Emiel Koning Mar 26 '18 at 15:08
-
1@FerX32 You should fix the .html to .htm. I've been burnt several times by using html instead of htm. – BillRob Dec 19 '18 at 23:44
a little cheat we use is to rename the old files first (something like my.dll.old
), then copy over the new dlls. Then you can either force or wait for an app pool restart.

- 16,237
- 14
- 70
- 101
-
1I'm trying to script the copying to the web server using MSBUILD and TeamCity. Does Kestrel not block the rename? – flipdoubt Dec 14 '16 at 19:06
-
If the files are in use, they will certainly not allow a rename. – QuietSeditionist Dec 14 '16 at 19:56
-
1
-
@flipdoubt Nope. And neither does Windows when renaming GAC dlls in use. – Mike_G Dec 15 '16 at 20:37
-
Unfortunately, MSBUILD does not have an option for rename, but I'll give you a bump because I didn't specify MSBUILD. – flipdoubt Dec 16 '16 at 16:34
-
Wow, just tried this and whilst I can't copy over the `.exe` and `.dll` of the project (i.e. just updating the project codebase), I could rename and then restart the app pool - Amazing! – RemarkLima Aug 30 '17 at 11:10
-
Usually I take a backup of the existing version. Then I almost simultaneously recycle the app domain (if I'm using iis) and overwrite the entire contents of the root folder. This way the app restarts with the new version of the code. But it has to be super quick or else there can be issues. In case if anything fails backup can be used to restore to original state.

- 758
- 2
- 8
- 20
You can switch the physical path of your IIS site/application with PowerShell:
($curPath = Get-WebFilePath -PSPath "IIS:\Sites\www.example.com\MyApp")
if ($curPath -like "*Blue*") {
Copy-Item -Path "D:\inetpub\wwwroot\MyAppPath\Staging\*" -Destination "D:\inetpub\wwwroot\MyAppPath\Green" -Recurse -Force
Set-ItemProperty IIS:\Sites\www.example.com\MyApp -name physicalPath -value "D:\inetpub\wwwroot\MyAppPath\Green"
} else {
Copy-Item -Path "D:\inetpub\wwwroot\MyAppPath\Staging\*" -Destination "D:\inetpub\wwwroot\MyAppPath\Blue" -Recurse -Force
Set-ItemProperty IIS:\Sites\www.example.com\MyApp -name physicalPath -value "D:\inetpub\wwwroot\MyAppPath\Blue"
}
Use a staging folder to which you copy your new published files. Then, the above script switches between the green and blue folder. You don't have to stop or recycle your app.

- 650
- 7
- 20