03 July 2015

Umbraco to Azure / Transformed Web.config MSDeploy error

Could not open Source file: Could not find a part of the path

A rather simple umbraco nuget based install and base Publishing profile from Azure getting me these types of errors:

Transformed Web.config using D:\Solutions\xxx\src\xxx.Web\Web.Release.config into obj\Release\TransformWebConfig\transformed\Web.config.
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.targets(2294,5): Error : Could not open Source file: Could not find a part of the path 'D:\Solutions\xxx\src\xxx.Web\umbraco\Install\Views\Web.config;\umbraco\Install\Views\Web.config'.

Others having the same issue.
http://forums.iis.net/t/1217423.aspx?MSDeploy+error+Could+not+open+Source+file+Could+not+find+a+part+of+the+path+

Issue

Our default projects have a .wpp.Targets file that handles packages for msdeploy on our central build server, the package template for umbraco contains all files related to umbraco leaving "no one behind" strategy. 

wpp.Targets defines default packages information that is set throughout any publishing profiles.

Combined with the default publishing profile where a connection string wants to replace content in web.config this gives issues on web.config files other places than the root of the site. 

Our wpp.Targets contains a simple content inclusion, that makes sure the msdeploy package contains all required umbraco files even tho they are not part of the VS Project.

<ItemGroup>
  <!-- Umbraco -->
  <Content Include="css\**\*" />
  <Content Include="content\**\*" />
  <Content Include="macroscripts\**\*" />
  <Content Include="masterpages\**\*" />
  <Content Include="properties\**\*" />
  <Content Include="umbraco\**\*" />
  <Content Include="umbraco_client\**\*" />
    
  <Content Include="App_Browsers\**\*" />
  <Content Include="App_Plugins\**\*" />
  <Content Include="App_Start\**\*" />
 </ItemGroup>

http://www.asp.net/mvc/overview/deployment/visual-studio-web-deployment/deploying-to-production
A .pubxml file contains the settings that pertain to a specific publish profile. If you want to configure settings that apply to all profiles, you can create a .wpp.targets file. The build process imports these files into the .csproj or .vbproj project file, so most settings that you can configure in the project file can be configured in these files. For more information about .pubxml files and .wpp.targets files, seeHow to: Edit Deployment Settings in Publish Profile (.pubxml) Files and the .wpp.targets File in Visual Studio Web Projects.

Solution: AutoParameterizationWebConfigConnectionStrings

Several places online the proposed solution was AutoParameterizationWebConfigConnectionStrings=false as a parameter on msbuild but using VS Publishinging it was not clear how to introduce this parameter.

It turns out that you just through it in the "PropertyGroup" of the publishing profile. 
<AutoParameterizationWebConfigConnectionStrings>False</AutoParameterizationWebConfigConnectionStrings>

This is ninja kungfu knowledge that is apparently only learned after several hours of fidling about... any msbuild property can be set on the "PropertyGroup" of a profile.. enjoy.

The only change left is that the release profile must replace the connection string to the production connection string is otherwise would be set on the publishing replace event.

Double bonus solution

The PropertyGroup> <AutoParameterizationWebConfigConnectionStrings can be set in the Wpp.Targets file and thereby allowing for a "default" wpp.Targets that can handle imported profiles from Azure without requiring changes in the imported profile pubxml.

Our wpp.Targets on all Umbraco projects is now:


<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <ItemGroup>
  <!-- Umbraco -->
  <Content Include="css\**\*" />
  <Content Include="content\**\*" />
  <Content Include="macroscripts\**\*" />
  <Content Include="masterpages\**\*" />
  <Content Include="properties\**\*" />
  <Content Include="umbraco\**\*" />
  <Content Include="umbraco_client\**\*" />
    
  <Content Include="App_Browsers\**\*" />
  <Content Include="App_Plugins\**\*" />
  <Content Include="App_Start\**\*" />

 </ItemGroup>
 <PropertyGroup>
  <AutoParameterizationWebConfigConnectionStrings>False</AutoParameterizationWebConfigConnectionStrings>
  <AfterAddIisSettingAndFileContentsToSourceManifest Condition="'$(AfterAddIisSettingAndFileContentsToSourceManifest)'==''">
     $(AfterAddIisSettingAndFileContentsToSourceManifest);
     MakeEmptyFolders;
  </AfterAddIisSettingAndFileContentsToSourceManifest>
 </PropertyGroup>
 <Target Name="MakeEmptyFolders">
  <Message Text="Adding empty folders" />
  <MakeDir Directories="$(_MSDeployDirPath_FullPath)\App_Data" />
  <MakeDir Directories="$(_MSDeployDirPath_FullPath)\App_Code" />
  <MakeDir Directories="$(_MSDeployDirPath_FullPath)\css" />
  <MakeDir Directories="$(_MSDeployDirPath_FullPath)\imagecache" />
  <MakeDir Directories="$(_MSDeployDirPath_FullPath)\macroscripts" />
  <MakeDir Directories="$(_MSDeployDirPath_FullPath)\masterpages" />
  <MakeDir Directories="$(_MSDeployDirPath_FullPath)\media" />
  <MakeDir Directories="$(_MSDeployDirPath_FullPath)\usercontrols" />
  <MakeDir Directories="$(_MSDeployDirPath_FullPath)\views\partials" />
  <MakeDir Directories="$(_MSDeployDirPath_FullPath)\views\macropartials" />
 </Target>
</Project>

No comments: