jqGrid and ASP.NET MVC - Basics

The purpose of this post is to start a small series about jqGrid. Basics which will be presented here have been already discussed around the web, so I will try to keep it short.
First we need to download jqGrid (we can choose which features should be included). Grid is themed with jQuery UI themes, so we have to download one of those as well (I will be using simple start theme). Having all this downloaded, unpacked and copied to our application, we should reference all the necessary files:
<head>
  <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
  <link href="../../Content/jquery-ui-1.7.2.custom.css" rel="stylesheet" type="text/css" />
  <link href="../../Content/ui.jqgrid.css" rel="stylesheet" type="text/css" />
  <script src="/Scripts/jquery-1.3.2.js" type="text/javascript">
  </script>
  <script src="/Scripts/grid.locale-en.js" type="text/javascript">
  </script>
  <script src="/Scripts/jquery.jqGrid.min.js" type="text/javascript">
  </script>
</head>
Let's add two placeholders in our html code - one for grid (table) and one for pager (div)
<table id="jqgProducts" cellpadding="0" cellspacing="0"></table>
<div id="jqgpProducts" style="text-align:center;"></div>

In next step we should initialize grid with some options (most of them can be changed later) and setup colModel.
<script type="text/javascript">
  $(document).ready(function() {
    $('#jqgProducts').jqGrid({
      //url from wich data should be requested
      url: '/Home/ProductsGridData/',
      //type of data
      datatype: 'json',
      //url access method type
      mtype: 'GET',
      //columns names
      colNames: ['ProductID', 'ProductName', 'SupplierID', 'CategoryID', 'QuantityPerUnit', 'UnitPrice', 'UnitsInStock'],
      //columns model
      colModel: [
                  { name: 'ProductID', index: 'ProductID', align: 'left' },
                  { name: 'ProductName', index: 'ProductName', align: 'left' },
                  { name: 'SupplierID', index: 'SupplierID', align: 'left' },
                  { name: 'CategoryID', index: 'CategoryID', align: 'left' },
                  { name: 'QuantityPerUnit', index: 'QuantityPerUnit', align: 'left' },
                  { name: 'UnitPrice', index: 'UnitPrice', align: 'left' },
                  { name: 'UnitsInStock', index: 'UnitsInStock', align: 'left' }
                ],
      //pager for grid
      pager: $('#jqgpProducts'),
      //number of rows per page
      rowNum: 10,
      //initial sorting column
      sortname: 'ProductID',
      //initial sorting direction
      sortorder: 'asc',
      //we want to display total records count
      viewrecords: true
    });
  });
</script>

Now we must prepare a method (which is pointed by url option) in our Controller. This method has to return data in one of acceptable formats. In this example we will go with json. The easiest way is to return an anonymous type corresponding with the format.
/// <summary>
///
Provides json data for jqGrid
/// </summary>
/// <param name="sidx">
sorting column
</param>
/// <param name="sord">
sorting direction
</param>
/// <param name="page">
page number
</param>
/// <param name="rows">
number of rows per page
</param>
/// <returns>
json data</returns>
public ActionResult ProductsGridData(string sidx, string sord, int page, int rows)
{
  //Getting total records count from repository
  int totalRecords = _repository.GetProductsCount();

  //Preparing anonymous variable with json data
  var productsData = new
  {
    //total pages count
    total = (int)Math.Ceiling((float)totalRecords / (float)rows),
    //page number
    page = page,
    //total records count
    records = totalRecords,
    //table with rows data
    rows = (from product in _repository.GetProducts(sidx, sord, page - 1, rows)
            select new
            {
              //row id
              id = product.ProductID,
              //table of cells values
              cell = new string[] {
                                     product.ProductID.ToString(),
                                     product.ProductName,
                                     product.SupplierID.ToString(),
                                     product.CategoryID.ToString(),
                                     product.QuantityPerUnit,
                                     product.UnitPrice.ToString(),
                                     product.UnitsInStock.ToString()
                                   }
            }
           ).ToArray()
  };

  //Returning json data
  return Json(productsData);
}

