Web Widgets with .Net : Part One


Web Widgets with .Net : Part One


This two part article is based on a presentation I gave at Tech Ed North America, Developers Week, 2008, about using .Net to create Web Widgets for the MSDN and TechNet sites. Part one will cover the creation of a basic widget, written in C# and JavaScript. Part two will update that widget to be more dynamic using C#, LINQ, JavaScript, JSON (JavaScript Simple Object Notation), and CSS.


Web Widgets : A Simple Definition


The best place to start is to give you a definition of Web Widgets. From Wikipedia.org, the following is a good description: “(a web widget) is a portable chunk of code that can be installed and executed within any separate HTML-based web page by an end user without requiring additional compilation.”


The basic idea is that a consumer site only needs to deploy a simple script block which requires no compilation. We achieve this by setting the script block’s source (src) parameter to a Uri on a separate widget host server. All server side processing is done on the host server, which sends back client-side script to render the widget on the consumer. There are probably hundreds of possible ways to build a Web Widget, but I’m going to walk through one specific example using .Net.


Typically, Web Widgets can be consumed on any domain outside the host domain. However, Browser Cookie data is available in the Request if in the widget is deployed within the same domain as it is hosted. Additionally, Request information such as Server Variables and QueryString are available in any domain.


Let’s Write Some Code :  A Basic Widget using an HttpHandler


Now that we’ve covered some background about what we are building, let’s get to work. As I mentioned before, we are going to be using C# and JavaScript to build this. You could really use any .Net language for the Middle-Tier, but I found that the syntactical similarities between JavaScript and C# made switching gears between the two tiers a bit less jarring.


The code for this first example can be downloaded here:  http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=webwidgetsdotnet&DownloadId=2330


 


Step 1 : Create an HttpHandler Base Class for all widgets to use.


First, let’s create a base class that can be used for multiple widgets. It will handle the basic functionality of an HttpHandler. Note: I chose to use an HttpHandler here in order to avoid the overhead of the ASP.Net Lifecycle. There is no need in this pattern to use Viewstate, Page Events, or Postbacks, so I can avoid all the unnecessary overhead by using an HttpHandler.


1)      Create a new Visual Studio C# Web Project and call it “Demo1”


2)      Add a new directory called Handlers and add a WidgetBase.cs class file inside this folder. Mark that class as abstract since it will be our base class.


3)      Implement the IHttpHandler interface


4)      Using the VS2008 IntelliSense context menu, stub out the required members for an HttpHandler


 


 



 


 


 


 


 


This will add the following interface members…


IsReusable - property to let IIS know whether this handler can be re-used by other threads.


ProcessRequest(HttpContext context)- The main method of a handler. This is where we will do the work to write a response to the browser.


5)      Set IsReusable to return false to ensure thread safety – We don’t want any other requests to come in and modify variables


6)      Add null reference checks to ProcessRequest, to avoid null reference exceptions


if (context != null && context.Request != null && context.Response != null)


{


 


} 


7)      Add an abstract BuildOutput() method that returns a string. We want to force inheritors to use this method.


 


    public abstract string BuildOutput();


8)      Add a member variable to hold a reference to the HttpContext object that is passed into ProcessRequest


   


    private HttpContext _context;


 


9)      Response.Write the results of BuildOutput in ProcessRequest, using the Response object in the _context member variable just added in step 8.


   


                _context = context;


                _context.Response.Write(BuildOutput());


 


10)  Add Request and Response shortcuts, using _context member variable. We will be using these shortcuts later, in the widgets that use this base class.


/// <summary>


/// Shortcut to Request object


/// </summary>


public HttpResponse Response


{


    get { return _context.Response; }


}


 


/// <summary>


/// Shortcut to Request object


/// </summary>


public HttpRequest Request


{


    get { return _context.Request; }


}


That is all the work we need to do in WidgetBase for now. Let’s move on to create a object of type WidgetBase.


Step 2 : Create an EventsWidget class and wire up the handler in IIS


1)      Add a new class file called EventsWidget.cs to the Handlers directory


2)      Implement the WidgetBase class and stub out the BuildOutput method using the handy VS2008 Intellisense dropdown


3)      Create and return a string called “output” in the BuildOutput method and initialize it to the common “Hello World!” value, since this is the first time we’ll run this application.


public override string BuildOutput()


{


    string output = "Hello World!";


    return output;


}


4)      Open an IIS Management Console and navigate down the application you are running this project in. (Create an application if you haven’t already)


5)      In the application configuration features view, look for the “Handler Mappings” feature and double click it to see a list of existing handlers.


6)      In the “Actions” area of this view, click the link to “Add Managed Handler”


7)      Set up the new Managed Handler similar to the settings below.


 


Managed Handler Screenshot



 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


Request Path: eventswidget.jss


Type: Demo1.Handlers.EventsWidget


Name: EventsWidget


 


8)      The handler should be ready to run now, so let’s check it in a browser. Open up your favorite browser and navigate to the application you’ve been working in. Add the request path you created in step 7 above to the URI to hit the handler you’ve created. You should see a friendly “Hello World!” message on the screen.


