Late-bound Eval – email templates revisited
programming, spark, tech, templating January 27th, 2009Going back to December there was a comment on Using Spark as a general purpose template engine about the use of anonymous types for your ViewData model. Or about surfacing information in general without being type-specific.
Out of curiosity. If in EmailView I just had a public property…
public object data {get; set;}
and set the data using an anonymous type like so…
view.data = new {user = new {first=”Phil”, Last=”Haack”}};
Could I do this in the template
Hi ${data.user.last}, ${data.user.first}
To which I replied
Well… Sort of… But not really…
Thinking about it later I was mulling over the steps you would take to inject small DLR expressions of something like Ruby or Python. For performance you’d want to have keep and re-use the same code instance, because it trains and optimizes itself based on the types that pass through it. Most DLR expressions are ultimately run with the same type of value at most of their code points, which is how dynamic language engines can get blisteringly fast performance out of a run-time-type situation.
Then I realized something. That’s what the dynamic keyword does! It’s a tiny instantiation of a csharp DLR expression.
Hey, wait a second! Isn’t this exactly what the C# 4.0 dynamic keyword is for?
So then the answer is yes – with C# 4.0 you’ll be able to do exactly what you were asking.
And then after thinking about it even more I realized that’s also exactly what ViewData.Eval is for. The problem with ${ViewData.Eval(“data.user.last”)} is you’re not really gaining the benefit of late binding from a wrist pain standpoint. Yes, you haven’t declared the viewdata types, but taken together the repeated ViewData.Eval( ) will increase the overall template size and reduce readability.
Enter a new syntax! Within a code expression it’s never valid to have a # in front of an identifier, or series of identifiers connected by dots. That syntax is now repurposed – when it’s seen it’s treated as the string argument for a call to Eval.
Hi ${#user.last}, ${#user.first}
You can also provide a format string immediately after the late-bound expression. Like ${#foo.price '#,##0.00'}. Be sure not to put a comma between the #property and ‘format’ – the syntax doesn’t expect a comma because you could accidentally consume the next argument in a method call where a late-bound expression is used as a parameter.
There’s an example of using Spark directly for email or text templating with late-bound anonymous data in the Samples folder of the download.
Label3.Text = MessageBuilder.Current.Transform(
"Promo42b",
new
{
siteroot = "http://example.com",
user = new { id = 65321, name = "Fred", email = "fred.foo@bar.com" },
promo = new { size = 30000, msgnum = 24376, dist = "C3" },
product = new { id = 938, name = "Green Flashlight", price = 19.95, discount = 5 }
});
Here’s promo42b.spark:
Hi ${#user.name},
You opted into our spam at some point, and now that's going to pay off!
Because now you have the option of owning your very
own ${#product.name} today for the
low price of ${#product.price "$#,##0.00"}!
That's a saving of like ${#product.discount "#,##0"} bucks!!
Yeah! I know! How cool is that!?!?
Click the following link to get yourself some of that action.
${#siteroot}/addtocart?id=${#product.price}&offer=${#promo.dist}
<test if="IsInStock((int)#product.id)">
Yours is in stock and ready to fly!!!
<else/>
We can't keep them on the shelves! So get your order in today!!!
</test>
Regards,
- Spark view engine
${#siteroot}/unsubscribe/${#user.id}?source=${#promo.dist}
(I really need a different source code plugin)
And here’s the base class. For a direct usage scenario it’s “Bring Your Own Eval” so this example relies on the ViewDataDictionary.
public override void Transform(
string templateName, object data, TextWriter output)
{
var descriptor = new SparkViewDescriptor()
.AddTemplate(templateName + ".spark");
var view = (TemplateBase)_engine.CreateInstance(descriptor);
try
{
view.ViewData = new ViewDataDictionary(data);
view.RenderView(output);
}
finally
{
_engine.ReleaseInstance(view);
}
}
public abstract class TemplateBase : AbstractSparkView
{
public ViewDataDictionary ViewData { get; set; }
public object Eval(string expression)
{
return ViewData.Eval(expression);
}
public string Eval(string expression, string format)
{
return ViewData.Eval(expression, format);
}
/// <summary>
/// Members of this class are also available to the views
/// </summary>
public bool IsInStock(int productId)
{
return DateTime.UtcNow.Second % 2 == 1;
}
}
January 29th, 2009 at 7:09 am
I started using the email templating last week, was about to write my own and noticed it in the samples directory. Works a treat, great job :D
January 30th, 2009 at 1:32 pm
This is cool. I can definitely see how this is useful. I’m assuming ViewData.Eval is something specific to asp.net mvc? What would it take to get this into Monorail?
February 2nd, 2009 at 8:29 pm
The #foo.bar syntax will become a call to an Eval method on the view class, so all it would take is a
public object Eval(string expression)
and
public string Eval(string expression, string format)
method on the Castle version of the SparkView base class. The only tricky part would be breaking up the expression on the dots and evaluating it down through reflection.
April 30th, 2009 at 10:37 pm
Ooh, cool! I just found this, I’m sorry I’d missed it before. Unfortunately, it solved one problem only to create another…
This works great, but breaks when using a JavascriptViewResult and the Spark.*.RenderView client-side method (“Eval is not defined…”).
May 4th, 2009 at 4:45 pm
Yeah… A lot of the javascript generating functionality assumed you’ll be providing look-alike implementation for the code which appears on client/server templates, like html helpers, or after a certain point some templates would be client-only and jump onto the javascript language fully.
I have to admit I wasn’t really sure if people would adopt dual-use client/server templates to the extent they have been. You have to *really* want them to work. :)
May 4th, 2009 at 6:47 pm
Thanks Lou!
Yeah, I’m making very heavy use of dual-use templates, it’s actually one of the killer features of Spark for me, that drove me away from the standard MVC views or alternates like NHaml. I’m making some interesting work-arounds to get these things working right, and it’s paying off for my project.
When you mention providing “look-alike implementation”, do you mean that I can define how the Javascript Spark compiler processes certain C# lines into Javascript? This would be very useful for me, as it would allow me to implement a lot of features that are currently not able to be used in dual-use templates.
May 4th, 2009 at 9:42 pm
Nope, not what I meant but hooking into the code generation would be really nice.
By look-alike implementation I just meant things like declaring an object named Html in javascript and adding methods named ActionLink to be able to have ${Html.ActionLink(…)} work client-side.
May 4th, 2009 at 11:48 pm
Ah I see, that makes a lot of sense. It’s not quite as flexible as being able to control the code-generation directly, but it sounds like a useful approach for certain tasks. I’ll probably be using that technique, so thanks for the tip!
December 15th, 2009 at 3:23 am
thanks very usefull information !
December 23rd, 2009 at 9:15 am
Hello I discovered this website by mistake, I was surfing around the net for sites to see on Oahu when I came upon your website, I must say your site is very cool I truely think the theme, its astounding!. I’m strapped for time in this instance to totally read through your blog but I have favorited it and also subscribed for your RSS feeds. I will be back when I free up some time. Thanks for a great site.
December 29th, 2009 at 10:20 am
Thanks for writing this up, great post. I have a few clients in mind that could get a lot out of this site so I will be sending them a link. Thanks again and keep up the good work.
April 6th, 2010 at 9:00 am
Try & Retain your iPad for Nothing! -> http://bit.ly/cFBuis
June 21st, 2012 at 11:22 am
Эйвон в СПб Каталог Эйвон 2010
June 27th, 2012 at 1:21 am
ФМ Групп – это изумительные ароматы. Купить духи FM Group в онлайн магазине. Возможность заработать деньги с сильной компанией. Средства для бритья на любой вкус
June 30th, 2012 at 1:32 pm
Интернет-магазин канекалон доставка в подарок .
July 5th, 2012 at 2:43 am
Gradance.Ru – Портал любителей танца видео танцоров. Ча-ча-ча найти партнера в клубе умело . Поговорить о тренерах с профессионалами. Пригласить приятелей.
July 12th, 2012 at 3:31 am
Музконтент – Минусовки мп3 скачать бесплатно и без регистрации. Текты песен. Акапеллы и инструменталы для караоке Лушие подборки музыки. Скачать бесплатно.
July 14th, 2012 at 11:12 am
Antediluvian world project – comparative study of antiques myths and contemporary sciences
August 11th, 2012 at 3:33 pm
где взять денег
September 14th, 2012 at 3:39 pm
У нас Вы можете легко подать любое объявление о продаже квартиры. Сайт ПродаёмВсё.Рф.
September 17th, 2012 at 5:57 pm
На нашем сайте Вы можете бесплатно подать любое объявление о аренде транспорта.
October 28th, 2012 at 6:58 pm
Legal, solicitor, barrister, lawyer and notarial services in Cyprus. Business in Cyprus. Immigration services, setting up companies including offshore companies. Cypriot legislation consulting. Buy-sell agreements, contracts. Trusts, last will, property, licences, citizenship and etc.
February 14th, 2013 at 12:12 am
Класмнеоченьпонравилось.ЯвсегдазаинтересовантакуюИнформацию.большое спасибоза то,что вы здесьтворите.вдругпожелаетеоценитевидео. вамуверенпорадует
February 16th, 2013 at 2:38 pm
Get Phentermine via internet and begin dropping pounds with out delay.
April 11th, 2013 at 2:59 am
Hello there, just become alert to your blog via Google, and found that it’s really informative. I am going to watch out for brussels. I will be grateful if you proceed this in future. Lots of folks might be benefited out of your writing. Cheers!
April 12th, 2013 at 8:04 pm
Battle your pain with the most effective Tramadol pills.
April 13th, 2013 at 9:24 am
Order Diazepam and spend less cash getting your great anti-anxiety drug on line.
April 15th, 2013 at 7:34 am
Order Ambien on-line saving cash and time.