Archive

Posts Tagged ‘tutorial’

LINQ to Tridion

January 8, 2010 4 comments

Contents

Introduction

Its Friday evening, a good time to share a little something I’ve been working on.

.NET 3.0 brought with it a fantastic new language (VB, C#) extension called LINQ which stands for Language-Integrated Query.

Microsoft describes it as “a set of extensions to the .NET Framework that encompass language-integrated query, set, and transform operations. It extends C# and Visual Basic with native language syntax for queries and provides class libraries to take advantage of these capabilities.”

In short it gives the developer a more general syntax for querying sets or collections of data.

The beautiful thing about LINQ is that it can be used over any collection whether its XML, Database or even objects so long as they support the IEnumerable<T> interface.

For more information see the resources section of this article or simply google/bing it.

Read more…

A Few Useful Tridion Extension Methods

October 26, 2009 8 comments

Following my recent blog about extension methods. Here are a few useful extension methods I’ve created recently for working with Tridion’s TOM API.

.NET Interops – COM API (5.2 and onwards)

Here are a few useful methods to use with the older TOM API (interops), these can come in handy when writing custom tools, event system code, etc.

Publish

The publish method for both Page and Component objects require quite a few parameters which in many cases are always set the same within a single application scope. If you want to use defaults for these values you can use these extension methods to predetermine the values of the parameters leaving a shorter and more convenient way for sending the items to be published:

For Components:

1
2
3
4
5
6
7
8
/// <summary>
/// Offers a simple call to publish a components using defaults
/// for all of the publish parameters  
/// </summary>
/// <param name="targets">one or more pucliation targets or target
/// types to publish to
/// </param>
public static void Publish(this Component component, object targets, 
                                          EnumPublishPriority priority)
{
     component.Publish(targets, false, false, false, DateTime.Now, 
            DateTime.MinValue, DateTime.Now, true, priority, true, 100);
}

For Pages:

1
2
3
4
5
6
7
8
/// <summary>
/// Offers a simple call to publish a components using defaults
/// for all of the publish parameters
/// </summary>
/// <param name="targets">one or more pucliation targets or
/// target types to publish to
/// </param>
public static void Publish(this Page page, object targets,
                                   EnumPublishPriority priority)
{
page.Publish(targets, false, false, false, DateTime.Now,
        DateTime.MinValue, DateTime.Now, true, priority, true, 100);
}

UnPublish

Very similarly to the publish method, here’s an example for creating a shorter way to call un-publish on a page object:

1
2
3
4
public static void UnPublish(this Page page, object targets,
                                     EnumPublishPriority priority)
{
     page.UnPublish(targets, true, false, false, DateTime.Now, 
                                                 false, priority);
}

IsPublished

Tridion provides a method to check whether a page is published to a specific Target Type or Publication Target but what if you just want to check whether the page is published or not?
You need to check each target.
Here’s a way to add a method to the page type that will check whether a page is published by providing a list of targets to the method call:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/// <summary>
/// Assert whether a page is published or not
/// </summary>
/// <param name="page">The page in question</param>
/// <param name="targets">A list of target types or
/// publication targets to check
/// </param>
/// <returns>True if the page is published to at least
/// one of the provided targets</returns>
public static bool IsPublished(this Page page, IEnumerable<string> targets)
{
    foreach (var t in targets)
    {
        if (page.IsPublishedTo(t)) return true;
    }

    return false;
}

Release

Its very important to make sure you correctly dispose of the Tridion COM objects exposed by the interops.

Here’s an example of how to easily do that for components and pages without having to add: “using System.Runtime.InteropServices;” to every code file:

For Component:

1
2
3
4
5
6
7
/// <summary>
/// Releases the COM Component object
/// </summary>
public static void Release(this Component component)
{
    Marshal.ReleaseComObject(component);
}

For Page:

1
2
3
4
5
6
7
/// <summary>
/// Releases the COM Page object
/// </summary>
public static void Release(this Page page)
{
    Marshal.ReleaseComObject(page);
}

TOM.NET (5.3 and onwards)

Fields

One of the things I was quite astonished to find when i first started working with the TOM.NET API was that the Component object no longer exposed a fields collection as a property. Instead to get an instance of those fields you are required to write code which is not very intuitive and definitely shouldnt be required for such a basic property.
I’ve since filed a formal request to our R&D department to change this but there’s no guarantee that this is going to change anytime soon.

If you are using Tridion 2009 and .NET 3.5 or brave enough to write your .NET templates on 5.3 or 5.3 SP1 with .NET 3.5 you might be interested in using the following extension method:

1
2
3
4
5
6
7
/// <summary>
///  Returns an ItemFields collection for the Component
/// </summary>
public static ItemFields Fields(this Component component)
{
     return new ItemFields(component.Content, component.Schema);
}

With this method in place to get the fields collection of a component you only need the following: comp.Fields()…

Root StructureGroup

Another oddity in the relatively new API is that the publication object doesnt expose a RootStructureGroup property while it does expose a RootFolder property. Slightly annoying but easily fixed with… you guessed it! An extension method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// <summary>
/// Returns the root structure group for this publication
/// </summary>
public static StructureGroup RootSG(this Repository publication)
{
    Filter filter = new Filter();
    filter.Conditions["ItemType"] = ItemType.StructureGroup;
    IList<RepositoryLocalObject> items = publication.GetItems(filter);

    if (items.Count == 0)
       return null;
    else
       return (StructureGroup)items[0];
}

Conclusion

These are just a few useful methods that can make your Tridion development quicker and more convenient.
Undoubtedly there’s many more such methods people can think of, if you do have some that you use please share them and if we have enough I will create an extension on World with all of them!

Code

You can download the methods ive shown in this article here: code.

for all of the

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

Implementing the XSLT Mediator – Part 1

July 11, 2009 4 comments

Contents

Introduction

In the next series of articles I plan on showing how to use the XSLT Mediator which Im currently maintaining as an eXtension available on SDLTridion World.

The Mediator can be downloaded from the XSLT Mediator Page

An explanation why should you use the XSLT Mediator can be found at the aforementioned download page, so I won’t go into that, ill simply show how it can be used.

This is the first part in a series of at least 3 articles; in following articles I will mainly be discussing how to extend the XSLT transformation with .NET code.

This article assumes basic knowledge of XSLT and basic Tridion experience in templating.

Setting up the Mediator

In the Mediator zip file you will find the assembly DLL which can be used as is as well as the source code of the mediator project.

You should be able to simply drop the DLL somewhere on the Content Manager Server to begin using it but you may choose to first use the source code either to build it against a different version of Tridion (currently that’s 5.3GA) or if you wish to add extension objects to the assembly (will be discussed on the next article in this series).

The simple setup requires an edit to the Tridion configuration file, which is located in the Config folder under the Tridion installation folder (i.e.: C:\Program Files\Tridion\Config) and the file name is Tridion.ContentManager.config.

Open the file for editing and insert the following XML fragment in the <mediators> element:

<mediator matchMIMEType="text/xml" type="Tridion.Extensions.Mediators.XsltMediator" assemblyPath="C:\Program Files\Tridion\bin\Tridion.Extensions.Mediators.dll"/>

If you’re using the binary as it is supplied then there is no need to change the ‘type’ attribute but make sure the ‘assemblyPath’ attribute is pointing to the right location of where you placed the DLL file.

To begin using the Mediator you should restart the following: Tridion COM+ package (Component Services), IIS, Tridion Publisher service and any open Template Builder instance.

Next step is to create the parameters schema which will be used with the XSLT TBBs we will be creating.

In the zip file you will find XSLT_Transformation_Parameters.xsd, In Tridion create a new parameters schema and use the upload button in the source tab to load the contents of the included XSD file:

XSLT transformation parameters schema

XSLT transformation parameters schema

That’s it. This is all the setting-up needed for now.

Creating an XSLT Component Template

Now you’re ready to create your first XSLT TBB which can be used in a compound template.

Note: For a long time it was possible to create XSLT component templates in Tridion, this has not changed. XSLT page templates however are not supported so in order to create these, the Mediator is required. The Mediator has another advantage of being able to incorporate managed (.NET) code into XSLT templates (will be discussed in a later article).

Lets create a simple schema which you will be able to use to test your new XSLT template with.
(The schema is included in the downloadable for this article)

Simple Schema

Simple Schema

The schema contains a title text field, a body rich text field, a date field and a multimedia link for an image.

Create a new component based on this schema and populate its fields with some values.
Based on this schema we will start with a simple XSLT TBB which we can extend later on:


<?xml version="1.0" encoding="utf-8"?>


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:simple="uuid:3CC625ED-34E6-4B51-BDD8-72BBD0D71469" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:tcm="http://www.tridion.com/ContentManager/5.0"
exclude-result-prefixes="msxsl simple">

<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

<xsl:template match="/">
<xsl:element name="p">

<xsl:apply-templates select="tcm:Component/tcm:Data/tcm:Content/simple:Content"/>
</xsl:element>
</xsl:template>

<xsl:template match="simple:Content">

<xsl:element name="h3">

<xsl:value-of select="simple:title"/>

</xsl:element>

<xsl:element name="div">

<xsl:copy-of select="simple:body"/>

</xsl:element>

<xsl:element name="div">

Publish Date: <xsl:value-of select="simple:pubDate" />

</xsl:element>

<xsl:element name="img">

<xsl:attribute name="src">

<xsl:value-of select="simple:image/@xlink:href"/>

</xsl:attribute>

</xsl:element>

</xsl:template>

</xsl:stylesheet>

If you’re familiar with doing normal XSLT component templates you will notice the declaration of the “simple” namespace prefix at the top, this is necessary to be able to output the component’s content. The uuid:3CC625ED-34E6-4B51-BDD8-72BBD0D71469 namespace is copied from the schema we’ve just created (notice that each new schema receives a new target namespace by default which is in this long string format).

The rest of the template is very straight forward and just outputs the field values from the component.

In Tridion create a new TBB and copy the above code into the source tab. In the general tab make sure to add the parameters schema created before then save & close the template:

XSLT TBB with parameter schema

XSLT TBB with parameter schema

To use this new template open the Template Builder and create a new compound component template:

Template Builder Compound CT with XSLT TBB

Template Builder Compound CT with XSLT TBB

You can now run the template with the component you created earlier, the result should be something like this:

Run Compound CT in Template Builder

Run Compound CT in Template Builder

Note: Above I mentioned that I wont go into the merits of using the XSLT Mediator but one very important thing to notice is how quick it is in comparison to the Dreamweaver Mediator, obviously this example cannot be taken into account but even in real life templates, XSLT ones out run their DW counterparts by hundreds or percent.

There is no need to fill in any of the parameters attached to the XSLT Template but lets take a moment to review these:

Input Item Name – This is the item in the package to use as the input xml for the transformation.The default item which will be used for a component template is the item with name ‘Component’, for a page template it will be the ‘Page’ item.

Output Item Name – This is the name of the item the Mediator will create in the package with the result of the transformation; the default is ‘Output’.

Get Parameters from Package – A true/false value determining whether the Mediator should include items in the package as parameters for the transformation. Default is ‘true’.

For performance purposes it is recommended to change this to ‘false’ unless you require all of the items to act as parameters or plan on using specific items by specifying a prefix.

Package Items Name Prefix – The value of this parameter tells the mediator to only use items in the package which have the specified prefix. Presuming, the value of the previous parameter is ‘true’.

For example all items in the package with a prefix of ‘_par’ will be used if this value is specified.
The mediator will strip the prefix from the actual parameter name when its added to the transformation.

Output Format Type – Which content type to use for the result item created by the Mediator Default is ‘XHTML’.


Getting back to our new template:

Notice the broken image in the last  screen shot, by using some of the default TBBs provided by Tridion we can easily sort this out:

Compound Template with Image

Compound Template with Image

The order in which to place these TBBs (Extract, Publish, Resolve) is critical for the image to be published and displayed correctly.

Component Linking

The XSLT Mediator supports “linking” natively in a very similar way to how it was accomplished in XSLT CTs – by use of the document() function.

To demonstrate this ability I will use a metadata field set on the multimedia component to set the alt attribute of the image element in the resulting html. First the modified XSLT TBB:


<?xml version="1.0" encoding="utf-8"?>


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:simple="uuid:3CC625ED-34E6-4B51-BDD8-72BBD0D71469" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:tcm="http://www.tridion.com/ContentManager/5.0"
xmlns:image="http://www.tridion.com/ContentManager/5.0/DefaultMultimediaSchema"
exclude-result-prefixes="msxsl simple">

<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

<xsl:template match="/">
<xsl:element name="p">

<xsl:apply-templates select="tcm:Component/tcm:Data/tcm:Content/simple:Content"/>
</xsl:element>
</xsl:template>

<xsl:template match="simple:Content">

<xsl:element name="h3">

<xsl:value-of select="simple:title"/>

</xsl:element>

<xsl:element name="div">

<xsl:copy-of select="simple:body"/>

</xsl:element>

<xsl:element name="div">

Publish Date: <xsl:value-of select="simple:pubDate" />

</xsl:element>

<xsl:element name="img">

<xsl:attribute name="alt">
<xsl:value-of select="document(simple:image/@xlink:href)/tcm:Component/tcm:Data/tcm:Metadata/image:Metadata/image:altText"/>
</xsl:attribute>


<xsl:attribute name="src">
<xsl:value-of select="simple:image/@xlink:href"/>

</xsl:attribute>

</xsl:element>

</xsl:template>

</xsl:stylesheet>

The interesting additions are in red, first add the namespace of the multimedia schema, in this case this is the default MM schema, We use  ‘image’ as the prefix.

Then add a definition for a second attribute to the ‘img’ element, in the example we use the document function to load the entire multimedia component’s XML by passing the xlink:href attribute of the link field, this attribute’s value is the TCM URI of the image  component. (In the content component the link is stored like this: <image xlink:type=”simple” xmlns:xlink=”http://www.w3.org/1999/xlink&#8221; xlink:title=”chrome” xlink:href=”tcm:42-15992″ />)

We then use an inline XPATH statement to get to the altText metadata field.

The result of this can be seen here:

XSLT CT - component links

XSLT CT - component links

With the document function we can successfully retrieve information from any other Tridion item as long as we know its ID (TCM URI).

Conclusion

It is very easy to set up and start using the XSLT Mediator, it provides both flexibility and speed which are not catered so well by the Dreamweaver mediator and for customers wishing to make use of an XSLT based solution it gives the possibility of using XSLT templates for components and pages alike.

However this article does not show some of these advantages, In the second part of this series I will look into:

  • Extending the XSLT transformation with extension objects
  • Using Extension objects to publish binaries, render component presentations, etc.
  • Creating an XSLT Page Template

Source Code

You can download the example XSLT and Schema here.

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: