0 Comments

Gravatar is a service that associates your e-mail addresses with a picture of you for use on blog comments, forums and bulletin boards. I’ve been a happy user for years.

A cool thing about Gravatar images is that they can be used from any application either on a website or a desktop application. But still, they are primarily used on blogs and forums.

Today, I played with the thought of a wider use and wrote some code that makes working with Gravatars very easy on both web and the desktop. The reason for this is that I needed a way to collect Gravatar images for a list of users, but only the users that actually have a Gravatar associated with their e-mail address.

The Gravatar service doesn’t have an API you can use to check if an e-mail address is associated or not. But by downloading a Gravatar image, the response header Last-Modifed is 1970-01-01 if no image is found and the default image is returned. This information can be used to only store the images users have uploaded to the Gravatar service.

An example

The class is called Gravatar and is very simple and small. Here is an example of using the class to download a Gravatar image and save it to disk.

string email = "name@example.com";

Gravatar gravatar = new Gravatar(email);

 

if (!gravatar.IsDefaultImage)

{

  using (FileStream writer = new FileStream("c:\\" + email + ".jpg", FileMode.Create))

  {

    writer.Write(gravatar.Image, 0, gravatar.Image.Length);

  }

}

Download

Download the class below and put it in your App_Code folder. Then you can use the example above from any ASP.NET page or control.

Gravatar.zip (888,00 bytes)

3 Comments

All blog platforms send out pings using the XML-RPC protocol whenever a new post is created or an old one is updated. It is very simple to send out XML-RPC pings using C#, because it is just a normal HTTP request with some XML in the request body. See here how to ping using C#.

To send a ping is the client part of the transaction. There must also be a server to intercept the ping – an endpoint. Feedburner is probably the most widely used by blogs at the moment. What happens is that when you write a post, the blog engine sends a ping to Feedburner’s XML-RPC endpoint. In the XML body of the ping request is the URL of your blog so Feedburner knows who sent the ping. It then retrieves your blog’s RSS feed, parses it, and spits it out to your readers. That’s how simple and powerful it is to use XML-RPC pings.

In an earlier post I showed you how to write the ping client, now let’s look at the server or endpoint. The endpoint can be used by any service that needs to be notified whenever content is updated on a website. That goes for all applications that listen to RSS feeds for instance.

The code

In 100 lines of code including comments, we are able to build an XML-RPC ping server endpoint. All it has to do is to listen for POST requests and parse the XML sent in the request body as shown in my earlier post. By parsing the XML it can find the URL that has been updated. The method HandleUrl is where the URL is passed to and it’s from here you write your logic to handle the ping request.

#region Using

 

using System;

using System.IO;

using System.Net;

using System.Xml;

using System.Web;

 

#endregion

 

public class XML_RPC : IHttpHandler

{

 

  ///<summary>

  ///Handles the URL that was sent by the ping request.

  ///</summary>

  private void HandleUrl(Uri url)

  {

    //This is where you write the code for handing the incoming URL.

    //It is the only place you need to change.

    HttpContext.Current.Response.Write(url);

  }

 

  #region Parse the request

 

  ///<summary>

  ///Parses the request body and returns the URL.

  ///</summary>

  private static string ParseXml(string xml)

  {

    XmlDocument doc = new XmlDocument();

    doc.LoadXml(xml);

 

    string methodName = doc.SelectSingleNode("//methodName").InnerText;

    if (methodName == "weblogUpdates.ping")

    {

      XmlNodeList values = doc.SelectNodes("//value");

      if (values.Count == 2)

      {

        return values[1].InnerText;

      }

    }

 

    throw new NotSupportedException("'" + methodName + "' XML-RPC method not supported");

  }

 

  ///<summary>

  ///Receives this content from the current HTTP request stream.

  ///</summary>

  public static string ReceiveBody()

