Skip to main content

A Implementation - Pagination (Models)

This post adds pagination capabilities to an AJAX Dynamic Component Presentation (DCP) presented in an earlier post Rendering Only a Partial for AJAX.

The use case is the following: we have a controller that displays a list of DCPs in a paginated way. Due to the dynamic nature of this list, the list of DCPs should be rendered as a partial using AJAX. This implies that an actual AJAX request is made to the controller, which triggers only the list of DCPs be recalculated and served back. The paginated AJAX URL produces HTML directly, therefore the Javascript logic can simply replace the container div 'innerHTML' with the markup received from pagination. A whole page reload is thus not necessary. Additionally the list of DCPs can be sorted before being paginated, but about that in a later post.

This post descries the server-side model builder that generated the paginated list of models. In a subsequent post I will present the server-side views that render the same and the client-side Javascript performing the AJAX handling.

In RouteConfig.cs, I modified the partial AJAX route, by adding the lines highlighted below. They basically accept a new URL path parameter 'page' of type integer:

        name: "DCP",
        url: "{controller}/{action}/{publication}/{component}/{view}/{partial}/{page}.ajax",
        defaults: new
            partial = UrlParameter.Optional,
            page = UrlParameter.Optional
        constraints: new
            controller = @"\w{1,50}",
            action = @"\w{1,50}",
            publication = @"\d{1,3}",
            component = @"\d{1,6}",
            view = @"\w{1,50}",
            partial = @"_[\w\.]{1,50}",
            page = @"\d{0,3}"

An example URL for calling this partial paginated URL would be:

The URL above calls controller Device, action method Index on Component with id tcm:123-456 and uses view FullDetail to retrieve the DD4T strong model. The controller dispatches to view _PartialDocument.cshtml and displays page 2 of the list of documents that the controller built.

The models that make all this possible and their builders are as follows. We start with a very simple BaseBuilder class that holds a generic type 'ModelType' representing the actual model we build from. The class is abstract because it simply defines the signature of a Build() method to be implemented in one of the specific subclasses of it:

public abstract class BuilderBase<ModelType>
    public ModelType Model { get; protected set; }

    public BuilderBase(ModelType model)
        Model = model;

    public abstract void Build();

Next, we define base class AjaxBase, another generic that provides some common properties for AJAX calls, such as controller name, view, partialView, partialUrl:

