colinramsay.co.uk

Reviewing ExtSharp 2.0.1

02 Apr 2008

After my earlier post on JS generation from C#, I wanted to investigate my options. Although zproxy highlighted the jsc project, I wanted to focus on a real world scenario first and so I'm looking at ExtSharp, which relies on Script#, a project which will "compile your C# source code into JavaScript".

ExtSharp leverages Script# to allow you to write ExtJS applications in C#, which was my target when I began thinking about JS generation. I'd like full intellisense, documentation and compile-time checking when working with this rich framework. Will ExtSharp give me that?

Downloading ExtJS2Samples-v2.0.1.zip from the Google Code site gives me a solution of samples. Here an interesting implementation issue arises - all of the actual C#-Javascript class files are in a separate project to the .aspx pages which display them. This is down to necessity; Script# uses an assembly called sscorlib which, bizarrely, seems to provide its own implementations of many of the .NET types found in the mscorlib assembly.

This separate project also runs an MSBuild targets file from Script# which runs after main compilation to compile the C# into Javascript. Straight away I'm seeing two bits of magic - sscorlib and post-build events - which I'm not too keen on. But the solution builds, and after changing the web.config references to nStuff.ScriptSharp.Web to 0.4.5.0, I am able to view the samples.

Based on my earlier post, I was interested in the Window sample, but unfortunately that didn't work. The array Grid one did though, and it operated just as the ExtJS website sample does. Many of the other samples are missing, which is disappointing; of the ones which are present, most work very well. Overall, I was encouraged, and I moved on to looking at the C# code which was generating these samples.

Let's look at how a ColumnModel is built when working in Javascript:

var colModel = new Ext.grid.ColumnModel([
           {id:'company',header: "Company", width: 160, sortable: true, dataIndex: 'company'},
            {header: "Price", width: 75, sortable: true, renderer: 'usMoney', dataIndex: 'price'},
            {header: "Change", width: 75, sortable: true, renderer: change, dataIndex: 'change'},
            {header: "% Change", width: 75, sortable: true, renderer: pctChange, dataIndex: 'pctChange'},
            {header: "Last Updated", width: 85, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
 ]);

I think that's pretty concise - there's not a lot of cruft. Now the ExtSharp version:

ColumnModel colModel = new ColumnModel(new Dictionary[] {
    new Dictionary("id", "company", "header", "Company", "width", 160, "sortable", true, "locked", false, "dataIndex", "company"),
    new Dictionary("header", "Price", "width", 75, "sortable", true, "renderer", new MoneyRenderer(Format.usMoney), "dataIndex", "price"),
    new Dictionary("header", "Change", "width", 75, "sortable", true, "renderer", new ColumnRenderer(change), "dataIndex", "change"),
    new Dictionary("header", "% Change", "width", 75, "sortable", true, "renderer", new ColumnRenderer(pctChange), "dataIndex", "pctChange"),
    new Dictionary("header", "Last Updated", "width", 85, "sortable", true, "renderer", Format.dateRenderer("m/d/Y"), "dataIndex", "lastChange")
});

Hmm. Lots of strings - I'm not keen. This is one of two methods of providing a configuration to an Ext class, the second of which involves a specific config class:

Ext.grid.GridPanel grid = new Ext.grid.GridPanel(new Ext.grid.GridPanelConfig()
    .el("grid-example")
    .ds(ds)
    .cm(colModel)
    .autoExpandColumn("company")
    .height(350)
    .width(600)
    .title("Array Grid")
    .ToDictionary()
);

Unconventional style, to say the least, but at least it's properly typed. This is pretty far away from my ideal API for this kind of thing. Let's look at how this is turned into Javascript.

As I previously mentioned, the Script# project contains MSBuild targets which generate the JS code after the build is complete. This code can then either be referenced directly, or via some ASP.NET controls from your ASPX pages. As well as your own generated code, you must also reference a couple of Script# files and a wrapper file for Ext itself. That wrapper file is actually what makes everything work here - rather than your C# code being converted into something which works with the Ext library, it instead only works with the Ext wrapper provided by ExtSharp.

Looking at the ExtSharp project overall, I'm not a convert. There are too many layers between your C# and where it finally touches the "real" Javascript:

1. Your generated JS
2. ExtSharp JS wrapper
3. Script# utility JS

The C# API is also pretty horrible - certainly not in my style but also far from being an API I recognise from any other project I've worked on. Whether this is a style choice or due to technical limitations, I'm not sure.

The ExtSharp project definitely drew my curiosity, and could hold promise. In its current state, I wouldn't consider using it in a project of my own, as the API is not strong enough to make me swap from native Javascript. Still, I will continue to follow future work with interest.