Archive

Posts Tagged ‘RSS’

Creating a Webservice Proxy with jQuery

August 2, 2009 23 comments

Contents

Introduction

In a previous post I’ve shown how to use WCF, jQuery and jTemplates to retrieve information from the server and lay it out on the page using jTemplates’ templating engine.

The code example in that article used the Microsoft Ajax client library and the proxy it creates at run time to ease the javascript code needed to call the methods of the webservice I created.

In this article I would like to show you an easy way of creating a similar proxy to the Microsoft one in pure javascript and the help of jQuery’s AJAX capabilities. This makes a lot of sense if you do not have the option to use the MS library on the client or simply because you don’t want to.
I will be relying mostly on the code examples and concepts I described in the previous article  so I’d recommend reading it first before continuing to read this one.

You can let me know if you find this article useful or not by using the ratings and comments below.

Server Side

The good news: no need to change anything on the server side, the web service can continue to work as it always did. All we’re doing in this exercise is to replace the client side logic and so we will not touch the server code.

Client Side

Using the same website I’ve shown how to create in the previous article we will create the new proxy for our WCF webservice.
In the System folder create a javascript file and call it ServiceProxy.js, To the file add the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
ServiceProxy = function() //constructor for the proxy
{
  this._baseURL = "Services/TutorialService.svc/";
};

ServiceProxy.prototype =
{
  _defaultErrorHandler: function(xhr, status, error)
  {
    alert(xhr.statusText);
  },

  _doAjax: function(method, data, fnSuccess, fnError)
  {
    if (!data) data = {};

    if (!fnError) fnError = this._defaultErrorHandler;

    $.ajax({
      type: "GET",
      url: this._baseURL + method,
      data: data,
      contentType: "application/json; charset=utf-8",
      dataType: "json",
      success: fnSuccess,
      error: fnError,
      dataFilter: function(data)
          {
            var response;

            if (typeof (JSON) !== "undefined" && typeof (JSON.parse) === "function")
              response = JSON.parse(data);
            else
              response = val("(" + data + ")");

            if (response.hasOwnProperty("d"))
              return response.d;
            else
              return response;
          }
    });
  }
};

Lets examine the code:

The first section is the constructor of the proxy object, in there we define the base URL of the service we will be calling.

The second method is _defaultErrorHandler, this is a default error handler, its strictly a developer friendly method, allowing the calling method to leave the pointer to an error handling method empty. Of course the implementation of this default error handler should be changed in a real life scenario as its not wise to show any raw error information to a website’s visitor.

The third and most important method is _doAjax, this is where the “magic” happens which takes care of the back and forward communication with the server.

The first two lines take care of the defaults, if there is no data passed to the webservice we assign an empty object and if there is no pointer supplied to an error handler we assign our default method.

Next is the where we use jQuery’s incredibly convenient Ajax method, lets examine this call, jQuery’s ajax method accepts an object that sets all the needed information:

‘type’: The HTTP verb: could be GET, POST, etc. In this example we use GET since we’re only retrieving from the server.
For a more robust scenario we would probably want to turn this into a parameter of the method.

‘url’: The URL of the webservice method, in this case the base URL defined in the constructor and the name of the method.

‘data’: The parameters passed to the service method, constructed as a JSON object.

‘contentType’: the content type of the data being sent to the server. In our case we’re communicating with the webservice using JSON and therefore we use: “application/json; charset=utf-8”

‘success’: A pointer to the method to be called when the asynchronous call has finished successfully.

‘error’: A pointer to the method to be called when the asynchronous call finished with an error.

‘dataFilter’: I’ve taken the code block in this example from Dave Ward’s Encosia blog. I will add the links to a couple of his articles at the end of this post.

The dataFilter is used whenever there is a successful response from the server and allows us to modify the response in any way we like before its passed to the success method.

In this example there are two uses to the filter: The first one is to turn the response into a JSON object from the string result coming from the server. It will first check whether the current browser supports JSON parsing natively (Firefox 3.5, IE8 for example). If it does it will use the native JSON object and if not will use the less optimized and less secure eval() function.

The second part is to check whether the response is enclosed within a ‘d’ property, this ‘d’ property is added automatically by Microsoft’s WCF service and since we want to abstract this fact from the caller we only return the relevant response if this is the case.

Now that we have everything we need for our base proxy functionality all we need to do is add the methods that match the exposed methods on the webservice. To the prototype of the ServiceProxy object add these two methods:

1
2
3
4
5
6
7
8
9
10
11
getArticles: function(success, error)
{
  this._doAjax("GetArticles", null, success, error);
},

getArticle: function(link, success, error)
{
  var data = {link: link};

  this._doAjax("GetArticle", data, success, error)
},

These two methods call our _doAjax, passing the necessary information such as the method name and the parameters if needed to the call.

In fact the methods mirror the methods available on the webservice thus completing the proxy.

Now the only thing to do is create a HTML file (or any other file, could even be JSP) that will replace the aspx page we created in the previous article.
You can find all the source code in the example site ive made available for download, in this post I will only show the changes needed.

- First, create a default.html in the root of the site.
- In the head element add these links:

<script src=”System/jquery.js” type=”text/javascript”></script>
<script src=”System/jquery-jtemplates.js” type=”text/javascript”></script>
<script src=”System/ServiceProxy.js” type=”text/javascript”></script>
<link href=”System/Styles.css” rel=”stylesheet” type=”text/css” />

- Copy over the entire javascript element.
- Add the following code as the first line of the script to declare the proxy:

<script type="text/javascript">
    var proxy = new ServiceProxy();

- In the document ready function replace the call to the GetArticles method with this one:

1
2
3
4
$(document).ready(function() //executes this code when page loading is done
{
       proxy.getArticles(articlesRetrieved);
});

- In the loadArticle function replace the call to getArticle with this one:

1
2
3
4
5
6
7
function loadArticle(link)
{
    $("#LoadingImg").removeClass("Hidden");
    $("#SingleArticle").html("");

    proxy.getArticle(link, articleRetrieved, serviceDefaultErrorHandler);
}

That’s all! Now you have a working page doing exactly the same as it did before only using our own javascript proxy without any dependencies on the Microsoft proxy or the MS Ajax library.
The end result is as expected identical to the one before:

serviceproxy result

Source Code

Can be downloaded here.

Resources

Tying in WCF, JSON and jTemplates

June 26, 2009 5 comments

Contents

Introduction

In this post id like to show a useful way of combining a few technologies together in a way that might not be readily apparent to everyone.

Let me start by saying that I think WCF, jQuery, MS AJAX Library and jTemplates are all great each on its own, but combining all of these together can produce some amazing results in a very short time.

I won’t be concentrating too much on explaining how to work with each of the aforementioned technologies separately or dive into each of their best practices and possible appliances but rather show a concise way of using them together, there are some great articles and tutorials which ill list by the end of this article for you to go out and learn more about these subjects on your own.

Id like to apologize for the way the code fragments on this article look like, it seems that WordPress.com doesn’t support plugins so i can’t use any syntax highlighter… I’m looking into finding a host provider that will host my blog where i could install such plugins to make my technical articles look more professional, soon, i promise.

Just before we begin, a short disclaimer, The code in this article is definitely not optimized or should be taken as is, its just the essence of how you can achieve this type of result.

This article assumes the reader has previous experience working with WCF, javascript and AJAX.

Now we can begin…

Concept

The purpose of this article is to show how to create a service end-point using WCF which can be called from the client-side using JavaScript to retrieve data in JSON format and update parts of the page without causing a full post-back to the server.

I wont go into the discussion of why you would want to use AJAX instead of post-backs, there’s plenty of articles about that. I wont go into the discussion of the merits of JSON either, you can read about it here.

For demonstration purposes I decided to build a very simple “RSS Reader” which will poll on the feed from one of my favorite podcasts: The 404, it will present a list of the articles titles in the feed and allow the user to select any from that list to view its entire information.

So lets get to some coding already…

Server Side

We’ll start with the server side where we will create the WCF service and write some methods to get the RSS content.

First thing first though, lets create our website, in Visual Studio (im using 2008 SP1) create a new ASP.NET website and then:

  • Create a new folder called “Services”.
  • Right-click the new folder and select ‘Add New Item’, Select ‘Ajax-Enabled WCF Service’ and name it “TutorialService”, then click Add.

You will notice that you now have an “App_Code” folder with one class and in the Services folder you have a svc file.

Also your web.config file has been updated with the necessary information about the service and its end-point in the <system.serviceModel> element.

Notice the behavior element with the <enableWebScript/> tag, this makes your service send and receive JSON instead of XML.

You’d want to add the following XML fragment into the behaviors element

1
2
3
4
5
6
<serviceBehaviors>
   <behavior name="TutorialServiceBehavior">
     <serviceMetadata httpGetEnabled="true" />
     <serviceDebug includeExceptionDetailInFaults="true" />
   </behavior>
</serviceBehaviors>

This will enable you to send GET requests to the service instead of the default POST which will make your service a bit more “REST-ful”.

It will also allow you to debug your service when an exception is being thrown on the server-side by setting the property includeExceptionDetailInFaults to ‘true’. in a production environment you will probably want to set this to false.

  • Make sure you add the following attribute to the service element like so:
1
2
<service name="TutorialService" 
behaviorConfiguration="TutorialServiceBehavior">
  • Last thing to do in the configuration is change the contract attribute of the end-point from “TutorialService” to “ITutorialService” because we are going to create an interface to behave as the contract for our service.
1
2
3
<endpoint address="" 
behaviorConfiguration="TutorialServiceAspNetAjaxBehavior" 
binding="webHttpBinding" contract="ITutorialService" />
  • Close the web.config file.
  • To the App_Code folder add an interface called: ITutorialService.
  • Decorate it with the ServiceContract attribute from the System.ServiceModel namespace.  By setting the optional  ‘Namespace’ and ‘Name’ properties we’re telling the framework how to name the proxy object that will be auto-created for us on the client side.
1
2
3
4
[ServiceContract(Namespace = "Tutorials", Name="RssService")]
public interface ITutorialService
{
}
  • Add the following method definitions to the interface:
1
2
3
4
5
[OperationContract, WebGet]
IEnumerable<TutorialArticle> GetArticles();

[OperationContract, WebGet]
TutorialArticle GetArticle(string link);

These methods will be called from the client side in order to retrieve and show the content on the page.

  • Add a class to the App_Code folder called TutorialArticle and decorate the class with the DataContract attribute from the System.Runtime.Serialization namespace. This attribute will allow this class to be serialized and de-serialized when its passed back and forth between the service and the client side.
  • Add the following code to this class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[DataContract]
public class TutorialArticle
{
  public static DateTime ParseRssItemDate(string timestamp) 
  { //quick and dirty way of parsing the date element of the RSS item
   return DateTime.Parse(timestamp.Substring(0, timestamp.Length - 4), 
      CultureInfo.InvariantCulture,   DateTimeStyles.AllowWhiteSpaces);  
  }

   [DataMember]
   public string Title { get; set; }

   [DataMember]
   public DateTime PublishDate { get; set; }

   [DataMember]
   public string PublishedBy { get; set; }

   [DataMember]
   public string Link { get; set; }

   [DataMember]
   public string Description { get; set; }

   [DataMember]
   public bool New { get; set; }
}

Notice here the DataMember attribute which is used with the properties to mark them as serializable.

  • Open the TutorialService.cs file: remove the ServiceContract attribute and the default method.
  • Make your class implement the ITutorialService interface and its methods.
  • For the GetArticles method add this code:

