Kentico Macro Secrets - Object Transformations

Posted: 5/22/2018 4:11:07 PM by Chris Bass | with 0 comments
Filed under: How-To, Macros, Performance

One of the more difficult thing new developers in Kentico seem to have trouble with is macros. On the surface, it seems simple: you've got your macro expressions doc page that lets you use a subset of C#, and you can write your own macro methods. But did you know you can do basic listing and transformations using just a macro, without ever touching a Repeater webpart? Yep, one of the more powerful things you can do out of the box with macros is buried in the bottom of the Macro Methods reference document

The two methods we're looking at here are ApplyTransformation() and Transform().
ApplyTransformation is the most integrated one: it takes in an object collection (which I'll explain later) and a transformation (plus a header and footer transformation if you want them), and applies the transformation and outputs it in place of the macro. The transformation has to be a Text / XML transformation (the sort with {% %}, not with <% %>) - but those have better performance and and the recommended transformation type by Kentico anyways, so you should already be using those :)

Transform() is the simple one, for when you don't want to bother making a whole transformation for something you'll definitely only use in one place, or you just want to test the output of an object collection before using it. That one you just pass in the transformation text directly. 

Important note on Transform()!  Since you're writing transformations, which almost certainly have macro tags in them (if nothing else, you probably want to output *something* dynamically, otherwise just write it out manually)... After checking in with Kentico Support, there is no escape sequence for their macro expressions. if you write {% "{% FullName %}" %} it's not going to output "FullName" and it's not going to output "{% FullName %}". It's going to output "{% FullName". The way you have to get around this is breaking up your string. So you'd write {% "{" + "% FullName %" + "}" %}... Technically you only have to do it for the closing tag but I like symmetry.

So in full, to write the user's full name in a strong tag (Kentico's example) - you'd write 
{% CurrentUser.Transform("<strong>{" + "% FullName %" + "}</strong>") %}. This is a simple example, but even this has an advantage over CurrentUser.FullName, in that it'll only output the <strong> tag if it actually finds the FullName property in the object you provide it.

To show the real power of this, though, let's look at the second piece I want to talk about today, SiteObjects and GlobalObjects.

This is simple to explain but once you see it you'll be amazed. You can find this in System -> Macros -> Console, or the various "Insert Macro" screens in Kentico, but I prefer the former since you can test out your macro before using it in many cases.

It turns out, in addition to the various Context objects (MembershipContext, DocumentContext, etc) there are two objects, SiteObjects and GlobalObjects. These have collections of seemingly every Kentico object in the system - seriously, go open SiteObjects in the console and watch it unload pages upon pages of collections, from Customers to Currencies to Orders to Groups to MediaLibraries to Emails to SKUs to Polls to Categories to... the list goes on. And if you open GlobalObjects, you'll find even more, all the collections that aren't site-dependent.

HOWEVER. Note that Kentico, for whatever reason, doesn't sort these. At all. So you can't just scroll through and find the one you want. I can't fathom how this was overlooked, but it does mean if you want something, you basically have to ctrl+F for it. Well worth it though.

That same user object I mentioned earlier? Want *all* the firstNames of users?  and want those names to be uppercase?
{% GlobalObjects.Users.Transform("<strong>{" + "% FullName.ToUpper() %" + "}</strong>") %}

Want *some* users? All of the Data Manipulation macros work here, so
{% GlobalObjects.Users.Columns("UserName, FullName").Where("UserName LIKE '%Johnny%'").TopN(4).OrderBy("FullName DESC").Transform("<strong>{" + "% FullName %" + "}</strong>") %}

My only caveat here is that for Pages, you probably still want to stick to the standard repeaters, because they automatically handle things like Publishing.
And remember, because this is Macros, you can do caching, just by adding the Cache() expression around your transformation.  

So, all of this, and I wanted to mention it because, as far as I can tell, SiteObjects/GlobalObjects are only each mentioned in one place, neither of which are the focus of the place they're mentioned. And the Transformation methods are at the very bottom of the Macros document and are similarly not granted more than an example's worth of attention.

Blog post currently doesn't have any comments.
 Security code