共用方式為


Web Widgets with .Net : Part Two

Introduction

This is a continuation of an article about Web Widgets posted previously here.

This article builds upon concepts learned in the first article, so if you haven’t read it, I recommend you start there. It walked through the basic steps to create an HttpHandler to output JavaScript. Here, I will continue with that concept and build upon it by making a dynamic, data-driven, Web Widget.

The full working VS project with code examples for this article can be downloaded here:

https://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=webwidgetsdotnet&DownloadId=2331

The Base project to start with this in this article can be downloaded here:

https://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=webwidgetsdotnet&DownloadId=2407

Events Widget Background

The purpose of the widget we are going to build is to display Developer and IT Pro Events from a data store. The events will be displayed as a list of hyperlinks that will take the user to more details about each event. This is similar to a web widget my group, STO (Server and Tools Online) built for MSDN and TechNet in 2007. This widget displayed events (Live Events, Webcasts, etc) for Developers and IT Pros, targeted towards their interests. The widget has since been replaced, during the latest upgrades to the sites, but a screenshot is below so you can get an idea. Note, the Data Access Layer used in my demo projects is returning example data.

https://i283.photobucket.com/albums/kk303/pajohnms/eventswidgetscreenshot3.jpg

Step 1 : Make it Data-Driven

If you look in the “Demo2 Start Here” project, you will see some new directories and files have been added since Demo1. First, notice the Data directory which contains two csharp files, DAL.cs and Event.cs. This is a very basic Data Access Layer which we’ll use to get example data to pass to JavaScript. Also notice that Core.js file has several functions added. These functions are used to create various controls, tags, event handlers, and to attach scripts.

1) Open up the “Demo2 Start Here” project and navigate to the files in the Data directory.

2) If you open /Data/Event.cs, you will notice the following attributes in the file:

[DataContract] attribute applied to the class

[DataMember] attribute applied to each property in the class

These attributes are what makes this class serializable. We will be serializing the Event Data to a format that JavaScript can use, called JSON. JSON stands for JavaScript Simple Object Notation, and is a simple way to define data structures in JavaScript. The DAL.cs file is our Data Access Layer, and simply has one method in it that will return a generic list of example Events.

3) Navigate to /Templates/Core.js and walk through the methods I’ve added here. We will use these methods in /Templates/EventsWidget.js to create controls, attach scripts, and stylesheets.

4) Navigate to /Templates/EventsWidget.js and notice the code that already exists here. I have created an EventsWidget object, and gave it two methods. We will be calling the render method at runtime to render the widget to the page.

5) Now to write some code. Open up Handlers/EventsWidget.cs. Add the following line to BuildOutput() method to access the DAL.

List<Event> eventData = DAL.GetData(5);

 

6) Next, open up Handlers/WidgetBase.cs. Add the following method, which we’ll use to serialize our Data to JSON format.

 

public string SerializeToJson(object obj)

{

var serializer = new DataContractJsonSerializer(obj.GetType());

using (var stream = new MemoryStream())

{

serializer.WriteObject(stream, obj);

return Encoding.Default.GetString(stream.ToArray());

}

}

This code uses a great feature of .Net 3.5, the DataContractJsonSerializer, which makes the job of serializing to JSON a snap.

6) Jump back over to EventsWidget.cs. Now we can serialize our data and pass it into the JavaScript template. Add the following lines below your GetData() call in BuildOutput().

            string eventJsonData = base.SerializeToJson(eventData);

            string placeholder = ConfigurationSettings.AppSettings["EventDataPlaceholder"];

      output = output.Replace(placeholder, eventJsonData);

7) Notice the following config setting in web.config. This creates a string that we will use as a placeholder for the data in our JavaScript file.

   <add key="EventDataPlaceholder" value="{eventData:placeholder}"/>

8) Open up Templates/EventsWidget.js and add the following line to the constructor.

this.eventData = {eventData:placeholder};

This variable’s value will be replaced at runtime by the code we added in step 6. Then you can see that this variable gets passed into core.createHyperlinkList(), which loops through the data and creates a unordered list of hyperlinks.

