July 22, 2020

How to include external files/folders in Publish Profile

Often we need to include external files/folders in publish profile to deploy on published site. We have two ways to achieve this:

General file inclusion

In this method we use the DotNetPublishFiles tag, which is provided by a publish targets file in the Web SDK.

The following example's demonstrates how to copy a folder located outside of the project directory to the published site.

<ItemGroup>
    <MyCustomFiles Include="$(MSBuildProjectDirectory)/../ExternalContent/**/*" />
    <DotNetPublishFiles Include="@(MyCustomFiles)">
      <DestinationRelativePath>wwwroot/ExternalContent/%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
    </DotNetPublishFiles>
  </ItemGroup>
  • Declares a MyCustomFiles(it can be any custom name) tag to cover files matching the globbing pattern specified in Include attribute. The ExternalContent folder referenced in the pattern is located outside of the project directory. We are using a reserved property $(MSBuildProjectDirectory), which resolves the project file's absolute path.

  • In DotNetPublishFiles tag, we provide our custom tag name MyCustomFiles in the Include attribute, whih serves as a source path for files/folders. In DestinationRelativePath tag, we specified the target path(with respect to published folder) where we want to copy the files. In this example, we are copying ExternalContent folder's content to wwwroot/ExternalContent folder. We have also used item metadata such as %(RecursiveDir), %(Filename), %(Extension). This represents the wwwroot/ExternalContent folder of the published site.

If you don't want to specify source path relative to the project file's absolute path, you can also specific local absolute path, like:

  <ItemGroup>
    <MyCustomFiles Include="C:\Test\ExternalContent\*" />
    <DotNetPublishFiles Include="@(MyCustomFiles)">
      <DestinationRelativePath>wwwroot/ExternalContent/%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
    </DotNetPublishFiles>
  </ItemGroup>

Here we have changed the source relative path from $(MSBuildProjectDirectory)/../ExternalContent/**/* to C:\Test\ExternalContent\*.

Selective file inclusion

In this method we will use the ResolvedFileToPublish tag, which is provided by a publish targets file in the .NET Core SDK. Because the Web SDK depends on the .NET Core SDK, either item can be used in an ASP.NET Core project.

The following exmaple demonstrates how to copy a file located outside of the project into the published site's wwwroot folder. The file name of externalfile.txt is maintained.

  <ItemGroup>
    <ResolvedFileToPublish Include="..\externalfile.txt">
      <RelativePath>wwwroot\externalfile.txt</RelativePath>
    </ResolvedFileToPublish>
  </ItemGroup>
  • In ResolvedFileToPublish tag, we are using Include attribute to specify the file we want to copy. This file resides in the parent directory of the project file's container directory.

  • RelativePath represent the relative path for the published directory.

The default behavior of ResolvedFileToPublish is to always copy the files provided in the Include attribute to the published site. We can override this default behavior by including a CopyToPublishDirectory child tag with inner text of either Never or PreserveNewest. For example:

 <ResolvedFileToPublish Include="..\externalfile.txt">
   <RelativePath>wwwroot\externalfile.txt</RelativePath>
   <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
 </ResolvedFileToPublish>

Again, if you don't want to specify source path relative to the project file's absolute path, you can also specific local absolute path, like:

  <ItemGroup>
    <ResolvedFileToPublish Include="C:\Test\externalfile.txt">
      <RelativePath>wwwroot\externalfile.txt</RelativePath>
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </ResolvedFileToPublish>
  </ItemGroup>

References:

July 21, 2020

How to exclude files from Publish Profile

When publishing ASP.NET Core web apps, it will publish/deploy the:

  • Build artifacts
  • files with .config extension
  • files with .json extension
  • everything inside wwwroot folder

At certain times you may need to exclude some specific file or folder from deployment content.

There are two ways you can exclude files from publishing.

Content Tag

If you need to prevent multiple files from being copied to deployed folder, you can use globbing patterns to cover a range of matching files.

Content tag will be used to specify the action on the file. For example, the following Content element will exclude all (.txt) files in the wwwroot\content folder and its subfolders.

<ItemGroup>
  <Content Update="wwwroot/content/**/*.txt" CopyToPublishDirectory="Never" />
</ItemGroup>

Note that it will delete all (.txt) files that are already exists at the deployed site within specified folder path.

You can specify different globbing patterns as per your requirement. Another version of pattern coud be like this:

<ItemGroup>
  <Content Update="wwwroot/content/Site*.css" CopyToPublishDirectory="Never" />
</ItemGroup>

This will match all css files in wwwroot/content folder with file name starts with Site e.g. SiteAdmin.css, SiteCustomer.css, etc...

You can add this markup to a publish profile (.pubxml file) or the .csproj file. Since .csproj file operates at the global level, if you add this tag to the .csproj file, the rule will be applied to all publish profiles in the project.

MsDeploySkipRules Tag

Another way to exclude file or folder is to use MsDeploySkipRules tag.

The following tag excludes all files/folders from the wwwroot\content folder:

<ItemGroup>
  <MsDeploySkipRules Include="CustomSkipFolder">
    <ObjectName>dirPath</ObjectName>
    <AbsolutePath>wwwroot\\content</AbsolutePath>
  </MsDeploySkipRules>
</ItemGroup>

Note that unlike Content tag, this will not delete the targeted file or folder if that are already exists on the deployed site.

Similarly you can specify a single file in AbsolutePath tag, but you need to change the ObjectName tag to filePath rather than dirPath, and also change the value of Include attribute from CustomSkipFolder to CustomSkipFile.

<ItemGroup>
  <MsDeploySkipRules Include="CustomSkipFile">
    <ObjectName>filePath</ObjectName>
    <AbsolutePath>wwwroot\\content\\Site.css</AbsolutePath>
  </MsDeploySkipRules>
</ItemGroup>

References: