My Search for Rails and Why I found Python Instead

Recently I've been drawn to the 'dynamic languages' hype. It's been clear that developments in C#3.5 and C#4.0 have been made to bring elements of dynamic languages into the compiler and CLR. In addition things like Microsoft's DLR, and releases like WebMatrix and Microsoft.Data.dll show clearly that Microsoft are trying to give some of the dynamic language experiences to .NET developers....click here to read more
David Barone, 14 August, 2010, 5:24 pm
Last Modified: 14 August, 2010, 5:29 pm

Copy jqGrid CSV Data to Clipboard

Here's a simple snippet for JQuery's jqGrid to enable the data in the grid to be copied to the clipboard. You'll need to set the grid's multiselect property to true. Then you simply add some extra code below your jqGrid initialisation code:...click here to read more
David Barone, 11 March, 2010, 1:21 pm
Last Modified: 11 March, 2010, 1:29 pm

Building a Template Engine - Part 2

In part 1, I start to build a very simple template engine using regular expressions. In this article I want to add another trick which can be helpful for creating dynamic content programmatically - the use of the using System.CodeDom.Compiler namespace, and run-time compilation of code. In a project I did a couple of years ago, we wanted the ability for users to store parameters based on some 'expression'. This expression would then be parsed to produce text on a report. Typically, the expression would be to generate today's date or some date based on today (eg end of last month, start of last month etc). Rather than building a pre-defined list of suitable placeholders for these variables, I decided to use the power of the System.CodeDom.Compiler classes, so that the user could type in a .NET 'snippet' expression, and this expression would be compiled during execution of the program, and then evaluated, to return the required text value. Therefore, users would be able to enter in strings like: ...click here to read more
David Barone, 5 August, 2009, 9:21 pm
Last Modified: 5 August, 2009, 9:21 pm

Building a Template Engine - Part 1

Being able to master templates is a useful skill for a programmer, not only are templates a major part of many languages (XSLT, ASP.NET to name but two), but templates are also useful for code autogeneration and quick manipulation of code and data. Although there are templating tools available, I thought I'd investigate how simple it was to create a basic templating engine. One side goal of this is that I would like to eventually create a templating engine that I could use in my MVC framework instead of NVelocity (just for the challenge!). To begin with, I decided to see how far I could get using the regular expression library (RegEx) in .NET: ...click here to read more
David Barone, 5 August, 2009, 9:05 pm
Last Modified: 25 February, 2010, 8:00 pm

Game of Life in Silverlight

Every now and then you start on something that is so addictive that you just can't leave the code. I've experienced that today, and it was meant to be a day off work! ...click here to read more
David Barone, 23 July, 2009, 8:31 pm
Last Modified: 23 July, 2009, 8:31 pm

ASP.NET MVC - Adding Grids Using Flexigrid

