Mittwoch, 29. Juni 2011

Developing Custom RenderTags

Did you ever think of implementing your own RenderTag to ease up template development?
Management Server already provides everything you need for that task. There was only one small bug that was actually blocking the load mechanism of custom RenderTags. This was fixed for version 11 now and will soon be available in one of the next hotfixes for 10.1 SP2.

Here are the steps to develop your own RenderTag:

1. Open up Visual Studio and create a new class library project, e.g. My.CustomRenderTag
2. Add references to Reddot.CMS and Reddot.CMS.Rendering
3. Now add a new class and implement the Reddot.CMS.Rendering.IRenderTag interface, e.g. HelloWorldRenderTag:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Reddot.CMS.Rendering.Tags;
using Reddot.CMS.Rendering.Objects;
using System.Xml;
using Reddot.CMS.Rendering;

namespace My.CustomRenderTag
{
    public class HelloWorldRenderTag : IRenderTag
    {
        public HelloWorldRenderTag()
        {
        }

        public void Render(RenderStream outputStream, TagProcessor tagProcessor, XmlNode tag, ObjectLoadManager objectLoadManager, PageBuildContext context)
        {

            string text = tag.InnerText;
            if (string.IsNullOrEmpty(text))
            {
                outputStream.WriteLine("Hello World!");
            }
            else
            {
                outputStream.WriteLine("Hello {0}!", tag.InnerText);
            }          }
    }
}


4. Build the project
5. Adapt the main.config in your ASP directory:
add the following line in the <RenderTag>-section:
<RenderTags>
      <Tag name="helloworld" typename="HelloWorldRenderTag" namespace="My.CustomRenderTag" filename="<PathToAssembly>\My.CustomRenderTag.dll" />
6. Kill the RDCMSServiceProcess.exe
7. Now add your new RenderTag (<helloworld>) to your template

Kommentare:

  1. Nice to hear about the improvements comming up with version 11. Two and a half years after the significant 10.X release.
    Writing our own rendertags sounds interesting. We have to look into the methods and properties provided by the objects passed to the render - method. (Maybe we are able to traverse the project-tree via ObjectLoadManager, PageBuildContext, ... to move data between multiple levels of the project-tree, ...)
    Is it possible to process nested rendertags? Custom rendertag contains nested rendertag provided by the product and vice versa.

    AntwortenLöschen
  2. First of all, let me thank you for this comment.

    We're currently thinking of what to document. We're also thinking of changing the interface a bit to only provide interfaces to the outside world. Thus, it is not clear at the moment if it will be documented, but let me say that the PageBuildContext will be documented somehow, because it is necessary to get vital information like the rendermode, pageguid, etc.

    You can also use RQLs to get all the information you need. I don't think that the ObjectLoadManager is needed for this, though it can be a better choice.

    Regarding nested RenderTags. I'm not sure if this is working, but this definitely something, I will test soon.

    AntwortenLöschen
  3. Good idea to pass a interface (or abstract class) instead of a conrete class to the render-method. (Should make it easier to change internal behaviour in future version without breaking existing customer code.)

    On mour question about rendertags. You know customers are little monsters. You give them your small finger and they try to take the whole hand. ;-)
    PageBuilder and ObjectServer/ServiceProcess for the NavigationManager/Rendertags have (at least until 10.x as far as i know) their own caches. There is a limited amout of cache invalidation when a element is changed. Some type of elements are invalidated in de ObjectServer/ServiceProcess-Cache, others not. This results in getting old data when reading this elements via rendertag. It will be nice to see a this limitations resolved in future versions.

    AntwortenLöschen
  4. Yeah, at the moment, we still have this different caches in version 11. This means, we have the PageCache in Pagebuilder and a whole bunch of different caches in the Navigation (aka RDCMSServiceProcess in pre 11 versions). Some of them get informed of changes, other not as you pointed out.

    What we do in version 11 is to provide some more documentation about what a cache is meant for and if it is informed about updates or not.

    We'll have a look at refactoring the caches stuff when we have a look at moving WSM into the cloud.

    AntwortenLöschen