Xperience by Kentico uses a storage path registry to manage how application file system paths are routed to file system providers. Each Xperience module registers the file system paths it uses and classifies them by a path type. A mapping method reads these registrations and routes each path to the correct storage provider based on the hosting environment.
To activate storage path mapping, call the appropriate extension method in Program.cs for your hosting scenario. See Choose a mapping approach for details.
All system paths (media libraries, content item assets, form file attachments, AIRA files, and others) are registered by Xperience modules during startup. You only need to register custom paths if your application stores files in additional directories.
The mapping system consists of two parts:
SharedPersistent, SharedTemp, or LocalOnly). These declarations are collected in a central path registry (IStoragePathRegistry).All file I/O in Xperience goes through the CMS.IO abstraction layer, which delegates to the configured storage provider for each path. Application code reads and writes files through CMS.IO, and the underlying provider handles the rest. See Files API and CMS.IO for details.
The PathType enum classifies registered paths so the mapping system knows how to route them:
| Path type | Description | Mapping behavior | Examples |
|---|---|---|---|
SharedPersistent | Data shared across all instances with long-term persistence. | Mapped to persistent shared storage (e.g., Azure Blob Storage). | Content item assets, media library files, form file attachments, AIRA files |
SharedTemp | Temporary data shared across instances but not requiring long-term persistence. | Mapped to shared file system storage. | Content synchronization files |
LocalOnly | Instance-local data never shared across instances. | Uses the default local file system provider (no external mapping). | Caches, temporary files |
On Azure App Service (both SaaS and private cloud), all instances share the same local file system (an Azure-managed file share). Because of this, LocalOnly and SharedTemp paths both physically reside on storage accessible to all instances – the path type distinction has no practical effect on file accessibility between instances. The distinction matters in environments where each instance has a truly separate local disk (such as on-premises instances or container deployments without shared volumes), where SharedTemp paths are explicitly mapped to shared storage while LocalOnly paths remain instance-local.
The mapping approach depends on your hosting environment:
| Hosting scenario | Action | Details |
|---|---|---|
| Local single-instance development | No mapping needed. | All files stay on local disk via the default provider. |
| SaaS | Call AddXperienceCloudStoragePathMapping(). | See Azure Blob storage for SaaS. |
| Private cloud (Azure App Service) | Call AddAppServiceStoragePathMapping(). | See Azure Blob storage for private cloud. |
| Other private cloud (Amazon S3, on-premises, etc.) | Create a custom mapping module. | See Custom file system providers. For Amazon S3-specific configuration, see Amazon S3. |
Xperience modules register the following paths during application startup:
| Path | Path type | Identification method | Description |
|---|---|---|---|
| Media library files | SharedPersistent | IsMediaLibraryPath() | Binary files for media libraries (~/assets/media). |
| Content item assets | SharedPersistent | IsContentItemAssetPath() | Files stored in content item asset fields (~/assets/contentitems). |
| Content item asset temp | SharedTemp | IsContentItemAssetTempPath() | Temporary files for content item asset processing. |
| Form file attachments | SharedPersistent | IsBizFormFilesPath() | Files uploaded via form components (~/assets/bizformfiles). |
| Form file temp | SharedTemp | IsBizFormTempFilesPath() | Temporary files for form uploads. |
| AIRA files | SharedPersistent | IsAiraPath() | Files uploaded by the AIRA feature (~/assets/aira). |
| Synchronization data | SharedTemp | IsSynchronizationPath() | Content synchronization data files (~/assets/synchronizations). |
| Temporary files, caches, CI repository, event logs, wwwroot | LocalOnly | – | Instance-local files that are not mapped to external storage. |
The Identification method column lists extension methods from the CMS.IO.Extensions namespace. Use these methods in per-path configuration callbacks (such as CreateProviderForPath or ConfigureContainerForPath) to identify system paths.
If your application stores files in custom directories beyond what modules register, register them so the mapping system includes them.
using CMS.IO;
builder.Services.AddStoragePathRegistration("~/custom-uploads", PathType.SharedPersistent);
builder.Services.AddStoragePathRegistration("~/custom-temp", PathType.SharedTemp);If you develop custom Xperience modules that store files on the file system, register paths in the module's OnPreInit method:
using CMS;
using CMS.DataEngine;
using CMS.IO;
[assembly: RegisterModule(typeof(MyCustomModule))]
public class MyCustomModule : Module
{
public MyCustomModule()
: base(nameof(MyCustomModule)) { }
protected override void OnPreInit(ModulePreInitParameters parameters)
{
base.OnPreInit(parameters);
parameters.Services.AddStoragePathRegistration("~/assets/my-custom-data", PathType.SharedPersistent);
parameters.Services.AddStoragePathRegistration("~/assets/my-custom-temp", PathType.SharedTemp);
}
}Registered custom paths participate in the mapping system alongside system paths. Choose the appropriate path type based on the nature of the stored data.
AddStoragePathRegistration(). Unregistered paths are not included in automatic mapping, and files may be lost during redeployment or slot swaps.CreateProviderForPath, ConfigureContainerForPath, or similar callbacks), use extension methods from the CMS.IO.Extensions namespace (for example, IsMediaLibraryPath(), IsBizFormFilesPath()) to identify system paths. Avoid comparing against path strings directly, as paths may change between versions.