<

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public IEnumerable<TutorialArticle> GetArticles()
{
   XNamespace rssNS = "http://purl.org/dc/elements/1.1/";

   var rssXML = 
        XDocument.Load("http://www.cnet.com/8300-13952_1-81.xml?tag=rtcol;about");

   var q = from r in rssXML.Descendants("item")
         select new TutorialArticle()
         {
           Title = (string)r.Element("title"),
           Link = (string)r.Element("link"),
           PublishedBy = (string)r.Element(rssNS + "creator"),
           PublishDate = 
            TutorialArticle.ParseRssItemDate((string)r.Element("pubDate")),
           New = (DateTime.Now.Subtract(
            TutorialArticle.ParseRssItemDate((string)r.Element("pubDate"))).TotalDays < 3)
         };

   var articles = q.ToList();

   return articles;
}

This code is using LINQ to XML in order to load the feed’s xml and convert it into a collection of articles.

  • For the GetArticle method add this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public TutorialArticle GetArticle(string link)
{
   XNamespace rssNS = "http://purl.org/dc/elements/1.1/";

   var rssXML = 
     XDocument.Load("http://www.cnet.com/8300-13952_1-81.xml?tag=rtcol;about");

   var q = from r in rssXML.Descendants("item")
       where (string)r.Element("link") == link
       select new TutorialArticle()
       {
        Title = (string)r.Element("title"),
        Link = (string)r.Element("link"),
        PublishedBy = (string)r.Element(rssNS + "creator"),
        PublishDate =
         TutorialArticle.ParseRssItemDate((string)r.Element("pubDate")),
        New = (DateTime.Now.Subtract(TutorialArticle.ParseRssItemDate(
                    (string)r.Element("pubDate"))).TotalDays < 3),
        Description = (string)r.Element("description")
       };

   return q.FirstOrDefault();
}

This method does roughly the same as the previous one only it selects just one item based on the link parameter which is expected to be unique, its also selecting the “description” element of the article which you’d want to display in the full view of the article.

Thats all that is needed for the server-side functionality.

Client Side

Before coding the client-side logic a few things require setting up, in the downloadable source code you will find the necessary files to get everything working, this includes:

  • The jQuery library version 1.3.2 (and the vsdoc file)
  • The jTemplates plugin
  • A CSS file to style the page a little bit
  • A couple of images

If you’re following the naming convention and locations in this article to the letter, put the javascript files and css file in a folder called “System” under the root of the website. And the images in a “Images” folder.

Open the default.aspx file (you can get rid of the aspx.cs file, its not needed) and add the <asp:ScriptManager> element with the following references:

1
2
3
4
5
6
7
8
9
10
<form id="form1" runat="server">
 <asp:ScriptManager runat="server" ID="ScriptManager1">
  <Scripts>
    <asp:ScriptReference Path="~/System/jquery.js" />
    <asp:ScriptReference Path="~/System/jquery-jtemplates.js" />
  </Scripts>
  <Services>
    <asp:ServiceReference Path="~/Services/TutorialService.svc" />
  </Services>
 </asp:ScriptManager>

The ScriptReferences simply add the javascript references to the jQuery library and the jTemplates plugin js files.

The ServiceReference pointing to our svc file will automatically create a javascript proxy for the service which can be used to call the methods of the web service from the client side. [In a second article I will look into replacing this proxy with a pure javascript solution.]

A few html elements are needed to act as containers for the content which will be loaded onto the page.

  • Add the following html to your form:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div>
  <div id="Articles">
    <div id="ArticlesList">
     Loading...
    </div>
    <div id="ArticleMain">
     <div id="ArticleInfo">
     </div>
     <img id="LoadingImg" src="Images/ajax-loader.gif"
                                        class="Hidden" />
     <div id="SingleArticle">
     </div>
   </div>
  </div>
