Tuesday, April 27, 2010

Installing Pre-Requisite Assemblies For VSTO Applications

If you've read my previous post How to Deploy a VSTO Word Template Application you would probably be thinking cool, nothing else to it. But...

If you were like me and were trying to install it into an environment that had absolutely none of the pre-requisites then I'm guess you would be getting an exception that went along the lines of "The common language runtime could not be loaded by ... "

What the heck does this mean? If you were like me, you'd be scouring the web and coming up with pages that reference the pages you've already looked at. Useless!

It wasn't until a mate at Readify, Jake Ginnivan, that if the box doesn't have the .net framework then it can't even read the VSTO file to know what to do.

The solution: the user needs to run the Setup.exe manually! Once this is done, the user can then go and open up the office document (mine was a word template). Now that the pre-requisite assemblies are there the VSTO app can now get installed. Hallelujah!

I hope this has helped.

Enjoy!

Wednesday, April 21, 2010

How to Deploy a VSTO Word Template Application

I recently had to build a word macro that read an Excel spreadsheet and produced a series of PDF files that were then sent out to an email that existed within each row.

The approach that I took was to develop a VSTO Word Template application that would step the user through the process of selecting the spreadsheet, reading the data and finally processing the data.

Step One - Creating the Application
To create a Word Template application is relatively straight forward. From the New Application dialog browse for Office > 2007 > Word 2007 Template. You should now be presented a .dotx file that you can now customise to your hearts content.

Step Two - Adding the Controls to Template
Not having worked with a VSTO application before I simply copied the RichTextContentControl from an example application I found. However, like any .Net application all the controls that can be utilised in the Word Template can be found in the toolbox. (Thanks Mr Obvious!)

Here's what mine looked like...

Step Three - Adding the Actions Pane Control
Just having some controls embedded in a template isn't going to do a lot, you need some way for the users to interact with the template. This is where the Actions Pane Control comes in play.

Here's what mine looked like...


So you can basically added all manner of controls to the Action Pane and treat it like a Windows Form.

Step Four - Deploying
Developing all of the above is fairly straight forward, just like developing a web/win app, F5 and away you go. But how to deploy that was a little different.

Googleing "How to deploy a VSTO word template application" and the like continued to give me information on the problems people were having. Not very helpful! Thankfully due to the awesome resources available from Readify I was eventually pointed to the following links:




These links are your one stop shop for deploying VSTO applications.

Enjoy!

[Edit]
I also came across these screencasts yesterday. They provide an awesome walk through of the deployment process.
VSTO: Deployment via ClickOnce screencast and VSTO: Deployment via SharePoint

Next: Installing Pre-Requisite Assemblies For VSTO Applications

Friday, April 9, 2010

A New Beginning

Well last Wednesday, 7th April 2010, marked a new beginning for me as I started at Readify as a Senior Developer.

I hadn't been 100% happy at my previous employer and so I had begun priming myself for my application as soon as my 12 months was up. Unfortunately for my previous employer I started attending Sydney's ALT.NET User Group and told Richard Banks of my intent. His response was as simple as "well... we're looking for approximately 10 developers right now." and he left it at that.

Needless to say the rest is history and here I am now a proud Readifarian.

But wait! There's more!

Readify are still looking for more developers (2 for VIC and 5 for ACT/NSW plus a SharePoint guru for WA) who can also experience the awesome benefits of working for Readify.

Enjoy!

Monday, March 15, 2010

Aggregate Functions in Linq Group Statements

I was refactoring some of my linq queries in my budget app today and was having some difficulty with some of the grouping statements especially when I wanted to sum up the values in a decimal field.


Without showing you the code I'm refactoring (that would be way too embarrassing), here's a particular query that I was working with.

from mc in MthCategories
from s in (from s in Spendings where mc.MthCategoryId == s.MthCategoryId select s).DefaultIfEmpty()
where mc.Mth.Month == 3 && mc.Mth.Year == 2010
group s by mc.MthCategoryId into g
select new {
    MthCategoryId = g.Key,
    AmountSpent = (from s1 in g select s1.Amount).Sum()
}

This looks fine, however, when executed you will get the following InvalidOperationException

