Exago Logo
Generic filters
Exact matches only

Storage Management: Custom Implementation

Recommended Reading

The following articles provide background on Exago’s Storage Management system. It is highly recommended to review them before writing a custom implementation of Storage Management.


Clients may write their own implementation of the Storage Management assembly to replace Exago’s out-of-the-box implementation.

In v2020.1, a custom assembly must contain one class that implements the entire IStorageManagement interface.

In v2021.1+, the IStorageManagement interface methods have been virtualized, so clients need only implement the methods that will operate differently than Exago’s out-of-the-box behavior. Refer to the basic example at the end of this article.

Clients looking to write their own Storage Management assembly may download Exago’s Storage Management implementation code as a Visual Studio project from the Downloads page on Support Site. Clients are also encouraged to open a Services Ticket in our Support Center for assistance if desired.


The SessionInfo object is not available in the Storage Management system. However, there is a dictionary of options passed around the Storage Management system that stores pertinent information for the database, but additional key-value pairs can be added as needed. This dictionary may be accessed with the .NET API, REST Web Service API and within the Storage Management assembly itself.


This example modifies the constructor of Exago’s Storage Management example.

public StorageMgmtDatabase(StorageMgmtConfig config) {
 //set the value of the companyId identity key to Exago, Inc.
 config.SetIdentity("companyId", "Exago, Inc.");
 //set a Custom Option named userProfile
 config.SetOption("userProfile", "support_Administrator");



This article references <WebApp>/, <WebSvc>/ and <Sched>/as a placeholder for the Web Application, Web Service API and Scheduler Service’s install location respectively. The default install location is C:Program FilesExagoExagoWeb (/opt/Exago/ on Linux), C:Program FilesExagoExagoWebApi ( /opt/Exago/WebServiceApi/ on Linux) or C:Program FilesExagoExagoScheduler (/opt/Exago/Scheduler/ on Linux); however, these directories can be changed during installation.

Once developed, move the finished library into a directory accessible to the Exago Web Application e.g. <WebApp>/bin, Scheduler Services e.g. <Sched>/bin (if applicable) and REST Web Service API e.g. <WebSvc>/bin (if applicable). Then set the Admin Console > Storage Management > Assembly Location and Class Name settings accordingly.


Name the DLL file something other than WebReports.ContentDatabase.dll as not to overwrite the Exago provided library. This way, if troubleshooting is ever needed in the future, it is easy to change back to the factory provided implementation.

ContentMetadata Class

The ContentMetadata class contains metadata about reports and other content. This data is saved to the Storage Management database, and is serializable as JSON.

Namespace: WebReports.Api.Common


A ContentMetaData object has the following properties. Properties that appear as hyperlinks below require constants or enums which are documented in the Constants and Enumerators article.

Table A — ContentMetaData Class Properties
AccessFlagsContentPermissionyesInteger representation of bitmap of the access flags bitmap
AgeTimeSpannoThe age of the object, used internally
AllowExportCsvbooleanyesWhether this report object can be exported to CSV.
AllowExportExcelbooleanyesWhether this report object can be exported as an Excel workbook.
AllowExportHtmlbooleanyesWhether this report object can be run in a Report Viewer
AllowExportPdfbooleanyesWhether this report object can be exported as a PDF file.
AllowExportRtfbooleanyesWhether this report object can be exported as an RTF file.
AttributestringyesIf this content is a theme, then this is theme type (i.e. Chart, CrossTab, Express, ExpressView, ExpressView_v2, Map)
CacheKeystringnoReturns the content ID of this object.
CanRenamebooleanyesThis field is not implemented and is ignored.
CanSharebooleanyesThis field is not implemented and is ignored.
ClientDatastringyesContent of the UDF metadata string from a custom folder management implementation.
ContentDataarray of byteyesHolds the binary content of templates
ContentIdGUIDyesThe GUID which uniquely identifies this content item throughout the application
ContentTypewrContentTypeyesThe type of content that this content item is
ContentXMLstringyesHolds the text string for reports and themes
DescriptionstringyesUser supplied report description field
ExportFlagsintegeryesBitmap indicating the various permitted export types. From MSB to LSB: Excel, CSV, RTF, PDF, HTML.

This property is for informational purposes only. Changing it will not affect the report’s output types. Output types are only controlled by the report.

ExtendedAttributesstringyesThis field is reserved for use by Exago clients, for storing metadata about content as they see fit in their custom implementation.
ExtensionDatastringyesThis field is for future functionality and is not implemented yet.
FolderstringyesRelative folder path of this content item
FullNamestringyesFolder path plus the report name
Example: My Reports\Sales Report
IsFolderbooleanyesIndicates if this content item is a folder as opposed to a report
IsOwnerbooleanyesIndicates if the current user is the owner of the content item
IsReadOnlybooleanyesDetermines if this item is considered to be read-only.
IsReportbooleanyesIndicates if this content item is a report. True if it is a report, False is it is not a report.
NamestringyesReport name without the folder or file extension
ParentIdGUIDyesThe GUID that uniquely identifies the parent (folder) of this content item
ReportTypewrReportTypeyesIf the ContentType property is wrContentType.Report, this property indicates the report type it is
TimestampDateTimeyesA DateTime representing the moment when this object was created.
DefaultExportTypeExportFlagyesThe report’s Default Export Type setting, represented by the ExportFlag enumeration.
ReportTreeShortcutActionTreeShortcutyesThe report’s Report Tree Shortcut setting, using the TreeShortcut enumeration.
UseCacheExecutionbooleanyesIf this content item is a report, this column is True if Execution Caching is enabled for this report, or False if Execution Caching is disabled.
IsCacheValidbooleanyesThis column is for future functionality and is not implemented yet.
AssociatedReportsList of GUIDyesA list of content_ids as GUIDs for each report that is associated with this one. Reports become associated with others when they are components in a Composite Report such as Chained Report or Dashboard, or if an Advanced Report contains linked reports.

  • Chained Reports: Each component report in a chain is included.
  • Dashboards: Each Existing Report tile is included.
  • Advanced Report with linked report: a report is included for each cell that is linked. For example, if there are 4 cells that link to the same report, the same content_id will appear in this list 4 times.
SourceIdGUIDyesThe content ID that this ContentMetadata object is based on.

For newly created content or when saving a report with the same name this field will be Guid.Empty.

For duplicated reports or when saving an existing report with a new name, this field will be the content ID of the original report.

When exporting an ExpressView to an Advanced Report, this field will be the content ID of the ExpressView.

Based on the value of this field, it can be determined if an item is being saved for the first time, being duplicated in the user interface, or saved with either a new or existing location.


public ContentMetadata()

DescriptionInstantiate a new ContentMetadata object. ContentMetadata.AccessFlags will be set to full permissions.

public ContentMetadata(ContentMetadata other)

DescriptionCopy constructor: Instantiate a new ContentMetadata object and copy the properties of the passed object other to this one.
The following properties are copied:

  • ContentId
  • ParentId
  • ReportType
  • ContentType
  • Name
  • Folder
  • Description
  • IsReadOnly
  • ExportFlags
  • TimeStamp
  • ContentXML
  • ContentData
  • AccessFlags
  • ClientData
  • ExtendedAttributes
  • SortOrder
  • IsOwner
  • ReportTreeShortcutAction
  • DefaultExportType
  • other: the ContentMetadata object to copy into this new one


string GetUdfJson()

DescriptionSerializes this content object as JSON. Includes metadata about the item. Properties included in the JSON:

  • ContentId
  • ContentType
  • ReportType
  • AccessFlags
  • ClientData
ReturnsA JSON encoded String of this object for use in the client

static ContentMetadata GetMetadataFromJson(string jsonStr)

DescriptionReturn a ContentMetadata object from the supplied string, assumed to be a JSON serialized form of a ContentMetadata object. This method is static.
  • jsonStr: a JSON serialized form of a ContentMetadata object
ReturnsA ContentMetadata object

void SetFullNamesFromFullName(string fullName)

DescriptionSet the report name (Name property) and folder (Folder property) from the specified FullName property string.
  • fullName: a string representing the FullName property of a content item.

string ToString()

DescriptionReturn a string representation of the ContentMetadata object
ReturnsA string in the following format:

ReportMetadata Id: {contentId} Name: {name} Folder: {folder} Type: {report or content type}

Items in {braces} will be replaced by the object’s properties. Examples:

ReportMetadata Id: 34952c9c-9b0c-869a-c850-3b623ba4005b Name: Current Product Listing Folder: General Reports Type: ExpressView
ReportMetadata Id: 141f017a-e8c2-4a9a-baec-90826bab4d77 Name: SA Timesheet (blank).pdf Folder: NULL Type: Template

IStorageManagement Interface

The IStorageManagement interface defines all of the necessary methods that will be called from Exago BI to read and write content to the Storage Mechanism. All of the permissions logic, if applicable, can be built into the methods of this class.

WebReports.Api.Report.ReportProperties objects can be used for reading information about reports directly from their XML definition, without having to first load the report with ReportObjectFactory.LoadFromRepository(string name).

Namespace: WebReports.Api.ReportMgmt

public interface IStorageManagement
  wrContentType? GetContentType(Guid contentId)
  IEnumerable<ContentMetadata> GetContentList(wrContentType contentType, bool includeContent = false);
  ContentMetadata GetContent(ContentMetadata metadata);

  string GetCacheKey();

  void RenameContent(ContentMetadata metadata, string newName, ContentMetadata parentMetadata);

  void DeleteContent(ContentMetadata metadata);

  void SaveContent(ContentMetadata metadata);
  StorageMgmtResult ValidateContentName(string reportName, string udfData);

  void AddFolder(ContentMetadata metadata);
  void MoveFolder(ContentMetadata folder, ContentMetadata target, bool updatePermissions);

  IEnumerable<string> GetTemplateList();

  byte[] GetTemplate(string templateName);

  void SaveTemplate(string templateName, byte[] templateData)

  IEnumerable<ContentMetadata> GetThemeList(string themeType);

  bool ExistTheme(string themeType, string themeName);

  string GetTheme(string themeType, string themeName);

  void SaveTheme(string themeType, string themeName, string themeData);

  void ClearReportListCache();
  string TestConnection();

  string InitDb(string jsonSchemaFilePath, bool showSQL);


wrContentType? GetContentType(Guid contentId);

DescriptionReturn the content type (e.g. report, folder, theme, template) of the object whose ID is contentId


This call ignores the user’s access permissions.

  • contentId: a GUID, the content ID in the database of the content whose type to retrieve
Returnsa value from the wrContentType enumeration representing the type of content (e.g. folder, report, theme, template) to return

IEnumerable<ContentMetadata> GetContentList(wrContentType contentType,
bool includeContent)

DescriptionReturn a collection of content items of the specified type as ContentMetadata objects.

This method is called whenever a list of content is needed, such as by the Report Tree, in the Linked Report Wizard, the Name tab of the Report Wizard, the Duplicate Report dialog, the Role Folders dialog in the Admin Console.

  • contentType: a value from the wrContentType enumeration representing the type of content (e.g. folder, report, theme, template) to return
  • includeContent: boolean value indicating whether or not the content item’s full content (either the text or binary content) will be returned in the ContentMetadata object. Set to true to return content, false to return metadata only. Default value is false.
ReturnsA collection of ContentMetadata objects

ContentMetadata GetContent(ContentMetadata metadata)

DescriptionReturn the metadata and content (text or binary) for the specified content item.

This method is called whenever content needs to be retrieved from the Storage Management database. This includes opening a report to edit or execute, reading in template files or themes during report design or execution. This method is also called after clicking Finish in the Report Wizard to load the newly created report into the Designer, and when clicking on items in the Report Tree to load details about the item (e.g. export types).

  • metadata: a ContentMetadata object representing the content item to retrieve.
ReturnsA ContentMetadata object that represents the content requested

string GetCacheKey()

DescriptionReturn the report list cache key. This is generally user specific and is constructed from containing all the identity keys referenced in the party type table.

Exago will compare the returned cache keys. If the cache key is different, the cache should be considered expired.

This method is called frequently to check if the cache has expired for a particular user, including the start of the session, starting the Report Designers or Report Wizards, and stepping through the Report Wizard.

ReturnsA string with the cache key.

void RenameContent(ContentMetadata metadata, string newName, ContentMetadata parentMetadata)

DescriptionRenames or moves a content item. Move an item by specifying a different parent item. The content indicated by metadata has its name changed to newName.

This method is called when moving or rename reports and when renaming folders. Folders are moved with the void MoveFolder method.

  • metadata: the ContentMetadata object to be renamed or moved.
  • newname: string with the new name for the content item
  • parentMetadata: a ContentMetadata object representing the parent of metadata. To move a content item to a new folder, specify a different parent object here. To keep the item in the same folder, specify the content item’s existing parent here.

void DeleteContent(ContentMetadata metadata)

DescriptionDelete the content in the metadata object.

This method is called anytime a content item is deleted, after the user interface requests confirmation from the user the item should be deleted.


void SaveContent(ContentMetadata metadata)

DescriptionSave the content in the metadata object. This may be a new or updated content.

This method is called when writing changes to content into the database. This could be a report, or a theme. Folders are added with the separate void AddFolder(ContentMetadata metadata) method.


StorageMgmtResult ValidateContentName(string reportName, string udfData)

DescriptionUsed to validate that a report name is legitimate and allowed in the database. The method should permit only valid report names to be saved in the database.

In Exago’s implementation of the interface, this method simply returns null as report name validation is handled elsewhere in the application.

  • reportName: the report name to be validated
  • udfData: additional UDF report data
ReturnsA StorageMgmtResult object that can be queried for a result code.

void AddFolder(ContentMetadata metadata)

DescriptionAdd a new folder. The new folder’s parent is set in the metadata object.

void MoveFolder(ContentMetadata folder, ContentMetadata target, bool updatePermissions)

DescriptionMove a folder into a new location, and optionally copy the permissions from the destination folder to content in the one being moved.

This method is called whenever a folder is moved, by dragging it around the Report Tree or when choosing Move Folder to Root from the right-click menu.

  • folder: a ContentMetadata object representing the folder to be moved.
  • target: a ContentMetadata object representing the destination where folder will be moved to.
  • updatePermissions: true if the permissions of target should be copied to content in folder or false if the permissions should not be copied. The permissions will only be changed for content that the current user is the owner of.

IEnumerable<string> GetTemplateList()

DescriptionReturn a collection of template names.

This method is called when opening the Template dialog on the Report Designer’s Settings menu and after after selecting a new Template file to upload with the Upload button.

ReturnsA collection of strings with names of the templates in the database.

byte[] GetTemplate(string templateName)

DescriptionGet the binary conrents of a Microsoft Word, Microsoft Excel or PDF template file.

This method is called when selecting a template from the dropdown list in the Template dialog, immediately after uploading a new template and after saving a report that includes a template.

  • templateName: the name from the Content table of the template file to read.
ReturnsA byte array of the binary contents of the template file.

void SaveTemplate(string templateName, byte[] templateData)

DescriptionSave the binary contents of a Microsoft Word, Microsoft Excel or PDF template file to the database.

This method is called to Upload a new template to the database from the Templates dialog in the Report Designer.

  • templateName: the name from the Content table of the template file to be saved.
  • templateData: a byte array of the binary contents of the template file.

IEnumerable<ContentMetadata> GetThemeList(string themeType)

DescriptionRetrieve a collection of theme names that match the specified theme type as ContentMetadata objects.

This method will be called from the Report Designers when they are opened, and before calling void SaveTheme(string themeType, string themeName, string themeData)

  • themeType: the type of theme to retrieve (e.g. ExpressView, Chart, Map, CrossTab, Express)
ReturnsAn enumerable collection of ContentMetadata objects representing all of the available themes of the requested type.

bool ExistTheme(string themeType, string themeName)

DescriptionCheck to see if a theme exists in the database.

This method is called when saving a theme to see if it already exists.

  • themeType: the type of the theme to check for.
  • themeName: the name of the theme to check for.
Returns true if the theme exists in the database, false if it does not

string GetTheme(string themeType, string themeName)

DescriptionGet the content of the theme.

This method will be called by a Report Designer to retrieve the theme data to apply it to the report.

  • themeType: the type of the theme to read.
  • themeName: the name of the theme to read.
ReturnsA string with the text content (XML, JSON or CSV) of the theme.

void SaveTheme(string themeType, string themeName, string themeData)

DescriptionSave new contents into a theme. If the theme exists, it will be overwritten.

This method is called when a theme is saved from one of the Report Designers.

  • themeType: the type of theme that will be saved
  • themeName: the name of theme that will be saved
  • themeData: the XML, JSON or CSV content of the theme that will be saved
this.SaveTheme("Chart", "Crimson Mountain", "#F0433A,#C9283E,#820333,#540032,#2E112D")

void ClearReportListCache()

DescriptionClear the report list cache.

This method should be called when saving or updating reports to make sure the Report Tree is up to date with the content changes.

string TestConnection()

DescriptionCheck the connection to the Storage Management database specified in the configuration file is valid.

This method is called when clicking the Check Database Settings button in the Admin Console.

ReturnsA string containing any error message, otherwise null if the connection is successful.

string InitDb(string jsonSchemaFilePath, bool showSQL)

DescriptionInitialize a Storage Management database with the schema definition found in the provided JSON file.

This method is called when clicking the Initialize Database or Show Schema SQL buttons in the Admin Console.

More information can be found in the Storage Management: Database Schema article.


Default location is <WebApp>ConfigOtherStorageMgmtSchema.json where <WebApp> is the installation directory of the Web Application.

  • jsonSchemaFilePath: full path to the schema definition JSON file.
  • showSQL: whether or not database intializing SQL statements should be returned
ReturnsIf showSQL is true, this method will return SQL statements that can be used to initialize a Storage Management database. If showSQL is false, this method will return null.

Virtualized Methods v2021.1+

Below is a basic example of a class that overrides only the SaveContent and AddFolder methods.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebReports.Api.Common;
using WebReports.Api.ReportMgmt;
using WebReports.ContentDatabase;

namespace V_versions
 public class V_storage : StorageMgmtDatabase
  private static readonly Logger logger = Log.GetLogger();

   * Provide a constructor
  public V_storage(StorageMgmtConfig config) : base(config)

   * Override the SaveContent method
   * <param name="metadata">the ContentMetadata object to be saved</param>
  public override void SaveContent(ContentMetadata metadata)
   //Custom implementation of the method goes here

   * Override the AddFolder method
   * <param name="metadata">a ContentMetadata object representing the folder to be added</param>
  public override void AddFolder(ContentMetadata metadata)
   //Custom implementation of the method does here

Then, based on this example in the Admin Console, set the following:

  • Assembly Location to the full path to the DLL produced by the project
  • Class NameV_versions.V_storage
Was this article helpful?
0 out of 5 stars
5 Stars 0%
4 Stars 0%
3 Stars 0%
2 Stars 0%
1 Stars 0%
How can we improve this article?
Please submit the reason for your vote so that we can improve the article.
Table of Contents