</div> 
  • Add the following code at the bottom of the page just above the </body> tag.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<script type="text/javascript">

   $(document).ready(function() //executes this code when page loading is done
   {
      Tutorials.RssService.GetArticles(articlesRetrieved,
                 serviceDefaultErrorHandler); //get articles from the web service
   });

   function articlesRetrieved(results)
   {
     if (results)
     {
       if (results.length > 0)
       {   //set the articles template on the div element
        var templateItem =
         $("#ArticlesList").setTemplateURL("Templates/Articles.htm",
          null, { filter_data: false });

            //execute the template with the data
            templateItem.processTemplate(results); 
        }
        else
        {
           alert("no articles found");
        }
     }
   }

   function serviceDefaultErrorHandler(xhr, context, method)
   {
     alert(xhr.get_message()); //show error message(only on dev)
   }
</script>

You can see that VS recognized the service reference and is giving auto-completion for the service proxy which is pretty damn cool:

javascript Intellisense

The GetArticles method on the proxy class accepts two function parameters, the first is the method that will be called on a successfull request, in this case the ‘articlesRetrieved’ method will be called, the second parameter is for the function which will be called when an error has occurred.

At this point you’re simply calling the GetArticles method on the web service when the page has finished loading in the browser and displaying the count of how many were retrieved. which looks like this:

articles result

Much more interesting would be to look at the information which was downloaded to the browser using Firebug’s capability to display the network activity related to the current page.

(If you don’t know or haven’t started using Firebug, go download it right now, seriously, stop reading this and go get it, then come back and continue reading :) )

In Firebug the raw JSON data can be viewed:

Firebug Raw JSON

This is a great tool to see the amount and type of data being passed to the client but not so easy to read, using a tool such as JSON viewer paints a clearer picture:

JSON-Viewer

Now you can see that indeed 10 items were retrieved and even see the data for each one.

Next step is to actually display the data as HTML so the viewer of the page can make some sense of it, one way would be to start injecting individual element into the page’s DOM, or start concatenating all the html into a giant string and then update the page with that, both of these approaches are very problematic for several reasons, to name a few:

  • They usually result in unreadable code.
  • The more data and properties there are the more difficult it becomes to manage the code and make modifications.
  • The designer – developer process is severely hurt since there’s no design the developer can simply employ to inject the data in the right places and a designer will usually resent having to write the javascript for this themselves.

Here is where jTemplates comes into play. jTemplates is a “template engine for javascript”. It gives you the power of defining a template in HTML and inject or bind it with your data which could come from just about anywhere.

With jTemplates you can:

  • Create reusable templates
  • Have a very clear separation between data and layout
  • Bind the layout and data in just a couple lines of code
  • Enjoy the designer-developer process where each person does what they do best, designer does the layout while the developer supplies the data to be presented.

As a side note, ASP.NET 4.0 will have a very similar feature for doing client-side templates but if you wish to start using templates now, jTemplates is already available while ASP.NET 4.0 isnt and if you plan on using such a feature in your organization it will probably be easier to convince your boss to use a jQuery plugin (especially if you’re using jQuery already) than to convince them to use a preview version of ASP.NET and it will probably be a while before your organization upgrades to .NET 4.0.

With jTemplates you can now create a template either in-line in the javascript code or take the approach I prefer which is to create an HTML file which will only contain the template.

  • In VS create a “Templates” folder.
  • In this folder create a new file: Articles.htm.
  • Remove its content and paste in the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 16
17
<ul>
 {#foreach $T as article}
  <li>
    <a href="javascript:loadArticle('{$T.article.Link}')">
      {$T.article.Title}
    </a>

    {#if $T.article.New}
       <img src="images/new.gif" title="New Post" />
    {#/if}
    <div>
      Title: <b>{$T.article.Title}</b>
      <br />
      Date: <b>{$T.article.PublishDate}</b>
      <br />
      Published By: <b>{$T.article.PublishedBy}</b>
   </div>
  </li>
 {#/for}
</ul>

You will immediately notice the jTemplates syntax in between the html elements, this syntax conveniently includes a foreach structure, a if conditional and few more which make it perfect for iterating over a set of data and define a template for each item in the set as the above example does.

The {#foreach $T as article} statement begins the loop over the array of articles where $T is the root object we’re passing to the template engine, in this case its an array so it can easily be iterated over. The “as article” will make it easier to access the current item inside the loop.

Inside the loop you can access each item’s property which was marked as a DataMember so {$T.article.Title} will write out the title of the article.

You may have noticed the Boolean “New” property which the TutorialArticle has, this property is set to True when the article’s publish date is in the last couple of days, using the {#if $T.article.New} allows to inject html based on the conditional being set, so in the case of a new article the template will show an image marking it as new.

Hopefully the usefulness of such an approach to display data is immediately obvious, with just a few lines of HTML and a little bit of special syntax we achieved a result which would have been messy at best if we were to try to do this with just in-line javscript.

Now to actually bring the data and layout together on the page:

  • Go back to the default.aspx and replace the alert() line of code in the articlesRetrieved() method with this code:
1
2
3
4
var templateItem =
   $("#ArticlesList").setTemplateURL("Templates/Articles.htm",
                              null, { filter_data: false });
templateItem.processTemplate(results);

That’s it, two lines of code and presto, we have a list on the left side of the page with the titles of the articles in the RSS feed.

The first line of code will attach the template to the DIV element (“ArticleList“) that will contain the result of rendering the template.
The second line executes the template with the object passed as a parameter to the processTemplate method. This object is the response received from the web service’s GetArticles method, it should contain an array of JSON objects each having the properties of the TutorialArticle class defined on the server side.

  • Go ahead and add the next function to your page:
1
2
3
4
5
6
7
function loadArticle(link)
{
    $("#LoadingImg").removeClass("Hidden");
    $("#SingleArticle").html("");

    Tutorials.RssService.GetArticle(link,
        articleRetrieved, serviceDefaultErrorHandler);
}

This method will call the web service’s method GetArticle with the link property of the selected article as a parameter, based on this property the service can retrieve the single article with all of its information to be displayed in the main section of the page.

To display the article we will use a second template.

  • In the Templates folder create a new file called: Article.htm and replace its content with the following HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<h3>
  {$T.Title}
</h3>

{#if $T.New}<img src="images/new.gif" title="New Post" />{#/if}

<p>
  Date: <b>{$T.PublishDate}</b>
  <br />
  Published By: <b>{$T.PublishedBy}</b>
  <br />
  From: <a href="{$T.Link}">CNET</a>
</p>

<p>
  {$T.Description}
</p>

This time to present just one article there is no need for a loop, $T in this case will be the Article object itself.

  • To the default.aspx add the last function:
1
2
3
4
5
6
7
8
9
10
11
12
13
 14
15
function articleRetrieved(results)
{
  if (results)
  {
    var templateItem =
      $("#SingleArticle").setTemplateURL("Templates/Article.htm",
                                   null, { filter_data: false });
    templateItem.processTemplate(results);
  }
  else
  {
    alert("couldnt find the article");
  }

  $("#LoadingImg").addClass("Hidden");
}

In this case the code is attaching the Article.htm template to the SingleArticle DIV element and the next line executes it with the context of the result received from the service’s GetArticle method.

By now you should have a page that looks something along these lines:

Result

Review

Let’s review what we have accomplished so far:

  • We created a WCF web service with a couple of methods.
  • These methods poll on an RSS feed to get real information from the web.
  • Our service exposes the information it retrieves as JSON so it can easily be parsed and used on the client-side using javascript.
  • Using Microsoft’s AJAX client library we are able to call the methods of our service in a somewhat strongly-typed way.
  • Using jQuery and jTemplates we present the information we retrieve from the web service in a very structured, scalable and maintainable way using templates.
  • We do all of this without refreshing the page even once.

Hopefully I have been able to demonstrate the power and simplicity of combining all of these exciting technologies into one, elegant solution which can be used to create a more rich and friendlier experience for the user while making the life of the developer easier.

Source Code

You can download it here.

Resources

Follow

Get every new post delivered to your Inbox.

Join 315 other followers

%d bloggers like this: