Wednesday, May 9, 2012

Creating JavaScript widget in ASP.Net

Widgets are generally used to insert small functionality on other websites. These are small JavaScript snippets which creates controls on the page where you will insert the script. They can interact with the target page and they can also detect the URL from which it is called. So they can used for various purposes. I happened to create a JavaScript widget and would like share an easy way of doing it in ASP.Net.

Basics:
To create a widget the very first thing you need to create is a file which when inserted as a script on the target page will run some javascript on that page and will create some controls. You can do it by creating a .js file on your server. But I prefer using HTTP handlers. The benefits of using HTTP handlers over .js file is it is easy to interact with database in the handler file and accordingly the widget can be modified.

Step 1:
To create a widget add a HTTP handler file to your project(lets say create a new folder named widget in your website and add it under that. That way its easier to manage resources for that.)
Lets say we added the file MyWidget.ashx under widget folder. Now when you create this file it will look something like this


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

using System;
using System.Web;

public class MyWidget : IHttpHandler {
   
    public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "text/plain";
        context.Response.Write("Hello World");
    }

    public bool IsReusable {
        get {
            return false;
        }
    }

}

For HTTP handlers there are no XML files. Only a code file. Now we only need to deal with the first method ProcessRequest (HttpContext context). If you see the first line of code in the method, it specifies the ContentType. We dont need to touch that since this is going to output plain text which will behave as javascript code. Now if you look at the next line context.Response.Write("Hello World"); this is the function we will deal with to output our JS code from this file.
Now we need to write JS code in this file to output it. Lets say we need to give a small bar which will allow user to Like the target page on facebook or +1 it on google or tweet it. For all these functionality lets create a page called WidgetCall.aspx. This is a usual ASPX page where you can put your code for whatever functionality you want. I would leave this to the users to design it.
Now we need to write a JS to show this page as a widget. To do this I will be using document.write() function of JS. Look at the my code below:

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

using System;
using System.Web;

public class MyWidget : IHttpHandler {
   
    public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "text/plain";
        context.Response.Write("document.write('<div style=\"position: fixed; top: 20%; right: 0px; width: 70px; height: 500px; background-color: transparent;\" id=\"divMyMyWidget\">" +
        "<iframe src=\"http://www.mydomain.com/widget/WidgetCall.aspx\" width=\"100%\" height=\"480px\" scrolling=\"no\" frameborder=\"0\" id=\"frameMyWidget\" name=\"frameMyWidget\"></iframe>" +
        "</div>')");
    }

    public bool IsReusable {
        get {
            return false;
        }
    }

}


What I am doing over here is I removed the context.Response.Write("Hello World"); line and added the line above so that when this handler is called the text in context.Response.Write() will be written. Now let me explain what I am trying to output from this handler file. Its pretty simple. I am just trying to output a JS command called document.write to the existing html on the target site. In document.write I am creating a div and assigning its position to fixed and then giving the position from top as 20% and right as 0px. This will make sure the widget sticks to the right. also for my widget I have defined the width and height as 70px by 500px. Again you can customize it according to your requirements.

Now Inside my div I am including an iframe which will call the page I made for the widget functionality. Remember you have to specify the full URL of the widget including your domain name because it is going to be inserted in different website. As you can see I have customized the iframe according to my requirements.
So this is the only thing we need to do to create the widget. As you see since you call your C# classes in this handler file so it becomes easy to control the widget and also you can pass arguments while calling the widget. Also the content to output to as a JS can also be stored in a separate file and can be just retrieved here and passed it in the context.Response.Write() method.

Now just upload the file to your server and run it from the browser. It should give something like this in your browser:
document.write('<div style="position: fixed; top: 20%; right: 0px; width: 70px; height: 500px; background-color: transparent;" id="divMyMyWidget"><iframe src="http://www.mydomain.com/widget/WidgetCall.aspx" width="100%" height="480px" scrolling="no" frameborder="0" id="frameMyWidget" name="frameMyWidget"></iframe></div>')



Step 2:
Now the next step is to create a snippet which needs to be inserted into the other website. Now since this file is outputting nothing but javascript, you can call this in a simple script tag. It should look something like this:

<script type="text/javascript" src="http://www.mydomain.com/widget/MyWidget.ashx?argument1=value"></script>

So in the above snippet you just need to call your handler file and if you want to pass any querystring parameters you can pass it along with the URL. I have given the example with querystring above. Again remember since this is going on some other website you have to give the full URL of the file. Now when this snippet is put on a website it writes the JS we defined in the HTTP handler file as a javascript on that page and creates a div widget on the target page.


Column wise GridView

Ever been in a situation where you had to represnted data in GridView where entries will be column wise.
For example if you queried the database and populated the GridView like this:

ID  Name  Age
1   John      20
2   Mark     30

And you had to represent it as:

ID          1         2
Name     John    Mark
Age        20       30

This format is generally used when you are displaying comparison data. The standard ASP.Net gridview doesnt give this functionality by default. But you can do it by querying the data in original format in a datatable and then transposing it and then assigning it to gridview. I have done it by writing this function:


public static DataTable TransposeDataTable(DataTable dt)
    {
        DataTable dtNew = new DataTable();
        for (int i = 0; i < dt.Rows.Count + 1; i++)
        {
            dtNew.Columns.Add(i.ToString());
        }
        for (int i = 0; i < dt.Columns.Count; i++)
        {
            DataRow dr = dtNew.NewRow();
            dtNew.Rows.Add(dr);
            dr[0] = dt.Columns[i].ColumnName;
        }
        for (int i = 0; i < dtNew.Rows.Count; i++)
        {
            for (int j = 1; j < dtNew.Columns.Count; j++)
            {
                dtNew.Rows[i][j] = dt.Rows[j - 1][i];
            }
        }
        return dtNew;
    }

This will return the following datatable for the above example:

0            1         2
ID          1         2
Name     John    Mark
Age        20       30

Here I am creating the header of the datatable with numbers starting from 0. Since you dont need header for this kind of data representation in gridview you can assign it to the gridview and just set the 'ShowHeader' property of gridview to false.