Introducing the Marker Kentico Business Library (MKB)

Posted by: admin | Technical | 05.02.2010

Marker Kentico Business Library

Marker Kentico Busi­ness Library

Marker have created a complete busi­ness layer facade for work­ing across the kentico docu­ment apis. Why would we do such a crazy thing? Well, we found that on larger and more complex web appli­ca­tions that we had a certain amount of trou­ble with the stan­dard approach.

When you use custom docu­ment types in Kentico, your rows are either returned as a CMS.TreeEngine.TreeNode or a System.Data.DataRow depend­ing on what part of the api you are using. So the first main driver for our busi­ness layer was to be able to have a busi­ness entity class that mapped directly to a custom docu­ment type in Kentico. This means we know exactly  how a partic­u­lar docu­ment type is repre­sented in our appli­ca­tion and know exactly what prop­er­ties it has.

Also, you have differ­ent apis depend­ing on whether or not you are using workflow/versioning or not.  All of the recom­mended devel­op­ment arti­cles within the Kentico docu­men­ta­tion gener­ally assume you are work­ing with published docu­ments on your site which might not always be the case.

It should be noted that this approach is really for aspx template advo­cates look­ing to get the maxi­mum control and perfor­mance from Kentico. This approach is likely overkill for smaller sites and is not applic­a­ble for the portal engine approach.

This arti­cle will focus on the basics of creat­ing an entity class mapping to your custom docu­ment type and using the generic repos­i­tory to perform some stan­dard oper­a­tions. There’s a lot of func­tion­al­ity in the MKB library beyond what is shown here and we doubt there is anything you can do with the kentico docu­ment 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 docu­ment entity class…

You can see a sample entity below which maps to a custom docu­ment type in our appli­ca­tion. You will need to create this for each custom docu­ment type in your appli­ca­tion. Note that we are currently work­ing on code gener­a­tion which will auto­mat­i­cally gener­ate these classes for you against the Kentico data­base. We think this would be a great feature to have within Kentico itself at some point.

Make sure you entity class inher­its from the Docu­mentEn­tity class (Marker.Kentico.Business.Entities.DocumentEntity). This class includes all the core fields for a kentico docu­ment instance.

Next, you should apply a special table attribute. The table attribute allows you to set the class name (maps to kentico docu­ment 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 addi­tion (not shown below) there is the possi­bil­ity of setting the default site code (default site code for all data access for the entity by default if required with multi site solu­tions and also a default wild­card alias key (for auto­mat­i­cally load­ing the entity based on a wild­card alias. If you don’t set this it’s the name of the entity lower­cased, in this case ‘supplier’).

Next, apply special field attrib­utes for each prop­erty you want to map to a kentico docu­ment type. Note that your prop­erty names can be differ­ent from the under­ly­ing field if you want, and you can specific the nature of the bind­ing (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 enti­ties using the docu­ment repository…

All you need to do is to put a using state­ment to the enti­ties and repos­i­tory namespaces

using Marker.Kentico.Business.Repository;
using Marker.Kentico.Business.Entities;

Then you can retrieve a strongly typed repos­i­tory to work with your supplier enti­ties as follows. This retrieves a single­ton instance of the repos­i­tory class, it could also be created using depen­dency injec­tion if preferred, but this is the simplest api to be offered.

var repository = RepositoryFactory<DocumentRepository<Supplier>>.Instance;

Once you have your repos­i­tory you can then load enti­ties or get the current entity (if it is a supplier other­wise 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 prop­er­ties and call the save method

supplier.Url = "http://newurl.com";
repository.Save(supplier);

Dele­tion is just as easy:

repository.Delete(supplier.DocumentID);

Custom Query Support with Paging!

You can see below that our repsi­tory enables query­ing with paging support (return­ing 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 struc­ture 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)

Crite­ria objects (not overloads)

You will likely have noticed that Kentico has dozens of over­loads for it’s core meth­ods. MKB gets round this by having a limited number of over­loads with crite­ria objects that contain prop­er­ties with sensi­ble defaults for all core operations.

For exam­ple, the QueryFind­Cri­te­ria mentioned above has the follow­ing properties.

  • Site­Name (defaults to current site)
  • Culture­Code
  • Where
  • TopN
  • Selec­tOn­ly­Pub­lished
  • OrderBy
  • CheckUser­Per­mis­sions
  • Query­Name
  • Para­me­ters

And there is a simpler TreeFind­Cri­te­ria accepted as an over­load to the Find method on any repos­i­tory with these properties:

  • Site­Name (defaults to current site)
  • Culture­Code
  • Where
  • TopN
  • Selec­tOn­ly­Pub­lished
  • OrderBy
  • CheckUser­Per­mis­sions
  • Alias­Path
  • CombineWith­De­fault­Cul­ture
  • MaxRel­a­tiveLevel
  • Select­Lat­estVer­sion — allows you to work with latest version of docu­ment under work­flow, no need to change your api!

We hope you can see how much simpler this is as you just need to set the prop­er­ties you expl­citly need for any query rather than being forced to use a partic­u­lar overload.

Conclu­sion

We are shar­ing this library because we believe that it will be of value for kentico devel­op­ers and part­ners to assess and make use of. We hope that it will also be useful for Kentico them­selves who might consider the devel­op­ment of such an api to make it easier to work with Kentico.

This code base is provided as is and we recom­mend you use it for test­ing purposes at this stage (although we feel the api cover­age is pretty good). We’ll support and answer ques­tions 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 inter­est is there!

Get the code!

We are provid­ing a debug compiled version of our busi­ness assem­bly to solicit feed­back on the apis offered. If there is suffi­cient inter­est we will release the code base on codeplex.

Down­load the latest version here: Marker.Kentico.Business.v3

11 Responses to “Introducing the Marker Kentico Business Library (MKB)”

Leave a Reply