public abstract class AjaxBase<ModelType>
    : BuilderBase<ModelType> where ModelType : ModelBase
    public string Controller { get; private set; }
    public bool IsPostback { get; protected set; }
    public string View { get; private set; }
    public string PartialView { get; private set; }
    public string PartialUrl
            Uri uri = HttpContext.Current.Request.Url;
            TcmUri modelId = new TcmUri(Model.Id);

            return string.Format("http://{0}{1}/{2}/Index/{3}/{4}/{5}/{6}",
                uri.Port == 80 ? string.Empty : string.Format(":{0}", uri.Port),

    public AjaxBase(ModelType model, string controller,
        string view, string partialView)
        : base(model)
        Controller = controller;
        View = view;
        PartialView = partialView;

Next, we define the PaginationBase class. In order not to reinvent the wheel, this class makes use of the package PagedList, which "makes it easier for .Net developers to write paging code", and "allows you to take any IEnumerable(T) and by specifying the page size and desired page index, select only a subset of that list". The class defines properties such as PageNumber and PageSize that will be used later on to determine which sub-set of the paged list to display. The class also helps us construct the paged partial URL that we call from client-side Javascript.

public abstract class PaginationBase<ModelType, PagedType> : AjaxBase<ModelType>
    where ModelType : ModelBase
    where PagedType : ModelBase
    public IPagedList<PagedType> PagedItems { get; protected set; }
    public int PageNumber { get; set; }
    public int PageSize { get { return 10; } } // just an example

    public PaginationBase(ModelType model, string controller, string view,
        string partialView, int pageNumber)
        : base(model, controller, view, partialView)
        PageNumber = Math.Max(1, pageNumber);

    public string GetPagerUrl(int pageNumber)
        return string.Format("{0}/{1}.ajax", PartialUrl, pageNumber);

    protected void ToPagedList(IEnumerable<PagedType> items)
        PagedItems = items.ToPagedList(PageNumber, PageSize);

Next, the actual implementation of the paginated model is class DocumentPartial. This class defines the Build() method that creates the list of Document object and then paginates it. Notice the use of IsPostback property -- this implies the method Build is only invoked during a postback from AJAX, otherwise this model partial does not actually build the paginated list.

public class DocumentPartial : PaginationBase<Device, Document>
    public DocumentPartial(Device device, int pageNumber)
        : base(device, "Device", "Device", "_PartialDocument", pageNumber)
    { }

    public override void Build()
        IsPostback = true;
        IEnumerable<Document> documents = // fetch the documents...

Finally, the calling code sits inside the controller. In our case, the Device controller, action Index has the following simplified logic. The DocumentPartial class is used to build the list of Document only if the partial variable is actually specified and has value '_PartialDocument'; otherwise, the DocumentPartial is created, but not built. The controller either dispatches directly to the _PartialDocument partial view with the corresponding paginated list of Document, or it attaches the empty DocumentPartial to the ViewBag for later processing during the Device view.

public class DeviceController
    public ActionResult Index(int? publication, int? component,
            string view, string partial, int? page)
        Device device;
        string viewName;
        ResolveModelAndView<Device>(publication, component, view, out device,
                out viewName);

        if (partial == null || partial == "_PartialDocument")
            var documentPartial = new DocumentPartial(device, page ?? 1);
            if (partial == null)
                ViewBag.DocumentPartial = documentPartial;
                return View(partial, documentPartial);

        return View(viewName, device);

The mechanism above is quite flexible and can be used in many situations time and time again, by simply providing implementation classes for the abstract PaginationBase and wiring them up in the Component Controller.

The pagination, ajax, or base models are quite versatile and can be used together or individually depending on the requirement to display simple embedded lists of DCPs, or AJAX lists, or paginated AJAX lists, or any combination thereof.

In a follow-up post Pagination (Views), I tackled the server-side view logic.


Popular posts from this blog

A Implementation - Custom Binary Publisher

The default way to publish binaries in DD4T is implemented in class DD4T.Templates.Base.Utils.BinaryPublisher and uses method RenderedItem.AddBinary(Component) . This produces binaries that have their TCM URI as suffix in their filename. In my recent project, we had a requirement that binary file names should be clean (without the TCM URI suffix). Therefore, it was time to modify the way DD4T was publishing binaries. The method in charge with publishing binaries is called PublishItem and is defined in class BinaryPublisher . I therefore extended the BinaryPublisher and overrode method PublishItem. public class CustomBinaryPublisher : BinaryPublisher { private Template currentTemplate; private TcmUri structureGroupUri; In its simplest form, method PublishItem just takes the item and passes it to the AddBinary. In order to accomplish the requirement, we must specify a filename while publishing. This is the file name part of the binary path of Component.BinaryConten

Event System to Create Mapped Structure Groups for Binary Publish

As a continuation of last week's Publish Binaries to Mapped Structure Group , this week's TBB is in fact the Event System part of that solution. Make sure you do check out the previous post first, which explains why and what this Event System does. To reiterate, the Event System intercepts a Multimedia Component save, take its Folder path and create a 1-to-1 mapping of Structure Groups. The original code was written, again, by my colleague Eric Huiza : [ TcmExtension ( "MyEvents" )] public class EventsManager  : TcmExtension {     private Configuration configuration;     private readonly Regex SAFE_DIRNAME_REGEX = new Regex ( @"[\W_]+" );     public EventsManager() {         ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap ();         fileMap.ExeConfigFilename = Path .GetDirectoryName( Assembly .GetExecutingAssembly().Location) + "\\EventSystem.config" ;         configuration = ConfigurationManager

Running sp_updatestats on AWS RDS database

Part of the maintenance tasks that I perform on a MSSQL Content Manager database is to run stored procedure sp_updatestats . exec sp_updatestats However, that is not supported on an AWS RDS instance. The error message below indicates that only the sa  account can perform this: Msg 15247 , Level 16 , State 1 , Procedure sp_updatestats, Line 15 [Batch Start Line 0 ] User does not have permission to perform this action. Instead there are several posts that suggest using UPDATE STATISTICS instead: I stumbled upon the following post from 2008 (!!!), , which describes a way to wrap the call to sp_updatestats and execute it under a different user: create procedure dbo.sp_updstats with execute as 'dbo' as