<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:georss="http://www.georss.org/georss" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>DotNetDude.com - Dev Stuff</title>
    <link>http://www.dotnetdude.com/</link>
    <description>Miguel A. Castro's Blog</description>
    <image>
      <url>http://www.dotnetdude.com/feed-icon-24x24.gif</url>
      <title>DotNetDude.com - Dev Stuff</title>
      <link>http://www.dotnetdude.com/</link>
    </image>
    <language>en-us</language>
    <copyright>Miguel A. Castro</copyright>
    <lastBuildDate>Wed, 28 Jul 2010 02:57:11 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>miguelcastro67@gmail.com</managingEditor>
    <webMaster>miguelcastro67@gmail.com</webMaster>
    <item>
      <trackback:ping>http://www.dotnetdude.com/Trackback.aspx?guid=7f97d63e-24c6-4455-a7c8-6452e0b23b19</trackback:ping>
      <pingback:server>http://www.dotnetdude.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnetdude.com/PermaLink,guid,7f97d63e-24c6-4455-a7c8-6452e0b23b19.aspx</pingback:target>
      <dc:creator>Miguel A. Castro</dc:creator>
      <wfw:comment>http://www.dotnetdude.com/CommentView,guid,7f97d63e-24c6-4455-a7c8-6452e0b23b19.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnetdude.com/SyndicationService.asmx/GetEntryCommentsRss?guid=7f97d63e-24c6-4455-a7c8-6452e0b23b19</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <strong>
            <font color="#ff0000">Note: Using a Console app for hosting should be done
for development only !</font>
          </strong>
        </p>
        <p>
Now that the disclaimer is out of the way, I currently doing some development work
for a customer and I had the need to know every time any of my services receives a
call.  Since I do my development using a console application for service hosting,
it was easy enough to write out to the console from each service operation. 
Of course, putting code in every method was possible but not only would it be time
consuming, to turn it off later would be a pain.  The answer needed to be something
that gets hit on every operation.  Since WCF is essentially one giant inversion
of control container, I knew there was a point I could tap into before any operation
call.
</p>
        <p>
Enter behaviors !
</p>
        <p>
This turned out to be a multi-step process but once it’s in my library of WCF stuff,
I can reuse it and it actually turned out to be quite cool.  I’ll explain each
step and the reasons for the step.<br /></p>
        <p>
          <strong>
            <font size="2">Step 1 – Write a custom Parameter Inspector</font>
          </strong>
        </p>
        <p>
The first class you need to write is one that implements the <strong>IParameterInspector</strong> which
is in the <strong>System.ServiceModel.Dispatcher</strong> namespace.  This class
will later be installed in such a way that it gets hit on every operation call. 
The operation name is one of the arguments you have access to, as well as all the
operation arguments which I don’t need in this case.
</p>
        <p>
The methods in this implementation are <strong>BeforeCall</strong> and <strong>AfterCall</strong>,
and it is the <strong>BeforeCall</strong> that I’m interested in.  The code I’ll
place in this method very simply outputs something out to the console using <strong>Console.Writeline</strong>.
</p>
        <p>
Unfortunately the name of the service is not passed into this method so I need to
get that into this class using a custom constructor; you’ll see how I’ll get it to
the class later.
</p>
        <p>
Here’s the code for my <strong>ConsoleReportInspector</strong> class:
</p>
        <p>
 
</p>
        <pre class="brush: csharp;">public class ConsoleReportInspector : IParameterInspector
{
    public ConsoleReportInspector(string serviceName)
    {
        _ServiceName = serviceName;
    }

    string _ServiceName = string.Empty;

    void IParameterInspector.AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
    {
    }

    object IParameterInspector.BeforeCall(string operationName, object[] inputs)
    {
        Console.WriteLine(string.Format("{0} - '{1}.{2}' operation called.", DateTime.Now.ToLongTimeString(), _ServiceName, operationName));

        return null;
    }
}

</pre>
        <p>
          <br />
 
</p>
        <p>
          <font size="2">
            <strong>Step 2 – Install the class using an Operation Behavior</strong>
          </font>
        </p>
        <p>
In order to install the parameter inspector, I’ll need to write a custom operation
behavior class.  This is a class that implements the <strong>IOperationBehavior</strong> interface. 
You need to remove the throw to <strong>NotImplementedException</strong> from all
the methods; and the method of concern here is <strong>ApplyDispatchBehavior</strong>.
</p>
        <p>
The name of the service being called is accessible through the <strong>Parent</strong> property
of the <strong>dispatchOperation</strong> argument.  I need to instantiate my <strong>ConsoleReportInspector</strong> class
and send the service name into the constructor I added earlier.  Afterward, I
just need to add my parameter inspector class to the list of parameter inspectors
accessible in this behavior. 
</p>
        <p>
I also inherited this class from the <strong>System.Attribute</strong> class so I
can use it as an operation behavior attribute on individual operations if I wanted. 
This is just for flexibility since I plan on hooking this into a service so it affects
all operations.
</p>
        <p>
Here’s the code for my <strong>ConsoleReportOperationBehaviorAttribute</strong> class:
</p>
        <p>
 
</p>
        <pre class="brush: csharp;">[AttributeUsage(AttributeTargets.Method)]
public class ConsoleReportOperationBehaviorAttribute : Attribute, IOperationBehavior
{
    void IOperationBehavior.AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
    {
    }

    void IOperationBehavior.ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    {
    }

    void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
    {
        string serviceName = dispatchOperation.Parent.Type.Name;
        dispatchOperation.ParameterInspectors.Add(new ConsoleReportInspector(serviceName));
    }

    void IOperationBehavior.Validate(OperationDescription operationDescription)
    {
    }
}

</pre>
        <br />
        <p>
As-is, I can simply decorate a service operation with [ConsoleReportOperationBehavior]
and if hosted on a console application, you’ll see output to the console when the
decorated operation is called.
</p>
        <p>
 
</p>
        <p>
          <strong>
            <font size="2">Step 3 – Install the operation behavior on all operations using
a Service Behavior</font>
          </strong>
        </p>
        <p>