  {

    using (StreamReader reader = new StreamReader(HttpContext.Current.Request.InputStream))

    {

      return reader.ReadToEnd();

    }

  }

 

  #endregion

 

  #region IHttpHandler members

 

  ///<summary>

  ///Gets a value indicating whether another request can use the<see cref="T:System.Web.IHttpHandler"></see>instance.

  ///</summary>

  ///<value></value>

  ///<returns>true if the<see cref="T:System.Web.IHttpHandler"></see>instance is reusable; otherwise, false.</returns>

  public bool IsReusable

  {

    get { return false; }

  }

 

  ///<summary>

  ///Enables processing of HTTP Web requests by a custom HttpHandler that implements the<see cref="T:System.Web.IHttpHandler"></see>interface.

  ///</summary>

  ///<param name="context">An<see cref="T:System.Web.HttpContext"></see>object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>

  public void ProcessRequest(HttpContext context)

  {

    string body = ReceiveBody();

 

    if (!string.IsNullOrEmpty(body))

    {

      try

      {

        string parsedUrl = ParseXml(body);

        Uri url;

 

        if (Uri.TryCreate(parsedUrl, UriKind.Absolute, out url))

          HandleUrl(url);

      }

      catch (Exception ex)

      {

        // Put whatever error handling you like here.

        context.Response.Write(ex.Message);

      }

    }

  }

 

  #endregion

 

}

Implementation

To use this XML-RPC server class you need to download the class below and put it in your App_Code folder. Then you need to register the handler in the web.config like so:

<httpHandlers>
  <add verb="*" path="xml-rpc.axd" type="XML_RPC" />
</httpHandlers>

The endpoint will then be located at example.com/xml-rpc.axd. The last thing you need is to add some logic to the HandleUrl method of the class and you are ready to go.

XML-RPC.zip (1,18 kb)

0 Comments

I experienced a strange behaviour with the DateTime class and formatting today. For some reason this error only occurs when you format a DateTime in certain cultures like Italian. The error is not present in English, Danish and most other cultures.

It happens when you use the DateTime.ToString and DateTime.ParseExact methods. When you write the following:

String date = DateTime.Now.ToString("yyyy-MM-dd HH:mm")

You would expect the date variable to be formatted like so 2008-01-05 11:30. In Italian it doesn’t. Instead it replaces the colon with a period which produces this 2008-01-05 11.30. This might be correctly formatted for the Italian culture, but I explicitly wrote I wanted the colon delimiter in the format string. However, there is a workaround.

All you need is to change the format string into a less obvious one. The following produces the right colon delimited date and time string:

String date = DateTime.Now.ToString("yyyy-MM-dd HH\\:mm")

Strangely enough, you have to escape the colon with two backslashes for it to work. This trick seems to work in all cultures.

0 Comments

For so many years I’ve written code that needed to know whether or not a collection of objects has been changed or not. Now I’ve finally written the code that tells me just that.

The scenario is typical. You have a class called Order with a property called OrderLines which is a generic List containing OrderLine objects. You retrieve the Order class from the database including all the OrderLines, change some properties and then you save the Order object back to the database. Now the question is if you need to save the OrderLines as well. To know that, you need to know if the OrderLines collection has been changed. It would be a waste of resource to persist all the order lines each time you make a modification to the Orders object. To know if it has changed, we need a list that is aware of its own state.

The StateList<T>

This class is a subclass of the List<T> generic class but with a few twists. It does exactly what a normal List<T> does, but has two new members – a MarkUnChanged method and an IsChanged property. It also overrides the GetHashCode method. That’s all it does.

The MarkUnChanged method tells the StateList what the original list contains. You call this method after you’ve retrieved all the OrderLines and populated the list. That let’s the StateList know what the comparison is for reference. Behind the scenes, the MarkUnChanged method stores the hash code of the items in the list in a private integer variable.

The IsChanged property returns a Boolean value that indicates whether or not the items in the list produce the same hash code as the one stored in the private variable. If it doesn’t, then the list is changed. This is the class.

[System.Serializable]

public class StateList<T> : System.Collections.Generic.List<T>

{

  public override int GetHashCode()

  {

    long hash = 0;

    foreach (T item in this)

    {

      hash += item.GetHashCode();

    }

 

    return hash.GetHashCode();

  }

 

  private int _HashCode = 0;

 

  ///<summary>

  ///Gets if this list's data has been changed.

  ///</summary>

  public virtual bool IsChanged

  {

    get

    {

      return this.GetHashCode() != _HashCode;

    }

  }

 

  ///<summary>

  ///Marks the object as being clean,

  ///which means not changed.

  ///</summary>

  public virtual void MarkUnChanged()

  {

    _HashCode = this.GetHashCode();

    base.TrimExcess();

  }

}

Example

Here is a little taste of how it works:

StateList<int> list = new StateList<int>();

list.Add(3);

list.Add(4);

list.Add(5);

// list.IsChanged = true

 

list.MarkUnChanged();

// list.IsChanged = false

 

list.Add(6);

// list.IsChanged = true

 

list.Clear();

list.Add(3);

list.Add(4);

list.Add(5);

// list.IsChanged = false

The order of the items

The code above produces the same hash code no matter in what order the individual items are located in the list. So if the same items are located in the list but at different locations, the IsChanged property is false. To support location awareness, you can just switch the overridden GetHashCode method with this one:

public override int GetHashCode()

{

  long hash = 0;

  for (int i = 0; i < this.Count; i++)

  {

    hash += this[i].GetHashCode() ^ i;

  }

 

  return hash.GetHashCode();

}

0 Comments

A month ago I challenged Simone to a friendly duel about who could get the best YSlow score. I did all sorts of things to improve the score but the one thing I never figured out was how to gzip compress the WebResource.axd handler. Then yesterday I was playing around with Fiddler and noticed that IE doesn’t cache WebResource.axd but loads it at every request to a page. Then I knew I had to do something about it and I might as well give the gzip compression another try.

I already have a HTTP compression module that works like a charm, so I just needed it to compress WebResource.axd and implement the right client cache mechanisms as well. Sounds simple right?

The compression

I knew this was my Achilles heel since I’ve failed at it before. Lucky for me, Miron Abramson just did it a week ago so I took a look at his solution. It was exactly what I needed, so I picked out the parts I needed and stuck them into my own compression module.

What Mirons code does is to create an HTTP request to the WebResource.axd, copy the response to a memory stream, compress it and serve it back to the client. That is a very clever approach but had a big problem. Every time the browser requested the WebResource.axd handler his module created an HTTP request. That was too big an overhead for me. I fixed it easily by caching the response at the first request and then served the compressed bytes from the cache from then on. Apart from that, his code rocks.

The caching

First of all I set the expires, last-modified and ETag HTTP headers that let’s any browser cache the response. Browsers are a little different when it comes to caching web resources so by specifying both an ETag and last-modified header takes care of them all.

Further more I added support for the If-None-Match request header. What it does is that when a page is refreshed by hitting F5 or similar, the browser sends the If-None-Match header to the server with the ETag as the value. Then I can simply check if the incoming ETag value is the same as the server ETag and terminate the response with a 304 Not modified response header.

That saves bandwidth and tells the browser to use the version from its cache instead of loading the content from the server again. The thing is that files served from WebResource.axd are always static so no harm can be done by using all means to let the browser cache them.

Limitations

The module expects that all files served by the WebResource.axd are JavaScript. That means that you probably run into trouble if you serve images or other file types from the WebResource.axd handler. Most websites don’t and I don’t like doing that in my projects, so that’s why I didn’t spend extra time on supporting it.

Download

Get the CompressionModule.cs file below to compress both your pages and WebResource.axd handler.

CompressionModule.zip (2,27 kb)

PS. I won the YSlow challenge.