All what is left is some cool database (or other data source) access code and we can watch our first jqGrid in action.

Example source code can be found here (it uses good old Northwind Database). I will be extending this example while digging into jqGrid features.

Simple SystemIconsHandler for ASP.NET

One of web projects I'm working on needed a web file explorer. There was one specific requirement for this explorer, files should be displayed with icons they have on server. I decided that the best way will be dedicated HttpHandler.

So first I needed to P/Invoke SHGetFileInfo and DestroyIcon functions:
/// <summary>
///
Retrieves information about an object in the file system, such as a file, folder, directory, or drive root
/// </summary>
/// <param name="pszPath">Contains the path and file name. Both absolute and relative paths are valid
</param>
/// <param name="dwFileAttributes">
A combination of one or more file attribute flags
</param>
/// <param name="psfi">
SHFILEINFO structure to receive the file information
</param>
/// <param name="cbSizeFileInfo">
The size, in bytes, of the SHFILEINFO structure
</param>
/// <param name="uFlags">
The flags that specify the file information to retrieve
</param>
/// <returns>
Meaning depends on the uFlags parameter</returns>
[DllImport("shell32.dll")]
static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFileInfo psfi, uint cbSizeFileInfo, uint uFlags);
/// <summary>
///
Destroys an icon and frees any memory the icon occupied
/// </summary>
/// <param name="handle">
Handle to the icon to be destroyed
</param>
/// <returns>
If the function succeeds, the return value is nonzero</returns>
[DllImport("user32.dll", CharSet = CharSet.Auto)]
extern static bool DestroyIcon(IntPtr handle);

With those two functions getting icon for file looks like this:
Icon tempIcon;
SHFileInfo tempFileInfo = new SHFileInfo();
//Getting SHFileInfo for file (based on extension)
SHGetFileInfo(extension, 0, ref tempFileInfo, (uint)Marshal.SizeOf(tempFileInfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | (uint)iconSize);
//Creating Icon based on SHFileInfo
tempIcon = (Icon)Icon.FromHandle(tempFileInfo.hIcon);
//Making managed clone
Icon managedIcon = (Icon)tempIcon.Clone();
//Destroying unmanaged handle
DestroyIcon(tempIcon.Handle);
return managedIcon;

There is only one difference when getting icon for folder:
//Getting SHFileInfo for folder
SHGetFileInfo(null,
FILE_ATTRIBUTE_DIRECTORY,
ref tempFileInfo, (uint)Marshal.SizeOf(tempFileInfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | (uint)iconSize | (uint)folderType );

So having this done, all what is left is processing request:
public void ProcessRequest(HttpContext context)
{
  Icon systemIcon = null;
  //Ckecking parameters
  if(!String.IsNullOrEmpty(context.Request.QueryString["type"
])
  && !
String.IsNullOrEmpty(context.Request.QueryString["size"
]))
  {

    //Setting icon size
    IconSize size = IconSize.SHGFI_SMALLICON;
    if (context.Request.QueryString["size"].Equals("large"
))
      size =
IconSize.SHGFI_LARGEICON;

    //Getting icon
    if (context.Request.QueryString["type"].Equals("dir"
))
      systemIcon = GetFolderIcon(size,

      FolderType
.SHGFI_CLOSEICON);
    else if(context.Request.QueryString["type"].Equals("file"
))
      systemIcon = GetExtensionIcon(
      context.Request.QueryString[
"ext"], size);
  }

  if (systemIcon != null
)
  {

    MemoryStream systemIconStream = new MemoryStream();

    //Converting icon to .png
    systemIcon.ToBitmap().Save(systemIconStream,
    ImageFormat
.Png);
    systemIconStream.Close();

    byte
[] systemIconBytes = systemIconStream.GetBuffer();

    //Setting the response
    context.Response.ContentType = "image/png"
;
    context.Response.BufferOutput =
true
;
    context.Response.OutputStream.Write(systemIconBytes, 0,
    systemIconBytes.Length);
  }
}

Simple example can be found here. Below you can see it's result.