Thursday, February 11, 2010

Wrapping WCF Services in a Using Statement

Considering that the WCF Services I've created for my budget application are the first I've written, I hadn't actually given much thought into how I would actually call them.

Here's what I came up with!

IMthService svc = new MthServiceClient();
svc.Save( newMonthObject );

Of course, what I discovered was that my services were timing out after the sixth call (not sure why it was six as the default is ten). Any how, I quickly discovered that while the service that's is written doesn't directly inherit from IDisposable, the service client does. So in effect my code was not disposing of the service client properly. So how do I dispose of the client considering that the Dispose method is private? Easy, call Close or Abort. Duh!

There are various posts floating around that instruct on wrapping your service call in a try catch, but I didn't want to write try{...}catch{...} time and time again.

It was at this time that I recalled reading a nice post about a common WCF exception message that provided a nice little solution to my problem. Thanks Damien McGivern for coming up with the following solution.

public static void Using<TService>( Action<TService> action )
  where TService : ICommunicationObject, IDisposable, new()
{
  var service = new TService();
  bool success = false;
  try
  {
    action( service );
    if ( service.State != CommunicationState.Faulted )
    {
      service.Close();
      success = true;
    }
  }
  finally
  {
    if ( !success )
    {
      service.Abort();
    }
  }
}

So now I can call my services like this...
WCFHelper.Using<MthCategoryServiceClient>
  ( svc => svc.Save( mc ) );
and
WCFHelper.Using<MthCategoryServiceClient>
  ( svc => mthCategories = svc.GetByMonth( mthId ) );

Enjoy

Wednesday, February 10, 2010

Handling AJAX requests with ExtJs GridPanel and jQuery Consistently

In my previous post, An Implementation of the ExtJs GridPanel, I demonstrated how you could implement a GridPanel using the ExtJs framework, and mentioned the writer object that creates default CRUD AJAX calls.

This is handy and quite easy to handle server side, as the writer object injects a hidden form element (id='xaction') into the DOM.

string action = Request.Form["xaction"];
if ( !string.IsNullOrEmpty( action ) )
{
  switch ( action )
  {
    case "create":
      CreatCategory();
      break;
    case "update":
      UpdateCategory();
      break;
    case "destroy":
      DeleteCategory();
      break;
    default:
      ListCategory();
      break;
  }
}

However, on another page I didn't want to submit a request per edit or per row edit, but wanted to submit a request in bulk. So how did I go about that?


Firstly, I removed the writer object from the store object as below...
var mcStore = new Ext.data.Store({
  id: 'dsMthCategories',
  proxy: mcProxy,
  reader: mcReader,
  baseParams: { xaction: "LISTING" }, // *** take note
  //writer: mcWriter,    // <-- remove the Writer object
  listeners: {
    'beforeload': function(store, options) {
      options.params['mthId'] = mthid;
    }
  }
});
Next I added the following in the handler of the Update button...
var data = [];
Ext.each(mcGrid.getStore().getModifiedRecords(), function(record) {
 data.push(record.data);
});

$.ajax({
  type: "POST",
  url: 'Data/MthCategories.aspx?xaction=batchupdate', // *** take note
  data: JSON.stringify(data),
  contentType: "application/json;",
  dataType: "json",
  success: function(msg) {
    mcGrid.store.load();
  },
  error: function(msg) {
    alert('An error occured during the update.');
  }
});

Two things to note about the above code is that the default action of the store is to add the value "LISTING" to the injected xaction form element and in the jquery ajax function call I've added xaction to the querystring.

This enables the ability to utilise the HttpRequest.Params property, which picks up both Form and QueryString items.
string action = Request.Params["xaction"];
if ( !string.IsNullOrEmpty( action ) )
{
  switch ( action )
  {
    case "batchupdate":
      BatchUpdate();
      break;
    default:
      ListMonthCategories();
      break;
    }
}

And there you have it.

Enjoy!

Sunday, February 7, 2010

An Implementation of the ExtJs GridPanel

So in my last post I demonstrated how I put together some an ExtJs TabPanel. Now this is not the only way to do this, but it is one way. Now I'm going to take you through how I put together an ExtJs GridPanel.

The html is remarkably simple.

<div id="CategoriesContainer">
    <div class="TabContent"></div>
</div>

Next comes the more complex part of the implementation :)

