CONTENTSTART
EXCLUDESTART EXCLUDEEND

Transformations - To ASCX, or to Macro, that tis the Question!

The transformation engine in Kentico is one of the greatest things in the Portal method.  To be able to take any page type, any query, (and with some extra tools) any API source, and transform it.

But the question every new intern or employee asks who first dives into Transformations asks, is "...what type?"  ASCX, Text/XML, or one of the others.  

As with most things, the answer is "it depends" so let's dive into the situations to help you make the best decision!

What's are the Types of Transformations?

There are currently 5 different types of transformations.  ASCX, Text/XML, HTML, XSLT, and jQuery.  For all intensive purposes in the years I've used Kentico, I've never used XSLT and jQuery ever, and HTML is the same as Text/XML but with a WYSIWYG editor.

So the two I use primarily are ASCX and Text/XML.  These two have two distinct differences, one uses ASCX markup, the other uses Kentico's K# macro syntax.

Unique Things ASCX Can do

ASCX has some very unique capabilities.  

Access any available methods

Since the transformation is ASCX, you can call upon any function, even ones that aren't defined as a custom Transformation method.  For example, say you need to use the ValidationHelper method to convert a value to a specific type to execute other methods, you can call it.  See the sample below:

<%@ Import namespace="CMS.Helpers" %>
DateTime: <%# ValidationHelper.GetDate(Eval("Title"), new DateTime()).Format("MMM dd, YYYY") %>

Pull in Controls

The other huge benefit (and often the deciding factor of whether or not to use ASCX) is that you can pull in any control you want.  You can register controls (such as web parts) and use them.  Below I have a nested repeater example.

<%@ Register Src="~/CMSWebParts/Viewers/Documents/cmsrepeater.ascx" TagPrefix="uc1" TagName="cmsrepeater" %>
<div class="Children">
	<uc1:cmsrepeater runat="server" ID="myRepeater" ClassNames="Custom.ChildItems" TransformationName="Custom.MyTransformation" StopProcessing="true" />
</div>
<script runat="server">
	protected override void OnInit(EventArgs e)
        {
            myRepeater.StopProcessing = false;
            myRepeater.Path = Eval("NodeAliasPath") + "/%";
            // I believe the databind is what is called to render it.
            myRepeater.DataBind();
         }
</script>

Unique things Macros can do

Kentico's Macro engine is pretty slick, and when doing transformations, it's super easy to work with.

Context Aware

A big thing with macros is that you have access not only to the object you are transforming, but the entire context of the macro engine.  This means you have access to things like the Current Document, the current site, site settings, etc, all at your finger tips.  You even can do some pretty crazy things with doing Object Queries and applying transformations inline, and use inline widgets.

<div class="page {% ClassName == CurrentDocument.ClassName ? "SameClass" : "" %}">The Page</div>

Note: Technically you CAN access macros in ASCX, but you have to call the CMS.MacroEngine.MacroContext.CurrentResolver.ResolveMacros("{% The Macro %}") to do it, and really, who wants to do that?!

Cleaner Transformations with if/else type logic

Another big feature is macro's ability to do open condition loops, ternary ( true/false ? true : false), and other syntax-fully nifty things.  This makes transformations much cleaner, easier to read and manage.  Let's compare a k# transformation and ASCX doing the same operation:

{% if (string.IsNullOrWhiteSpace(HeaderText) {  %}
  <h1 class="title {% HeaderCSSClass %}">
  {% !string.IsNullOrWhiteSpace(HeaderLink) ? "<a href=\""+HeaderLink+"\">" : "") %}
    {% HeaderText %}
  {% !string.IsNullOrWhiteSpace(HeaderLink) ? "</a>" : "") %}
  </h1>
{% } @%}




<%# IfEmpty(Eval("HeaderText"),
  "",
  "<h1 class=\"title +"+Eval("HeaderCSSClass")+"\">"+
     IfEmpty("HeaderLink", "", "<a href=\""+Eval("HeaderLink")+"\">")
      +Eval("HeaderText")
     +IfEmpty("HeaderLink","","</a>")
  +"</h1>"
) %>
<!-- Not much better using String.Format -->
<%# IfEmpty(Eval("HeaderText"),
  "",
  string.Format("<h1 class=\"title {0}\">{1}{2}{3}</h1>",
    Eval("HeaderCSSClass"),
    IfEmpty("HeaderLink", "", "<a href=\""+Eval("HeaderLink")+"\">"),
    Eval("HeaderText"),
    IfEmpty("HeaderLink", "", "</a>")
  )
) %>

Intellisense makes sense!

This one is a biggy for me.  Any coder who uses Visual Studio (or any modern IDE) depends heavily on Intellisense.  That's where you are given hints on what methods/properties are available, and what parameters them up.  In ASCX, you do not have any intellisense (which when you create your own custom methods, can be a real bother when you have to go into your code to look up the format of your method).

Macros have that intellisense, and when you create your own custom macros, YOU get that intellisense as well.  This becomes a huge time saver.

I love it when Kentico speaks intellisense to me.

So...when do i use which one?

After all my experience with them, this is usually what it comes down to when deciding which transformation to use.
  • Do you need Context awareness?  Go with Text/XML
  • Does it contain advanced structure?  Go with Text/XML
  • Do you want ease of transformations and custom methods?  Go with Text/XML
As for ASCX....
  • Do you need to pull in ASCX Controls? Then you must go with ASCX transformation

Yeah, that's pretty much it.  The only time you really need to go with ASCX is if you are using custom ASCX controls in your transformation.  Ecommerce transformations are a great example as they have to pull in various Ecommerce controls (such as the Add to Cart).  I'm pretty much using Text/XML in most all of my transformations and I'm really loving how smooth things are working, and having intellisense for my various functions, and the ability to have full CMS context and access to all the macro engine has to offer.

One thing to watch out for with Macros

One thing with Macros is the signatures.  In many cases, Kentico adds a # symbol to the end of your macros, signing them as you for security purposes.  In the vast majority of cases, these really aren't necessary, you can replace the #%} ending with a @%} ending and not sign them, this reduces the footprint of the macros and also reduces the risk of needing to resign your macros.

Be aware that some times you DO need a signature and a macro won't work without it, such as when you query objects using macros.

Don't forget to cache!

One last thing before i wrap this up, don't forget that you can Cache macros inline, so if you're doing an object query that can be cached, you should consider using the caching syntax to do so.  Some macro items are already cached (like the Settings["TheSettingsKey"] macro calls are cached internally). 

That's all, Folks!

Thanks for reading through this lengthy article.  Hopefully this will help equip you to really leverage the amazing transformation engine and make your code easier to read, easier to maintain, and even more enjoyable to create.  Happy Kentico-ing!
Comments
Blog post currently doesn't have any comments.
Is two > than seven? (true/false)
CONTENTEND