Don't miss out Virtual Happy Hour this Friday (April 26).

Try our conversational search powered by Generative AI!

Loading...

Recommended reading 

Note: Episerver uses the Episerver asset system by default. If you want to enable the legacy asset management system, set the UseLegacyAssetSystem configuration setting to true in the web.config files of both the Commerce Manager and the front-end sites. 

Episerver Commerce provides several options for storing assets. Episerver Commerce comes with providers for file storage, MSSQL storage, and Amazon S3. You can also create your own asset management provider. 

Classes in this topic are available in the following namespaces:

Key classes and files

  • ecf.asset.config
  • S3DownloadProfile
  • AssetConfiguration (in Configuration.cs)
  • S3StorageProvider
  • SqlBlobStorageProvider
  • PublicDiskBlobStorageProvider
  • FolderElementEntity

Configuration

In the Web.Config file of your Episerver Commerce site, under the element section, the AssetManagement element will point to the file ecf.asset.config.CommerceFramework.

Example: asset configuration section

XML
<CommerceFramework>
<!-- Asset Configuration -->
<AssetManagement configSource="Configs\ecf.asset.config"></AssetManagement>
</CommerceFramework>

In ecf.asset.config, you can declaratively specify different values for FolderProviders, DownloadFilters, and ElementTypes. These are made accessible through the static Instance property of the AssetConfiguration class.

What these asset types do:

  • FolderProviders. Specifies locations to store the binary data.
  • DownloadFilters. Performs additional actions before item is downloaded.
  • ElementTypes. Gets the element MIME types.

Example: specifying folders, downloads and element types

XML
<!-- Accessed through AssetConfiguration.Instance.FolderProviders -->
<FolderProviders>
  <add path="\Root\Cloud\*">
    <add storageProvider="S3StorageProvider" downloadProfile="s3"/>
  </add>
  <add path="\Root\Database\*">
    <add storageProvider="SqlBlobStorageProvider" downloadProfile="open"/>
  </add>
  <add path="\*">
    <add storageProvider="PublicDiskBlobStorageProvider" downloadProfile="iis"/>
  </add>
</FolderProviders>

<!-- Accessed through AssetConfiguration.Instance.DownloadFilters -->
<DownloadFilters>
  <add name="thumbnail" type="Mediachase.Commerce.Assets.DownloadFilterThumbnail, Mediachase.Commerce"/>
</DownloadFilters>

<!-- Accessed through AssetConfiguration.Instance.ElementTypes -->
<ElementTypes>
  <add mimeType="image/jpeg" type="Mediachase.Commerce.Assets.ImageFolderElementExtension, Mediachase.Commerce"/>
</ElementTypes>

Blob storage providers

SqlBlobStorageProvider and PublicDiskBlobStorageProvider extend the abstract class BlobStorageProvider, which defines a set of properties and methods for blob storing of data.

  • Mediachase.BusinessFoundation.Blob.PublicDiskStorageProvider. Stores blob data on a file system.
  • Mediachase.BusinessFoundation.Blob.SqlBlobStorageProvider. Stores blob data on an SQL database server.

Amazon S3 storage provider

S3StorageProvider extends the BlobStorageProvider  abstract class, which defines a set of properties and methods for blob (binary large object) storing of data. See also Amazon Simple Storage Service (Amazon S3).

  • Mediachase.Library.AmazonProviders.S3StorageProvider - used for storage blob data on Amazon's Simple Storage Service (S3).

Using FolderProviders

The collection of declaratively set FolderProviders is used by the FolderElementEntity class to store blob data. Operations on the blob data are abstracted away through the FolderElementEntity class's methods.

Example: using FolderElementEntity for blob storage

C#
/// <summary>
    /// Creates a new folder element.
    /// </summary>
    /// <param name="parentId">The parent id.</param>
    /// <param name="fileName">The Name of the file.</param>
    /// <param name="content">The content stream.</param>
    /// <param name="progressId">The progress id.</param>
    /// <returns></returns>
    public static FolderElementEntity Create(int parentId, string fileName, Stream content, Guid progressId)
    {
      FolderElementEntity result = new FolderElementEntity();

      result.ParentId = parentId;

      BlobInfo blobInfo = new BlobInfo(Guid.NewGuid());

      // Try recognizing the provider from configuration settings.
      BlobStorageProvider provider = BlobStorage.Provider;
      String providerName;
      String contentType = Mediachase.BusinessFoundation.Blob.ContentTypeResolver.ContentType.ResolveByPath(fileName);
      long fileSize = content.Length;

      if (TryRecognizeStorageProvider(result, fileName, contentType, fileSize, out providerName))
        provider = BlobStorage.Providers[providerName];

      blobInfo.FileName = fileName;
      blobInfo.Provider = provider.Name;
      blobInfo.Created = DateTime.UtcNow;
      blobInfo.ContentSize = fileSize;
      blobInfo.ContentType = contentType;
      // The content type assigned by provider.

      // Save blob info to storage.
      using (Stream stream = provider.CreateStream(blobInfo))
      {
        WriteToStream(stream, content, 0, fileSize, progressId);
      }

      provider.CommitStream(blobInfo);

      result.BlobStorageProvider = provider.Name;
      result.BlobUid = blobInfo.Uid;
      result.Created = DateTime.UtcNow;
      result.Name = blobInfo.FileName;

      if (result.Properties.Contains("ContentSize"))
        result.Properties["ContentSize"].Value = (Int32)blobInfo.ContentSize;
      if (result.Properties.Contains("ContentType"))
        result.Properties["ContentType"].Value = blobInfo.ContentType;

      // try
      IFolderElementExtension folderElement = GetCfgFolderElementExtension(blobInfo);

      if (folderElement != null)
        folderElement.Process(result);

      result.PrimaryKeyId = BusinessManager.Create(result);

      return result;
    }

    // ...

    /// <summary>
    /// Tries the recognize provider.
    /// </summary>
    /// <param name="element">The element.</param>
    /// <param name="fileName">Name of the file.</param>
    /// <param name="contentType">Type of the content.</param>
    /// <param name="fileSize">Size of the file.</param>
    /// <param name="providerName">Name of the provider.</param>
    /// <param name="profileName">Name of the profile.</param>
    /// <returns></returns>
    public static bool TryRecognizeStorageProvider(
      FolderElementEntity element
      , string fileName
      , String contentType
      , long fileSize
      , out String providerName
      , out string profileName
      )
    {
      providerName = String.Empty;
      profileName = String.Empty;

      FileLibraryLocationCollection locations = AssetConfiguration.Instance.FolderProviders;

      if (locations != null)
      {
        Dictionary<String, LocationRuleElement> matchList = new Dictionary<string, LocationRuleElement>();

        string hierarhy = element.GetElementPath("\\");
        foreach (FileLibraryLocationElement location in locations)
        {
          bool wildcard = location.Path.EndsWith(ConstWildcardCharacter);
          string locationPath = wildcard == true ?
              location.Path.Substring(0, location.Path.IndexOf(ConstWildcardCharacter))
              : location.Path;

          if (hierarhy.Equals(locationPath, StringComparison.InvariantCultureIgnoreCase)
            || ((wildcard == true) && (hierarhy.StartsWith(locationPath, StringComparison.InvariantCultureIgnoreCase))))
          {

            LocationRuleCollections rules = location.LocationRules;

            foreach (LocationRuleElement rule in rules)
            {
              bool found = true;

              if (!String.IsNullOrEmpty(rule.Extension))
              {
                found = fileName.EndsWith(rule.Extension,
                  StringComparison.InvariantCultureIgnoreCase) ? found : false;
              }

              if (!String.IsNullOrEmpty(rule.MimeType))
              {
                found = contentType.Equals(rule.MimeType,
                  StringComparison.InvariantCultureIgnoreCase) ? found : false;
              }

              if (!String.IsNullOrEmpty(rule.MaxSize))
              {
                String regExpPat = @"(?<size>[0-9]+)\s*(?<unit>Kb|Mb|Gb)?";
                Regex regExp = new Regex(regExpPat, RegexOptions.IgnoreCase);
                Match sizeMatch = regExp.Match(rule.MaxSize);
                if (sizeMatch.Success)
                {
                  long maxSize = Convert.ToInt64(sizeMatch.Groups["size"].Value);
                  string unit = sizeMatch.Groups["unit"].Value;
                  if (!String.IsNullOrEmpty(unit))
                  {
                    if (unit.Equals("Kb", StringComparison.InvariantCultureIgnoreCase))
                      maxSize *= 1024;
                    else if (unit.Equals("Mb", StringComparison.InvariantCultureIgnoreCase))
                      maxSize *= 1048576;
                    else if (unit.Equals("Gb", StringComparison.InvariantCultureIgnoreCase))
                      maxSize *= 1073741824;
                  }

                  found = fileSize >= maxSize ? found : false;
                }
              }

              if ((found == true) || (String.IsNullOrEmpty(rule.MaxSize)
                && String.IsNullOrEmpty(rule.MimeType)
                && String.IsNullOrEmpty(rule.MaxSize)))
              {
                matchList.Add(location.Path, rule);
                break;
              }
            }
          }
        }

        if (matchList.Count != 0)
        {
          // Get the location element with max depth.
          int maxDepth = -1;
          String maxKey = String.Empty;
          foreach (String key in matchList.Keys)
          {
            int depth = key.Split(new Char[] { '\\' }).Length;
            if (depth > maxDepth)
            {
              maxDepth = depth;
              maxKey = key;
            }
          }
          providerName = matchList[maxKey].StorageProvider;
          profileName = matchList[maxKey].DownloadProfile;
          return true;
        }
      }

      return false;
    
}
Do you find this information helpful? Please log in to provide feedback.

Last updated: Oct 12, 2015

Recommended reading