After seeing the Hanselman \"You are doing it wrong\" video I start to use the Web Publish feature of VS2010.
What I\'m really missing is that the websites sometimes giv
This question is a duplicate of App_Offline in MSBuild Remote Web Deploy, but I've pasted the answer below. MSDeploy v3 has support for app_offline directly but you need MSDeploy v3 on both sides. We have not updated the VS Web Publish experience to be able to leverage this yet, but we will in an update at some point.
I just recently blogged about this at http://sedodream.com/2012/01/08/HowToTakeYourWebAppOfflineDuringPublishing.aspx. It's more difficult than it should be and I'm working on simplifying that for a later version. In any case I've pasted all the content here for you.
I received a customer email asking how they can take their web application/site offline for the entire duration that a publish is happening from Visual Studio. An easy way to take your site offline is to drop an app_offline.htm file in the sites root directory. For more info on that you can read ScottGu’s post, link in below in resources section. Unfortunately Web Deploy itself doesn’t support this . If you want Web Deploy (aka MSDeploy) to natively support this feature please vote on it at http://aspnet.uservoice.com/forums/41199-general/suggestions/2499911-take-my-site-app-offline-during-publishing.
Since Web Deploy doesn’t support this it’s going to be a bit more difficult and it requires us to perform the following steps:
1 will take the app offline before the publish process begins.
2 will ensure that when we publish that app_offline.htm is not deleted (and therefore keep the app offline)
3 will delete the app_offline.htm and bring the site back online
Now that we know what needs to be done let’s look at the implementation. First for the easy part. Create a file in your Web Application Project (WAP) named app_offline-template.htm. This will be the file which will end up being the app_offline.htm file on your target server. If you leave it blank your users will get a generic message stating that the app is offline, but it would be better for you to place static HTML (no ASP.NET markup) inside of that file letting users know that the site will come back up and whatever other info you think is relevant to your users. When you add this file you should change the Build Action to None in the Properties grid. This will make sure that this file itself is not published/packaged. Since the file ends in .htm it will by default be published. See the image below.
Now for the hard part. For Web Application Projects we have a hook into the publish/package process which we refer to as “wpp.targets”. If you want to extend your publish/package process you can create a file named {ProjectName}.wpp.targets in the same folder as the project file itself. Here is the file which I created you can copy and paste the content into your wpp.targets file. I will explain the significant parts but wanted to post the entire file for your convince. Note: you can grab my latest version of this file from my github repo, the link is in the resource section below.
$(MSDeployPath)msdeploy.exe
InitalizeAppOffline;
<_AoPubAppOfflineSourceProviderSetting Include="contentPath">
$(MSBuildProjectDirectory)\app_offline-template.htm
$(DeployEncryptKey)
$(_MSDeploySourceWebServerAppHostConfigDirectory)
$(_MSDeploySourceWebServerManifest)
$(_MSDeploySourceWebServerDirectory)
<_AoPubAppOfflineDestProviderSetting Include="contentPath">
"$(DeployIisAppPath)/app_offline.htm"
$(_PublishMsDeployServiceUrl)
$(UserName)
$(Password)
$(DeployEncryptKey)
False
$(AuthType)
$(_MSDeployDestinationWebServerAppHostConfigDirectory)
$(_MSDeployDestinationWebServerManifest)
$(_MSDeployDestinationWebServerDirectory)
app_offline.htm
filePath
app_offline-template.htm
<_AoDeleteAppOfflineDestProviderSetting Include="contentPath">
$(DeployIisAppPath)/app_offline.htm
$(_PublishMsDeployServiceUrl)
$(UserName)
$(Password)
$(DeployEncryptKey)
$(AuthType)
$(_MSDeployDestinationWebServerAppHostConfigDirectory)
$(_MSDeployDestinationWebServerManifest)
$(_MSDeployDestinationWebServerDirectory)
<_Cmd>"$(MSDeployExe)" -verb:delete -dest:contentPath="%(_AoDeleteAppOfflineDestProviderSetting.Path)"
<_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.ComputerName)' != '' ">$(_Cmd),computerName="%(_AoDeleteAppOfflineDestProviderSetting.ComputerName)"
<_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.UserName)' != '' ">$(_Cmd),username="%(_AoDeleteAppOfflineDestProviderSetting.UserName)"
<_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.Password)' != ''">$(_Cmd),password=$(Password)
<_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.AuthType)' != ''">$(_Cmd),authType="%(_AoDeleteAppOfflineDestProviderSetting.AuthType)"
The implementation for #1 is contained inside the target PublishAppOfflineToDest. The msdeploy.exe command that we need to get executed is.
msdeploy.exe
-source:contentPath='C:\Data\Personal\My Repo\sayed-samples\AppOfflineDemo01\AppOfflineDemo01\app_offline-template.htm'
-dest:contentPath='"Default Web Site/AppOfflineDemo/app_offline.htm"',UserName='sayedha',Password='password-here',ComputerName='computername-here',IncludeAcls='False',AuthType='NTLM' -verb:sync -enableRule:DoNotDeleteRule
In order to do this I will leverage the MSDeploy task. Inside of the PublishAppOfflineToDest target you can see how this is accomplished by creating an item for both the source and destination.
This part is accomplished by the fragment
app_offline.htm
filePath
app_offline-template.htm
The item value for FilesForPackagingFromProject here will convert your app_offline-template.htm to app_offline.htm in the folder from where the publish will be processed. Also there is a condition on it so that it only happens during publish and not packaging. We do not want app_offline-template.htm to be in the package (but it’s not the end of the world if it does either).
The element for MsDeploySkiprules will make sure that app_offline-template.htm itself doesn’t get published. This may not be required but it shouldn’t hurt.
Now that our app is published we need to delete the app_offline.htm file from the dest web app. The msdeploy.exe command would be:
%msdeploy% -verb:delete -dest:contentPath="{IIS-Path}/app_offline.htm",computerName="...",username="...",password="..."
This is implemented inside of the DeleteAppOffline target. This target will automatically get executed after the publish because I have included the attribute AfterTargets=”MSDeployPublish”. In that target you can see that I am building up the msdeploy.exe command directly, it looks like the MSDeploy task doesn’t support the delete verb.
If you do try this out please let me know if you run into any issues. I am thinking to create a Nuget package from this so that you can just install that package. That would take a bit of work so please let me know if you are interested in that.