Introducing the Marker Kentico Business Library (MKB)
Posted by: Marker | Technical | 05.02.2010
Marker have created a complete business layer facade for working across the kentico document apis. Why would we do such a crazy thing? Well, we found that on larger and more complex web applications that we had a certain amount of trouble with the standard approach.
When you use custom document types in Kentico, your rows are either returned as a CMS.TreeEngine.TreeNode or a System.Data.DataRow depending on what part of the api you are using. So the first main driver for our business layer was to be able to have a business entity class that mapped directly to a custom document type in Kentico. This means we know exactly how a particular document type is represented in our application and know exactly what properties it has.
Also, you have different apis depending on whether or not you are using workflow/versioning or not. All of the recommended development articles within the Kentico documentation generally assume you are working with published documents on your site which might not always be the case.
It should be noted that this approach is really for aspx template advocates looking to get the maximum control and performance from Kentico. This approach is likely overkill for smaller sites and is not applicable for the portal engine approach.
This article will focus on the basics of creating an entity class mapping to your custom document type and using the generic repository to perform some standard operations. There’s a lot of functionality in the MKB library beyond what is shown here and we doubt there is anything you can do with the kentico document api that you can’t do more easily and cleanly with the MKB library, if there is, let us know!
This library works against v5 with the 5.0.5 hot fix applied only. Just drop it in your bin folder and off you go..
Let’s create our first document entity class…
You can see a sample entity below which maps to a custom document type in our application. You will need to create this for each custom document type in your application. Note that we are currently working on code generation which will automatically generate these classes for you against the Kentico database. We think this would be a great feature to have within Kentico itself at some point.
Make sure you entity class inherits from the DocumentEntity class (Marker.Kentico.Business.Entities.DocumentEntity). This class includes all the core fields for a kentico document instance.
Next, you should apply a special table attribute. The table attribute allows you to set the class name (maps to kentico document type’s class name) and default alias path (the default alias path which forms the basis of all data access for the entity by default). In addition (not shown below) there is the possibility of setting the default site code (default site code for all data access for the entity by default if required with multi site solutions and also a default wildcard alias key (for automatically loading the entity based on a wildcard alias. If you don’t set this it’s the name of the entity lowercased, in this case ‘supplier’).
Next, apply special field attributes for each property you want to map to a kentico document type. Note that your property names can be different from the underlying field if you want, and you can specific the nature of the binding (read, insert, update, all) as required.
This is all that is required to start using MKB, create a simply entity and move on to the next step, where the fun begins!
using Marker.Kentico.Business.Attributes;
using Marker.Kentico.Business.Enumeration;
using Marker.Kentico.Business.Entitie;
using Marker.Kentico.Business.Attributes;
using Marker.Kentico.Business.Enumerations;
using Marker.Kentico.Business.Entities;
public class Supplier : DocumentEntity
{
private string _companyName = string.Empty;
public Supplier()
{ }
[Field("CustomerCode", FieldBindingType.All)]
public string CustomerCode { get; set; }
[Field("CompanyName", FieldBindingType.All)]
public string CompanyName {
get { return _companyName; }
set
{
_companyName = value;
this.DocumentName = value;
}
}
[Field("ImageThumb", FieldBindingType.All)]
public Guid ImageThumb { get; set; }
[Field("Url", FieldBindingType.All)]
public string Url { get; set; }
[Field("Address", FieldBindingType.All)]
public string Address { get; set; }
[Field("Phone", FieldBindingType.All)]
public string Phone { get; set; }
}
Let’s work with our entities using the document repository…
All you need to do is to put a using statement to the entities and repository namespaces
using Marker.Kentico.Business.Repository; using Marker.Kentico.Business.Entities;
Then you can retrieve a strongly typed repository to work with your supplier entities as follows. This retrieves a singleton instance of the repository class, it could also be created using dependency injection if preferred, but this is the simplest api to be offered.
var repository = RepositoryFactory<DocumentRepository<Supplier>>.Instance;
Once you have your repository you can then load entities or get the current entity (if it is a supplier otherwise it will be null)
Supplier supplier = repository.Load(string aliasPath); Supplier supplier = repository.GetCurrent();
Here are some other thigns you can do…
Saving and Deleting
Just update your entity’s properties and call the save method
supplier.Url = "http://newurl.com"; repository.Save(supplier);
Deletion is just as easy:
repository.Delete(supplier.DocumentID);
Custom Query Support with Paging!
You can see below that our repsitory enables querying with paging support (returning the total results)
var searchCriteria = new QueryFindCriteria(); searchCriteria.QueryName = "FindSuppliers"; // set the query name here searchCriteria.SelectOnlyPublished = false; // let's include unpublished nodes searchCriteria.Take = 10; // take 10 rows searchCriteria.Skip = 10; // start at row 11 int totalCount = 0; List<Supplier> suppliers = repository.Find(searchCriteria, out totalCount);
To support this you must be running SQL 2005 or above and simply structure your query as follows.
WITH AllResults AS ( -- core paged query should go in here select SupplierView.*, Row_Number() over (order by ##ORDERBY## as RowIndex FROM View_SMS_Supplier_Joined as SupplierView ##WHERE## ) SELECT (SELECT COUNT(NodeID) FROM AllResults ) As TotalResults, * FROM AllResults WHERE RowIndex > @skip AND RowIndex <= (@skip + @take)
Criteria objects (not overloads)
You will likely have noticed that Kentico has dozens of overloads for it’s core methods. MKB gets round this by having a limited number of overloads with criteria objects that contain properties with sensible defaults for all core operations.
For example, the QueryFindCriteria mentioned above has the following properties.
- SiteName (defaults to current site)
- CultureCode
- Where
- TopN
- SelectOnlyPublished
- OrderBy
- CheckUserPermissions
- QueryName
- Parameters
And there is a simpler TreeFindCriteria accepted as an overload to the Find method on any repository with these properties:
- SiteName (defaults to current site)
- CultureCode
- Where
- TopN
- SelectOnlyPublished
- OrderBy
- CheckUserPermissions
- AliasPath
- CombineWithDefaultCulture
- MaxRelativeLevel
- SelectLatestVersion – allows you to work with latest version of document under workflow, no need to change your api!
We hope you can see how much simpler this is as you just need to set the properties you explcitly need for any query rather than being forced to use a particular overload.
Conclusion
We are sharing this library because we believe that it will be of value for kentico developers and partners to assess and make use of. We hope that it will also be useful for Kentico themselves who might consider the development of such an api to make it easier to work with Kentico.
This code base is provided as is and we recommend you use it for testing purposes at this stage (although we feel the api coverage is pretty good). We’ll support and answer questions as best we can. There’s lots not covered here that is offered with the library that i’ll cover in future posts if the interest is there!
Get the code!
We are providing a debug compiled version of our business assembly to solicit feedback on the apis offered. If there is sufficient interest we will release the code base on codeplex.
Download the latest version here: Marker.Kentico.Business.v3

Very interesting… I’ve been mulling on something very similar. I especially like the server-side paging (ROW_NUMBER) stuff. Have you considered implementing SQL cache dependencies as well?
Great work, thanks so much for sharing it!
I have been working on something like this as well. In fact, I started from the opposite side, I now have auto-generated strongly typed classes based on custom document types (using a build provider). I haven’t had the time to develop a clean repository and querying API. I materialize these objects only for the current node.
I really feel that Kentico underdelivers on their API, and I see no signs that they will deliver a clean API in the _near_ future (5.x timeline). It seems that ASPX developers for Kentico are not the majority (but much more vocal on the uservoice site), thus it’s not the most important feature for them to develop.
Just out of curiosity, how are you unit testing this library? Do you use an example site, and roll back after running the tests? And how long did it take you to develop this library?
Thanks for posting this!
Hi Michiel,
I think that if Kentico are truly positioning Kentico CMS as an enterprise offering then they will have to provide a much better set of apis moving forwards, i don’t think the Portal Engine approach is for everyone. You only have to look at SharePoint to see that there is a lot of development work required behind the scenes to make things easier for users, and i don’t think the portal engine approach is enough.
Our testing has so far been rather limited to using aspx pages against each method of the repositories. It is definitely something we would like some help with if we decided to open source.
Would you be interested in looking at the code? Perhaps if you like the repository apprach etc. you could maybe integrate your build provider and we could get code generation added in?
Thanks for the feedback
Hi Rick,
Thanks for the feedback. haven’t got as far as cache dependencies on the sql side as yet. I’d need to do a bit more research on that to ensure it wouldn’t conflict with anythign kentico is doing on the caching side but interesting idea.
Downloading it now and looking forward to checking it out. Our team is also in the ASPX camp. As our projects increase in complexity, I am on the lookout for ways to work smarter.
great, let me know how you get on..
This is a really great idea. When we use custom document types (which is frequently!) we create a CustomObjectInfoProvider and a CustomObjectInfo class that allows you to create a new CustomObjectInfo(DataRow dr) by simply passing a DataRow to it, the same way Kentico handles it’s own document types.
What would be great is an application that could create these classes and the document type in Kentico CMS, we’ve thought about it a couple of times while going through the pain of writing providers.
Great job.
I have done a few tests with the library and so far I’m impressed. But automatic generation of the document entity classes (using a Build Provider for instance) is a must.
Another improvement is to automatically make properties that represent documents or attachments into entities as well. Kentico just stores a guid for those, so in our Build Provider we generate classes with properties of type Attachment or Document. So given a document type with a field that stores attachments, we can write code like this:
for(Attachment a in Document.Model.Downloads) {
// a.Url
// a.Filename
// a.Size
}
Where Attachment is a custom class that encapsulates an attachment in Kentico, Document.Model is a property on our custom TemplatePage class (derives from System.Web.UI.Page) and its Downloads property would be automatically generated to be of type List based on the field definition of the document type in Kentico. As you can see we separate Document (base properties that all documents have) and the Model (extra fields defined by the document type). I saw it as a 1-to-1 relationship between those two, not necessarily as a single type.
But what we have is read-only, just in order to ease template development. It’s also limited to stronly typed access to the current document for a template, with no repository to find other objects.
Regarding open sourcing this library. I don’t think there is such a strong community of Kentico developers. But if you do release it on Codeplex or something like that, I would be willing to devote some of my time to a Build Provider (but no guarantees, it would depend of time being available).
Has Kentico shown any interest in adopting the library?
Thanks again for sharing, great job!
I have done a few tests with the library and so far I’m impressed. But automatic generation of the document entity classes (using a Build Provider for instance) is a must.
Keith > Well, yes. We haven’t found it too much of a problem hand craftign the entities ourselves. I agree it will be a nice solution and we are part way there so it will come in a future release.
Another improvement is to automatically make properties that represent documents or attachments into entities as well. Kentico just stores a guid for those, so in our Build Provider we generate classes with properties of type Attachment or Document.
KP > We opted to keep things simple with the Guid. You can load an Attachment, optionally including the binary via the AttachmentRepository. This is consistent with us not attempting to have object properties at all as that leads into more complexity than we are able to handle at this time. For example Kentico doesn’t really support the notion of foreign keys or many to many doc types explicitly. We tend to just store the ids and then if we really want to, we create extra methods on the specific entity’s repository to return the objects or collections that we need. Obviously something like Linq for SQL/Entities would do this automatically, but we haven’t found the need as yet.
Regarding open sourcing this library. I don’t think there is such a strong community of Kentico developers. But if you do release it on Codeplex or something like that, I would be willing to devote some of my time to a Build Provider (but no guarantees, it would depend of time being available).
KP > We’ll probably release it with the next major version which will have code generation capabilities.
Has Kentico shown any interest in adopting the library?
KP > Nope. I originally shared it with them and they said that most kentico users/developers would not find the need for somethign so advanced. I think Martin the CTO liked some of the approaches and i genuinely hope it informs how they tackle things in 5.5 and beyond
Hey, thanks for your answers! I’m looking forward to a new release with a build provider.
I have done a few tests with the library and so far I’m impressed. But automatic generation of the document entity classes (using a Build Provider for instance) is a must.
Keith > Well, yes. We haven’t found it too much of a problem hand craftign the entities ourselves. I agree it will be a nice solution and we are part way there so it will come in a future release.
Another improvement is to automatically make properties that represent documents or attachments into entities as well. Kentico just stores a guid for those, so in our Build Provider we generate classes with properties of type Attachment or Document.
KP > We opted to keep things simple with the Guid. You can load an Attachment, optionally including the binary via the AttachmentRepository. This is consistent with us not attempting to have object properties at all as that leads into more complexity than we are able to handle at this time. For example Kentico doesn’t really support the notion of foreign keys or many to many doc types explicitly. We tend to just store the ids and then if we really want to, we create extra methods on the specific entity’s repository to return the objects or collections that we need. Obviously something like Linq for SQL/Entities would do this automatically, but we haven’t found the need as yet.
Regarding open sourcing this library. I don’t think there is such a strong community of Kentico developers. But if you do release it on Codeplex or something like that, I would be willing to devote some of my time to a Build Provider (but no guarantees, it would depend of time being available).
KP > We’ll probably release it with the next major version which will have code generation capabilities.
Has Kentico shown any interest in adopting the library?
KP > Nope. I originally shared it with them and they said that most kentico users/developers would not find the need for somethign so advanced. I think Martin the CTO liked some of the approaches and i genuinely hope it informs how they tackle things in 5.5 and beyond
Is it working with V6.0