This content is retired. See latest version here.

Last updated: Oct 21 2014

Introduction

This topic describes legacy features still available in the Commerce Manager back-end system. The legacy asset management in Commerce Manager has been disabled and replaced with the EPiServer asset system.

EPiServer Commerce provides several options for storing assets. Out-of-the-box, EPiServer Commerce comes with providers for file storage, MSSQL storage and Amazon S3. You can also create your own asset management provider. This document describes the usage of some of the storage options available.

Classes referred to here 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 does:

  • FolderProviders - specifies different locations that binary data can be stored.
  • DownloadFilters - used to perform additional actions before an item is downloaded.
  • ElementTypes - used to get 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

The following blob (binary large object) storage provider types are available out-of-the-box:

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

SqlBlobStorageProvider and PublicDiskBlobStorageProvider are types defined in the Mediachase.BusinessFoundation assembly. They extend the abstract class BlobStorageProvider which defines a set of properties and methods for blob storing of data.

Amazon S3 storage provider

The following storage provider type is available out-of-the-box for Amazon S3 storage:

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

S3StorageProvider is a type defined in the Mediachase.Library.AmazonProviders assembly. It extends the abstract class BlobStorageProvider which defines a set of properties and methods for blob (binary large object) storing of data. Refer also to Amazon Simple Storage Service (Amazon S3) for more information

Using FolderProviders

The collection of declaratively set FolderProviders are 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;
    }

Comments