Azure/DXP ImageProcessor Config Transform

  • Page Owner: Not Set
  • Last Reviewed: 2020-10-09

How do you do config transforms for Azure/DXP Sites.


Answer

This will need to be set on the Web.Integration.config so it will flow through all environments. If you deploy to stage/preproduction directly or through the api, you will need to add the transform in the Web.PreProduction.config file as well.

  <imageProcessor xdt:Transform="Replace">
    <security configSource="config\imageprocessor\security.config" />
    <caching configSource="config\imageprocessor\cache.azure.config" />  // This file
    <processing configSource="config\imageprocessor\processing.config" />
  </imageProcessor>

The file you need to add is cache.azure.config or whatever you want
you will need to use the nuget package “ImageProcessor.Web.Episerver.Azure“
https://world.episerver.com/blogs/vincent-baaij/dates/2017/11/episerver-and-imageprocessor-now-also-on-azure-and-cms-11/

FILENAME = "cache.azure.config"
<caching currentCache="EpiserverAzureBlobCache">
  <caches>
    <cache name="DiskCache" type="ImageProcessor.Web.Caching.DiskCache, ImageProcessor.Web" maxDays="365" memoryMaxMinutes="1" browserMaxDays="7">
      <settings>
        <setting key="VirtualCachePath" value="~/app_data/cache" />
      </settings>
    </cache>
    <cache name="EpiserverBlobCache" type="ImageProcessor.Web.Episerver.FileBlobCache, ImageProcessor.Web.Episerver" maxDays="365" browserMaxDays="7">
      <settings />
    </cache>
    <cache name="EpiserverAzureBlobCache" type="ImageProcessor.Web.Episerver.Azure.AzureBlobCache, ImageProcessor.Web.Episerver.Azure" maxDays="365">
      <settings>
        <setting key="StreamCachedImage" value="true" />
        <setting key="CDNTimeout" value="1000" />
      </settings>
    </cache>
  </caches>
</caching>

Additional Posts

A little more of an overview on this:

First, you will need a file for each environment:

  • Web.config - Your local environment
  • Web.Integration.config - Integration. Add all the necessary Azure/DXP stuff and redirects here.
  • Web.Preproduction.config - Preproduction. Replace any Preproduction-specific items here.
  • Web.Production.config - Production. Replace any Production-specific items here.

For each environment, assume that all the previous environment's transforms will be applied. For example:

  • Local - Web.config
  • Itegration - Web.config -> Web.Integration.config
  • Preproduction - Web.config -> Web.Integration.config -> Web.Preproduction.config
  • Production - Web.config -> Web.Integration.config -> Web.Preproduction.config -> Web.Production.config

Transforms cascade through the environments.

You will need to be sure that each config file is listed as Content in the csproj file. Otherwise, deployments done through the PAAS portal will not do the transformations.

Important Gotcha If you make any of the transforms DependentUpon the Web.config, even if they are embedded as Content, you must include /p:MarkWebConfigAssistFilesAsExclude=false in your MSBuild arguments in DevOps.

Some example transformations:

Integration Includes the Sentry environment, debug mode OFF, HTTPS redirect, 404 page handling, max versions, the Azure blobs and events, setting imageProcessor to the Azure settings, and includes a X-Environment header for testing that config transforms are working:

  <?xml version="1.0" encoding="utf-8"?>
  <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <appSettings>
      <add key="episerver:EnvironmentName" xdt:Locator="Match(key)" xdt:Transform="Remove" />
      <add key="sentry:Environment" value="DEV" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
    </appSettings>
    <system.web>
      <compilation optimizeCompilations="true" debug="false" xdt:Transform="SetAttributes" />
      <customErrors xdt:Transform="Remove" />
      <customErrors mode="On" xdt:Transform="Insert">
        <error statusCode="404" redirect="/404" />
      </customErrors>
    </system.web>
    <episerver>
      <applicationSettings uiMaxVersions="20" xdt:Transform="SetAttributes" />
    </episerver>
    <system.webServer>
      <httpErrors xdt:Transform="Remove" />
      <httpErrors errorMode="Custom" existingResponse="Replace" xdt:Transform="Insert">
        <remove statusCode="404" />
        <error statusCode="404" path="/404" responseMode="ExecuteURL" />
      </httpErrors>
      <rewrite xdt:Transform="InsertAfter(/configuration/system.webServer/handlers)">
        <rules>
          <rule name="Force HTTPS" enabled="true">
            <match url="(.*)" ignoreCase="false"/>
            <conditions>
              <add input="{REQUEST_URI}" pattern="^/indexingservice/indexingservice.svc" negate="true"/>
              <add input="{HTTPS}" pattern="off"/>
            </conditions>
            <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent"/>
          </rule>
        </rules>
        <outboundRules>
          <clear />
          <rule name="AddEnvironment">
            <match serverVariable="RESPONSE_X_ENVIRONMENT" pattern="^$" />
            <action type="Rewrite" value="Int" />
          </rule>
        </outboundRules>
      </rewrite>
    </system.webServer>
    <episerver.framework>
      <blob xdt:Transform="Remove" />
      <blob defaultProvider="azureblobs" xdt:Transform="InsertIfMissing">
        <providers>
          <add name="azureblobs" type="EPiServer.Azure.Blobs.AzureBlobProvider,EPiServer.Azure" connectionStringName="EPiServerAzureBlobs" container="webassets" />
        </providers>
      </blob>
      <event xdt:Transform="Remove" />
      <event defaultProvider="azureevents" xdt:Transform="InsertIfMissing">
        <providers>
          <add name="azureevents" type="EPiServer.Azure.Events.AzureEventProvider,EPiServer.Azure" connectionStringName="EPiServerAzureEvents" topic="webtopics" />
        </providers>
      </event>
    </episerver.framework>
    <imageProcessor xdt:Transform="Replace">
      <security configSource="config\imageprocessor\security.config" />
      <caching configSource="config\imageprocessor\cache.azure.config" />
      <processing configSource="config\imageprocessor\processing.config" />
    </imageProcessor>
  </configuration>

Preproduction Sets the updated Sentry environment and debugging X-Environment header.

  <?xml version="1.0" encoding="utf-8"?>
  <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <appSettings>
      <add key="sentry:Environment" value="STAGE" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
    </appSettings>
    <system.webServer>
      <rewrite>
        <outboundRules>
          <rule name="AddEnvironment" xdt:Transform="Replace" xdt:Locator="Match(name)">
            <match serverVariable="RESPONSE_X_ENVIRONMENT" pattern="^$" />
            <action type="Rewrite" value="Preprod" />
          </rule>
        </outboundRules>
      </rewrite>
    </system.webServer>
  </configuration>

Production Sets the correct Sentry environment and removes the X-Environment header (which should never appear in production). As an example, this one also sets the site to use infinite versions, but generally we should only do that if necessary.

  <?xml version="1.0" encoding="utf-8"?>
  <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <appSettings>
      <add key="sentry:Environment" value="PROD" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
    </appSettings>
    <episerver>
      <applicationSettings uiMaxVersions="0" xdt:Transform="SetAttributes" />
    </episerver>
    <system.webServer>
      <rewrite>
        <outboundRules>
          <rule name="AddEnvironment" xdt:Transform="Remove" xdt:Locator="Match(name)" ></rule>
        </outboundRules>
      </rewrite>
    </system.webServer>
  </configuration>