Step 3 : Modify the HttpHandler to output JavaScript


1)      Add a new directory called “templates” to hold script templates, and add a new file called core.js. This file will be used as a utility class to hold functions common to widgets.


2)      Open /templates/core.js and add the following code to setup a namespace, constructor, and class definition for an object called Core. (Note: you should modify the namespace to match your own company or team)


 


/** Microsoft.Com.SyndicationDemo.Core.js: shared functionality for widgets **/


 


// Namespace definition : All Widget Classes should be created in this namespace  //


if (!window.Microsoft)


  window.Microsoft = {};


 


if (!Microsoft.Com)


  Microsoft.Com = {};


 


if (!Microsoft.Com.SyndicationDemo)


  Microsoft.Com.SyndicationDemo = {};


 


// Widget Core Constructor //


Microsoft.Com.SyndicationDemo.Core = function(message)


{


     document.write(message);


}


 


// Widget Core Class Definition //


Microsoft.Com.SyndicationDemo.Core.prototype =


{


 


}  


 


var core = Microsoft.Com.SyndicationDemo.Core("Hello from JS!");


 


The above JavaScript code is using a feature of the JavaScript language to create a class definition, called Prototype-based Programming. When we “new” up a version of this Core object, it will run the code in the constructor and write out a message via JavaScript.


3)      Add a method to WidgetBase which will allow us to read the contents of the JavaScript file we just created. Modify WidgetBase.cs by adding the following method:


        public string ReadFromFile(string fileName)


        {


            string fileContents = string.Empty;


 


            if (HttpContext.Current.Cache[fileName] == null)


            {


                string filePath = HttpContext.Current.Server.MapPath(fileName);


 


                if (File.Exists(filePath))


                {


                    StreamReader reader;


 


                    using (reader = File.OpenText(filePath))


                    {


                        fileContents = reader.ReadToEnd();


                    }


                }


 


                HttpContext.Current.Cache.Insert(fileName, fileContents, new System.Web.Caching.CacheDependency(filePath));


            }


            else


            {


                fileContents = (string)HttpContext.Current.Cache[fileName];


            }


 


            return fileContents;


        }


4)      Modify EventsWidget.cs to read the JavaScript file using the method we just created.  Change the content of the BuildOutput() method to the following:


string output = base.ReadFromFile(ConfigurationSettings.AppSettings["CoreJavascriptFileName"]);


return output;


5)      Lastly, lets hook up this handler in a script block so that it actually runs in a script context. Add a new file called default.aspx to the root of the application. This file will serve as a test harness for our widgets. Add the following script block to the new page:


<script type="text/javascript" src="eventswidget.jss">


        </script>


6)      At this point, we can now hit the new default.aspx in the browser. It should display a friendly message from JavaScript. If you do not see any message, try hitting the handler directly to see if it is throwing an error.


In part two of this article, I will use this project as a starting point and make it dynamic. Part two will cover accessing data, passing data to JavaScript, and working with Styles via CSS.

