ASP.NET Core + Custom Installation Directory

I am experimenting with deploying ASP.NET Core applications, and have come across a problem when trying to use the Custom Installation Directory feature of Octopus Deploy. ASP.NET Core runs as an executable file, and Octopus is not able to purge or overwrite this file because it is in use.

Now I hear you already saying “Just don’t use a Custom Installation Directory!”

I realize the Custom Installation Directory is a feature that is advised against in the docs, and with good reason. But we replicate IIS configuration between all of our servers, and Octopus makes no guarantee that the Package Installation Directory will be the same on every server. An example of how they can get out of sync would be if I deploy version to server A, and then later server B comes online and I deploy to both server A and B. The Package Installation Directory on server A will be “”, while the _1 suffix will be absent on server B.

Do you have any suggestions for us to keep using Custom Installation Directories with ASP.NET Core?

Hi Travis,

Due to the way ASP.NET Core apps run under IIS (as you’ve described), you’d need to do the following:

  1. Stop the app pool your website runs under (this will release all the file locks)
  2. Deploy the new package (which will update the files in your custom installation directory)
  3. Start the app pool again

If you need to have zero-downtime deployments, you can run those steps in a rolling deployment where 1 (or more) servers gets deployed to at a time.

I hope that helps.

Thank you and best regards,

I can confirm that this process works. Thank you for sharing.

I’m having pretty good success with utilizing the app_offline.htm file. If you place that in the web application’s root directory before the deployment, the ASP.NET Core application will stop, and release all file locks.

Yes, you are correct and I should’ve mentioned that in my initial response. Using an app_offline.htm(l) file will also work just a well as it will automatically stop the app pool when present.


Note: in my experiments, I show that the file must end in .htm, not .html for this to work :wink:

Also here is the documentation about it:

Well there you go, I stand corrected (I assumed either would work), html should not be used. Thanks for the correction!