I've decided the best way to learn ASP.NET MVC is to start building a 'sample' web site. I've decided to build a web app based on the Northwind database. I'm looking at building a toolkit of widgets and other libraries that I can then call on when constructing a real web application. I figured a good widget to start with was a grid. Grids are a really important aspect to most web application sites. Most CRUD operations originate from a web page containing some kind of grid or table to show the records. Grids are so important that ASP.NET provides a number of ways to create a grid (eg ListView, GridView, Repeater etc etc). I also want to use JQuery. JQuery seems to be the frontrunner when it comes to Javascript Libraries, and ASP.NET MVC has good integration with it. Looking around on Google, it appears there are a few 'Grid' plugins. I went for flexigrid on account of it being very light-weight (just one moderately small js file) whilst still looking professional. There are a couple of good articles that I also used to get started with flexigrids: If you look at the attached code, you'll see I've not added that much to my example. I have introduced an extension method on the HtmlHelper class to add a fully-formed Flexigrid. I've done this so that you get nice .NET intellisense when entering all the Flexigrid parameters.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Text; using System.Web.Mvc; using System.Reflection; namespace mvc.Helpers { [AttributeUsage(AttributeTargets.Property, AllowMultiple=false)] public class TextDelimiterAttribute : Attribute { public string Delimiter; public TextDelimiterAttribute(string delimiter) { Delimiter = delimiter; } } public enum Alignment { Left, Middle, Right } public class FlexigridButton { public FlexigridButton(string name, string bClass, string onPress) { Name = name; BClass = bClass; OnPress = onPress; } [TextDelimiter("\"")] public string Name {get; set;} [TextDelimiter("\"")] public string BClass { get; set; } public string OnPress { get; set; } } public class FlexiGridColumn { public FlexiGridColumn(string display, string name, int width, bool sortable, Alignment alignment) { Display = display; Name = name; Width = width; Sortable = sortable; Align = alignment; } public FlexiGridColumn(string display, string name, int width, bool sortable, Alignment align, string process) { Display = display; Name = name; Width = width; Sortable = sortable; Align = align; Process = process; } [TextDelimiter("\"")] public string Display {get; set;} [TextDelimiter("\"")] public string Name { get; set; } public int Width {get; set;} public bool Sortable {get; set;} [TextDelimiter("'")] public Alignment Align {get; set;} public string Process { get; set; } } public class FlexiGridParameters { public string TableContainerName {get; set;} public string Title {get; set;} public string Url {get; set;} public int Width {get; set;} public int Height {get; set;} public FlexiGridColumn[] Columns {get; set;} public FlexigridButton[] Buttons {get; set;} public FlexiGridSearchItem[] SearchItems {get; set;} public bool AllowPaging {get; set;} public int PageSize {get; set;} public bool ShowTableToggleButton { get; set; } } public class FlexiGridSearchItem { public FlexiGridSearchItem(string display, string name) { Display = display; Name = name; } [TextDelimiter("\"")] public string Display { get; set; } [TextDelimiter("\"")] public string Name { get; set; } } public static class ExtensionMethods { private static string ToJson(this object obj) { StringBuilder sb = new StringBuilder(); sb.Append("{"); Type objType = obj.GetType(); string delim = string.Empty; foreach (PropertyInfo pi in objType.GetProperties()) { string delimiter = string.Empty; if (Attribute.IsDefined(pi, typeof(TextDelimiterAttribute))) { delimiter = ((TextDelimiterAttribute)pi.GetCustomAttributes(typeof(TextDelimiterAttribute), false)[0]).Delimiter; } object value = pi.GetValue(obj, null); if (value !=null && value.GetType() == typeof(bool)) value = value.ToString().ToLower(); if (value != null) { sb.Append(delim + pi.Name.ToLower() + ":" + delimiter + value.ToString() + delimiter); delim = ","; } } sb.Append("}\n"); return sb.ToString(); } public static string FlexiGrid(this HtmlHelper helper,FlexiGridParameters parameters) { StringBuilder sb = new StringBuilder(); sb.Append("<table id=\"" + parameters.TableContainerName + "\" style=\"display:none\"></table>\n"); sb.Append("<script type=\"text/javascript\">\n"); sb.Append("$(document).ready(function(){\n"); sb.Append(" $(\"#" + parameters.TableContainerName + "\").flexigrid\n"); sb.Append(" (\n"); sb.Append(" {\n"); sb.Append(" url: '" + parameters.Url + "',\n"); sb.Append(" dataType: 'json',\n"); sb.Append(" colModel : [\n"); string delim = ""; foreach (FlexiGridColumn c in parameters.Columns) { sb.Append(delim + c.ToJson()); delim=","; } sb.Append(" ],\n"); sb.Append(" buttons : [\n"); delim = ""; foreach (FlexigridButton b in parameters.Buttons) { sb.Append(delim + b.ToJson()); //sb.Append(delim + " {name: '" + b.Name + "', bclass: '" + b.BClass + "', onpress : " + b.OnClick + "}\n"); delim=","; } sb.Append(" ],\n"); sb.Append(" searchitems : [\n"); delim = ""; foreach (FlexiGridSearchItem s in parameters.SearchItems) { sb.Append(delim + s.ToJson()); delim=","; } sb.Append(" ],\n"); sb.Append(" sortname: \"id\",\n"); sb.Append(" sortorder: \"asc\",\n"); sb.Append(" usepager: true,\n"); sb.Append(" title: '" + parameters.Title + "',\n"); /* sb.Append(" useRp: true,\n"); sb.Append(" rp: 10,\n"); sb.Append(" showTableToggleBtn: true,\n"); */ sb.Append(" width: 700,\n"); sb.Append(" height: 255\n"); sb.Append(" }\n"); sb.Append(" ); }) \n"); sb.Append("</script>\n"); return sb.ToString(); } } }
The amount of code written for the flexigrid using the extension method is about the same is if you just wrote the JQuery code yourself. Not sure if this is a worthwhile step. Time will tell. The actual markup code using the HtmlHelper is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<mvc.Models.Customer>>" %> <%@ Import Namespace="mvc.Helpers" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Customers </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <script type="text/javascript" language="javascript"> function makeLink(celDiv) { $(celDiv).html('<a href="Customer/Edit?customerId=' + $(celDiv).html() + '">' + $(celDiv).html() + '</a>'); } function test(com, grid) { if (com == 'Delete') { var itemsSelected = $('.trSelected', grid).length; if (itemsSelected > 0) { if (confirm('Delete ' + itemsSelected + ' items?')) { var items = $('.trSelected', grid); var itemList = ''; for (i = 0; i < items.length; i++) { itemList += items[i].id.substr(3) + ","; } $.ajax({ type: "POST", dataType: "json", url: "JSon/DeleteCustomer", data: "customerIds=" + itemList, success: function(data) { alert(data.Message); $("#tableCustomer").flexReload(); } }); } } else { return false; } } else if (com == 'Add') document.location = "/Customer/Create"; } </script> <div> <%=Html.FlexiGrid( new FlexiGridParameters { TableContainerName = "tableCustomer", Title = "Customers", Url = "JSon/GetCustomers", Width = 300, Height = 400, Columns = new FlexiGridColumn[] { new FlexiGridColumn("Customer Id","CustomerId",50,true,Alignment.Left, "makeLink"), new FlexiGridColumn("Company Name","CompanyName",100,true,Alignment.Left), new FlexiGridColumn("Contact Name","ContactName",100,true,Alignment.Left), new FlexiGridColumn("Address","Address",100,true,Alignment.Left), new FlexiGridColumn("City","City",100,true,Alignment.Left), new FlexiGridColumn("Contact Title","ContactTitle",100,true,Alignment.Left), new FlexiGridColumn("Country","Country",100,true,Alignment.Left), new FlexiGridColumn("Fax","Fax",100,true,Alignment.Left), new FlexiGridColumn("Phone","Phone",100,true,Alignment.Left), new FlexiGridColumn("Postal Code","PostalCode",100,true,Alignment.Left), new FlexiGridColumn("Region","Region",100,true,Alignment.Left) }, Buttons = new FlexigridButton[] { new FlexigridButton("Add","add","test"), new FlexigridButton("Delete","delete","test") }, SearchItems = new FlexiGridSearchItem[] { new FlexiGridSearchItem("Customer Id","CustomerId"), new FlexiGridSearchItem("Contact Name","ContactName") }, AllowPaging = true, PageSize = 10, ShowTableToggleButton = true } ) %> </div> </asp:Content>
I've added a JsonController class so I can start learning Json and play with AJAX calls. You can see how I get the customer list and delete customers through Ajax calls. Again, JQuery and ASP.NET MVC handle this seamlessly.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Ajax; using Csa.Data.Entities; using mvc.Models; namespace mvc.Controllers { public class JsonController : Controller { NorthwindEntities context = new NorthwindEntities(); public ActionResult Index() { return View(); } public JsonResult DeleteCustomer(string customerIds) { try { string[] customerIdArray = customerIds.Split(','); int processed = 0; foreach (string customerId in customerIdArray) { if (!string.IsNullOrEmpty(customerId)) { var customer = context.Customers.First(c => c.CustomerID == customerId); context.DeleteObject(customer); context.SaveChanges(); processed++; } } return Json(new { Message = "Delete successful: " + processed + " records processed." }); } catch (System.Data.UpdateException ex) { return Json(new { Message = "Error: " + ex.InnerException.Message }); } catch { return Json(new { Message = "An error has occured!" }); } } public JsonResult GetCustomers() { NorthwindEntities context = new NorthwindEntities(); var customers = context.Customers.Take(10).Select(c => new { CustomerId = c.CustomerID, CompanyName = c.CompanyName, ContactName = c.ContactName, Address = c.Address, City = c.City, ContactTitle = c.ContactTitle, Country = c.Country, Fax = c.Fax, Phone = c.Phone, PostalCode = c.PostalCode, Region = c.Region }).ToList(); FlexigridDataSet dataset = new FlexigridDataSet("CustomerId", customers); JsonResult result = this.Json(dataset); return result; } } }
There's not much else to add at this point. The demo displays the customers from the Northwind database. You can add, edit and delete customers. The edit link is done using the 'process' parameter on the column model. The edit/create customer page is a bit bland (it's the auto-generated one). I think I might try and use an AJAX popup window for this as well (maybe the next article to write!). ...click here to read more
David Barone, 4 April, 2009, 11:17 pm
Last Modified: 4 April, 2009, 11:17 pm

The Future's Bright. The Future's MVC

With the recent RTM of the ASP.NET MVC framework, a new era has dawned on the web development landscape. This is probably as big a shift in development frameworks as ASP.NET was to classic ASP. It will need a similar level of adjustment as well, and those who don't embrace it may miss out. ...click here to read more
David Barone, 3 April, 2009, 9:40 pm
Last Modified: 3 April, 2009, 9:40 pm

Maze Game in Silverlight

I thought I'd take LINQ and Silverlight for a spin by writing a simple maze program. A maze game uses several collections - collection of cells, collections of borders around each cell. This is perfect for taking LINQ for a test drive. Firstly, I need an algorithm to generate a maze: ...click here to read more
David Barone, 21 October, 2008, 10:50 am
Last Modified: 21 October, 2008, 10:50 am

Resizing Arrays Using Extension Methods

Extension methods are a useful addition to .NET 3.5. Without them, there would be no LINQ. They're easy to create, and are well worth considering if you want to extend a class, but cannot use inheritance. A recent question popped up at work about resizing the built-in array types in .NET. There is the static generic method Resize() that will do the job, and you can use generic collections like List to give you type safety and performance benfits as well. However, I though I'd see what I can do using Extension methods:: The following code illustrates this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ResizingArraysUsingExtensionMethods { public static class MyExtensionMethods { public static T[] ResizeTo<T>(this T[] sourceArray, int length) { if (length < 0) throw new ApplicationException("new length cannot be negative"); T[] destinationArray = new T[length]; int elementsToCopy = sourceArray.Count() > length ? length : sourceArray.Count(); Array.Copy(sourceArray, destinationArray, elementsToCopy); return destinationArray; } } class Program { static void Main(string[] args) { int[] intArray = { 1, 2, 3 }; string[] stringArray = { "a", "b", "c" }; Console.WriteLine("Original length of int array = {0}", intArray.Length); Console.WriteLine("Original length of string array = {0}", stringArray.Length); intArray = intArray.ResizeTo(5); stringArray = stringArray.ResizeTo(6); Console.WriteLine("New length of int array = {0}", intArray.Length); Console.WriteLine("New length of string array = {0}", stringArray.Length); foreach (int element in intArray) Console.WriteLine(element.ToString()); foreach (string element in stringArray) Console.WriteLine(element ?? ""); intArray = intArray.ResizeTo(1); stringArray = stringArray.ResizeTo(2); Console.WriteLine("New length of int array = {0}", intArray.Length); Console.WriteLine("New length of string array = {0}", stringArray.Length); foreach (int element in intArray) Console.WriteLine(element.ToString()); foreach (string element in stringArray) Console.WriteLine(element ?? ""); Console.ReadKey(); } } }
...click here to read more
David Barone, 3 October, 2008, 9:43 am
Last Modified: 3 October, 2008, 9:43 am

Book Review - C# in Depth (Jon Skeet)

Another C# book. This one with a slightly different angle. If you want to master all the new language features in C#3.0 in order to write really elegant code, then look no further. Quite simply, this book follows the evolution of the C# language from its inception, through version 2.0 and finally brings us up to date with version 3.0. For each enhancement to the language, the reason it was introduced and the problems it solves are explained. Many enhancements are linked (mostly to LINQ), and these relationships are also discussed by the author. The book is divided into 3 main parts:
  • Part 1 - Introduction / C# 1.2
  • Part 2 - C# 2.0
  • Part 3 - C# 3.0
...click here to read more
David Barone, 11 September, 2008, 9:13 am
Last Modified: 11 September, 2008, 9:13 am