Writing a Record Cabinet provider

A provider connects Record Cabinet to another document system. If your organization has developers, they can write one in house. This guide covers what a provider must do.

This guide applies to Record Cabinet version 0.9.0.

Overview

Record Cabinet finds providers when it starts, by scanning for assemblies in its own folder. A provider is a .NET assembly with a class that implements IDataSourceProvider. No configuration file or code change is needed.

Once a provider is in place, an administrator adds the repository in Record Cabinet. Record Cabinet then uses the provider to browse cabinets and retrieve documents from the connected system. Repositories that use a custom provider are always read-only. Their cabinets cannot be edited, deleted, or written to.

Provider projects reference RecordCabinet.Core.dll, which is in the Record Cabinet installation folder.

What a provider must implement

The provider class implements IDataSourceProvider. It returns an IRepositoryContext, which supplies the repositories that Record Cabinet reads from. If an assembly contains more than one qualifying class, each one is registered separately.

IDataSourceProvider

public interface IDataSourceProvider
{
    string DisplayName { get; }
    Task<bool> CanHandleAsync(DbConnectionOptions connection);
    IRepositoryContext GetContext(DataSource dataSource);
}
  • DisplayName is the name of the document system, shown to administrators as the repository type. Use the product's name, not a class or assembly name.
  • CanHandleAsync is called when an administrator tests a connection. Open a connection with the supplied options and return true if the database is one your provider recognizes. Return false, and never throw, if it is unreachable or not recognized.
  • GetContext is called when Record Cabinet needs to read from a repository your provider owns. Return an IRepositoryContext backed by the supplied data source. Its Connection is never null at this point.

IRepositoryContext

public interface IRepositoryContext
{
    ICabinetRepository       CabinetRepository  { get; }
    IDocumentRepository      DocumentRepository { get; }
    IDocumentContentResolver ContentResolver    { get; }
    Task<RepositoryStats>    GetStatsAsync();
}

Each property must return a non-null implementation, and GetStatsAsync must never return null.

Repository interfaces

ICabinetRepository

MemberDescription
GetAsync()Returns all cabinets visible through this repository.
GetAsync(short cabinetId)Returns the cabinet with the given Id. Throws if it is not found.

Every cabinet your provider returns is listed in Record Cabinet. Create each one with the Cabinet.FromProvider factory method, passing the cabinet's id, name, and ordered fields. You can also pass a description and creation date if your system has them. Record Cabinet treats provider cabinets as locked.

IDocumentRepository

MemberDescription
GetAsync(short cabinetId, int limit)Returns up to limit document indices for the cabinet.
SearchAsync(Criteria criteria)Returns indices matching the search criteria.

Both members must return their indices already ordered. That order is what the document list shows, and nothing after your provider sorts it again. Choose the ordering that suits your source. When limit cuts the result short, return the indices your ordering puts first.

IDocumentContentResolver

MemberDescription
GetContentAsync(short cabinetId, int documentId)Returns the primary renderable content for a document.
GetContentPartsAsync(short cabinetId, int documentId)Returns all content parts for a document.

Statistics

GetStatsAsync returns a RepositoryStats with a display name and a CabinetStats entry for each cabinet, holding its document and index counts. Record Cabinet shows these on the administration home page.

Assembly requirements

A provider assembly must:

  • Target net10.0 and be binary-compatible with the installed application.
  • Reference RecordCabinet.Core as shipped with the application.
  • Contain a provider class that is public, not abstract, and has a public parameterless constructor. Record Cabinet creates each candidate by reflection with no arguments. A class that cannot be created this way is skipped without a message, as is an assembly that cannot be loaded.

There are no file naming rules.

The class name is a published identifier

Record Cabinet stores the provider's full type name with every repository configured against it, and uses that name at startup to pair the repository with its provider. Treat the namespace and class name as part of your published contract. If you rename or move the class after a repository has been set up, the repository stops loading until an administrator adds it again.

Deployment

  1. Build the provider assembly for net10.0.
  2. Copy the .dll, and any dependencies not already present, into the Record Cabinet application folder, the one that contains RecordCabinet.Web.dll.
  3. Restart the web application. The provider is discovered when it starts.
  4. As an administrator, add a repository and test the connection. If the provider recognizes the database, it is identified automatically. Save the repository to make its cabinets available.

Questions about a legacy system, or want me to write the provider? Contact me.