A read/write data provider

Creating a Read/Write Data Provider

In general, if you need a read/write data provider:

  1. You should inherit it from IWritableDataProvider rather than IDataProvider (which is read-only).
  2. In addition to three methods it has in common with IDataProvider (GetData<T>(), GetData<T>(IDataId dataId), GetSupportedInterfaces()) you have learnt to implement in other examples, you should implement three more methods for “write” operations on data:
  • AddNew<T>(IEnumerable<T> datas)
  • Delete(IEnumerable <DataSourceId> dataSourceId)
  • Update(IEnumerable <IData> datas)

Here is the sample project (with comments to code), which creates a custom data provider to manage vCards from the CMS Administrative Console. You can build, deploy and use the sample as described in the project’s Readme.txt.

If you want to implement the vCard data provider on your own, the following are the steps you should take.

Creating a vCard data provider from scratch

vCard is a widely used file format for electronic business cards.

We are going to manage vCard files (.vcf) by exposing them in C1 CMS as a data type. The vCard files will be kept in a specific folder on a CMS Website (/App_Data/Composite/VCardDataStores), the path to which will be configured in Composite.config and used as a parameter of the constructor for the vCard data provider.

To create a custom data provider for vCards from scratch:

  1. Implement the IDataId interface to uniquely identify a vCard in a data store.
  2. Create and implement an IData-based interface for vCard.
  3. Implement the IWritableDataProvider interface providing logic for CRUD operations on vCards.
  4. Add the data provider to C1 CMS
  5. (optionally) Provide GUI access to manage vCards from the Administrative console.

Before you begin:

  1. In Visual Studio, create a new project (Class Library).
  2. Add a reference to Composite.dll, and other ones required in the project (most likely, Microsoft.Practices.EnterpriseLibrary.Common.dll and System.Configuration).

(In the sample project, you may need to re-add the references to the above assemblies before building it.)

Implementing the IDataId interface

Before you get to the IData-based interface and its implementation, you should implement the IDataId interface (e.g. VCardDatId).

The class is used by the data provider when creating a new instance of the class that represents a vCard and uniquely locates the vCard in the data store.

In this case, it will set and get the Id property of the vCard class you are about to create, which is enough for a vCard ID.

Please see VCardDataId.cs in the sample project for an example.

Creating and implementing IData-based interface

Now you should create a data interface for your vCards (e.g. IVCard) inheriting from the IData interface and assigning required and optional attributes to both the interface and fields.

Please refer to “Data Types Using C#” for information about creating IData-based interfaces.

The interface should include a number of properties that match the fields used in vCards, e.g. Name (N), FormattedName (FN), Title (TITLE), Email (EMAIL). Plus, you should add a key property to the interface (e.g. Id).

The interface must be assigned a number of attributes:

  • AutoUpdateble
  • ImmutableTypeId
  • KeyPropertyName
  • DataAncestorProvider
  • DataScope
  • LabelPropertyName
  • CachingAttribute

The properties (“fields”) must be also assigned a number of attributes:

  • DefaultFieldStringValue (where appopriate)
  • StoreFieldType
  • ImmutableFieldId

Please see IVCard.cs in the sample project for an example.

Once you have created the interface, implement it in a class (e.g. VCard). In this class, implement all the properties you need from the IVCard interface.

In addition, add a private field as well as a public property of the VCardDataId type and add a parameter to the constructor to get the VCardDataId instance and assign it to the field.

Please see VCard.cs in the sample project for an example.

Implementing IWritableDataProvider

Finally, create your vCard data provider:

  1. Implement the IWritableDataProvider (e.g. VCardDataProvider).
  2. Add a private field and a public property of the DataProviderContext type. (You will use its CreateDataSourceId method when creating a new vCard).
  3. Implement the following methods:
  • GetSupportedInterfaces()
  • GetData<T>(), GetData<T>(IDataId dataId)
  • AddNew<T>(IEnumerable<T> datas)
  • Delete(IEnumerable <DataSourceId> dataSourceId)
  • Update(IEnumerable <IData> datas)

Since managing vCards, which are files (.vcf), requires file I/O operations, you may need to create some auxiliary methods that facilitate these operations when CRUD’ing.

If you are going to hard-code the path to the folder with .vcf files, you can keep your provider non-configurable:

[ConfigurationElementType(typeof(NonConfigurableDataProvider))]

To allow setting this path in Composite.config, you will need to implement an additional configuration element, add a parameter to get the path to the constructor of the provider, and initialize the provider by reading the value form the configuration and passing it to its constructor (via the IAssembler implementation class).

Please see VCardDataProvider.cs in the sample project for an example.

Adding vCard Provider to C1 CMS

Once you have created your custom data provider, build the project and do the following:

  1. Copy the project's DLL to /Bin folder of your website.
  2. Edit the /App_Data/Composite/Composite.config file and locate the element: Composite.Data.Plugins.DataProviderConfiguration/DataProviderPlugins
  3. Add the configuration element below (just before its end tag </DataProviderPlugins>) specifying its type and name. For example:
    <add dataDirectory="~/App_Data/Composite/VCardDataStores" type="Composite.WritableDataProvider.VCardDataProvider, Composite.WritableDataProvider" name="VCardDataProvider" />
  4. Log in to the CMS Administrative Console and then execute Tools | Restart Server.

As you can see in the above example, we use the ‘dataDirectory’ attribute to set the path to the folder where vCard files are to be kept.

Managing vCards from code

Once you have hooked the vCard data provider in C1 CMS, you can access and manage the exposed vCard data type programmatically via C1 CMS API .

Create a vCard:

using (DataConnection connection = new DataConnection()) 
{
  IVCard card = connection.CreateNew<IVCard>();
  card.Id = Guid.NewGuid();
  card.Name = "Doe;John";
  card.FormattedName = "John Doe";
  card.Title = "CEO";
  card.EMail = "johndoe@contoso.com";
  connection.Add(card);
}

Update a vCard:

using (DataConnection connection = new DataConnection()) 
{
  IVCard updateCard = connection.Get<IVCard>().First();
  updateCard.Name = "Smith;John";
  connection.Update(updateCard);
}

Delete a vCard:

using (DataConnection connection = new DataConnection()) 
{
  IVCard deleteCard = connection.Get<IVCard>().First();
  connection.Delete(deleteCard);
}

Adding GUI Elements

To allow users to view vCards in the Administrative console, you can use a Tree Definition. (Please see a “Guide to Console Application” for more information.)

Please see VCardView.xml in the sample project for an example.

To allow users add or edit vCards in the the Administrative console, you can also use a dynamic form for vCards exposed as a data type in C1 CMS. (Please see “Editing Form Markup” for more information.) You can then use the form in your tree definition for Add and Edit actions.

Please see VCardForm.xml in the sample project for an example.

The data type VCards from the sample project will be available in the Data perspective where you can add, edit and remove the vCards. The vCard files will be stored in /App_Data/Composite/VCardDataStores.