Customize system providers
Providers in the Xperience API are classes that allow the system to manipulate objects and perform various actions. The following list presents the providers that the system uses and their purpose:
Info providers contain methods for working with specific types of objects stored in the database, such as users, contacts, and custom entities.
Xperience uses two distinct types of info provider classes.
Dedicated providers
This type of provider consists of a dedicated class and interface implementation and is solely responsible for a single database entity –UserInfoProvider
(with theIUserInfoProvider
interface) responsible forUserInfo
objects (from the CMS_User database table), for example. These providers are being actively phased out, to be replaced by generic providers.Generic providers
Generic providers are instances ofIInfoProvider<TInfo>
, where TInfo is the managed *Info class. We recommend using the generic provider pattern for all custom object types added to the system.The info provider customization pattern differs depending on provider type. See Providers based on I*InfoProvider interfaces for dedicated providers and Providers based on IInfoProvider<TInfo> for generic providers. For general overview of both types of providers, see Database table API.
Data provider handles low-level database operations. Info providers are built on top of the Data provider and use it to store and fetch data.
File system providers allow you to access various file systems. They extend the CMS.IO namespace.
By developing custom providers and using them instead of the standard ones, you can modify the behavior of the application (or a specific feature) according to your requirements.
Customization best practices
When developing custom functionality, we recommend placing your code files into a separate Class Library project (assembly), which is referenced by the main application. See Integrate custom code for details.
Info provider customization
Providers based on IInfoProvider<TInfo>
Generic providers must be customized via inheritance from InfoProviderDecorator<TInfo>
. The class offers a set of virtual methods open to modification.
using CMS.DataEngine;
// Decorates a generic provider for objects of the 'MyInfo' type
public class MyInfoProviderDecorator : InfoProviderDecorator<MyInfo>
{
public MyInfoProviderDecorator(IInfoProvider<MyInfo> decoratedProvider)
: base(decoratedProvider)
{
}
public override void Set(MyInfo info)
{
// Execute custom logic then set using the underlying implementation
base.Set(info);
}
public override void Delete(MyInfo info)
{
// Execute custom logic then delete using the underlying implementation
base.Delete(info);
}
}
With the custom logic in place, register the decorator class using the RegisterCustomProvider
assembly attribute to replace it as the default for objects of the specified Info class.
[assembly: RegisterCustomProvider(typeof(MyInfoProviderDecorator))]
namespace Sample
{
public class MyInfoProviderDecorator : InfoProviderDecorator<MyInfo>
{
// ...
}
}
Providers based on I*InfoProvider interfaces
While using providers based on IInfoProvider<TInfo> is strongly recommended for all custom providers, not all system providers currently support this customization pattern. Use the approach described in this section to customize such providers.
Write the custom code
Custom provider classes must inherit from the original implementation. See Decorate system services for more information.
Register custom providers
Registering the customized provider replaces its default system implementation. To register custom providers, use the RegisterCustomProvider
assembly attribute.
[assembly: RegisterCustomProvider(typeof(UserInfoProviderDecorator))]
namespace Sample
{
public class UserInfoProviderDecorator : UserInfoProvider
{
// Decoration logic...
}
}
After the custom provider is registered, its implementation is automatically used when resolving the corresponding provider interface (IUserInfoProvider
in the case of the example) via dependency injection.
Info object validation
When saving info objects to the database, the system validates object code name format and uniqueness. You can extend this validation by implementing info-specific rules via IInfoValidator<TInfo>
.
- Create a new class that implements
IInfoValidator<TInfo>
. SubstituteTInfo
for the info object you want to validate. - Implement the
Validate
method. The method must returnInfoValidationResult
. We recommend storing error resource strings in resource files. - Register the validator into the service container as a singleton using the
RegisterImplementation
assembly attribute.
using CMS;
using CMS.Core;
using CMS.DataEngine;
// Registers the validator implementation to the service container
[assembly: RegisterImplementation(typeof(IInfoValidator<MyInfo>), typeof(MyInfoValidator), Lifestyle = Lifestyle.Singleton)]
public class MyInfoValidator : IInfoValidator<MyInfo>
{
public InfoValidationResult Validate(MyInfo info)
{
// Perform domain-specific validation and return a corresponding error
if (!IsValid(info))
{
return new InfoValidationResult(nameof(MyInfo.MyField), "resource.key");
};
// Indicates successful validation
return InfoValidationResult.Success;
}
private bool IsValid(MyInfo info)
{
// Validation logic...
}
}
Other provider types
Data and file system providers must customize the default implementation by inheriting from the original implementation. See Decorate system services for more information.
To replace the default system implementation, you must register the customized provider classes using the RegisterCustomProvider
assembly attribute. See Register custom providers for details about the registration attribute.
Additional customization options
In addition to providers, you can also customize the following helper classes:
Helper class name | Namespace | Description |
DirectoryHelper | CMS.IO | Manages directories in the file system. |
You can also use global event handlers to customize the behavior of the system. Handlers allow you to execute custom code whenever a specific event occurs in the system, such as page or object changes.