Sunday, November 6, 2011

MVCfied Datatable.js

In my last post I discussed how to create a very simple MVC control which demonstrated a notion of ways things are done in MVC in contrast to web form.

This post will focus on explaining a real and sophisticated MVC control which encapsulates jquery.datatable.js and jquery.ui.sortable.js jquery plugins.

Jquery.datatables.js is one of the sophisticated jquery plugin which provides a way to build a grid with complex functionality such as paging, sorting, filtering and many more. And it is really easy to integrate with MVC. Before going through this article I suggest you to understand the capability of jquery.datatable plugin and how to work with it without encapsulating it into MVC control.



Please also take a look at sortable for sortable plugin which is useful for row sorting.

We won’t be going into details how these plugins work. Rather we will be focusing on how to encapsulate these jquery plugins in MVC and simplify the process of creating a reusable and interactive control which can do all the heavy lifting and return a sophisticated grid with just single line of code.

As you must have understood by now that MVC controls simply emits necessary html string which will be rendered to the browser. Unlike webform’s controls which participates in full page lifecycle, MVC control simply can be a class which returns full html string in it’s ToString() function including the necessary html element and javascripts. Whatever is returned is appended to the response stream. So you just need to make sure that you emit required html string and javascript properly and in correct order.

Let’s first create another jquery plugin wrapping around the existing datatable plugin. The purpose of this is to incorporate all the necessary boilerplate code before hand which will significantly reduce the amount of html code to be returned for each grid in your page. Remember it is not absolutely necessary, however you will come to realize its significance as you will start building one yourself. I’ve named it dataTableMVC.

Let’s flrst take a quick look at how the wrapper javascript plugin looks like. Open DataTableJS.js file under MVCExtended Project in Controls/contents/scripts folder.

I know the code is a lot. But as I told you this wrapper does all the heavy lifting works, simplifying the process of control development. You’ll be amazed to see how your control user will respond when they are able to create a full functional grid control in just a single line of code. The javascript function callRowSorted is a bit of extra work for sending the data back to the server after the rows have been sorted. It actually recreates a model and forms an array in the order they currently appear, to be returned to the server.

Now Let’s look at DataTableJS class

public class DataTableJS : MvcHtmlString

        public DataTableJS(string name, string url):base("")
            Name = name;
            Url = url;

public override string ToString()
            StringBuilder builder = new StringBuilder();
            //start building all the required html and javascript.

            return builder.ToString();

The class is really simple as I told you. It derives from MvcHtmlString, which is absolutely not necessary. You can just override the ToString() method from object and return all the required scripts and html tags in correct order.

All others are the properties and methods exposed to the control user if they want to tweak the default behaviours. There are some method chaining functions such as ApplySetting which takes a lambda expression as Action delegate. This delegate will be called at the end of the process while building the necessary html strings. The control user can provide a lambda expression which changes the default settings of the DataTableJS class.

DatatableJS control works with the viewmodel class. Your properties in viewmodel are decorated with the appropriate DataTableJSColumn attribute. The DataTableJSColumns are another powerful part of this control which is responsible to return the content in appropriate format and supply the necessary script blocks. Each type of Column is supplemented by its corresponding attribute type. The attributes simply encapsulates all the properties required by the corresponding column type which can be modified at attribute level. Attributes also facilitates this control to transform the viewmodel data into appropriate format to be returned to datatable.js plugin incase of serverside paging and sorting.

The viewmodel will look something like this.

public class PersonalInformation
        [DataTableJSColumn(ColumnIndex = 0,Title = "Sort Index")]
        public int SortIndex { get; set; }

        [DataTableJSLinkColumn("PersonId",BaseUrl = "localhost/personalinfo/",Title = "Select",CellText = "Retrieve",IsSortable = false,ColumnIndex = 0)]
        public int PersonId { get; set; }

        [DataTableJSCheckBoxColumn("PersonName", Title = "Select All", ColumnIndex = 1)]
        public string PersonName { get; set; }

        [DataTableJSColumnAttribute("EmailAddress", Title = "Email Address", ColumnIndex = 3)]
        public string EmailAddress { get; set; }

        [DataTableJSColumnAttribute("DateOfBirth", Title = "Date of Birth", FormatString = "MM/dd/yyyy", ColumnIndex = 2)]
        public DateTime DateOfBirth { get; set; }

        [DataTableJSColumn("Gender", Title = "Gender", ColumnIndex = 4)]
        public string Gender { get; set; }


You can use the control using the html extension as

<%= Html.DataTableJS("ss", Url.Action("GetData")).AutoGenerateColumns(true).ApplySetting((m) => { m.DisplayLength = 5; m.AutoWidth = false; m.IsServerSide = true; m.ColumnByName = false;
}).DefaultSortBy("SortIndex", "asc") %>

Please download and go through the code. And always remember that there are thousands of ways of doing things, and this is one among them. I don’t claim it to be the best way out there. So google a bit more and find out other best ways of doing so. If you have or find any link then please let me know so that I can learn it myself too.

There is a tiny bug related to row sorting while resending the data back to the server for persisting. Please ignore it for now.

Thank you all for reading the post.

Sunday, October 2, 2011 Mvc Control, replacement for Server control

This tutorial is dedicated to all the newbie who just started out with MVC and have been wondering why all those mighty(and bulky) server controls have been suddenly discarded by MVC team. You might also be wondering why do MVC pros don’t recommend you to use server controls, and if so is it fair to have all those boiler plate codes scattered all over your pages which in case of server controls, minimized a lot with just few properties to tweak.

Well the fact is server controls have not vanished away from MVC. It’s just it really doesn’t fit and suit well with MVC. Having an Server control on your MVC view is like having to see a 60 year old man mingling with a hot girl of your dream. However it might blend sometime, totally depending on the various situations. To tell you the truth I’ve done that too.

