ASP.NET Core Web.config Transform for Production

September 01, 2021 by Anuraj

AspNetCore DevOps

This post is about enabling web.config transformation for deployment. Recently in one project I am working on I faced one issue. I had to enable some security configuration in the App Service - to remove Powered By header and Server header. These changes I did in the app service web.config. After another deployment it reverted back to default ASP.NET Core generated web.config file - when you execute the dotnet publish command - it will generated web.config file like this.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\DemoWebApp.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
    </system.webServer>
  </location>
</configuration>

In the web.config file, I had to add the following elements to fix the security headers issue.

To remove the Powered by header.

<httpProtocol>
  <customHeaders>
    <remove name="X-Powered-By"/>
  </customHeaders>
</httpProtocol>

And to remove the server header information.

<security>
  <requestFiltering removeServerHeader="true"/>
</security>

Both these configuration I have to add inside the system.webServer element. Then I found the web.config transformation. This will help you to transform your web.config while publishing your app. So I created a web.release.config file in the root folder. And modified the contents like this.

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <location>
    <system.webServer>
    <httpProtocol xdt:Transform="Insert">
    <customHeaders>
    <remove name="X-Powered-By" />
    </customHeaders>
    </httpProtocol>
    <security xdt:Transform="Insert">
      <requestFiltering removeServerHeader="true" />
    </security>
    </system.webServer>
  </location>
</configuration>

Now if you publish the app using dotnet publish you will get a web.config file like this.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\DemoWebApp.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
      <httpProtocol>
        <customHeaders>
          <remove name="X-Powered-By"/>
        </customHeaders>
      </httpProtocol>
      <security>
        <requestFiltering removeServerHeader="true"/>
      </security>
    </system.webServer>
  </location>
</configuration>

Both those elements are added to the web.config without any changes in the build steps or commands. If you’re using Visual Studio select the Web.Release.config file and set it build action to None. And if you’re using VS Code - add the following code in the project file.

<ItemGroup>
  <Content Remove="Web.Release.Config" />
</ItemGroup>
<ItemGroup>
  <None Include="Web.Release.Config" />
</ItemGroup>

This configuration will disable the deployment of the Web.Release.Config file to the deployment location.

Happy Programming :)

Copyright © 2024 Anuraj. Blog content licensed under the Creative Commons CC BY 2.5 | Unless otherwise stated or granted, code samples licensed under the MIT license. This is a personal blog. The opinions expressed here represent my own and not those of my employer. Powered by Jekyll. Hosted with ❤ by GitHub