$(document).ready(function() {

 $.namespace("category", {
  inherited: true,

  InitialiseControl: function() {
   $.fn.category.LoadCategoryGrid();
  },

  LoadCategoryGrid: function() {

   var tabContent = $("#CategoriesContainer").children(".TabContent");

   var proxy = new Ext.data.HttpProxy({
    url: 'Data/Categories.aspx'
   });

   var reader = new Ext.data.JsonReader({
    root: 'Data',
    totalProperty: 'Count',
    idProperty: 'CategoryId',
    fields: [
     { name: 'CategoryId', type: 'int' },
     { name: 'CategoryName', type: 'string', allowBlank: false },
     { name: 'BudgetAmount', type: 'float', allowBlank: false },
     { name: 'IsActive', type: 'boolean' },
     { name: 'Timestamp', type: 'date', dateFormat: 'M$' },
     { name: 'Version', type: 'auto' }
    ]
   });

   var writer = new Ext.data.JsonWriter({
    encode: true,   // <-- don't return encoded JSON -- causes Ext.Ajax#request to send data using 
        // jsonData config rather than HTTP params
    writeAllFields: true
   });

   var store = new Ext.data.Store({
    id: 'dsCategores',
    proxy: proxy,
    reader: reader,
    writer: writer,
    listeners: {
     'update': function(store, record, operation) {
      store.commitChanges();
     },
     'remove': function(store, record, index) {
      store.commitChanges();
     }
    }
   });

   var colModel = new Ext.grid.ColumnModel({
    defaults: {
     sortable: true
    },
    columns: [
     {header: 'Name', dataIndex: 'CategoryName', editor: new Ext.form.TextField({}) },
     { header: 'Budget Amount', dataIndex: 'BudgetAmount', xtype: 'numbercolumn', format: '$0,0.00', align: 'right', editor: new Ext.form.NumberField({}) },
     { header: 'Active', dataIndex: 'IsActive', xtype: 'booleancolumn', trueText: 'Yes', falseText: 'No', align: 'center', editor: new Ext.form.Checkbox({}) }
    ]
   });

   // use RowEditor for editing
   var editor = new Ext.ux.grid.RowEditor({
    saveText: 'Update'
   });

   var grid = new Ext.grid.GridPanel({
    iconCls: 'icon-grid',
    frame: true,
    title: 'Categories',
    loadMask: true,
    autoScroll: true,
    height: 300,
    store: store,
    plugins: [editor],
    colModel: colModel,
    tbar: [{
     text: 'Add',
     iconCls: 'silk-add',
     handler: function(btn, ev) {
      var u = new grid.store.recordType({
       Description: '',
       Amount: '',
       IsActive: true
      });
      editor.stopEditing();
      grid.store.insert(0, u);
      editor.startEditing(0);
     }
    }, '-', '->', '-', {
     text: 'refresh',
     iconCls: 'silk-table-refresh',
     handler: function() {
      grid.store.load();
     }
    }],
    viewConfig: {
     forceFit: true
    }
   });

   grid.render(tabContent[0]);

   store.load();
  }
 });
});

So what's actually going on here?