Well let’s get back to why…..? Its coz server controls are very tightly coupled with page lifecycle and maintaining the states between user requests. To do so it emits all those heavy and dirty viewstate strings to the user and does all the dirty work of re-parsing those view state to reinstate the control on postback. Web is actually stateless architecture. And it is why web is much favored much by many and in many cases. Working so hard to maintain the control state doesn’t seem right. And that is where ajax comes in play.

So what do we do to minimize the code for some portion of your application which might be repeated over and over again in your views. server controls did all the dirty jobs of emitting necessary scripts and html elements. All you had to do was to change few properties. Well I guess you already have the answer for this. Yes, the Html Helper. But not really , Html Helper comes to the rescue but doesn’t do much than to help you with some contextual data and render an Html string. You must have already seen a way to render a textbox using Html.TextBox() or a checkbox. Well the TextBox extension method of HtmlHelper actually takes a few parameters and based on that parameter returns the final string or a MVCHtmlString.
Let’s get back to the real thing building a small html helper extension which is responsible to build a table with supplied number of columns and rows and table headers.

All this starts with creating a static extension class.

Here I’d like to name the class as TableBuilderExtension
The class looks something like this.
using System.Web.Mvc;
 namespace MyApp.Helpers

public static class TableBuilderExtension


Now let’s create an extension method named Table which takes a tableName,numberOfColumns, numberOfRows and headers as parameters and build the table with headers based on these supplied parameter

public static System.Web.Mvc.MvcHtmlString Table(this HtmlHelper helper, string tableName, int numberOfColumns, int numberOfRows,string[] headers)
            TagBuilder builder = new TagBuilder("table");
for (int i = 0; i < numberOfRows; i++)
                TagBuilder rowBuilder = new TagBuilder("tr");

                for (int j = 0; j < numberOfColumns; j++)
                    TagBuilder cellBuilder = new TagBuilder("td");
                    if (i == 0)
                        cellBuilder = new TagBuilder("th");
                        cellBuilder.InnerHtml = headers[j];
                        cellBuilder.InnerHtml = " ";
                    rowBuilder.InnerHtml += cellBuilder.ToString();

                builder.InnerHtml += rowBuilder.ToString();

            return new MvcHtmlString(builder.ToString());
            //return builder.ToString(); //for this change the return type to a simple string type.

Remember the first parameter in the function. This makes your function an extension method for the type HtmlHelper class. And this is what extends the htmlhelper class and appends your function to the class(provided the namespace is imported wherever you are using this htmlhelper class). The code is really really simple. Here I’ve used a TagBuilder class to build an html element which simplifies our work. It also provides various other functions such as AddCssClass, MergeAttributes to add a css class and extra attributes to your html tag. And Finally note the MvcHtmlString return type which is nothing more than a HtmlString type and returns the html string on ToString() function. You can also replace the return type as a simple string and simply return a string instead. You also have your htmlhelper which provides you all the contextual data required related to your view. You can use them in various ways depending on the type of control you are building. There you have it…. It’s a piece of cake. You can simply use this in you view as
@Html.Table("mytable", 3, 10,new string[]{"Header 1","Header 2","Header 3"})

If you want to explore more you can simply download the MVC project from codeplex. It’s open source, so no charges and take a look at various htmlhelper extension methods such as TextBox, CheckBox and see how the htmlhelper object can be very helpful in generating the id and name of for your input elements and model errors, model values and blah blah blah…

Thank you all for reading this post.

Monday, January 24, 2011

Smart tag not working in visual studio

Recently in couple of threads in I saw a couple of questions regarding Common tasks such as add extender not showing in the web controls. If you are wondering what these common tasks are then, it’s a shortcut menu available for your web server control that helps you extend the functionality of your control such as  the “Add Extender” menu you can see below. When you click on Add Extender menu it generally pops up a dialog with a list of extender controls that you can use with your current control.

The problem can be generally resolved by enabling the smart tag. To do so
1.       Right click on the control.
2.       You can see “Show Smart Tag” menu as below.

3.       Check the menu, if it’s not. Now you will be able to see the menu as above.

But sometime this menu is greyed out or disabled. The problem is due to the mismatch version of your ajaxtoolkit and that of your current website target framework version. If the target version of your website is greater than the version of your ajaxtoolkit control then you may not be able to view the menu. If you are not sure which version of AjaxToolkit you are using then just go to the folder where your control toolkit is loaded from. Right click on the dll and view it’s property. Go to details/version tab and check out it’s file version. Generally if the target framework of your website is 3.5 then the version of your AjaxControlToolkit should be 3.5 as well.

Just make sure to download the correct version of AjaxControlToolkit from the CodePlex and reference it in your project. You can find the binary and source code for the ajax control toolkit in code plex.
If you have downloaded the source code for AjaxControlToolkit then you may wanna set the correct assembly version and build it. Just go to the AssemblyInfo file under Property and change the version in AssemblyVersion attribute.
 If you have already added an older verison of AjaxControlToolkit then remove them from your toolbox and add the new one.
And finally make sure to rebuild your website once again.

Saturday, January 22, 2011

Visual studio debugger hangs when stopping

Visual studio debugger hangs when stopping

Recenty I faced a very weird problem in my visual studio. When I run my application from visual studio and close it visual studio sorts of hang for few seconds. At first I guessed it was may be due to a lot of projects in 1 solution. Then I guessed It could be coz of a lot of library references in my projects. It went for a long time. And I didn't give it a damn.
But it became irritating soon. So I decided to give it a search. And after a long search I finally was able to solve my problem.
I just reset all settings in my import and export settings wizard.
And just solved my problem.
So in case at some point if you come accross this problem just use import and export settings wizard and reset all settings.