17 March 2010

ASP.Net Data meets Ext JS: Ext.net – Store and GroupingStore


Download the source code for Ext.net here.

Overview

Ext JS is my front-end platform of choice for all my ASP.Net applications.  The reasons are simple – Ext JS gives the developer more control, supports better coding practices, and takes better advantage of the IIS platform than native ASP development options.  But how could that be?

First, there is the question of control.  ASP controls are not open source.  It’s hard for the developer to understand what is going on under the covers without extensive study.  When will the page refresh?  When will the control talk to the server?  How can I give the control a different look?  Why is that Microsoft object emitting CSS?  Many of these questions are difficult for most people to understand and take valuable time to understand. 

Ext JS controls are open source and have a rich, well documented event model.  You can read the code directly if you need to.  Ext JS controls don’t make unexpected calls to the server or emit unexpected code  The developer controls how data is piped from the sever to the screen, which makes it easier to control events and identify performance bottlenecks. 

Simply put, the developer has complete control over everything that call that happens on the client.  There are not many mysteries. And aspects that annoy you can be fixed at programming time by looking at the source code.

Secondly, I have always been bothered by the mixed metaphor of ASP.Net development.  What’s on the browser?  What’s on the server?  Do I code this control with HTML or C#?  For all the remarkable work Microsoft did to make the process seem like coding a Visual Basic application (it is truly amazing), the actual results can be bizarre and fragmented.  .Net languages appear on the page with HTML, which then might have additional code capturing events somewhere else.  The page object model is complex, and ASP developers have to learn when and how to place each control on the page to

Ext JS controls are coded entirely in JavaScript and the separation between browser and server is clearly defined.  There is no half-HTML/half C# (or VB.Net) control that lives partially in code-behind and partially on the page.  There is no reason to carefully wedge control-code between page events to get everything working correctly.

This complete separation tends to drive business logic off the page and back onto the server where it belongs.  My personal preference is to keep the server code and UI code as separate as possible.  Ext JS enables the developer to keep the server-side code simple and clean.  Simply write your UI in JavaScript and expose the web services for the page.  This approach also simplifies testing because the developer can easily identify and test the logic used in each page.

Finally, Ext JS makes it possible to leverage the absolute strength of IIS, which is delivering web services.  It has always struck me as strange that ASP.Net controls do not explicitly consume services.  In an effort to make the communication seamless, Microsoft actually minimizes the strengths of exposing SOAP services.  This, in turn, leads to code-bloat, because the developer has to write custom code to deliver data to ASP.Net controls and then additional code to deliver data to other applications.

Despite all these advantages, communication between Ext JS and ASP web services can be tedious.  Ext JS was written by people who are clearly oriented towards JSON data delivery.  And why not?  It’s lightweight and native to JavaScript.  There is the XML reader, but the average .Net/Ext JS developer still has to write tedious (and needless) code to parse the data into stores.

But IIS (.Net) is an XML-oriented language.  It does not serve JSON without specialized server-side code and some hacking.  What if you work in a corporate environment that does not allow non-standard software to be installed on the server?  Shouldn’t the goal of the programmer be to stick to the standards and also leverage what each piece of software does best?

Ext.net.Store and Ext.net.GroupingStore

Ext JS.net started with simple questions.  Why should I write JavaScript code to describe my data structures, when an ASP.Net web services already delivers that data to my page?  Would my code be less coupled if I worried more about the UI and less about the structure of the data coming to my page? 
The result is Ext.net.Store and Ext.net.GroupingStore.  The goals of this project are as follows:
  • Reduce boilerplate code – on the server and the page
  • Increase web service reuse/simplify server-side code
  • Simplify data transport and consumption
Table names and data types have already been written and defined on the server – why write them again?

How does Ext.net work? 

The Ext.Net stores intercept the XML returned from a web-service call and build the data set before the store is completely initialized.  This means that the data definition that is defined on the server and delivered in the web service automatically becomes the data definition in the store. 
In order to take advantage of the store, the programmer simply exposes an ADO DataSet as the return data type.  Ext.Net stores consumes the meta-data, builds a table definition and then populates it with the service data.

On the server, create a standard data set.  The names of the tables do not matter.


IIS Server Side Code - C#