9) Now that we’ve got data passed into our object, we can call the render method to display the widget. Add the following line to /Templates/EventsWidget.js at the very bottom of the file.

ev_w.render();

            10) At this point, you can hit this in a browser. You should see a list of 5 hyperlinks from the event data, but they will be unstyled at this point. Next, I’m going to walk through adding a configuration setting to the querystring and adding a stylesheet.

Step 2 : Make it Configurable

Now I’m going to give adopters a way to configure the output of the widget on their site. The easiest thing to configure will be the amount of events to display. It seems quite feasible as an option adopters might want. I want them to be able to configure this in the script block they deploy, so the configuration variable will be sent in the querystring. Let’s start by modifying the middle-tier to accept this parameter.

1) Open /Handlers/EventsWidget.cs

2) Add a private member variable to hold the value for top number of events to display. Add the following line to the top of the class.

private int _topN;

3) Add the following method to the class to take the parameter out of the querystring and set the member variable we just added.

        private void GetRequestParameters()

        {

            _topN = 5;

            if (!string.IsNullOrEmpty(Request.QueryString["topN"]))

            {

               if (!int.TryParse(Request.QueryString["topN"], out _topN))

                    _topN = 5;

            }

        }

4) Reference the method we just added and change the hard-coded 5 value in GetData(5) to GetData(_topN). On the first line of BuildOutput(), add the following line.

GetRequestParameters();

5) Last, let’s add the parameter to the querystring in the script block. I’m going to change the value to 3, so we can tell it’s different from the previous 5 we were displaying.

        <script type="text/javascript"

            src="eventswidget.jss?topN=3" >

        </script>

6) Now, hit the widget again in a browser. You should now see 3 events listed (or whatever number you pass in).

Step 3 : Make It Pretty with CSS

Now, we’re going to attach a StyleSheet so that it looks a little better. You probably noticed I’ve been adding CSS class names on several elements in the JavaScript code. There is a stylesheet in the project that contains those classes, and now we’ll hook that up.

One important thing to note; when attaching objects such as other scripts, stylesheets, images, etc, you need to use the absolute path to those objects, since they are going to live on your host server. I have created a way to pass in a path from the middle-tier to the client-side tier, so that this doesn’t have to be configured separately for different deployments.

1) Add the widget path data in the middle tier. Open /Handlers/WidgetBase.cs and add the following to the ProcessRequest method. This will replace a placeholder value in core.js to give us the application path on our server.

                string widgetPathPlaceholder = ConfigurationSettings.AppSettings["WidgetPathPlaceholder"];

                if (output.IndexOf(widgetPathPlaceholder, 0) > -1)

                {

                 output = output.Replace(widgetPathPlaceholder, Request.Url.GetLeftPart(UriPartial.Authority) + HttpRuntime.AppDomainAppVirtualPath);

                }

2) Open /Templates/Core.js and add the following line to the constructor.

    this.widgetPath = '{widgetPath:placeholder}';

Now, we have a widgetPath property we can use in any widget for attaching scripts, stylesheets, etc.

3) Open /Templates/EventsWidget.js and add the following line inside the render method.

core.attachStyleSheet(core.widgetPath + '/styles/main.css', 'eventsStyle');

This will call the attachStylesheet method in our Core object and pass in the widgetpath parameter we created. This method adds our stylesheet into the head element of the adopters HTML page.

4) View your widget in a browser. The classes from the stylesheet should be applied and it should have a more appealing look and feel.

 

Note; an adopter now has a default style for the widget, but with CSS they would also have the freedom to modify the style by creating more specific styles for these elements.

Now you have learned a way to create a web widget, using C# middle-tier, and JavaScript client-tier. This useful approach allows rich and easy content syndication that you can now put to use. It is a very powerful technique, and is also fun to build. I personally really enjoy working on a project that encompasses this many techniques, languages and technologies. It keeps development interesting and makes it fun. Enjoy.