Firstly,
$(document).ready(function() {
  $.namespace("category", {
    inherited: true,

    InitialiseControl: function() {
      $.fn.category.LoadCategoryGrid();
    },
Here I am using a jquery namespace pluging to create (oddly enough!) a namespace for the javascript for this particular control (or tab). The line inherited: true allows you to interact with function parameters as normal, rather than referring to them as params[0], params[1] etc.

The rest of the javascript is fairly standard ExtJs syntax and extensive definitions can be found at the ExtJs API, but in short I follow these steps when setting up a grid:

  1. Create a proxy object and set the URL it should post to;
  2. Create a reader object. In my case it's a JsonReader and I set the properties that allow the object to interact with the returned Json data;
  3. Create a writer object. This creates default CRUD actions for you;
  4. Create a store object and set up listeners for update and delete calls (mind you I'm not actually deleting anything);
  5. Create a column model for the grid. This maps the fields from the reader to the columns;
  6. Create a RowEditor object. This is a plug-in that gets applied to the grid and can be downloaded from an ExtJs example Grid with RowEditor;
  7. Create the grid;
  8. Get the grid to render to a particular DOM element;
  9. And lastly load the store object;

Next up will be a short post on how to deal with the Ajax requests server side in a C# environment.

Enjoy!

Wednesday, January 20, 2010

An Implementation of the ExtJs TabPanel

So the first component I implemented was the ExtJs Tab Panel.




So how did I go about this?

I set my tabs up in HTML...
<div id="app_tabs">
    <div class="x-hide-display" id="current_month">
        Dashboard
    </div>
    <div class="x-hide-display" id="months">
        Months Tab
    </div>
    <div class="x-hide-display" id="categories">
        <uc1:categoriestabcontent id="CategoriesTabContent1" runat="server" />
    </div>
    <div class="x-hide-display" id="income">
        <uc1:incomestabcontent id="IncomesTabContent1" runat="server" />
    </div>
    <div class="x-hide-display" id="history">
        Tab Content
    </div>
</div>


Then I turned them into a TabPanel...
$(document).ready(function() {

 $.namespace("def", {

  InitialisePage: function() {

   var tabs = new Ext.TabPanel({
    renderTo: 'app_tabs',
    activeTab: 3,
    autoShow: true,
    plain: true,
    defaults: { autoHeight: true },
    items: [
     { contentEl: 'current_month', title: 'Current Month' },
     { contentEl: 'months', title: 'Months' },
     { contentEl: 'categories', title: 'Categories' },
     { contentEl: 'income', title: 'Income' },
     { contentEl: 'history', title: 'History' }
    ],
    listeners: {
     'tabchange': function(tabpanel, tab) {
      // empty all the tabs
      $("#IncomesContainer").children("#TabContent").empty();
      $("#CategoriesContainer").children("#TabContent").empty();
      // only render the appropriate tab content
      switch (tab.contentEl) {
       case 'income':
        $.fn.income.InitialiseControl();
        break;
       case 'categories':
        $.fn.category.InitialiseControl();
        break;
      }
     }
    }
   });
  },

  RenderTabContent: function() {
  }

 });

 $.fn.def.InitialisePage();
});
easy! Right? But was exactly is the javascript doing?

The first line you should recognise, the second one maybe not. Thanks go to Gilberto Saraiva for putting together jQuery.Namespace. Funnily enough this namespace behaves like a namespace.

I have one function that creates the tabs and defines what happens when the user interacts with them. The creation of the tabs can be broken into two sections, firstly the configuration of the tabs and secondly listeners for user interaction.

First up: Configuration...
To get an understanding of what each config option is doing visit the ExtJs API site. However what's important to note is that the tabs are configured to utilise the HTML divs (as shown above), I then define the items (or tabs) by indicating what HTML element each tab should use and then give it a title.

Lastly Interaction...
The ExtJs framework has this concept of listeners that listen for events being fired. The list of events available to hook into is quite extensive, but in this case we're only listening to one event and that is "tabchange". When the TabPanel initialises all the tabs are inactive, but by specifying the active tab in the config options you force this event to fire, so this allows us to control exactly what happens when ever a tab is activated.

So what's happening? This is where I utilise the jQuery framework. I empty the content of each tab then depending on the tab that is selected I call the appropriate InitialiseControl method. In this way I'm ensuring that the DOM does not contain any unwanted html.

You'll notice that I'm calling the empty() method for each tab. But it's just occurred to me that I should be able to do this in one line. Something like: $("#TabContent").empty();

Enjoy.

Mixing MixingExt JS GridPanel, JQuery and C#

Well it's been a while since I've last posted. What have I been doing? Not much to be honest, being busy at home and busy at work... oh and sleeping :)

However I finally got a comment on one of my posts, Budget App - Part 2 : Introducing WCF Into The Picture (yay!) asking for an insight into the UI. This would be have been even more exciting had I not know who the anonymous commenter was. Rob!

Anyhow, when I started this budget app I set out with the intent of using the DevExpress ASP.Net control set. However, as you can see from the image below with the trial version of the controls you get this really lovely message.



So with that in mind I set out to find a new control set to use. And here's what I found: ExJs. Why did I choose ExtJS? Firstly, I liked look of their products and secondly they have an awesome site show extensive details on their API.



Besides the ExtJs framework, I've also included the jQuery framework and since jQuery 1.4 was released I've naturally upgraded to that.

Next I'll provides some details on the set I've take and how the ExtJs framework can work with the jQuery framework.

Enjoy!

Sunday, November 22, 2009

A jQuery Dashboard

So I've been working on a dashboard type page utilising the jqueryui controls and thought I'd share how I went about it.

I went through a few iterations getting the css working but it finally panned out the way I wanted it.

There are basically three components, the styles, the javascript, and the actual html.

Here I'm setting out the structure of the table that the dashboard is going to represent.
.table
{
    float: left;
    width: 100%;
}
.table-row
{
    float: left;
    width: 100%;
}
.table-cell
{
    margin: 0;
    float: left;
    width: 24%;
    min-height: 15em;
    padding: 0.3em;
}
.item
{
    width: 10em; 
    display: inline; 
    float: left; 
    cursor: move; 
    margin-right: 0.4em;
}

Here's the script behind the page.
$(document).ready(function() {

    function EqualiseHeight(row) {        //remove the previous height
        $(row).children().removeAttr("style");        //set the new height
        $(row).equalHeights(true);
    }

    function moveTask(task, region) {
        task.fadeOut(function() {
            task.appendTo(region).fadeIn();
            EqualiseHeight($(region).parent());
        });
    }

    function makeDraggable(task) {
        var uniqueid = $(task).parent().attr("uniqueid");

        $(task).draggable({
            cancel: '.action',
            revert: 'invalid',
            containment: 'div[uniqueid =' + uniqueid + ']',
            helper: 'clone',
            cursor: 'move'
        });
    }

    $(".table-row").each(function() {
        //EqualiseHeight(this);
        $(this).equalHeights(true);
        //make children into draggable objects
        $(this).children().children().each(function() {
            makeDraggable(this);
        });
    });

    $("ul").droppable({
        accept: 'li',
        hoverClass: 'ui-state-highlight',
        drop: function(ev, ui) {
            moveTask(ui.draggable, this);
        }
    });
});
So we have a function, EqualiseHeight, that takes an element representing a row (funnily enough) it makes sure that any style attribute for each of the rows direct child elements has been removed. It then utilised the equalHeights function as provided by filament group.
We then have a function, moveTask, that is responsible for that actual moving of an item by fading it out and then appending it to the region it was dropped in.
Next we have, makeDraggable, that takes an item and makes it draggable.

Now that we have some functions predefined, we start setting the page elements that will draggable items and the area that will be droppable.

Next comes the html...
<div class="table">
    <div storyid="1" class="table-row">
        <ul storyid="1" class="table-cell ui-widget ui-widget-content">
            <li class="item ui-widget ui-widget-content ui-corner-all">
                <h6 class="ui-widget-header">Task 1</h6>
                <div class="details">Task one details.</div>
                <a href="#" class="ui-icon action" title="do something">actions</a></li>
            <li class="item ui-widget ui-widget-content ui-corner-all">
                <h6 class="ui-widget-header">Task 2</h6>
                <div class="details">Task two details.</div>
                <a href="#" class="ui-icon action" title="do something">actions</a></li>
            <li class="item ui-widget ui-widget-content ui-corner-all">
                <h6 class="ui-widget-header">Task 4</h6>
                <div class="details">Task one details.</div>
                <a href="#" class="ui-icon action" title="do something">actions</a></li>
            <li class="item ui-widget ui-widget-content ui-corner-all">
                <h6 class="ui-widget-header">Task 5</h6>
                <div class="details">Task two details.</div>
                <a href="#" class="ui-icon action" title="do something">actions</a></li>
            <li class="item ui-widget ui-widget-content ui-corner-all">
                <h6 class="ui-widget-header">Task 6</h6>
                <div class="details">Task one details.</div>
                <a href="#" class="ui-icon action" title="do something">actions</a></li>
        </ul>
        <ul storyid="1" class="table-cell ui-widget ui-widget-content">
            <li class="item ui-widget ui-widget-content ui-corner-all">
                <h6 class="ui-widget-header">Task 3</h6>
                <div class="details">Task three details.</div>
                <a href="#" class="ui-icon action" title="do something">actions</a></li>
        </ul>
        <ul storyid="1" class="table-cell ui-widget ui-widget-content">cell content</ul>
        <ul storyid="1" class="table-cell ui-widget ui-widget-content">cell content</ul>
    </div>
</div>

And there you have it.

References:
1. jQuery
2. jQuery ui

Friday, November 13, 2009

Setting Equal Heights with jQuery

I've been experimenting with jquery and jqueryui and trying to build a dashboard type page.

Everything was going quite well until I wanted to make the cells within a row the same height.

With a little searching I found this, setting equal heights with jquery. Absolutely brilliant!

Thank you filament group