Comments (21)
  1. Introduction This article is a continuation of an article about Web Widgets posted previously here: http://blogs.msdn.com/pajohn/archive/2008/06/18/web-widgets-with-net-part-one.aspx

  2. newbie says:

    i cannot access the widget from another domain. any ideas?

  3. Pat Crabtree says:

    Which version of IIS are you using? I don’t see the Add Managed Handler dialog box in the Microsoft Management Console version 3.0.

    Thanks,

    pcrabtree@raritantechnologies.com

  4. pajohn says:

    Crabtree,

    I am using IIS 7.0. The "Add Managed Handler" feature was not included in IIS 6.0. Try the following steps to find the feature.

    1) Using MMC snap-in for IIS 7.0, click on the site or application you want to manage. This will display a list of features that you can manage, grouped by area (ASP.NET, IIS, Management).

    2) Look in the IIS area for a feature called "Handler Mappings" and double click on it. This will take you to the "Handler Mappings" management feature. The main window displays a list of existing mappings, and the right pane displays a list of Actions you can take.

    3) In the right pane, look for "Add Managed Handler" link and click on it. This will open the feature’s dialog box, where you can follow the rest of the steps listed in my post above. You can also access this feature by right-clicking anywhere in the list of existing mappings.

    Hope that helps!

  5. pajohn says:

    Newbie,

    Can you provide any more information about the problem? Are you able to see any errors that might help me troubleshoot the issue?

    Also, you might try tools like Fiddler, httpWatch, or Firebug to see if there are networking or script errors with your widget. These types of debugging tools are absolutely invaluable when working with widgets!

  6. Nissan says:

    Great article!

    One question though,

    Is there any way to deploy/implement a .NET based widget with IIS 6.0 (which doesn’t have a managed handlers option of IIS 7.0 Mgt Console)?

  7. pajohn says:

    Nissan,

    I haven’t hooked this project up on an IIS 6.0 server, but you should be able to do the following to add an HttpHandler in IIS 6. The config setting for the Handlers in IIS 6.0 are stored in a different web.config section, see below…

    <system.web>

    <httpHandlers>

    <add verb="GET,HEAD" path="eventswidget.jss" type="Demo1.Handlers.WidgetBase, Demo1" validate="false" />

    </httpHandlers>

    </system.web>

    Please comment back if this doesn’t work for you!

  8. Romi says:

    Hi Paul,

    Thanks for this share this work. Could you help me plz. I tried to use in net2 using one external Json.net library. My problem is not this, but after full compiling with no errors and tried I have one error during use like: abstract class not well formed in WidgetBase Demo1, same problem in Demo2 in C#2005. I have controled many times and verify definition of abstract classes but nothing. Some suggestion. Regards

  9. Nissan says:

    Hey Paul,

    I implemented the recommendation you posted, and while it worked fine on my VS 2008 development environment, once I checked in my changes and it built to the Windows 2003 Server testing box it resulted in a "The page cannot be found" error when trying to reference the eventswidget.jss file.

    Now to be honest my dev box is Vista not XP but I am debugging in VS 2008 Pro so it should have worked once deployed to the 2003 server running IIS 6.0 since it executed the web.config changes successfully to render the page on the VS 2008 internal web server.

    Any ideas on next steps to troubleshooting this error?

  10. pajohn says:

    Hi Nissan,

    If you deploy to IIS 6.0, the web.config file will store the httpHandlers in a different section. This would cause you to get the 404 error. Please try the following.

    <system.web>

    <httpHandlers>

    <add verb="GET,HEAD" path="eventswidget.jss" type="Demo1.Handlers.WidgetBase, Demo1" validate="false" />

    </httpHandlers>

    </system.web>

  11. Amit Gautam says:

    Hi Paul,

    I was just wandering if i could create some web widgets (using VS 2005/2008, C#).  The code is superb and i could create and add my own widget to my local sample application.

    However, I have few questions…

    1. Do I need Scripts to make the widgets work?

    2. Is there any mechanism provided by ASP.NET to build widgets?

    3. Is there any tool which could emit Javascript for me?

    4. Can I use AJAX to create widgets?

    It’ll be very grateful if you throw some light on the questions i have.

    Regards,

    Amit Gautam

  12. Ramesh says:

    Hi Paul,

    I am unable to download the code from the given link…i get a server error. Is there any other way i can get the code.

    Thanks

  13. pajohn says:

    Ramesh,

    Please give that link another try. I think you may have hit a temporary error on the Code Gallery site. I don’t have the code hosted anywhere else, so hopefully that link will work for you the second time. If not, please let me know and I will see what I can do.

  14. pajohn says:

    Amit,

    I’ll attempt to answer your questions inline below…

    1. Do I need Scripts to make the widgets work?

    In the scenario I’ve demonstrated, yes. There are many ways to make widgets thoough, and you could conceivably find a way to just inject HTML into the consuming page without using JavaScript. Try searching for other widgets on the web and you will find other technologies used to achieve the same purpose.

    2. Is there any mechanism provided by ASP.NET to build widgets?

    With ASP.Net MVC framework and jQuery you could create widgets. I am looking into writing a part 3 of this article using ASP.Net MVC and jQuery.

    3. Is there any tool which could emit Javascript for me?

    Look into script#. Also, if you are shy about JavaScript, the jQuery library can provide a much easier way for you to utilize the language with the huge learning curve.

    4. Can I use AJAX to create widgets?

    Yes, and you could use Ajax to load data into widgets as well. I was attempting to create a one-request widget with this article, so I avoided making additional Http calls via Ajax. If you use the ASP.Net Ajax library, you need to ensure the consuming site also uses this technology.

  15. Dev The Web says:

    Thank you very much, that exactly what I was searching for 🙂

  16. MattH says:

    I’m trying this in VB (.Net 2.0) and IIS6 and I just get a blank page.  I’m guessing the mapping is incorrect, but I’ve added the web.config entry.  Is there anything else for IIS6?  Do you have to modify the file mappings in IIS to handle "jss"?

    Thanks,

    Matt

  17. Shool says:

    Hi Paul,

    I am learning step by step through this wonderful article of yours.

    I am now at step 2 point 8. I do not understand what you mean by getting the URI of eventswidget.jss

    I have iis 5.0 installed so i couldn’t get to the MMC to change the Handlers Request Path. Instead I opened up the "web.config" file in vs 2008 and edited it to look like this

    <httpHandlers>

    <add verb="GET,HEAD" path="eventswidget.jss" type="Demo1.Handlers.WidgetBase,Demo1" validate="false"/>

    </httpHandlers>

    How to run the handler? Please give detailed instructions as I am quite new to programming in the windows environment.

  18. CharityJob says:

    Hi Paul

    I am having trouble getting the widget to work in IE6 and IE7. It works fine on Firefox.

    Here is the link to the widget implementation.

    Can you tell me what is wrong?

    TIA

    – CharityJob

  19. eventswidget.jss is missing..??

  20. amits78 says:

    HI

    Can anyone provide me with running source code as the link which given it not hhaving downloaded source code init..

    -Amit

Comments are closed.

Skip to main content