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: https://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

  • Anonymous
    June 17, 2008
    The comment has been removed

  • Anonymous
    June 25, 2008
    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

  • Anonymous
    August 12, 2008
    i cannot access the widget from another domain. any ideas?

  • Anonymous
    August 21, 2008
    The comment has been removed

  • Anonymous
    September 08, 2008
    The comment has been removed

  • Anonymous
    September 08, 2008
    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!

  • Anonymous
    October 13, 2008
    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)?

  • Anonymous
    October 13, 2008
    The comment has been removed

  • Anonymous
    November 25, 2008
    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

  • Anonymous
    December 08, 2008
    The comment has been removed

  • Anonymous
    December 10, 2008
    The comment has been removed

  • Anonymous
    January 02, 2009
    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
  • Anonymous
    January 04, 2009
    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

  • Anonymous
    January 09, 2009
    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.

  • Anonymous
    January 09, 2009
    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.
  • Anonymous
    May 18, 2009
    Thank you very much, that exactly what I was searching for :)

  • Anonymous
    June 29, 2009
    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

  • Anonymous
    September 16, 2009
    The comment has been removed

  • Anonymous
    November 03, 2009
    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
  • Anonymous
    August 02, 2011
    eventswidget.jss is missing..??

  • Anonymous
    June 11, 2014
    HI Can anyone provide me with running source code as the link which given it not hhaving downloaded source code init.. -Amit