Composite C1 5.2
Composite C1 5.2 (5.2.6093.24082)
New name: September 21st we changed our project name from Composite C1 to Orckestra CMS Foundation. Existing releases (like this v5.2 release) have not been renamed.
Download
Download Composite C1 5.2, pre-compiled
What's new?
This release introduce a number of API level features and data layer changes in the core to enable support for storing multiple versions of data. This enable developers to create sophisticated multi version content publication features via add-ins.
Scheduled publication removed from the core
The feature driving the multiple data version changes is a more sophisticated “scheduled page publication” add-on that will be commercially available soon. The bad news is that we removed the original timed publication feature from the core to avoid clashes between the old and new models. This means you can no longer schedule page publishing on the open source version, at least not until we (or someone in the community) provide an add-on to fill in the gap. If this is affecting you, please raise an issue so we may dose the right amount of attention to this.
New interface IVersioned to signify a data type can be versioned
By implementing this new interface on a data type, you get a new Guid field VersionId, which will be part of the physical key of your data, but not the logical key.
If no other changes are made this mean you can receive multiple rows when you query for data on a specific logical key. This you may want in administrative lists, but to ensure a specific version is delivered - for instance on the public website - you can register a DataInterceptor to filter at data layer level, and eliminate the need for client code to be aware of data versioning.
DataInterceptors has existed for some years, and allow you to intercept queries for data and change the query (and thus the result). See the DataInterceptor class and the SetDataInterceptor method on DataFacade for info on this topic.
This interface has been added to the data types IPage and IPagePlaceholderContent and the base interface IPageMetaData – enabling data of these types to be versioned.
In case you want to add versioning features to a data type, but for some reason don't want to do this using the IVersioned interface, look at the property VersionKeyPropertyName below.
New Attribute for data interfaces [VersionKeyPropertyName(“somefield”)] to specify extra physical key field
Previously data types have had one or more key fields, which uniquely identified the data, both at data store level and logical level. To allow for multiple versions of a data to exist with the same logical key, we expand the physical key (like the Primary Key on a SQL table) with a second field to signify a sub version.
You can use the VersionKeyPropertyName attribute if you for some reason do not want to use the IVersioned interface to add versioning support, but you want to manage this aspect yourself.
Introducing data scope lifetime services
Data scopes now contain a way to register a service with the same lifespan as the data scope. This can be used in conjunction with data interceptors, to configure their behavior on a per connection (scope) basis.
Hooking in a service at connection scope level:
using (var con = new DataConnection())
{
con.AddService(MyService);
}
Hooking in a default service (to be used as fallback):
DataScopeServicesFacade.RegisterDefaultService(MyService);
You can disable all services you added to a connection (scope) using DisableServices() on the connection object. This will reset to underlying services that existed before your connection was created.
using (var con = new DataConnection())
{
con.AddService(MyService);
var filterdPages = con.Get<IPage>();
con.DisableServices();
var noneFilteredPages = con.Get<IPage>();
}
We mostly expect data scope lifetime services to be used to data interceptors – below is how you would register a data interceptor.
if (!DataFacade.HasGlobalDataInterceptor<IMyType>())
{
DataFacade.SetGlobalDataInterceptor< IMyType >(new MyFilteringDataInterceptor();
}
In your data interceptor, you can retrieve a service like this:
using (var con = new DataConnection())
{
object MyService = con.GetService(typeof (MyService));
}
As the code above imply, services are passed on to nested (child) scopes.
The concept being that your data interceptor with filter in different ways, depending on what has been added to the service.
Auxiliary URL / EntiryToken mapper support
In order to support URLs that address a specific version of a data, while keeping the existing URL / EntiryToken mapper engine, we introduced a new interface IServiceUrlToEntityTokenMapper which given a base URL and an EntityToken can ”specialize” the URL (append path info) and visa versa (given a URL with extra path info and a EntityToken matching the base path, specialize the EntityToken).
You can register your auxillary mapper like this:
UrlToEntityTokenFacade.Register(new MyUrlToEntityTokenMapper());
Despite the name ‘Service’ in this interface, this is not the place to inject services for data interceptors - for this a HTTP Module can do the trick.
ElementVisualizedData class now take ElementBundle and BundleElementName
For element providers (delivering the tree structures in the console) to allow users to interact with different versions of a data item, you can now define ‘bundles’ of elements, to be presented as a single node in the tree.
You define a bundle by having two or more elements share an ElementBundle value. You allow members in the bundle to be addressable by giving each of them a BundleElementName.
In the console, you will see a bundle as a single element. The first element in the bundle will be displayed by default. In the browser view a selector will appear, enumerating all the BundleElementName in the bundle. If the user change the selection, the selected element will be displayed in the tree and the associated URL for the selected element will be shown in the browser view.
var element = new Element(_elementProviderContext.CreateElementHandle(entityToken))
{
VisualData = new ElementVisualizedData
{
// ...
ElementBundle = data.Id.ToString(),
BundleElementName = data.VersionName
}
};
Versioned data helpers
To enable versioning features to be add-in based allow you to have custom columns to show up in existing views like “Bulk Publishing” and to support localized version naming (ex in the Version selector drop down in the browser) we introduced support for registering a helper class that can provide localized version name for data and extra columns to dynamically add in list views.
Your helper should inherit from VersionedDataHelperContract and can be registered like this:
VersionedDataHelper.RegisterVersionHelper(new MyVersionedDataHelper());
Form markup now support tooltips on document tabs
We’ve added support for controlling tooltip texts via the form markup. For situations where a user has multiple editors running with different versions of the same data, and each version share a title, the tooltip can be helpful to identify what version is running in a given tab, without having to focus it.
<?xml version="1.0" encoding="utf-8"?>
<cms:formdefinition ....>
<cms:bindings>
.....
<cms:binding name="Tooltip" type="System.String" optional="true" />
</cms:bindings>
<cms:layout iconhandle="...">
<cms:layout.tooltip>
<cms:read source="Tooltip" />
</cms:layout.tooltip>
....
</cms:layout>
<cms:formdefinition>
Other changes
Performance optimizations on data providers, C1 Console tree server rendering and “Bulk Publishing” view.
Method DataFacade.BuildNew() now works in unit test environment.
Client input validation messages are now localizable (ex. "required", "invalid number", etc.).