Next I need to write a service behavior.  This is a behavior that gets installed
when the service loads (the host is opened).  The job of this behavior is to
install my operation behavior on all the service operations.  A service behavior
is a class that implement the <strong>IServiceBehavior</strong> interface.  Like
before, I’ll remove the exception calls and once again the method I’m interested in
is <strong>ApplyDispatchBehavior</strong>.
</p>
        <p>
I’m going to iterate through all the endpoints of this service, which are accessible
through the serviceDescription argument, and for each endpoint I will iterate through
the operations of the contract of each endpoint.  To each operation I will add
an instance of my ConsoleReportOperationBehaviorAttribute class.
</p>
        <p>
This class too I will inherit from <strong>Attribute</strong> so I can use it to decorate
a service in the case that I wanted to take this approach at some time.  
</p>
        <p>
Here’s the code for my <strong>ConsoleReportServiceBehaviorAttribute</strong> class:
</p>
        <p>
 
</p>
        <pre class="brush: csharp;">[AttributeUsage(AttributeTargets.Class)]
public class ConsoleReportServiceBehaviorAttribute : Attribute, IServiceBehavior
{
    void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection&lt;ServiceEndpoint&gt; endpoints, BindingParameterCollection bindingParameters)
    {
    }

    void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
            foreach (OperationDescription operation in endpoint.Contract.Operations)
                operation.Behaviors.Add(new ConsoleReportOperationBehaviorAttribute());
    }

    void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }
}

</pre>
        <p>
 
</p>
        <p>
          <font size="2">
            <strong>Step 4 – Apply the service behavior to any service I want programmatically
at the host</strong>
          </font>
        </p>
        <p>
Whatever approach you take to hosting, all you need to do is access each instance
of <strong>ServiceHost</strong> and add the service behavior to the list of behaviors
in the host.  I have my own techniques for hosting which include some custom
declarative stuff to allow me to turn hosting on and off at will through config. 
I also like to separate the accumulation of my <strong>ServiceHost</strong> instances
from the actual application that will do the hosting.  This way I can move it
to a Windows Service when I’m ready to go to production.
</p>
        <p>
Here’s the code that installs the behavior:
</p>
        <p>
 
</p>
        <p>
 
</p>
        <pre class="brush: csharp;">ConsoleReportServiceBehaviorAttribute behavior = serviceHost.Host.Description.Behaviors.Find&lt;ConsoleReportServiceBehaviorAttribute&gt;();
if (behavior == null)
    host.Description.Behaviors.Add(new ConsoleReportServiceBehaviorAttribute());
</pre>
        <br />
        <p>
 
</p>
        <p>
The <strong>host</strong> variable is an instance of <strong>ServiceHost</strong>. 
I perform the code above in between a config check so I can toggle it off at will.
</p>
        <p>
The end result is quite cool since when turned on, every call to any of your services
will be shown on the console.
</p>
        <p>
 
</p>
        <h3>
          <em>Until next time…</em>
        </h3>
        <img width="0" height="0" src="http://www.dotnetdude.com/aggbug.ashx?id=7f97d63e-24c6-4455-a7c8-6452e0b23b19" />
      </body>
      <title>A Cool Technique For Reporting WCF Operation Calls On Your Host Console (dev-only of course)</title>
      <guid isPermaLink="false">http://www.dotnetdude.com/PermaLink,guid,7f97d63e-24c6-4455-a7c8-6452e0b23b19.aspx</guid>
      <link>http://www.dotnetdude.com/2010/07/28/ACoolTechniqueForReportingWCFOperationCallsOnYourHostConsoleDevonlyOfCourse.aspx</link>
      <pubDate>Wed, 28 Jul 2010 02:57:11 GMT</pubDate>
      <description>&lt;p&gt;
&lt;strong&gt;&lt;font color="#ff0000"&gt;Note: Using a Console app for hosting should be done
for development only !&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Now that the disclaimer is out of the way, I currently doing some development work
for a customer and I had the need to know every time any of my services receives a
call.&amp;nbsp; Since I do my development using a console application for service hosting,
it was easy enough to write out to the console from each service operation.&amp;nbsp;
Of course, putting code in every method was possible but not only would it be time
consuming, to turn it off later would be a pain.&amp;nbsp; The answer needed to be something
that gets hit on every operation.&amp;nbsp; Since WCF is essentially one giant inversion
of control container, I knew there was a point I could tap into before any operation
call.
&lt;/p&gt;
&lt;p&gt;
Enter behaviors !
&lt;/p&gt;
&lt;p&gt;
This turned out to be a multi-step process but once it’s in my library of WCF stuff,
I can reuse it and it actually turned out to be quite cool.&amp;nbsp; I’ll explain each
step and the reasons for the step.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;font size="2"&gt;Step 1 – Write a custom Parameter Inspector&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
The first class you need to write is one that implements the &lt;strong&gt;IParameterInspector&lt;/strong&gt; which
is in the &lt;strong&gt;System.ServiceModel.Dispatcher&lt;/strong&gt; namespace.&amp;nbsp; This class
will later be installed in such a way that it gets hit on every operation call.&amp;nbsp;
The operation name is one of the arguments you have access to, as well as all the
operation arguments which I don’t need in this case.
&lt;/p&gt;
&lt;p&gt;
The methods in this implementation are &lt;strong&gt;BeforeCall&lt;/strong&gt; and &lt;strong&gt;AfterCall&lt;/strong&gt;,
and it is the &lt;strong&gt;BeforeCall&lt;/strong&gt; that I’m interested in.&amp;nbsp; The code I’ll
place in this method very simply outputs something out to the console using &lt;strong&gt;Console.Writeline&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
Unfortunately the name of the service is not passed into this method so I need to
get that into this class using a custom constructor; you’ll see how I’ll get it to
the class later.
&lt;/p&gt;
&lt;p&gt;
Here’s the code for my &lt;strong&gt;ConsoleReportInspector&lt;/strong&gt; class:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;public class ConsoleReportInspector : IParameterInspector
{
    public ConsoleReportInspector(string serviceName)
    {
        _ServiceName = serviceName;
    }

    string _ServiceName = string.Empty;

    void IParameterInspector.AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
    {
    }

    object IParameterInspector.BeforeCall(string operationName, object[] inputs)
    {
        Console.WriteLine(string.Format("{0} - '{1}.{2}' operation called.", DateTime.Now.ToLongTimeString(), _ServiceName, operationName));

        return null;
    }
}

&lt;/pre&gt;
&lt;p&gt;
&lt;br&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;font size="2"&gt;&lt;strong&gt;Step 2 – Install the class using an Operation Behavior&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
In order to install the parameter inspector, I’ll need to write a custom operation
behavior class.&amp;nbsp; This is a class that implements the &lt;strong&gt;IOperationBehavior&lt;/strong&gt; interface.&amp;nbsp;
You need to remove the throw to &lt;strong&gt;NotImplementedException&lt;/strong&gt; from all
the methods; and the method of concern here is &lt;strong&gt;ApplyDispatchBehavior&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
The name of the service being called is accessible through the &lt;strong&gt;Parent&lt;/strong&gt; property
of the &lt;strong&gt;dispatchOperation&lt;/strong&gt; argument.&amp;nbsp; I need to instantiate my &lt;strong&gt;ConsoleReportInspector&lt;/strong&gt; class
and send the service name into the constructor I added earlier.&amp;nbsp; Afterward, I
just need to add my parameter inspector class to the list of parameter inspectors
accessible in this behavior. 
&lt;/p&gt;
&lt;p&gt;
I also inherited this class from the &lt;strong&gt;System.Attribute&lt;/strong&gt; class so I
can use it as an operation behavior attribute on individual operations if I wanted.&amp;nbsp;
This is just for flexibility since I plan on hooking this into a service so it affects
all operations.
&lt;/p&gt;
&lt;p&gt;
Here’s the code for my &lt;strong&gt;ConsoleReportOperationBehaviorAttribute&lt;/strong&gt; class:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;[AttributeUsage(AttributeTargets.Method)]
public class ConsoleReportOperationBehaviorAttribute : Attribute, IOperationBehavior
{
    void IOperationBehavior.AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
    {
    }

    void IOperationBehavior.ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    {
    }

    void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
    {
        string serviceName = dispatchOperation.Parent.Type.Name;
        dispatchOperation.ParameterInspectors.Add(new ConsoleReportInspector(serviceName));
    }

    void IOperationBehavior.Validate(OperationDescription operationDescription)
    {
    }
}

&lt;/pre&gt;
&lt;br&gt;
&lt;p&gt;
As-is, I can simply decorate a service operation with [ConsoleReportOperationBehavior]
and if hosted on a console application, you’ll see output to the console when the
decorated operation is called.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;font size="2"&gt;Step 3 – Install the operation behavior on all operations using
a Service Behavior&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Next I need to write a service behavior.&amp;nbsp; This is a behavior that gets installed
when the service loads (the host is opened).&amp;nbsp; The job of this behavior is to
install my operation behavior on all the service operations.&amp;nbsp; A service behavior
is a class that implement the &lt;strong&gt;IServiceBehavior&lt;/strong&gt; interface.&amp;nbsp; Like
before, I’ll remove the exception calls and once again the method I’m interested in
is &lt;strong&gt;ApplyDispatchBehavior&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
I’m going to iterate through all the endpoints of this service, which are accessible
through the serviceDescription argument, and for each endpoint I will iterate through
the operations of the contract of each endpoint.&amp;nbsp; To each operation I will add
an instance of my ConsoleReportOperationBehaviorAttribute class.
&lt;/p&gt;
&lt;p&gt;
This class too I will inherit from &lt;strong&gt;Attribute&lt;/strong&gt; so I can use it to decorate
a service in the case that I wanted to take this approach at some time.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
Here’s the code for my &lt;strong&gt;ConsoleReportServiceBehaviorAttribute&lt;/strong&gt; class:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;[AttributeUsage(AttributeTargets.Class)]
public class ConsoleReportServiceBehaviorAttribute : Attribute, IServiceBehavior
{
    void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection&amp;lt;ServiceEndpoint&amp;gt; endpoints, BindingParameterCollection bindingParameters)
    {
    }

    void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
            foreach (OperationDescription operation in endpoint.Contract.Operations)
                operation.Behaviors.Add(new ConsoleReportOperationBehaviorAttribute());
    }

    void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }
}

&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;font size="2"&gt;&lt;strong&gt;Step 4 – Apply the service behavior to any service I want programmatically
at the host&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Whatever approach you take to hosting, all you need to do is access each instance
of &lt;strong&gt;ServiceHost&lt;/strong&gt; and add the service behavior to the list of behaviors
in the host.&amp;nbsp; I have my own techniques for hosting which include some custom
declarative stuff to allow me to turn hosting on and off at will through config.&amp;nbsp;
I also like to separate the accumulation of my &lt;strong&gt;ServiceHost&lt;/strong&gt; instances
from the actual application that will do the hosting.&amp;nbsp; This way I can move it
to a Windows Service when I’m ready to go to production.
&lt;/p&gt;
&lt;p&gt;
Here’s the code that installs the behavior:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&lt;pre class="brush: csharp;"&gt;ConsoleReportServiceBehaviorAttribute behavior = serviceHost.Host.Description.Behaviors.Find&amp;lt;ConsoleReportServiceBehaviorAttribute&amp;gt;();
if (behavior == null)
    host.Description.Behaviors.Add(new ConsoleReportServiceBehaviorAttribute());
&lt;/pre&gt;
&lt;br&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
The &lt;strong&gt;host&lt;/strong&gt; variable is an instance of &lt;strong&gt;ServiceHost&lt;/strong&gt;.&amp;nbsp;
I perform the code above in between a config check so I can toggle it off at will.
&lt;/p&gt;
&lt;p&gt;
The end result is quite cool since when turned on, every call to any of your services
will be shown on the console.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;h3&gt;&lt;em&gt;Until next time…&lt;/em&gt;
&lt;/h3&gt;
&lt;img width="0" height="0" src="http://www.dotnetdude.com/aggbug.ashx?id=7f97d63e-24c6-4455-a7c8-6452e0b23b19" /&gt;</description>
      <comments>http://www.dotnetdude.com/CommentView,guid,7f97d63e-24c6-4455-a7c8-6452e0b23b19.aspx</comments>
      <category>Dev Stuff</category>
      <category>WCF</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnetdude.com/Trackback.aspx?guid=6f2ef28b-fbd6-4f3c-b978-b999b4c230c4</trackback:ping>
      <pingback:server>http://www.dotnetdude.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnetdude.com/PermaLink,guid,6f2ef28b-fbd6-4f3c-b978-b999b4c230c4.aspx</pingback:target>
      <dc:creator>Miguel A. Castro</dc:creator>
      <wfw:comment>http://www.dotnetdude.com/CommentView,guid,6f2ef28b-fbd6-4f3c-b978-b999b4c230c4.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnetdude.com/SyndicationService.asmx/GetEntryCommentsRss?guid=6f2ef28b-fbd6-4f3c-b978-b999b4c230c4</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
WCF 4.0 incorporates the features previously only obtainable via the REST Starter
kit for .NET 3.5.  Among the features included is the ability to cache REST requests
using a similar technique to caching ASP.NET pages.
</p>
        <p>
The 4.0 version of the <strong>System.ServiceModel.Web</strong> assembly includes
an attribute called <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.aspnetcacheprofileattribute.aspx" target="_blank">AspNetCacheProfile</a> which
takes a string as an argument.  The attribute is to be used on a service contract
operation as follows:
</p>
        <pre class="brush: csharp; ruler: true;">[OperationContract]
[WebGet(UriTemplate = "/{name}/getGreeting.xml",
        BodyStyle = WebMessageBodyStyle.Bare,
        RequestFormat = WebMessageFormat.Xml,
        ResponseFormat = WebMessageFormat.Xml)]
[AspNetCacheProfile("CacheFor10Seconds")]
string GetGreetingXml(string name);
</pre>
        <p>
 
</p>
        <p>
The string points to a cache profile to be defined in the <strong><system.web></system.web></strong>config section as follows:
</p>
        <pre class="brush: xml; ruler: true;">
          <caching>
            <outputcachesettings>
              <outputcacheprofiles>
                <add varybyparam="format" duration="10" name="CacheFor10Seconds" />
              </outputcacheprofiles>
            </outputcachesettings>
          </caching>
        </pre>
        <p>
 
</p>
        <p>
As you can see, this is pretty much identical to setting up cache profiles for ASPX
pages.  The effect is pretty much what you would expect, the caching of a REST
request.  This can be proven and tested by implementing the above contract as
such:
</p>
        <pre class="brush: csharp; ruler: true;">public string GetGreetingXml(string name)
{
    return string.Format("Hello {0}.  The time is {1}", name, DateTime.Now.ToLongTimeString());
}
</pre>
        <p>
 
</p>
        <p>
Now you can refresh the request and you’ll see the same time for 10 seconds before
it changes; once again, the same effect as in caching an ASPX page.
</p>
        <p>
So what did I learn the hard way you ask?  Well, common sense dictates that the
request go through ASP.NET in order to use its caching capability.  This not
only means that you have to host in IIS or WAS, but also that you need to turn on
ASP.NET compatibility mode.  This shifts the processing of the REST request over
to an HTTP handler that also sets an HTTP Context for you, something not normally
done with conventional IIS hosting for REST services.  To turn this on, you must
enable it in the <strong><servicehostingenvironment></servicehostingenvironment></strong>section under the <strong><system.servicemodel></system.servicemodel></strong>section using the <strong>aspNetCompatibilityEnabled</strong> attribute. 
Not only that, but you have to “allow” it on the service using the <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.activation.aspnetcompatibilityrequirementsattribute.aspx" target="_blank">AspNetCompatibilityRequirements</a> attribute.
</p>
        <p>
This part was not a surprise for me since I was already familiar with this technique
and the added scope your service receives because it.  I’m referring to the entire
HTTP Context including session, application, cache, etc.  Keep in mind that this
is not for everything and should be used in very specific scenarios as it ties the
service to the hosting style quite tightly.
</p>
        <p>
What drove me crazy is something I’m surprised I did not notice in the past and that
is the fact that your REST requests will not work while using the Visual Studio development
server.  Meaning you need to create an application in IIS and run it that way. 
No big deal but it drove me a little crazy since the meta data exposure worked fine,
and so did the new HTML Help pages (another new feature in WCF 4.0 For REST). 
But the second I tried to request one of my URLs, it bombed out.  Once I set
up my application under IIS, everything was fine.
</p>
        <p>
I have to give credit where it’s due and thank Jon Flanders.  I found the answer
in his book <a href="http://www.amazon.com/RESTful-NET-Build-Consume-Services/dp/0596519206/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1274734177&amp;sr=1-1" target="_blank">Restful
.NET</a> from O’Reilly press.
</p>
        <h3>
          <em>Until next time…</em>
        </h3>
        <img width="0" height="0" src="http://www.dotnetdude.com/aggbug.ashx?id=6f2ef28b-fbd6-4f3c-b978-b999b4c230c4" />
      </body>
      <title>What I learned the hard way about WCF REST Services Caching</title>
      <guid isPermaLink="false">http://www.dotnetdude.com/PermaLink,guid,6f2ef28b-fbd6-4f3c-b978-b999b4c230c4.aspx</guid>
      <link>http://www.dotnetdude.com/2010/05/24/WhatILearnedTheHardWayAboutWCFRESTServicesCaching.aspx</link>
      <pubDate>Mon, 24 May 2010 20:50:14 GMT</pubDate>
      <description>&lt;p&gt;
WCF 4.0 incorporates the features previously only obtainable via the REST Starter
kit for .NET 3.5.&amp;nbsp; Among the features included is the ability to cache REST requests
using a similar technique to caching ASP.NET pages.
&lt;/p&gt;
&lt;p&gt;
The 4.0 version of the &lt;strong&gt;System.ServiceModel.Web&lt;/strong&gt; assembly includes
an attribute called &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.aspnetcacheprofileattribute.aspx" target="_blank"&gt;AspNetCacheProfile&lt;/a&gt; which
takes a string as an argument.&amp;nbsp; The attribute is to be used on a service contract
operation as follows:
&lt;/p&gt;
&lt;pre class="brush: csharp; ruler: true;"&gt;[OperationContract]
[WebGet(UriTemplate = "/{name}/getGreeting.xml",
        BodyStyle = WebMessageBodyStyle.Bare,
        RequestFormat = WebMessageFormat.Xml,
        ResponseFormat = WebMessageFormat.Xml)]
[AspNetCacheProfile("CacheFor10Seconds")]
string GetGreetingXml(string name);
&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
The string points to a cache profile to be defined in the &lt;strong&gt;
&lt;system.web&gt;
&lt;/strong&gt;config section as follows:
&lt;/p&gt;
&lt;pre class="brush: xml; ruler: true;"&gt;
&lt;caching&gt;
&lt;outputcachesettings&gt;
&lt;outputcacheprofiles&gt;
&lt;add varybyparam="format" duration="10" name="CacheFor10Seconds" /&gt;
&lt;/outputcacheprofiles&gt;
&lt;/outputcachesettings&gt;
&lt;/caching&gt;
&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
As you can see, this is pretty much identical to setting up cache profiles for ASPX
pages.&amp;nbsp; The effect is pretty much what you would expect, the caching of a REST
request.&amp;nbsp; This can be proven and tested by implementing the above contract as
such:
&lt;/p&gt;
&lt;pre class="brush: csharp; ruler: true;"&gt;public string GetGreetingXml(string name)
{
    return string.Format("Hello {0}.  The time is {1}", name, DateTime.Now.ToLongTimeString());
}
&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Now you can refresh the request and you’ll see the same time for 10 seconds before
it changes; once again, the same effect as in caching an ASPX page.
&lt;/p&gt;
&lt;p&gt;
So what did I learn the hard way you ask?&amp;nbsp; Well, common sense dictates that the
request go through ASP.NET in order to use its caching capability.&amp;nbsp; This not
only means that you have to host in IIS or WAS, but also that you need to turn on
ASP.NET compatibility mode.&amp;nbsp; This shifts the processing of the REST request over
to an HTTP handler that also sets an HTTP Context for you, something not normally
done with conventional IIS hosting for REST services.&amp;nbsp; To turn this on, you must
enable it in the &lt;strong&gt;
&lt;servicehostingenvironment&gt;
&lt;/strong&gt;section under the &lt;strong&gt;
&lt;system.servicemodel&gt;
&lt;/strong&gt;section using the &lt;strong&gt;aspNetCompatibilityEnabled&lt;/strong&gt; attribute.&amp;nbsp;
Not only that, but you have to “allow” it on the service using the &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.activation.aspnetcompatibilityrequirementsattribute.aspx" target="_blank"&gt;AspNetCompatibilityRequirements&lt;/a&gt; attribute.
&lt;/p&gt;
&lt;p&gt;
This part was not a surprise for me since I was already familiar with this technique
and the added scope your service receives because it.&amp;nbsp; I’m referring to the entire
HTTP Context including session, application, cache, etc.&amp;nbsp; Keep in mind that this
is not for everything and should be used in very specific scenarios as it ties the
service to the hosting style quite tightly.
&lt;/p&gt;
&lt;p&gt;
What drove me crazy is something I’m surprised I did not notice in the past and that
is the fact that your REST requests will not work while using the Visual Studio development
server.&amp;nbsp; Meaning you need to create an application in IIS and run it that way.&amp;nbsp;
No big deal but it drove me a little crazy since the meta data exposure worked fine,
and so did the new HTML Help pages (another new feature in WCF 4.0 For REST).&amp;nbsp;
But the second I tried to request one of my URLs, it bombed out.&amp;nbsp; Once I set
up my application under IIS, everything was fine.
&lt;/p&gt;
&lt;p&gt;
I have to give credit where it’s due and thank Jon Flanders.&amp;nbsp; I found the answer
in his book &lt;a href="http://www.amazon.com/RESTful-NET-Build-Consume-Services/dp/0596519206/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1274734177&amp;amp;sr=1-1" target="_blank"&gt;Restful
.NET&lt;/a&gt; from O’Reilly press.
&lt;/p&gt;
&lt;h3&gt;&lt;em&gt;Until next time…&lt;/em&gt;
&lt;/h3&gt;
&lt;img width="0" height="0" src="http://www.dotnetdude.com/aggbug.ashx?id=6f2ef28b-fbd6-4f3c-b978-b999b4c230c4" /&gt;</description>
      <comments>http://www.dotnetdude.com/CommentView,guid,6f2ef28b-fbd6-4f3c-b978-b999b4c230c4.aspx</comments>
      <category>Dev Stuff</category>
      <category>WCF</category>
    </item>
    <item>
      <trackback:ping>http://www.dotnetdude.com/Trackback.aspx?guid=dcfc4c99-2794-4787-8f81-c3b1223f9ea1</trackback:ping>
      <pingback:server>http://www.dotnetdude.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.dotnetdude.com/PermaLink,guid,dcfc4c99-2794-4787-8f81-c3b1223f9ea1.aspx</pingback:target>
      <dc:creator>Miguel A. Castro</dc:creator>
      <wfw:comment>http://www.dotnetdude.com/CommentView,guid,dcfc4c99-2794-4787-8f81-c3b1223f9ea1.aspx</wfw:comment>
      <wfw:commentRss>http://www.dotnetdude.com/SyndicationService.asmx/GetEntryCommentsRss?guid=dcfc4c99-2794-4787-8f81-c3b1223f9ea1</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In the never-ending quest to keep my site up-to-date, I wanted to add a “latest tweet”
area to the top of my blog.  All these tweakings I’ve done (the syntax highlighter,
licensing, branding, etc) were actually inspired by a talk that <a href="http://www.hanselman.com" target="_blank">Scott
Hanselman</a> made in <a href="http://www.dotnetdude.com/2010/03/06/CairoCodeCampReviewFiles.aspx" target="_blank">Cairo
Code Camp</a> on making your blog suck less.  The talk is based on <a href="http://www.hanselman.com/blog/BlogInteresting32WaysToKeepYourBlogFromSucking.aspx" target="_blank">this
posting</a> he made some time ago.  I’ll post on all the tweakings I’ve done
later; let’s get back to the Twitter feed.
</p>
        <p>
The Twitter site self has a section where you can step through creating an <a href="http://twitter.com/badges" target="_blank">embedded
Twitter feed</a>, either in Flash or HTML.  In fact if you Google or Bing the
phrase “embed twitter feed on website”, you’ll see many different techniques. 
The one I used is the one right off the <a href="http://twitter.com/widgets/html_widget" target="_blank">Twitter
site</a>.
</p>
        <p>
After walking through the wizard, the site gives you this code:
</p>
        <pre class="brush: xml;">&lt;div id="twitter_div"&gt;
    &lt;h2 class="sidebar-title"&gt;Twitter Updates&lt;/h2&gt;
    &lt;ul id="twitter_update_list"&gt;&lt;/ul&gt;
    &lt;a href="http://twitter.com/miguelcastro67" id="twitter-link" style="display:block;text-align:right;"&gt;follow me on Twitter&lt;/a&gt;
&lt;/div&gt;
&lt;script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://twitter.com/statuses/user_timeline/miguelcastro67.json?callback=twitterCallback2&amp;count=5"&gt;&lt;/script&gt;
</pre>
        <p>
I first inserted this code as-is, just to get things working (my usual approach to
things).  The <strong>div</strong> tag was inserted into my <strong>homeTemplate.blogTemplate</strong> in
the area where I wanted to display my Twitter feed.  In my case, this was just
below the area that shows the admin bar (shown only when logged in).  The two <strong>script</strong> tags
need to be placed at the bottom of the same file, just above the closing <strong>body</strong> tag. 
This displayed my last five tweets in a unordered list.  The first script tag
includes the function that the Twitter site will call back to after retrieving my
feed information.  The second script tag makes the call to the Twitter API and
defines the name of the callback function defined in the first script.  This
worked fine but I wanted a different look.
</p>
        <p>
The first thing I did to modify the display is to browse to the <a href="http://twitter.com/javascripts/blogger.js">http://twitter.com/javascripts/blogger.js</a> link
and place the function in a javascript file in my site; then I replaced the <strong>src</strong> attribute
in the first script tag to point at my function.  The results of this of course
were no different than before – good.
</p>
        <p>
Next I modified the <strong>div</strong> section for my display to look like this:
</p>
        <pre class="brush: xml;">&lt;div class="twitter-div"&gt;
    &lt;a class="twitter-header" href="http://twitter.com/miguelcastro67" alt="Follow me on Twitter"&gt;Last Tweet:&lt;/a&gt;&amp;nbsp;
    &lt;span id="twitter-post" class="twitter-post"&gt;&lt;i&gt;retrieving last tweet...&lt;/i&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;br/&gt;
</pre>
        <p>
 
</p>
        <p>
As you can see, I eliminated the unordered list and replaced it with something more
simple, that’s one line only, and that expects only one tweet.  Then I took the
function I had obtained from the blogger.js file and modified to look like this:
</p>
        <pre class="brush: js;">function twitterCallback(twitters) 
{
    var statusHTML = [];
    var username = twitters[0].user.screen_name;
    var status = twitters[0].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\&lt;\&gt;]*[^.,;'"&gt;\:\s\&lt;\&gt;\)\]\!])/g, function(url) {
        return '&lt;a href="' + url + '"&gt;' + url + '&lt;/a&gt;';
    }).replace(/\B@([_a-z0-9]+)/ig, function(reply) {
        return reply.charAt(0) + '&lt;a href="http://twitter.com/' + reply.substring(1) + '"&gt;' + reply.substring(1) + '&lt;/a&gt;';
    });
    statusHTML.push('&lt;span&gt;' + status + '&lt;/span&gt; - &lt;a style="font-size:85%" href="http://twitter.com/' + username + '/statuses/' + twitters[0].id + '"&gt;' + relative_time(twitters[0].created_at) + '&lt;/a&gt;');
    document.getElementById('twitter-post').innerHTML = statusHTML.join('');
}

function relative_time(time_value)<br />
{ var values = time_value.split(" "); time_value = values[1] + " " + values[2] + ",
" + values[5] + " " + values[3]; var parsed_date = Date.parse(time_value); var relative_to
= (arguments.length &gt; 1) ? arguments[1] : new Date(); var delta = parseInt((relative_to.getTime()
- parsed_date) / 1000); delta = delta + (relative_to.getTimezoneOffset() * 60); if
(delta &lt; 60) { return 'less than a minute ago'; } else if (delta &lt; 120) { return
'about a minute ago'; } else if (delta &lt; (60 * 60)) { return (parseInt(delta /
60)).toString() + ' minutes ago'; } else if (delta &lt; (120 * 60)) { return 'about
an hour ago'; } else if (delta &lt; (24 * 60 * 60)) { return 'about ' + (parseInt(delta
/ 3600)).toString() + ' hours ago'; } else if (delta &lt; (48 * 60 * 60)) { return
'1 day ago'; } else { return (parseInt(delta / 86400)).toString() + ' days ago'; }
} </pre>
        <p>
Now I only worry about one tweet and display information about that tweet into the
inner section of the <strong>span</strong> tag called <strong>twitter-post</strong>. 
Incidentally, the original callback function looked like this:
</p>
        <pre class="brush: js;">function twitterCallback2(twitters) {
    var statusHTML = [];
    for (var i = 0; i &lt; twitters.length; i++) {
        var username = twitters[i].user.screen_name;
        var status = twitters[i].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\&lt;\&gt;]*[^.,;'"&gt;\:\s\&lt;\&gt;\)\]\!])/g, function(url) {
            return '&lt;a href="' + url + '"&gt;' + url + '&lt;/a&gt;';
        }).replace(/\B@([_a-z0-9]+)/ig, function(reply) {
            return reply.charAt(0) + '&lt;a href="http://twitter.com/' + reply.substring(1) + '"&gt;' + reply.substring(1) + '&lt;/a&gt;';
        });
        statusHTML.push('&lt;li&gt;&lt;span&gt;' + status + '&lt;/span&gt; - &lt;a style="font-size:85%" href="http://twitter.com/' + username + '/statuses/' + twitters[i].id + '"&gt;' + relative_time(twitters[i].created_at) + '&lt;/a&gt;&lt;/li&gt;');
    }
    document.getElementById('twitter_update_list').innerHTML = statusHTML.join('');
}
</pre>
        <p>
 
</p>
        <p>
Obviously I changed the name in the call to the Twitter API to use the callback function <strong>twitterCallback</strong> instead
of the original <strong>twitterCallback2</strong>, but of course this can be anything
so long as the two match.
</p>
        <p>
The last change was to change the <strong>count</strong> attribute in the call to
the Twitter API to <strong>1</strong> instead of <strong>5</strong>.  This wasn’t
crucial since I was only dealing with array item <strong>0</strong> in my callback
function, but in the interest of getting as much performance as possible I thought
it was a good idea.
</p>
        <p>
I added the style sheet tags to make the display look the way I wanted and voila. 
Because of the callback-nature of this technique, the blog page will render first
while the call to the Twitter API is made and in the meantime I display a “retrieving…”
message.
</p>
        <p>
Until next time.
</p>
        <img width="0" height="0" src="http://www.dotnetdude.com/aggbug.ashx?id=dcfc4c99-2794-4787-8f81-c3b1223f9ea1" />
      </body>
      <title>How to add a “Latest Tweet” area to the top of your site</title>
      <guid isPermaLink="false">http://www.dotnetdude.com/PermaLink,guid,dcfc4c99-2794-4787-8f81-c3b1223f9ea1.aspx</guid>
      <link>http://www.dotnetdude.com/2010/03/16/HowToAddALatestTweetAreaToTheTopOfYourSite.aspx</link>
      <pubDate>Tue, 16 Mar 2010 20:54:16 GMT</pubDate>
      <description>&lt;p&gt;
In the never-ending quest to keep my site up-to-date, I wanted to add a “latest tweet”
area to the top of my blog.&amp;nbsp; All these tweakings I’ve done (the syntax highlighter,
licensing, branding, etc) were actually inspired by a talk that &lt;a href="http://www.hanselman.com" target="_blank"&gt;Scott
Hanselman&lt;/a&gt; made in &lt;a href="http://www.dotnetdude.com/2010/03/06/CairoCodeCampReviewFiles.aspx" target="_blank"&gt;Cairo
Code Camp&lt;/a&gt; on making your blog suck less.&amp;nbsp; The talk is based on &lt;a href="http://www.hanselman.com/blog/BlogInteresting32WaysToKeepYourBlogFromSucking.aspx" target="_blank"&gt;this
posting&lt;/a&gt; he made some time ago.&amp;nbsp; I’ll post on all the tweakings I’ve done
later; let’s get back to the Twitter feed.
&lt;/p&gt;
&lt;p&gt;
The Twitter site self has a section where you can step through creating an &lt;a href="http://twitter.com/badges" target="_blank"&gt;embedded
Twitter feed&lt;/a&gt;, either in Flash or HTML.&amp;nbsp; In fact if you Google or Bing the
phrase “embed twitter feed on website”, you’ll see many different techniques.&amp;nbsp;
The one I used is the one right off the &lt;a href="http://twitter.com/widgets/html_widget" target="_blank"&gt;Twitter
site&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
After walking through the wizard, the site gives you this code:
&lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;div id="twitter_div"&amp;gt;
    &amp;lt;h2 class="sidebar-title"&amp;gt;Twitter Updates&amp;lt;/h2&amp;gt;
    &amp;lt;ul id="twitter_update_list"&amp;gt;&amp;lt;/ul&amp;gt;
    &amp;lt;a href="http://twitter.com/miguelcastro67" id="twitter-link" style="display:block;text-align:right;"&amp;gt;follow me on Twitter&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="http://twitter.com/statuses/user_timeline/miguelcastro67.json?callback=twitterCallback2&amp;amp;count=5"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
I first inserted this code as-is, just to get things working (my usual approach to
things).&amp;nbsp; The &lt;strong&gt;div&lt;/strong&gt; tag was inserted into my &lt;strong&gt;homeTemplate.blogTemplate&lt;/strong&gt; in
the area where I wanted to display my Twitter feed.&amp;nbsp; In my case, this was just
below the area that shows the admin bar (shown only when logged in).&amp;nbsp; The two &lt;strong&gt;script&lt;/strong&gt; tags
need to be placed at the bottom of the same file, just above the closing &lt;strong&gt;body&lt;/strong&gt; tag.&amp;nbsp;
This displayed my last five tweets in a unordered list.&amp;nbsp; The first script tag
includes the function that the Twitter site will call back to after retrieving my
feed information.&amp;nbsp; The second script tag makes the call to the Twitter API and
defines the name of the callback function defined in the first script.&amp;nbsp; This
worked fine but I wanted a different look.
&lt;/p&gt;
&lt;p&gt;
The first thing I did to modify the display is to browse to the &lt;a href="http://twitter.com/javascripts/blogger.js"&gt;http://twitter.com/javascripts/blogger.js&lt;/a&gt; link
and place the function in a javascript file in my site; then I replaced the &lt;strong&gt;src&lt;/strong&gt; attribute
in the first script tag to point at my function.&amp;nbsp; The results of this of course
were no different than before – good.
&lt;/p&gt;
&lt;p&gt;
Next I modified the &lt;strong&gt;div&lt;/strong&gt; section for my display to look like this:
&lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;div class="twitter-div"&amp;gt;
    &amp;lt;a class="twitter-header" href="http://twitter.com/miguelcastro67" alt="Follow me on Twitter"&amp;gt;Last Tweet:&amp;lt;/a&amp;gt;&amp;amp;nbsp;
    &amp;lt;span id="twitter-post" class="twitter-post"&amp;gt;&amp;lt;i&amp;gt;retrieving last tweet...&amp;lt;/i&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;br/&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
As you can see, I eliminated the unordered list and replaced it with something more
simple, that’s one line only, and that expects only one tweet.&amp;nbsp; Then I took the
function I had obtained from the blogger.js file and modified to look like this:
&lt;/p&gt;
&lt;pre class="brush: js;"&gt;function twitterCallback(twitters) 
{
    var statusHTML = [];
    var username = twitters[0].user.screen_name;
    var status = twitters[0].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\&amp;lt;\&amp;gt;]*[^.,;'"&amp;gt;\:\s\&amp;lt;\&amp;gt;\)\]\!])/g, function(url) {
        return '&amp;lt;a href="' + url + '"&amp;gt;' + url + '&amp;lt;/a&amp;gt;';
    }).replace(/\B@([_a-z0-9]+)/ig, function(reply) {
        return reply.charAt(0) + '&amp;lt;a href="http://twitter.com/' + reply.substring(1) + '"&amp;gt;' + reply.substring(1) + '&amp;lt;/a&amp;gt;';
    });
    statusHTML.push('&amp;lt;span&amp;gt;' + status + '&amp;lt;/span&amp;gt; - &amp;lt;a style="font-size:85%" href="http://twitter.com/' + username + '/statuses/' + twitters[0].id + '"&amp;gt;' + relative_time(twitters[0].created_at) + '&amp;lt;/a&amp;gt;');
    document.getElementById('twitter-post').innerHTML = statusHTML.join('');
}

function relative_time(time_value)&lt;br&gt;
{ var values = time_value.split(" "); time_value = values[1] + " " + values[2] + ",
" + values[5] + " " + values[3]; var parsed_date = Date.parse(time_value); var relative_to
= (arguments.length &amp;gt; 1) ? arguments[1] : new Date(); var delta = parseInt((relative_to.getTime()
- parsed_date) / 1000); delta = delta + (relative_to.getTimezoneOffset() * 60); if
(delta &amp;lt; 60) { return 'less than a minute ago'; } else if (delta &amp;lt; 120) { return
'about a minute ago'; } else if (delta &amp;lt; (60 * 60)) { return (parseInt(delta /
60)).toString() + ' minutes ago'; } else if (delta &amp;lt; (120 * 60)) { return 'about
an hour ago'; } else if (delta &amp;lt; (24 * 60 * 60)) { return 'about ' + (parseInt(delta
/ 3600)).toString() + ' hours ago'; } else if (delta &amp;lt; (48 * 60 * 60)) { return
'1 day ago'; } else { return (parseInt(delta / 86400)).toString() + ' days ago'; }
} &lt;/pre&gt;
&lt;p&gt;
Now I only worry about one tweet and display information about that tweet into the
inner section of the &lt;strong&gt;span&lt;/strong&gt; tag called &lt;strong&gt;twitter-post&lt;/strong&gt;.&amp;nbsp;
Incidentally, the original callback function looked like this:
&lt;/p&gt;
&lt;pre class="brush: js;"&gt;function twitterCallback2(twitters) {
    var statusHTML = [];
    for (var i = 0; i &amp;lt; twitters.length; i++) {
        var username = twitters[i].user.screen_name;
        var status = twitters[i].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\&amp;lt;\&amp;gt;]*[^.,;'"&amp;gt;\:\s\&amp;lt;\&amp;gt;\)\]\!])/g, function(url) {
            return '&amp;lt;a href="' + url + '"&amp;gt;' + url + '&amp;lt;/a&amp;gt;';
        }).replace(/\B@([_a-z0-9]+)/ig, function(reply) {
            return reply.charAt(0) + '&amp;lt;a href="http://twitter.com/' + reply.substring(1) + '"&amp;gt;' + reply.substring(1) + '&amp;lt;/a&amp;gt;';
        });
        statusHTML.push('&amp;lt;li&amp;gt;&amp;lt;span&amp;gt;' + status + '&amp;lt;/span&amp;gt; - &amp;lt;a style="font-size:85%" href="http://twitter.com/' + username + '/statuses/' + twitters[i].id + '"&amp;gt;' + relative_time(twitters[i].created_at) + '&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;');
    }
    document.getElementById('twitter_update_list').innerHTML = statusHTML.join('');
}
&lt;/pre&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Obviously I changed the name in the call to the Twitter API to use the callback function &lt;strong&gt;twitterCallback&lt;/strong&gt; instead
of the original &lt;strong&gt;twitterCallback2&lt;/strong&gt;, but of course this can be anything
so long as the two match.
&lt;/p&gt;
&lt;p&gt;
The last change was to change the &lt;strong&gt;count&lt;/strong&gt; attribute in the call to
the Twitter API to &lt;strong&gt;1&lt;/strong&gt; instead of &lt;strong&gt;5&lt;/strong&gt;.&amp;nbsp; This wasn’t
crucial since I was only dealing with array item &lt;strong&gt;0&lt;/strong&gt; in my callback
function, but in the interest of getting as much performance as possible I thought
it was a good idea.
&lt;/p&gt;
&lt;p&gt;
I added the style sheet tags to make the display look the way I wanted and voila.&amp;nbsp;
Because of the callback-nature of this technique, the blog page will render first
while the call to the Twitter API is made and in the meantime I display a “retrieving…”
message.
&lt;/p&gt;
&lt;p&gt;
Until next time.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.dotnetdude.com/aggbug.ashx?id=dcfc4c99-2794-4787-8f81-c3b1223f9ea1" /&gt;</description>
      <comments>http://www.dotnetdude.com/CommentView,guid,dcfc4c99-2794-4787-8f81-c3b1223f9ea1.aspx</comments>
      <category>Dev Stuff</category>
    </item>
  </channel>
</rss>