Razor Host Widget - Example Code
As an ASP.NET developer, I have come to appreciate the power and simplicity Razor templates give developers when creating web sites.
Since Telerik does not currently support Razor as a templating engine, I decided to create a simple Razor Host Widget with a little help from the Razor Engine project from codeplex. http://razorengine.codeplex.com/
Inheriting from ContentBlock i was able to leverage the builtin editor for managing the razor template and enable the control to parse and render the Razor syntax suprisingly few lines of code.By inheriting from ContentBlock, I can even share the Razor Template as a Content Block and reuse it accross multiple pages.
Here is my quick proof of concept for a razor host widget.
using
System;
using
System.Text;
using
RazorEngine;
using
RazorEngine.Templating;
using
Telerik.Sitefinity.Modules.GenericContent.Web.UI;
using
Telerik.Sitefinity.Web.UI;
namespace
Rosetta.Sitefinity.Web.UI.RazorHost
public
class
RazorHostWidget : ContentBlock
protected
override
void
InitializeControls(GenericContainer container)
base
.InitializeControls(container);
var template =
this
.ContentHtml.Text;
string
parsedText;
try
parsedText = Razor.Parse(template);
catch
(TemplateCompilationException ex)
var errorMessage =
new
StringBuilder(ex.ToString());
errorMessage.AppendLine();
errorMessage.AppendLine(
"<ul>"
);
foreach
(var error
in
ex.Errors)
errorMessage.AppendLine(
"<li>"
);
errorMessage.AppendLine(error.ToString());
errorMessage.AppendLine(
"</li>"
);
errorMessage.AppendLine(
"</ul>"
);
parsedText = errorMessage.ToString();
catch
(Exception ex)
parsedText = ex.ToString();
this
.ContentHtml.Text = parsedText;
As you can see, Most of the code is just plumbing and error handling.
Once you register this control in the toolbox, you can use the Razor Host Widget to create some really powerful templates like this example which renders a random FAQ Item from a sitefinity list.
@
var manager = Telerik.Sitefinity.Modules.Lists.ListsManager.GetManager();
var items = from i in manager.GetListItems()
where i.Parent.Title == "FAQ"
&& i.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live
select i;
var count = items.Count();
var skip = new Random().Next(count);
var item = items.Skip(skip).FirstOrDefault();
<
div
class
=
"callout green"
>
<
h3
>@item.Title</
h3
>
<
p
>@item.Content</
p
>
</
div
>
There are a few issues with this implementation mainly around &'s and > being html encoded by the designer but it is a pretty simple to fix them in the HTML view before you save the Razor Template.
I really think this is just scratching the surface and there are a lot of ways to make this even better. A few ideas i have had are:
1. configuring namespaces in Razor Engine to make the code shorter by eliminating the fully qualified references for a lot of the code.
2. Creating a base class for use in the template to enable Url and Html Helper extensions like MVC does.
3. Adding Telerik helper methods in to the base class to grab the current page, or something.
4. Fixing the editor to not encode &, > etc. in the razor code blocks. May be able to do this by adding a plain text area to the editior where you put your razor initialization code and then concatenating it with the Html view before parsing the template.
5. Investigate the security implications of allowing content managers to write arbitrary code when content editing.
Feel free to use this code as you will, just reply to this thread and let me know what you did with it. I would love to see more examples of razor code you used.
Thanks,
JASON CHESTER
Technology Director
629 Euclid Avenue / Cleveland, OH 44114
E jason.chester@rosetta.com
rosetta.com
ROSETTA | Pilots, inventors and builders for a connected world.™
Hi Jason Chester,
I'm really happy to see that you've managed to achieve this. We were planing to introduce support for Razor engine at some point in Sitefinity but you've manage to do it before us. Congratulations.
Greetings,Hi Jason Chester,
We are also adding some points to your account for sharing the solution with us and the rest from the Sitefinity community.
Keep up the good work.
Thanks Jason,
Great work! Thanks for sharing!
-Lino