Removing web.config from subversion (ASP.NET Project) - asp.net

I have a project which is source controlled using Subversion and VisualSVN. Since the version of web.config is different on the server and the developers' computers I want the file to remain on the computers but to be ignored by Subversion. I added it to the svn:ignore but it still remains (and still has a red exclamation mark too since we are not committing it).
How can I remove it from Subversion safely without it being deleted from the files system
Thanks,
Adin

you'll have to do both the remove and ignore operation
first make a backup of your local file (like #ibz said)
then remove the web.config from the repository.
then copy back the web.config to the same folder
finally use svn:ignore so that subversion does not try to add it again to the repository
since i use tortoisesvn i can't really tell you what svn commands you have to use, but using tortoisesvn it would be:
make backup
right click on web.config on the folder under source control, select TortoiseSVN | Delete
right click on web.config on the folder under source control, select SVN Commit => after this you will notice that the file is actually deleted from the file system
move up and right click on the folder under source control, select TortoiseSVN | Properties
on the properties window click new + property name "svn:ignore"; property value "web.config". accept changes
commit changes
on my .net projects i include the following exclusion with svn:ignore: bin, obj, *.suo, *.user

Ideally, you should maintain versions of server's copy of web.config in SVN too. We usually rename the production web.config to web.config.prod (a copy for each of the environments) and have the build tool pick the right file and rename it back to web.config while packaging for deployment.

svn rm --force web.config
svn commit
Be careful to back up your local copy (of web.config) before doing this, since it will be deleted.

I have solved this issue using nant with ccnet. Following nant build script replaces web.test.config file with local web.config file;
<?xml version="1.0"?>
<project name="Project1" default="build">
<target name="init" depends="clean" />
<target name="clean" />
<target name="checkout"/>
<target name="compile"/>
<target name="deploy"/>
<target name="test"/>
<target name="inspect"/>
<target name="build" depends="init, checkout">
<call target="compile" />
<call target="inspect" />
<call target="test" />
<call target="deploy" />
</target>
<copy file="..\TestDeployments\Project1\Project1.Solution\Project1.Web.UI\web.Test.config"
tofile="..\TestDeployments\Project1\Project1.Solution\Project1.Web.UI\web.config"
overwrite="true"
/>
<delete file="..\TestDeployments\Project1\Project1.Solution\Project1.Web.UI\web.Test.config" />
</project>
NAnt Copy Task

Related

How to exclude APP_DATA directory from publishing using custom target "PublishToFileSystem"

I am using a custom target for publishing my web site to a local folder.
The target (found here) looks like:
<Target Name="PublishToFileSystem"
DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
<Error Condition="'$(PublishDestination)'==''"
Text="The PublishDestination property must be set to the intended publishing destination." />
<MakeDir Condition="!Exists($(PublishDestination))"
Directories="$(PublishDestination)" />
<ItemGroup>
<PublishFiles Include="$(_PackageTempDir)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(PublishFiles)"
DestinationFiles="#(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')"
SkipUnchangedFiles="True" />
</Target>
The corresponding msbuild command looks like:
msbuild projectfile.csproj /p:DeployOnBuild=true /p:VisualStudioVersion=14.0 /p:configuration=Release /p:PublishDestination=C:\inetpub\wwwroot\WebSite /T:PublishToFileSystem
That works fine so far. However, I would like to exclude the APP_DATA directory from publishing.
So, is there a way to exclude the APP_DATA directory from publishing? Maybe by excluding it from the file set defined with <PublishFiles Include="$(_PackageTempDir)\**\*.*" />?
Environment:
Visual Studio 2015
MSBuild Tools 2015
The easiest way I found is to set this inside the publish profile.
<ExcludeApp_Data>False</ExcludeApp_Data>
You can do it from solution property. Just right click on solution and choose its property. You will get Package/Publish tab there you just need to check "Exclude files from the App_Data Folder". You can check at attached screen shot.
Hope this can help you.
It is possible to set the option (suggested by #Vipin Rathore) within the project file:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<ExcludeFoldersFromDeployment>APP_DATA</ExcludeFoldersFromDeployment>
</PropertyGroup>

how to set pubxml to delete temp files after publish

in VS 2012 with Update 2 i have a web site which i publish. the new publish wizard was configured to publish the site to a folder on my disk. while checking something on my temp files folder i ran a publish of my site. i saw that the publisher creates a folder on %TEMP%\WebSitePublish and in there creates 3 copies of the site:
r:\temp\WebSitePublish\web-1279598559\obj\Debug\AspnetCompileMerge\Source\
r:\temp\WebSitePublish\web-1279598559\obj\Debug\AspnetCompileMerge\TempBuildDir\
r:\temp\WebSitePublish\web-1279598559\obj\Debug\Package\
since my web site is huge (1.6GB) each of these folders take 1.6GB and 4.8 GB in total.
while i think this is wasting disk space even during a publish, i can't argue with MS about the way they implemented the publish. the only thing that does bother me is that even after closing the VS IDE, the r:\temp\WebSitePublish\web-1279598559 folder remains and still occupies 4.8GB. How can i make the publisher delete it's temp files after it finishes the publish?
my pubxml for this site is this:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>x86</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<ExcludeApp_Data>False</ExcludeApp_Data>
<publishUrl>C:\PrecompiledWeb\Site</publishUrl>
<DeleteExistingFiles>True</DeleteExistingFiles>
<PrecompileBeforePublish>True</PrecompileBeforePublish>
<EnableUpdateable>True</EnableUpdateable>
<DebugSymbols>True</DebugSymbols>
<WDPMergeOption>CreateSeparateAssembly</WDPMergeOption>
<UseFixedNames>True</UseFixedNames>
</PropertyGroup>
</Project>
I think you can set up a 'build target' in your .csproj file (maybe in the .pubxml file instead?), like Why does MSBuild ignore my BeforePublish target? or How can I prevent hidden .svn folder from being copied from the _bin_deployableAssemblies folder?. #sayed-ibrahim-hashimi has a lot of answers regarding build targets.
In my experience it's been tricky to figure out what target to attach to, since there has been some churn between different Visual Studio releases, but I think you want something like:
<!-- these are your instructions; name is arbitrary, `AfterTargets` says when -->
<Target Name="CleanTempDirectory" AfterTargets="AfterPublish">
<!-- use 'importance=high' to show in the Output window (?) -->
<Message Text="Cleaning up publish temp directories" Importance="high" />
<!-- here, specify the directory(ies) to clear; can use build event macros -->
<CreateItem Include="$(ProjectDir)App_Data\*\*">
<Output ItemName="GeneratedFiles" TaskParameter="Include" />
</CreateItem>
<Delete Files="#(GeneratedFiles)" />
</Target>
The important parts here are:
AfterTargets -- specifies when this task should be run (and AfterPublish should be self-explanatory; I think that's the right one)
CreateItem -- scan the given directory glob and set a list to the variable #(GeneratedFiles)
Delete -- delete the list created by CreateItem

How to get aspnet_compiler invoked from Visual Studio during build?

I want Visual Studio to precompile my ASP.NET application which is used as an Azure web role payload. So I've found this post that explains how to call aspnet_compiler to validate views.
I tried to add the following to "post-build event" of my ASP.NET application:
call "%VS100COMNTOOLS%\vsvars32.bat"
aspnet_compiler -v / -p $(ProjectDir)
or alternatively this (application name specified explicitly):
call "%VS100COMNTOOLS%\vsvars32.bat"
aspnet_compiler -v /ASP.NET-Application-ProjectNameHere -p $(ProjectDir)
In both cases when the build runs I see the following in the build output:
Setting environment for using Microsoft Visual Studio 2010 x86 tools.
Utility to precompile an ASP.NET application
Copyright (C) Microsoft Corporation. All rights reserved.
and clearly no precompilation happens because if I change any .aspx or .cshtml file "Build Action" to "None" it doesn't get to the Azure service package and the view no longer opens once the package is deployed to Azure.
How do I setup aspnet_compiler for precompiling from within Visual Studio?
If you want to use Asp.NET Compiler within your Visual Studio / msbuild then you can add
AspNetCompiler Task to your project file (.csproj/.vbproj) and set MvcBuildViews to true.
Example:
<Project>
<PropertyGroup>
<MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>
<!-- ... -->
<Target Name="PrecompileWeb" AfterTargets="build" Condition="'$(MvcBuildViews)'=='true'">
<Message Text="Starting AspNetCompiler for $(ProjectDir)" Importance="high" />
<AspNetCompiler
VirtualPath="temp"
PhysicalPath="$(WebProjectOutputDir)"
Force="true"
/>
</Target>
<!-- ... -->
</Project>
You may also set TargetPath attribute to specify destination directory.
AfterTargets="build" is similar to "post-build event". See Target Build Order for more.
Integrate ASPX compilation into Visual Studio
One of the principles I insist on is to always try my build on a clean environment and simulate installation as if it was done by QA. Lately I've noticed that I keep falling on errors hidden deep in the aspx files. So, why not using the old and familiar aspnet_compiler.exe tool? It is located at C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 and it is quite easy to use.
As a VS add-ins freak I've started thinking on an amazing add-in that will integrate to the VS and will listen to build events and display the results at the output pane. Heck, why not add some coffee serving capabilities?
It took me about 10 minutes of googling to stumble on this blog. Mike Hadlow had a genius in its simplicity idea. Use the POST BUILD EVENT!
All I need to do is put the following line in the post build event: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v / -p "$(ProjectDir)\"
Now, All that is left is to make the process of adding this line to each and every web project in our team to be automatic.
I have just the add-in for that :)
enter link description here
The answer from Matej was helpful for me, but I was not able to use it as-is and still get it to work for both local builds within Visual Studio and automated builds via TFS.
I had to add some extra msbuild settings. Actually, there were 2 different scenarios that I had. One project was an Web App that built into the _PublishedWebsites folder and one was an MVC Web App that did not build into the _PublishedWebsites folder.
First, add the following if it is not already in your project file:
<PropertyGroup>
<MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>
For the one WITH _PublishedWebsites:
<Choose>
<When Condition="'$(BuildingInsideVisualStudio)' == true">
<PropertyGroup>
<AspNetCompilerPhysicalPath>$(ProjectDir)</AspNetCompilerPhysicalPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<AspNetCompilerPhysicalPath>$(WebProjectOutputDir)</AspNetCompilerPhysicalPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Target Name="PrecompileWeb" AfterTargets="build" Condition="'$(MvcBuildViews)'=='true'">
<!-- aspnet_compiler.exe needs to be run on the folder that has the aspx files and the "bin" subfolder.
When running locally, the value needs to be the project directory, which is $(ProjectDir).
When running the TFS build, the value needs to be (BuildFolder)\(ProjectName)\_PublishedWebsites\(ProjectName).
The $(AspNetCompilerPhysicalPath) will hold the correct value for both types of builds.
-->
<Message Text="Starting AspNetCompiler for $(ProjectName) at $(AspNetCompilerPhysicalPath)" Importance="high" />
<AspNetCompiler
VirtualPath="/"
PhysicalPath="$(AspNetCompilerPhysicalPath)"
TargetPath="$(AspNetCompilerPhysicalPath)\bin_precompile"
Force="true"
/>
</Target>
For the one WITHOUT _PublishedWebsites:
<Choose>
<When Condition="'$(BuildingInsideVisualStudio)' == true">
<PropertyGroup>
<AspNetCompiler_CopyFilesFirst>false</AspNetCompiler_CopyFilesFirst>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<AspNetCompiler_CopyFilesFirst>true</AspNetCompiler_CopyFilesFirst>
</PropertyGroup>
<ItemGroup>
<AllOutputFiles Include="$(OutDir)\\**\*.*" />
</ItemGroup>
</Otherwise>
</Choose>
<Target Name="PrecompileWeb" AfterTargets="build" Condition="'$(MvcBuildViews)'=='true'">
<!-- aspnet_compiler.exe needs to be run on the folder that has the cshtml files and the "bin" subfolder. I could not find a setting that was appropriate for both.
When running locally, the value needs to be the project directory, which is $(ProjectDir).
When running the TFS build, there is no folder that matches both of those criteria.
So first we will copy the output into the source code folder's "bin" subfolder,
then run it against the source $(ProjectDir), the same as if we were building locally.
-->
<Message Text="Before running AspNetCompiler, copy files from $(OutDir) to $(ProjectDir)\bin" Importance="high" />
<Exec Command="( robocopy.exe /mir $(OutDir) $(ProjectDir)\bin ) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0" Condition="'$(AspNetCompiler_CopyFilesFirst)'=='true'" />
<Message Text="Starting AspNetCompiler for $(ProjectName) at $(ProjectDir)" Importance="high" />
<AspNetCompiler
VirtualPath="/"
PhysicalPath="$(ProjectDir)"
TargetPath="$(ProjectDir)\bin_precompile"
Force="true"
/>
</Target>

How do you use Web.config Transformation?

When I create a deployment package web.config is changed, but I don't understand this part:
I have two web.config transformation files, web.debug.config and web.release.config.
Are these transformation files only available or working when we make a web deployment or make a deployment package? Are the web.config transformations not used when the project runs locally from visual studio (e.g. via IIS Express)?
You are correct.
Config transformations are applied when you deploy or run a deployment package.
They do not transform on compilation.
If you need the transformed config file during compilation, you can get it by editing the project file (.csproj) and adding the below code.
<Target Name="AfterBuild">
<TransformXml Source="$(SolutionDir)WCFServices\Web.config"
Transform="$(SolutionDir)WCFServices\Web.Release.config"
Destination="$(OutDir)WebRelease.config"
StackTrace="true" />
</Target>
Multiple TransformXml tags can be added to get all the required config files. Also, This can be done before or after build.
You can invoke it using MSBuild and an extension called SlowCheetah.
There is an other VS extension called Configuration Transform good for this. If you don't want to install it, but to achieve this, just follow the examples shown in the demo solution to add different build config files and add some new MSBuild tasks in the project files. The download link for the demo solution can be found on the extension's Visual Studio Gallery webpage. This approach doesn't require any extra packages since MSBuild uses XSLT to do the XML tranformation.
Below are the MSBuild tasks added into a project file from the demo solution. In my case, when I followed it for a VS2015 ASP.NET MVC project, I didn't have to put <UsingTask TaskName="TransformXml" AssemblyFile=... in.
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterCompile" Condition="Exists('App.$(Configuration).config')">
<!--Generate transformed app config in the intermediate directory-->
<TransformXml Source="App.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="App.$(Configuration).config" />
<!--Force build process to use the transformed configuration file from now on.-->
<ItemGroup>
<AppConfigWithTargetPath Remove="App.config" />
<AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
<TargetPath>$(TargetFileName).config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
</Target>
<!--Override After Publish to support ClickOnce AfterPublish. Target replaces the untransformed config file copied to the deployment directory with the transformed one.-->
<Target Name="AfterPublish">
<PropertyGroup>
<DeployedConfig>$(_DeploymentApplicationDir)$(TargetName)$(TargetExt).config$(_DeploymentFileMappingExtension)</DeployedConfig>
</PropertyGroup>
<!--Publish copies the untransformed App.config to deployment directory so overwrite it-->
<Copy Condition="Exists('$(DeployedConfig)')" SourceFiles="$(IntermediateOutputPath)$(TargetFileName).config" DestinationFiles="$(DeployedConfig)" />
</Target>
Here is the way I applied in my .csproj file, quite simple:
<Target Name="AfterBuild" Condition="Exists('Web.$(Configuration).config')">
<Exec Command="attrib -R Web.config" />
<TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="Web.config" StackTrace="true" />
</Target>
Also there is a good post on this.
Further, for web.config transformation, Since VS2012 we can add a publish profile - Publish.pubxml (ProjectFolder/Properties/PublishProfiles/Publish.pubxml) to do a FileSystem publish, thus the web.config transformation will happen by default then. Below is a sample
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<SiteUrlToLaunchAfterPublish />
<publishUrl Condition="$(OutDir) != ''">$(OutDir)\_PublishedWebsites\$(ProjectName)</publishUrl> <!-- For MSBuild -->
<publishUrl Condition="$(OutDir) == ''">$(MSBuildThisFileDirectory)..\..\_PublishedWebsite\</publishUrl> <!-- For Visual Studio...cant use $(ProjectName) -->
<DeleteExistingFiles>True</DeleteExistingFiles>
</PropertyGroup>
</Project>

How do I get msdeploy to create App_Data if it doesn't exist, but not delete any contents of the remote directory?

I have an application setup with the following Package/Publish Web settings:
Only files needed to run this application
(unchecked) Exclude generated debug symbols
(checked) Exclude files from the App_Data folder
(checked) Include all databases configured in Package/Publish SQL tab - note I do not have any databases configured
(unchecked) include IIS settings as configured in IIS Express
In the project, I have an App_Data folder setup, primarily to handle application logs.
The behavior I'd like to see (and expect) is the following:
On initial deploy to a brand new server, the application is copied and an App_Data folder is created with write permissions assigned for the application.
On subsequent deployments, the App_Data folder is ignored because it already exists and the "Exclude files from the App_Data folder" is checked.
However, msdeploy does not appear to do step #1 (step 2 is fine if I create the folder manually). I've been unable to find any documentation on the web besides this unanswered so question that seems to confirm the behavior I see.
How do I get msdeploy to create App_Data and assign permissions on initial deployment in this scenario?
Getting App_Data deployed when starting from scratch
#tdykstra got this part right. To get App_Data out there (and ACLs set automatically), I did the following:
Adding a placeholder file in App_Data
Set the build action to content on the placeholder (my placeholder file has text in it to let people stumbling across it know why it's there).
Unchecked "Exclude files from the App_Data folder" on the Package/Publish Web tab of the project properties in VS 2010
This gets my App_Data folder created and ready for use on the server. However, it will result in all my files getting deleted whenever I republish. This is problem #2 in my question above, and pretty closely resembles this other SO question/answer.
Preventing data on the server from being deleted on subsequent publish events
There are two mechanisms in MsDeploy that can get confused (at least I confused them):
Excluding files
MsDeploy skip rules
These can both be used to solve the problem, depending on the scenario:
#tdykstra's solution will likely work if you:
Know the names of the files in App_Data in advance (e.g. a sqllite database)
Have the files included in the App_Data folder in your project
The use MsDeploy skip rules to tell MsDeploy to completely skip all deletes on the server for that directory and files in that directory. This solves the problem in all cases, but is much more involved.
Implementing MsDeploy skip rules
To implement skip rules you'll have to abandon the right-click, Deploy option in VS 2010 in favor of right-click, Package, go into a command line, re-jigger a batch file and run a command line). If you're willing to put up with this experience (I am, because I'm automating it all through a CI process), here are the details:
Edit the project file and add the following. Note that the AbsolutePath argument is a regular expression, so you can get way fancy:
<Target Name="AddCustomSkipRules">
<ItemGroup>
<MsDeploySkipRules Include="SkipDeleteAppData">
<SkipAction>Delete</SkipAction>
<ObjectName>filePath</ObjectName>
<AbsolutePath>$(_Escaped_PackageTempDir)\\App_Data\\.*</AbsolutePath>
<XPath>
</XPath>
</MsDeploySkipRules>
<MsDeploySkipRules Include="SkipDeleteAppData">
<SkipAction>Delete</SkipAction>
<ObjectName>dirPath</ObjectName>
<AbsolutePath>$(_Escaped_PackageTempDir)\\App_Data\\.*</AbsolutePath>
<XPath>
</XPath>
</MsDeploySkipRules>
</ItemGroup>
</Target>
Package, do not deploy the project. This will create a zip file and .cmd file in the target directory (defined by "Location where package will be created" on the Package/Publish Web Tab). By default, this is obj\Debug\Package (or obj\Release\Package)
Deploy the site using the the resulting command file
In my testing, you must package and run the command file. The project file tweaks will tell msbuild to put the necessary -skip rule into the command file. However, using the "publish" feature straight from VS 2010 doesn't seem to run the command file (see the warning on this walkthrough)...it calls msdeploy directly and doesn't seem to honor the project file skip rules. I believe this is the difference between VS using msbuild -T:Package and msbuild -T:MsDeployPublish to build the project, but I have not tested this.
Finally, the command file isn't quite correct, at least in VS 2010 SP1. There's a great description of what goes wrong in this SO answer, but basically, VS (or maybe the /t:Package target is a better culprit) sets up the command file to publish to the machine without specifying a site. To fix that, you'll need to somehow get "?site=sitename" (probably this is ?site=Default+Web+Site, for a full URL of https://machine:8172/MsDeploy.axd?site=Default+Web+Site) onto the end of the computerName argument.
The problem I had was that the command file (batch file) has a hard time with using site= anything on the command line since it mis-parses the command line argument (even if escaped). I don't see a way around this problem other than modifying the cmd file directly, but for testing I copied the msdeploy.exe output I saw from my failed test run and modified that to call msdeploy.exe directly without the script.
Now that it's working, my intention is to work this into my CI build processes. What I'll be doing for the final solution is:
Change my build script to use /T:Package (right now it's /T:MsDeploy)
Have a scripted search/replace routine alter the generated cmd deployment script
Run the altered deployment script
This really should be easier.
Update
Here's the scripted search/replace routine I've come up with in PowerShell:
(Get-Content "project.deploy.cmd")
-replace('^set _ArgComputerName=$'
,"set ArgComputerName=https://server:8172/MsDeploy.axd?Site=Default+Web+Site")
| Out-File -Encoding ascii deploy.cmd
Once that is run, deploy.cmd can be called (without the /M option) and it will work as expected.
Web Deploy won't create a folder if there are no files to copy to it. One workaround in your scenario would be to not use the Exclude files from the App_Data folder check box, put a dummy file in App_Data (such as a .txt file with nothing in it), and specify file exclusion rules for whatever else you have in the App_Data folder (such as your .sdf file).
On excluding individual files (you can use wildcards), see the first question in the deployment FAQ on MSDN:
http://msdn.microsoft.com/en-us/library/ee942158.aspx#can_i_exclude_specific_files_or_folders_from_deployment
On using the dummy file method for causing a folder to be created, see Making Sure that the Elmah Folder gets Deployed in this tutorial:
http://www.asp.net/web-forms/tutorials/deployment-to-a-hosting-provider/deployment-to-a-hosting-provider-configuring-project-properties-4-of-12
I managed to get it working when using the Publish Web dialog from within Visual Studio. Note: it works for any folder and not only App_Data.
This is the basic .pubxml profile:
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AfterAddIisSettingAndFileContentsToSourceManifest>AddCustomSkipRules</AfterAddIisSettingAndFileContentsToSourceManifest>
<WebPublishMethod>MSDeploy</WebPublishMethod>
<LastUsedBuildConfiguration>Local</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<ExcludeApp_Data>False</ExcludeApp_Data>
<MSDeployServiceURL>localhost</MSDeployServiceURL>
<DeployIisAppPath>SuperCoolAwesomeAppName</DeployIisAppPath>
<RemoteSitePhysicalPath />
<SkipExtraFilesOnServer>False</SkipExtraFilesOnServer>
<MSDeployPublishMethod>InProc</MSDeployPublishMethod>
<EnableMSDeployBackup>False</EnableMSDeployBackup>
<UserName />
<_SavePWD>False</_SavePWD>
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
</PropertyGroup>
<PropertyGroup>
<UseMsDeployExe>true</UseMsDeployExe>
</PropertyGroup>
<Target Name="CreateEmptyFolders">
<Message Text="Adding empty folders to Files" />
<MakeDir Directories="$(_MSDeployDirPath_FullPath)\Files\Folder 1" />
<MakeDir Directories="$(_MSDeployDirPath_FullPath)\Files\Folder 2" />
<MakeDir Directories="$(_MSDeployDirPath_FullPath)\Files\Folder 3\Test"/>
</Target>
<Target Name="AddCustomSkipRules" DependsOnTargets="CreateEmptyFolders">
<Message Text="Adding Custom Skip Rules" />
<ItemGroup>
<MsDeploySkipRules Include="SkipFilesInFilesFolder">
<SkipAction>Delete</SkipAction>
<ObjectName>filePath</ObjectName>
<AbsolutePath>$(_DestinationContentPath)\\Files\\.*</AbsolutePath>
<Apply>Destination</Apply>
</MsDeploySkipRules>
<MsDeploySkipRules Include="SkipFoldersInFilesFolders">
<SkipAction></SkipAction>
<ObjectName>dirPath</ObjectName>
<AbsolutePath>$(_DestinationContentPath)\\Files\\.*\\*</AbsolutePath>
<Apply>Destination</Apply>
</MsDeploySkipRules>
</ItemGroup>
</Target>
</Project>
Here's a detailed post explaining it:
Using MsDeploy publish profile .pubxml to create an empty folder structure on IIS and skip deleting it with MsDeploySkipRules
Summarizing and simplifying Emil and Leniel answers in a concise one, if you just want to allow App_Data deploy for adds and updates, but prevents deletes, add this to your .pubxml.
<Project>
...
<PropertyGroup>
<UseMSDeployExe>true</UseMSDeployExe>
<ExcludeApp_Data>False</ExcludeApp_Data>
</PropertyGroup>
<Target Name="AddCustomSkipRules"
AfterTargets="AddIisSettingAndFileContentsToSourceManifest">
<Message Text="Adding Custom Skip Rules" />
<ItemGroup>
<MsDeploySkipRules Include="SkipDeleteAppData">
<SkipAction>Delete</SkipAction>
<ObjectName>filePath</ObjectName>
<AbsolutePath>App_Data\\.*</AbsolutePath>
</MsDeploySkipRules>
<MsDeploySkipRules Include="SkipDeleteAppData">
<SkipAction>Delete</SkipAction>
<ObjectName>dirPath</ObjectName>
<AbsolutePath>App_Data</AbsolutePath>
</MsDeploySkipRules>
</ItemGroup>
</Target>
</Project>
<UseMSDeployExe>true</UseMSDeployExe> is really needed or it will fail complaining Unrecognized skip directive 'skipaction'.

Resources