"The null value cannot be assigned to a member with type System.Decimal which is a non-nullable value type."


What gives!


Now I was initially thinking that this had something to do with the inferred type that was being applied to "AmountSpent", so I had a look to see what g was.


I really wasn't thinking clearly and all sorts of things were going through my head. I tried checking if the FirstOrDefault() value was null and then doing the Sum, but that didn't work. A little while later it occurred to me that "g" was actually comprised of a key and a collection and regardless of how many items were in the collection it was still there and that my initial thinking was screwed up. The problem had nothing to do with the inferred type but was caused by the fact that my sub query (from s1 in g select s1.Amount).Sum() was selecting a null value and it was the act of trying to apply Sum to a null object that was causing the problem.


The resulting query was:


from mc in MthCategories
from s in (from s in Spendings where mc.MthCategoryId == s.MthCategoryId select s).DefaultIfEmpty()
where mc.Mth.Month == 3 && mc.Mth.Year == 2010
group s by mc.MthCategoryId into g
select new {
    MthCategoryId = g.Key,
    AmountSpent = (from s1 in g select s1 == null ? 0 : s1.Amount).Sum(), 
    Spendings = g
}

Of course all of this could have been avoided had I clicked the Activate autocompletion link in LINQPad.


I hope this has helped.


Enjoy!

Tuesday, March 9, 2010

fsBudget - A Small Budget Application Built with jQuery, Ext-Js, C# and WCF

Finished! My first OS project.

Built using C#, jQuery and Ext-Js, it utilises WCF to consume the business layer.

Feel free to have a look.

Enjoy!

Tuesday, March 2, 2010

Time Well Spent

Well this morning provided some time to find out a bit more about a guy by the name of the Joseph Albahari.

Firstly, listed to Talking Shop Down Under where Richard chatted with Joe regarding a range of stuff primarily on C# 4.0 and LINQPad.

Secondly, being prompted by the podcast I went and had a look at Joe's site and found reference to a webcast that he'd done for LIDNUG. This was absolutely awesome! If you've got approx. 1.5 hours free definitely worth a watch as Joe takes you through some of the new features of C# 4.0 and explains some of the pros and cons and offers some explanations as to the why's.

Enjoy!

Wednesday, February 24, 2010

Sydney's ALT.NET User Group Gathering

Yesterday was my first time at the ALT.NET User Group and it was a lot of fun.

Apart from Richard Banks (who I'd worked with before) it was a sea of new faces, which is cool as one of the reasons I wanted to go was to get to know other people in the industry.

So for those who haven't been before, here's my little run down on the night.

The night started at 6pm so people were rocking up from around 5:30.

Not know anyone, most of my time was walking around shaking hands and saying, "Hi my name's Matthew. How you doing?". There seemed to be a great variety of people with even a C++ developer amoungst us. :)

Richard kicked things off with general question to everyone about anything cool they'd seen/read/done etc, then we continued with two presentations, one from James Crisp on Automated Builds and another by Romain Prieto on Automated Deployments.

Automated Builds
James started off his talk by implying that all the xml based build systems were crap, and introduced nRake.
nRake removes the dependency on a huge amount of xml configuration and introduces Ruby's OO scripting in-order to programmatically generate a build. Very interesting.

Automated Deployments
Next came Romain who introduced the concept of automating the deployments. Romain has put together a little tool he's called psDeploy (which he informs us he'll be putting up on Github soon), which is a library of cmdlets to assist with the deployment of applications. He highlighted how this tool works well with TFSDeployer and psake.

Besides the talks being enjoyable, the sarcasm was great.

Overall an enjoyable and interesting evening which I'd recommend.

Next month => hands-on-lab in a coding dojo.

Enjoy.

[Edit] psDeploy is now up on GitHub.

Friday, February 12, 2010

Great Scrum Resources

I just read a nice little post on Richard's Braindump regarding a new Professional Scrum Developer Course being offered at Scrum.org. Rather parrot what Richard said go read his post.

Anyway, while having a look through the site I came across some awesome Scrum Instructional Videos. Even if you've worked with Scrum, or maybe you think you've worked with Scrum, these are worth a look.

Enjoy!

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!