by thorhalvor

Are you still writing your own TemplateEngine?

Years ago I was on a project that needed a dynamic engine for writing documents based on a template. It had to be possible to add keys like “$name$” in a text and the engines job was to replace with a Name from a given context. I ended up writing a module that used reflection on my context-object and it worked the way I wanted. – But it took some hours developing it…

NVelocity / TemplateEngine

Later I discovered NVelocity. NVelocity is an open source project, and as many others starting with a ‘N’, is based on the Java project Velocity. Castle Projects has abstracted the templating process and made it even easier to use in their TemplateEngine Component. This component gave me all I wanted and more. If I just had knew earlier..

An example of a template for Castle’s TemplateEngine is given below:

Hi $customer.FirstName,
your account has been lost..
We are sorry for that!

Regards,
The bank

The code below is reading the template, mapping the key-properties and writing the output the the variable ‘text’. As you can see, it is putting the Customer object into an Hashtable with keyword “customer” and then forwarding it to the Processor as context. More or less the same I did in “my own engine”.

string text;
var customer = GetCustomer();
using (var writer = new StringWriter())
{
    var context = new Hashtable();
    context.Add("customer", customer);
    TemplateEngine.Process(context, "yourtemplatefilename.txt", writer);
    text = writer.ToString();
}

You can also do if/else and foreach logic (see here for more examples):

#foreach($person in $people)
<table>
       <tr>
           <th>Name</th>
           <th>Age</th>
    </tr>
</table>
#end

And:

#if($order.Status == "Undefined")
  Sorry, but we don't know this order.
#elseif($order.Status == "Created")
  Your order is being processed. Hold on!
#end
RazorEngine

Most new web projects created in the “.NET World” today, at least the one I know of, is based on ASP.NET MVC 3 and the parsing technology Razor. Developers have learned to use and to like the Razor syntax. And what could be better for a new templateengine than using the same technology? Matthew Abbot has done something about this and made in late 2010 the first version of the Razor Template Engine, in v2.0 called RazorEngine. It is opensource and can be found on GitHub and as a nugetpackage, ‘Install-Package RazorEngine’.

Simple example:

var template = "Hi @Model.FirstName! Knock knock who's there?";
var result = Razor.Parse(template, new { FirstName = "KenSentMe" });

or you could offcourse read the template from a file:

var template = File.ReadAllText("yourfilename.txt");

 

A nice feature is that the template-engine support anonymous types, – as you can see in the second parameter of Razor.Parse(). (and also DynamicObject and ExpandoObject). With this loose coupling to the context/model it makes it easier for a developer to extend it. He can now just add a new property directly instead of creating a specific class just to works as a “placeholder”.

I guess there are many more template engines “out there” but these are the two I have used on my last projects. I use RazorEngine on my current project, with html-email-templates, and it works very well. The main reason I choose RazorEngine is mostly because we use MVC 3 and Razor on the websites and the email template is based on the same style and context(Viewmodels). But also the fact that it is so easily downloaded and upgraded through the NuGet Package.

So If you still write your own templateengines I hope you will take a look on one of these engines next time.

by thorhalvor

JSONP in ASP.NET MVC 3

When consuming a JSON REST API using AJAX the message is send as a XMLHttpRequest. Due to security reasons this is not allowed cross domain. Instead of returning the data as core JSON, JSONP is often used. The data will then not be parsed by the JSON parser but evaluated by the JavaScript interpreter.

Returning JSONP data does not come out of the box in ASP.NET MVC 3, but you can write a simple wrapper like this:

using System.Web.Mvc;
 
public class JsonpResult : JsonResult
{
    private const string CALLBACK_QUERYSTRING = "callback";
    private const string CALLBACK_CONTENTTYPE = "application/x-javascript";
 
    public override void ExecuteResult(ControllerContext controllerContext)
    {
        if (controllerContext != null)
        {
            var request = controllerContext.HttpContext.Request;
            object callback = request[CALLBACK_QUERYSTRING];
            if (callback == null)
            {
                controllerContext.RouteData.Values.TryGetValue(CALLBACK_QUERYSTRING, out callback);
            }
 
            var hasCallback = !string.IsNullOrWhiteSpace(callback ==null ? "" : callback as string);
 
            if (hasCallback)
            {
                SetContentTypeIfEmpty();
                var response = controllerContext.HttpContext.Response;
 
                response.Write(callback);
                response.Write("(");
                base.ExecuteResult(controllerContext);
                response.Write(")");
            }
            else
            {
                base.ExecuteResult(controllerContext);
            }
        }
    }
 
    private void SetContentTypeIfEmpty()
    {
        if (string.IsNullOrWhiteSpace(base.ContentType))
        {
            base.ContentType = CALLBACK_CONTENTTYPE;
        }
    }
}

 

It is now possible to just replace the jsonresult with jsonpresult in the code. If no callback is given it will work as normal.

        //return new JsonResult();
        return new JsonpResult();

 

When sending the request GET http://localhost/Website/Products/All?callback=myCallbackFunction the data will be wrapped like this: (same method used in last blogpost)

jsonp

by thorhalvor

Asp.NET MVC 3 and JSON

Creating a ASP.NET MVC 3 REST API returning JSON data is actually really simple.

If you have a MVC 3 Visual Studio project template and you add a Controller the default HomeController will be added:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

 

If you want this Index to return Json data the only thing needed is return JsonResult instead of a View.

        //return View();
        return new JsonResult();

 

To give an example I have created a ProductsController returning 3 products with the properties ProductId, Name and Price.

[AcceptVerbs(HttpVerbs.Get)]
public JsonResult All()
{
    var data = GetProducts();
    return new JsonpResult { Data = data, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}

Notice that you have to set JsonRequestBehavior.AllowGet. If forgotten you will get the self-explanatory errormessage:

This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. 
To allow GET requests, set JsonRequestBehavior to AllowGet.

 

When sending the request GET http://localhost/Website/Products/All, the method will return my three products:

(using Chrome with the extension JSONView)

json

As simple as that Smile

by Stian

jQuery validation not working in IE7 and IE8

jqueryWhen you create a new ASP.NET MVC 3 Project in Visual studio, your script folder will by default contain among others:

jquery-1.5.1.min.js
jquery.validate.min.js (which is version 1.8.0)

One of the first things you might want to do is update the jquery version to the latest version, which today is version 1.7.1

After doing this, your client side validation will stop working in Internet Explorer 7 and Internet Explorer 8.

This is because the jquery.validate version is not compatible with jquery versions > 1.6. The solutions is simple, you need to update your version of jquery.validate as well. You can find the current version 1.9 from Microsoft’s CDN or the latest version from GitHub here:

Microsoft Ajax CDN: http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js
GitHub Jquery Validation: https://github.com/jzaefferer/jquery-validation/downloads

Remember that you can always find the latest javascript library in Microsofts CDN, see the complete list of available libraries here: http://www.asp.net/ajaxlibrary/cdn.ashx