[WebMethod]
  public DataSet TableData()
  {
      DataSet ds = new DataSet("ds"); 
      string cnStr = ConfigurationManager.ConnectionStrings["local"].ToString();
      using (SqlConnection cn = new SqlConnection(cnStr))
      {
          string strSQL = "SELECT * FROM tblDataVals";
          using (SqlDataAdapter da = new SqlDataAdapter(strSQL, cn))
          {
              da.Fill(ds, "data");
          }
          strSQL = "SELECT COUNT(*) FROM tblDataVals";
          using (SqlDataAdapter da = new SqlDataAdapter(strSQL, cn))
          {
              da.Fill(ds, "count");
          }
          cn.Close();
      }
      return ds;
  }


The client-side JavaScript is just as simple.  In your HTML add a reference to Ext.net.Store.  Make sure the reference appears after the references to ExtJs code.

Declare a store by using Ext.net.Store or Ext.net.GroupingStore wherever you would declare a store.  All of the config parameters are the same, with very few differences. 

Ext.net.Store and Ext.net.GroupingStore will create a reader automatically, so you do not have to declare an XMLReader or any record definitions.  On large grids, this will save considerable code. 

There is one extra parameter to add to the grid – net. The net object has 3 fields:
  • dataTable (string): The name of the table that contains the data.  This will be translated into the store data.
  • dataTableId (string): The name of the field that contains the id of the data table.
  • totalRecords (string): The name of the table that contains the data count.  This parameter is optional.
Below is a sample store declaration.  Note that there is no record definition because it is created at run time. 
A big benefit to this is that the service can change and the grid will keep on working as it did before.  For large grids, you also save re-coding record definitions.


Sample Ext.net.Store declaration in JavaScript

var s = new Ext.net.Store({
net: {
     dataTable: 'data',
     dataTableId: 'id',
     totalRecords: 'count'
},
  remoteSort: true,
  sortInfo: { sort: 'fname', dir: 'ASC' },
  proxy: new Ext.data.HttpProxy({
     url: 'EmployeeServices.asmx/GetEmployees',
     method: 'GET'
  }),
  storeId: 'empStore'
});



The source code for Ext.net.Store and Ext.net.GroupingStore can be downloaded for free from http://extjsdata.codeplex.com/.  The code has been tested with Firefox 3.5+ and IE7+.  It was designed to be compatible with ExtJs Framework 2.2, but also works with 3.1.

16 March 2010

Bookmarklet: Add URL to Remember the Milk from the iPhone

I use Google Reader on all my mobile devices (currently an iPhone) and frequently find myself wanting to switch to the desktop to finish a story.  Google Reader has great desktop integration with other services to save articles, but is very limited on the iPhone.  Google Reader mobile allows you to email a link to yourself, but the whole process is painful and I get enough email.

I am also a heavy user of Remember the Milk as my task management system.  Wouldn't it be great to be able to add URL's directly from the iPhone?  Enter the RMilk iPhone Bookmarklet.


javascript:(function(){
var a = [
'name=' + document.title,
'url=' + location.href,
'due=today',
'priority=4',
'tags=iPhone'
        ];
location.href = "http://m.rememberthemilk.com/add?" + a.join("&");
})();

The Bookmaklet above adds the URL into the mobile Remember the Milk site.  The following values are populated:

  • name: The name of the page you are viewing will be the task name.
  • url: The URL is the page you are viewing.
  • due: The due date can be any legal value that Remember the Milk can validate as a date.
  • priority: Legal priority values are 1, 2, 3, and 4 (none).
  • tags: Any tag (or tags) you would like to use to populate your task.
Additionally, there are two other options worth noting:
  • estimate: Any valid time estimate can be used 
  • list: The integer list id that applies to your list.  If you want the URL to go to a specific list, go to http://m.rememberthemilk.com/add.  View the page source and find the list of values that contains your list.  Use the value attribute from the option tag as your list value.
To add this bookmarklet to your iPhone, do the following:
  • Copy the JavaScript Bookmarklet above into Notepad.
  • Edit the values in the array as to how you would like to populate Remember The Milk.  Add estimate and list to the array if you would like those values populated.
  • Copy the new JavaScript into an email and email it to your iPhone.  Copy the JavaScript from the email.
  • Bookmark any page in Safari.  Edit the bookmark by giving it a new name and pasting the JavaScript into the URL textbox.

This post is heavily indebted to Steve Ollis, The IT Juggler.