Category Archives: C#

jTemplates with jQuery, AJAX and Json

jTemplates is a jQuery plugin and template engine for Javascript.  If you keep up with Dave Ward and/or Rick Strahl you may already be familiar with jTemplates as they have both highlighted the plugin on their respective bolgs.  About 1.5 months ago, however, I got into the action and started using jTemplates in conjunction with jQuery, AJAX and Json to dynamically populate dropdowns and tables on the client side.

As you’ll see in the examples, jTemplates provides custom syntax to do such things as iterate through Json data and populate a predefined template.  Once you get a grasp of the syntax and the proper usage, you will be ready to roll.  Getting started is easy — just download the latest jQuery and jTemplate bits and reference them within your html or aspx file.

Next, you need to define and host your templates.  In the included sample project, I’ve defined two templates to aid in the population of my dropdown and my table respectively.  Here you will notice the dropdown template merely adds a singe “Select One” entry and then iterates over all project results adding a new option for each:

<%-- Project Dropdown Template --%>
<script type="text/html" id="TemplateProjectSelect">    
<option value="">Select One</option>
{#foreach $T.result as project}
    <option value="{$T.project.id}">{$T.project.name}</option>
{#/for}
</script>

And the following table template is a little more complex but still very to interpret.  Here, we are iterating over each task row and appending a new row to the table for each.  Notice there’s a MAIN template and a ROW template.  The MAIN template passes along the current record to the ROW template.  The ROW template sets the appropriate class (think table zebra stripes) and column values based on the current “cycle.”

<%-- Results Table Template --%>
<script type="text/html" id="TemplateResultsTable">    
{#template MAIN}
<table width="500" border="0" cellpadding="5" cellspacing="0">
  <tr>
    <th width="50">ID</th>
    <th width="300">Task</th>
    <th width="104">Hours</th>
  </tr>
  {#foreach $T.result as task}
    {#include ROW root=$T.task}
  {#/for}
</table>
{#/template MAIN}

{#template ROW}     
<tr class="{#cycle values=['','evenRow']}">
  <td>{$T.id}</td>
  <td>{$T.name}</td>
  <td>{$T.hours}</td>
</tr>
{#/template ROW}
</script>

How’s about hosting the templates?  You have a few options.  First, you could save the templates off in their own file.  This is the approach Dave Ward took in his article. Though this approach is clean, it doesn’t perform all that well.  The preferred approach is to “embed” your templates within the html/aspx file by wrapping each of the above templates with a script tag like so:

<script type="text/html" id="TemplateResultsTable"> 

... template here ...

</script> 

As shared on Rick Strahl’s post, this is the preferred approach as using <script type=”text/html”> that allows hiding any markup in the document without interfering with HTML validators. The script can be accessed by its ID and the content retrieved using the jQuery .html() syntax.

Once your template is in place, you simply need to assign your template to your container (a div) and then process the template using your Json data.  As noted above, you may reference an external template using the following:

$('#tasks').setTemplate('Template.htm');

Or you may select the template from the html/aspx itself:

$('#tasks').setTemplate($("#TemplateResultsTable").html());

Again, the preferred approach is the latter.  In either case, you process the template data (results) as follows:

$('#tasks').processTemplate(results);

A quick note on .processTemplate.  You don’t actually have to provide any data.  You can send null into the processTemplate method if, for example, no processing is required.  In the downloadable example, I create a static template which acts as a place holder when my page first loads and no table data is available. Here’s the sample template and javascript:

<%-- Emtpy Table Template --%>
<script type="text/html" id="TemplateResultsEmpty">    
Select a client and project...
</script>

$('#tasks').setTemplate($("#TemplateResultsEmpty").html());
$('#tasks').processTemplate(null);

Before I wrap things up, I should mention the downloadable sample project doesn’t only show off jTemplates.  It also demonstrates how to use jQuery and an “parameterized” HTTPHandler to pull back Json data which is somewhat an extension of my earlier HTTPHandler post.

Download jTemplates Sample Project: jTemplates.zip

 

HTTPHandler with JSON Data

As javascript libraries, particularly jQuery, increase in popularity so do web techniques using AJAX and JSON.

Have you ever seen this code?  It is front and back of an ASPX file with the single responsibility to return JSON data per an AJAX request.

GetDataPage.aspx

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="GetDataPage.aspx.cs" Inherits="GetDataPage" %>
<%-- 
    This minimal code is here to prevent the following error:
     "Using themed css files requires a header control on the page"
     Please see http://www.west-wind.com/WebLog/posts/4662.aspx 
     for more information --%>
<head id="Head1" runat="server" visible="false" />

GetDataPage.aspx.cs

using System;
using System.Web;
using System.Text;

public partial class GetDataPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // Clear out the buffer
        Response.ClearHeaders();
        Response.ClearContent();
        Response.Clear();

        // Do not cache response
        Response.Cache.SetCacheability(HttpCacheability.NoCache);

        // Set the content type and encoding for JSON
        Response.ContentType = "application/json";
        Response.ContentEncoding = Encoding.UTF8;

        int page = int.Parse(Request["p"]);
        string results = DataAccess.GetResults(page);

        Response.Write(results);

        // Flush the response buffer
        Response.Flush();

        // Complete the request.  NOTE: Do not use Response.End() here,
        // because it throws a ThreadAbortException, which cannot be caught!
        HttpContext.Current.ApplicationInstance.CompleteRequest();
    }
}

You may have noticed there’s a comment for nearly every code block.  At first, one may find the comments redundant and unnecessary, but really they are call for help.  A code:comment ratio like this usually indicates you really need to focus on what’s happening with the code because if you aren’t paying attention, bad things might happen.

As you have undoubtedly concluded, there’s a lot of overhead associated with returning JSON data from an ASPX file.  This statement is especially true if you consider the alternative, an HTTPHandler.  Here’s a cleaner, best-practices approach which provides the same outcome with less code, comments and risk.

GetDataHandler.ashx

<%@ WebHandler Language="C#" Class="GetDataHandler" %>

using System.Text;
using System.Web;

public class GetDataHandler : IHttpHandler
{
    public bool IsReusable
    {
        get { return false; }
    }
    
    public void ProcessRequest (HttpContext context) 
    {
        context.Response.ContentType = "application/json";
        context.Response.ContentEncoding = Encoding.UTF8;

        int page = int.Parse(context.Request["p"]);
        string results = DataAccess.GetResults(page);
        
        context.Response.Write(results);
    }
}

If you are already accustomed to using generic handlers to stream back images, XML, JSON data, etc, this post was probably a bore. But it’s sometimes easy to forget what’s available to imageyou in the vast .NET stack, so hopefully you appreciate the friendly reminder.  In either case, it still surprises me how many examples use the ASPX approach.  In fact, the practice is common enough that I sometimes wonder if there’s an HTTPHandler gotcha to which I’m not privy .  If I am missing something, please let me know.

If you’re still interested, attached you’ll find code which populates two jQuery Flexbox controls using JSON data provided through an ASPX and ASHX files.  This may be worthwhile download if you’re interest in the generic handler code or you want a further look at Flexbox in action after last week’s post.

Download JsonHandler Sample Project: JsonHandler.zip

C# Cache Helper Class

Do you need a quick and cache wrapper class? Here’s a static class which I included in my more recent C# web application.  You’ll notice the class uses generics to allow for some, umm, generic functionality. 

public static class CacheHelper
{
    /// <summary>
    /// Insert value into the cache using
    /// appropriate name/value pairs
    /// </summary>
    /// <typeparam name="T">Type of cached item</typeparam>
    /// <param name="o">Item to be cached</param>
    /// <param name="key">Name of item</param>
    public static void Add<T>(T o, string key) where T : class
    {
        // NOTE: Apply expiration parameters as you see fit.
        // In this example, I want an absolute 
        // timeout so changes will always be reflected 
        // at that time. Hence, the NoSlidingExpiration.  
        HttpContext.Current.Cache.Insert(
            key, 
            o, 
            null,
            DateTime.Now.AddMinutes(
                ConfigurationHelper.CacheExpirationMinutes),
            System.Web.Caching.Cache.NoSlidingExpiration);
    }

    /// <summary>
    /// Remove item from cache 
    /// </summary>
    /// <param name="key">Name of cached item</param>
    public static void Clear(string key)
    {
        HttpContext.Current.Cache.Remove(key);
    }

    /// <summary>
    /// Check for item in cache
    /// </summary>
    /// <param name="key">Name of cached item</param>
    /// <returns></returns>
    public static bool Exists(string key)
    {
        return HttpContext.Current.Cache[key] != null;
    }

    /// <summary>
    /// Retrieve cached item
    /// </summary>
    /// <typeparam name="T">Type of cached item</typeparam>
    /// <param name="key">Name of cached item</param>
    /// <returns>Cached item as type</returns>
    public static T Get<T>(string key) where T : class
    {
        try
        {
            return (T) HttpContext.Current.Cache[key];
        }
        catch
        {
            return null;
        }
    }
}

And here is a relatively standard sample usage of the library. 

public override List<Employee> GetEmployeeList()
{
    string key = ConfigurationHelper.CacheKeyEmployeeList;

    List<Employee> employees = CacheHelper.Get<List<Employee>>(key);

    if (employees == null)
    {
        employees = instance.GetEmployeeList();
        CacheHelper.Add(employees, key);
    }

    return employees;
}

Notice how I’m grabbing the cached value, storing it in a local variable and then checking if it is equal to null rather than using the CacheHelper.Exists() method.  If I used the CacheHelper.Exists() method, the cached object could expire between the time I check its existence and the time I get its value through the CacheHelper.Get() method.  Therefore, the above approach is the safest strategy to use when retrieving cached values.  CacheHelper.Exists() should really only be used for quick existence checks which are unrelated to the fetch.

But if you want to use the code CORRECTLY there’s a catch.  Did you notice the “class” constraint on the CacheHelper.Get() and CacheHelper.Add() methods?   I did this because you can’t always return null from a generic method.  If the return type were always a reference type it would be fine, but comparing a non-nullable value type to null would throw a runtime exception or would always evaluate to false.  Therefore, I’ve constrainted CacheHelper which limits its functionality but unsure safe use of the cache.  If you’re feeling dangerous, you’re welcome to remove the constraints.

I’ll update the library once I come up with a good work around.  Speaking of, any suggestions?

Let me know if you have any questions and/or this type of post is helpful.  Thanks.

UPDATE 12/10:

After further review, I’ve removed the “class” constraint from the CacheHelper.  The Get() method now follows the common Try(x, out y) pattern where x is what you wish to operate on, y is the resulting value and the method return success or failure.  Here’s a sample call:

string key = "EmployeeList";
List<Employee> employees;

if (!CacheHelper.Get(key, out employees))
{
    employees = DataAccess.GetEmployeeList();
    CacheHelper.Add(employees, key);
    Message.Text =
        "Employees not found but retrieved and added to cache for next lookup.";
}
else
{
    Message.Text = "Employees pulled from cache.";
}

And here’s the updated class.  Note, I’ve also provided a sample project for download.  Thanks for your comments!

using System;
using System.Web;

public static class CacheHelper
{
    /// <summary>
    /// Insert value into the cache using
    /// appropriate name/value pairs
    /// </summary>
    /// <typeparam name="T">Type of cached item</typeparam>
    /// <param name="o">Item to be cached</param>
    /// <param name="key">Name of item</param>
    public static void Add<T>(T o, string key) 
    {
        // NOTE: Apply expiration parameters as you see fit.
        // I typically pull from configuration file.

        // In this example, I want an absolute
        // timeout so changes will always be reflected
        // at that time. Hence, the NoSlidingExpiration.
        HttpContext.Current.Cache.Insert(
            key,
            o,
            null,
            DateTime.Now.AddMinutes(1440),
            System.Web.Caching.Cache.NoSlidingExpiration);
    }

    /// <summary>
    /// Remove item from cache
    /// </summary>
    /// <param name="key">Name of cached item</param>
    public static void Clear(string key)
    {
        HttpContext.Current.Cache.Remove(key);
    }

    /// <summary>
    /// Check for item in cache
    /// </summary>
    /// <param name="key">Name of cached item</param>
    /// <returns></returns>
    public static bool Exists(string key)
    {
        return HttpContext.Current.Cache[key] != null;
    }

    /// <summary>
    /// Retrieve cached item
    /// </summary>
    /// <typeparam name="T">Type of cached item</typeparam>
    /// <param name="key">Name of cached item</param>
    /// <param name="value">Cached value. Default(T) if 
    /// item doesn't exist.</param>
    /// <returns>Cached item as type</returns>
    public static bool Get<T>(string key, out T value) 
    {
        try
        {
            if (!Exists(key))
            {
                value = default(T);
                return false;
            }

            value =  (T) HttpContext.Current.Cache[key];
        }
        catch
        {
            value = default(T);
            return false;
        }

        return true;
    }
}

Download CacheHelper Sample Project:CacheHelperClass.zip

 

Guarding Against Multiple Empty Strings

Many of my C# methods include what is referred to as a guard clause.  It isn’t a complicated concept.  Simply the first few statements of a routine validates passed-in parameters and/or state of the object and immediately returns an error or gracefully exits to the function is constraints aren’t met.  If I’m not mistaken, this plays nicely with the Design by Contract approach to software design, but I no expect on the subject.  The bottom line is, a guard clause can really tighten and clean up your code because it will undoubtedly eliminate any number of nested conditional statements.

Consider the following sample taken directly from c2.com:

public Foo merge(Foo a, Foo b)
{
    Foo result;
    if (a != null)
    {
        if (b != null)
        {
            // complicated merge code goes here.
        }
        else
        {
            result = a;
        }
    }
    else
    {
        result = b;
    }
    return result;
}

Now with the guard clause…

public Foo merge(Foo a, Foo b)
{
    if (a == null) return b;
    if (b == null) return a;
    // complicated merge code goes here.
}

Much cleaner, eh? And that’s only two conditionals! Back to my point.  Many of my method include guard clauses.  Today I needed to validate that all three string parameters had a value.  In other words, each string’s length was greater than 0.

I started with my faithful Is-Not-Null-Or-Empty check:

string a = "a";
string b = "b";
string c = "";

if (string.IsNullOrEmpty(a) ||
    string.IsNullOrEmpty(b) ||
    string.IsNullOrEmpty(c))
    return;

But then I settled on this:

string a = "a";
string b = "b";
string c = "";

if (a.Length * b.Length * c.Length == 0) return;

What do you think?  Pretty hokey, right?

 

Export GridView to Excel within an UpdatePanel

There’s a ton of information online about exporting a DataGrid or GridView to Excel, but most variations do not consider the GridView may reside within an UpdatePanel.  It goes without saying, but I was disappointed when I recently dusted off my “Export GridView to Excel” code snippet and encountered a number of exceptions.  So I revisited a number of links and I collected a working solution.  If you need a “simple” way to export your GridView to Excel and you are using an UpdatePanel, I hope the following code finds you well:

protected void btnExport_Click(object sender, EventArgs e)
{
    // Reference your own GridView here
    if (AccountGrid.Rows.Count > 65535)
    {
        DisplayError("Export to Excel is not allowed" +
            "due to excessive number of rows.");
        return;
    }

    string filename = String.Format("Results_{0}_{1}.xls",
        DateTime.Today.Month.ToString(), DateTime.Today.Year.ToString());

    Response.Clear();
    Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);
    Response.Charset = "";

    // SetCacheability doesn't seem to make a difference (see update)
    Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);  

    Response.ContentType = "application/vnd.xls";

    System.IO.StringWriter stringWriter = new System.IO.StringWriter();
    System.Web.UI.HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);

    // Replace all gridview controls with literals
    ClearControls(AccountGrid);

    // Throws exception: Control 'ComputerGrid' of type 'GridView'
    // must be placed inside a form tag with runat=server.
    // ComputerGrid.RenderControl(htmlWrite);

    // Alternate to ComputerGrid.RenderControl above
    System.Web.UI.HtmlControls.HtmlForm form
        = new System.Web.UI.HtmlControls.HtmlForm();
    Controls.Add(form);
    form.Controls.Add(AccountGrid);
    form.RenderControl(htmlWriter);

    Response.Write(stringWriter.ToString());
    Response.End();
}

private void ClearControls(Control control)
{
    for (int i = control.Controls.Count - 1; i >= 0; i--)
    {
        ClearControls(control.Controls[i]);
    }

    if (!(control is TableCell))
    {
        if (control.GetType().GetProperty("SelectedItem") != null)
        {
            LiteralControl literal = new LiteralControl();
            control.Parent.Controls.Add(literal);
            try
            {
                literal.Text =
                    (string)control.GetType().GetProperty("SelectedItem").
                        GetValue(control, null);
            }
            catch
            {}
            control.Parent.Controls.Remove(control);
        }
        else if (control.GetType().GetProperty("Text") != null)
        {
            LiteralControl literal = new LiteralControl();
            control.Parent.Controls.Add(literal);
            literal.Text =
                (string)control.GetType().GetProperty("Text").
                    GetValue(control, null);
            control.Parent.Controls.Remove(control);
        }
    }
    return;
}
 

Update: 7/30/2008

I previously noted that SetCacheability doesn’t seem to make a difference.  Well, I was right…until I deployed my code to a site behind SSL.  As it turns out, in order for Internet Explorer to open documents in Office (or any out-of-process, ActiveX document server), Internet Explorer must save the file to the local cache directory and ask the associated application to load the file by using IPersistFile::Load.

http://support.microsoft.com/default.aspx?scid=KB;EN-US;q316431&

If the file is not stored to disk, this operation fails. When Internet Explorer communicates with a secure Web site through SSL, Internet Explorer enforces any no-cache request. If the header or headers are present, Internet Explorer does not cache the file. Consequently, Office cannot open the file.

RESOLUTION: Web sites that want to allow this type of operation should remove the no-cache header or headers. In other words, comment out the following line of code particularly if you are running under SSL:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache); 

 

Additional Comments

Per Jinath Blog, if you are using an UpdatePanel, you may get a System.WebForms.PageRequestManagerParserErrorException exception.  The solution is to add a PostBackTrigger and give it’s ControlID as the excel export button’s ID or you can move your excel export button out side of the update panel.  I verified both options and they work great.  I ultimately went with the former option as such:

    ...
    </ContentTemplate>
    <Triggers>
        <asp:PostBackTrigger ControlID="btnExport" />
    </Triggers>
</asp:UpdatePanel>
...

Per ASPAlliance, you may encounter issues a number of issues which require the following solution.  Check out the link (and the comments) for more details if you get stuck.  I only encountered #1 on the list.

  1. You may get an exception which states your Control ‘Grid’ of type ‘GridView’ must be placed inside a form tag with runat=server.  I overcame this by dynamically adding a form to the page and then the GridView to the form before RenderContent().  This solution came per the aforementioned post’s comments.
  2. You may need to included the following page directive: EnableEventValidation=”false”.  I didn’t need to include this directive.
  3. You may need Override the VerifyRenderingInServerForm Method.  I didn’t need to do so because I added my GridView control to a “mocked” form.
     

Per Dipal Choksi, one can format the spreadsheet results in a generic manner by replacing all controls within the GridView with Literals.  This is reflected in the ClearControls() method above.  My prior implementation merely cleaned up the links associated with the sort functionality tied to the sortable headers.  This solution tackles all cells.

Additional Reference: GridViewGuy 

C# Encryption / Decryption Helper Class

I have collected a reasonably good size library of C# helper files over the years.  The EncryptionHelper below is one of many which I plan to share.

using System;
using System.Security.Cryptography;
using System.Text;

namespace Common
{
    public static class EncryptionHelper
    {
        private const string cryptoKey = "cryptoKey";

        // The Initialization Vector for the DES encryption routine
        private static readonly byte[] IV =
            new byte[8] { 240, 3, 45, 29, 0, 76, 173, 59 };

        /// <summary>
        /// Encrypts provided string parameter
        /// </summary>
        public static string Encrypt(string s)
        {
            if (s == null || s.Length == 0) return string.Empty;

            string result = string.Empty;

            try
            {
                byte[] buffer = Encoding.ASCII.GetBytes(s);

                TripleDESCryptoServiceProvider des =
                    new TripleDESCryptoServiceProvider();

                MD5CryptoServiceProvider MD5 =
                    new MD5CryptoServiceProvider();

                des.Key =
                    MD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(cryptoKey));

                des.IV = IV;
                result = Convert.ToBase64String(
                    des.CreateEncryptor().TransformFinalBlock(
                        buffer, 0, buffer.Length));
            }
            catch
            {
                throw;
            }

            return result;
        }

        /// <summary>
        /// Decrypts provided string parameter
        /// </summary>
        public static string Decrypt(string s)
        {
            if (s == null || s.Length == 0) return string.Empty;

            string result = string.Empty;

            try
            {
                byte[] buffer = Convert.FromBase64String(s);

                TripleDESCryptoServiceProvider des =
                    new TripleDESCryptoServiceProvider();

                MD5CryptoServiceProvider MD5 =
                    new MD5CryptoServiceProvider();

                des.Key =
                    MD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(cryptoKey));

                des.IV = IV;

                result = Encoding.ASCII.GetString(
                    des.CreateDecryptor().TransformFinalBlock(
                    buffer, 0, buffer.Length));
            }
            catch
            {
                throw;
            }

            return result;
        }
    }
}

You may have noticed that my recent posts have been short and provide little more than featured code.   This is a new approach for me.  What do you think?  Should I continue to pepper in these quick code snippet posts with little commentary?

 

Check Status of Windows Service

In the same vein as my last post on how to programmatically update a service startup type, here’s how one might determine if a service is currently stopped in C#:

using System.Management;
/// <summary>
/// This routine checks if the provided service is stopped.
/// </summary>
/// <param name="serviceName">Name of the service to be checked</param>
/// <param name="errorMsg">If applicable, error message assoicated with exception</param>
/// <returns>Stopped = true else false</returns>
public static bool IsServiceStopped(string serviceName, out string errorMsg)
{
    bool isStopped = false;
    errorMsg = string.Empty;

    string filter =
        String.Format("SELECT * FROM Win32_Service WHERE Name = '{0}'", serviceName);

    ManagementObjectSearcher query = new ManagementObjectSearcher(filter);

    // No match = stopped
    if (query == null) return false;

    try
    {
        ManagementObjectCollection services = query.Get();

        foreach (ManagementObject service in services)
        {
            string currentStatus = Convert.ToString(service["State"]);
            isStopped = (currentStatus.ToLower() == "stopped");
        }
    }
    catch (Exception ex)
    {
        errorMsg = ex.Message;
        throw;
    }

    return isStopped;
}