With gravatars now becoming ubiquitous in blogs and forums, I have developed an ASP.NET Control that encapsulates their functionality in a simple, reusable component. It’s so easy to use, you can download and be using it on your ASP.NET sites within minutes.
I introduced the control in February of 2008, and updated the functionality in March of 2008.
I’ve since had a lot of interest in the source code for the control, and so this post describes how the control works, as well as providing a download containing the control, as well as the full control source and example website that uses the control.
OK, let me download it already!
Download the Control and get started. Note that the demo projects included in the ZIP were written in Visual Studio 2005, so if you’re using Visual Studio 2008, you’ll need to convert the solution. If you’ve not done a conversion before, just follow the instructions that Visual Studio provides. Please also note that the solution will not open in Express Editions, since they do not support control projects. However, you can still use the control that’s included in the ZIP file.
Unzip the .zip download, and you’ll have the following folder structure:
The root contains a small readme file, Visual Studio solution, FreshClickmedia.dll – the gravatar control assembly, Freshclickmedia.Web control project and GravatarSite website, which contains a few control examples.
Opening the solution in visual studio will give you this solution structure:
Fire up the website, and you should see something like this:
Examining the Code
<h1>Gravatar Examples</h1> <h2>My email address, size of 80 pixels:</h2> <fcm:Gravatar ID="Gravatar1" runat="server" Email="youremailaddress@domain.com" OutputGravatarSiteLink="true" Size="80" /> <h2>No email address, with default image (absolute url) specified:</h2> <fcm:Gravatar ID="Gravatar2" runat="server" Size="80" DefaultImage="http://farm3.static.flickr.com/2375/2552064340_192825f989_o.jpg" /> <h2>Email address not associated with Gravatar, with no default image:</h2> <fcm:Gravatar ID="Gravatar3" runat="server" Email="thisemaildoesnotexist@freshclickmedia.com" Size="80" />
The control requires an email address:
<fcm:Gravatar ID='Gravatar1' runat='server' Email='username@domain.com' />
For my email address, I get the following generated HTML:
And if we look at the generated source:
<a id="Gravatar1" href="http://www.gravatar.com" title="Get your avatar"><img width="80" height="80" src="http://www.gravatar.com/avatar.php?gravatar_id=ccf3b8c638f15d005e5d070aeb1a3923&rating=G&size=80" alt="Gravatar" /></a>
The default produces a hyperlink off to the Gravatar site with a title “Get your avatar”. The image contains the MD5 email hash, a rating of “G” (suitable for all audience types), and a size of 80.
Customisation
The control supports a number of properties supporting the customisation of its output.
Size
The size property of the control can be in the range 1 to 80. If it is outside this range, a default of 80 will be used.
MaxAllowedRating
The ‘highest’ allowed rating of image.
- A G rated gravatar is suitable for display on all websites with any audience type.
- PG rated gravatars contain may contain rude gestures, provocatively dressed individuals, the lesser swear words, or mild violence.
- R rated gravatars may contain such things as harsh profanity, intense violence, nudity, or hard drug use.
- X rated gravatars may contain hardcore sexual imagery or extremely disturbing violence.
OutputGravatarSiteLink
True by default, determines whether a hyperlink linking to the gravatar website will be output around the image.
LinkTitle
“Get your avatar” by default, allows the customisation of the ‘title’ attribute of the link (obviously doesn’t apply if OutputGravatarSiteLink property is set to false.)
DefaultImage
URL encoded URL, protocol included, of a GIF, JPEG, or PNG image that should be returned if either the requested email address has no associated gravatar, or that gravatar has a rating higher than is allowed by the “MaxAllowedRating” property.
The code snippet below shows the associated properties.
<fcm:Gravatar ID="Gravatar1" runat="server" Email="username@domain.com" DefaultImage="http://www.site.com/default.jpg" OutputGravatarSiteLink="true" Size="40" />
Examining the control code
The Gravatar control derives from System.Web.UI.WebControls.WebControl
and overrides the Render
method.
The various properties such as Email are all implemented as simple C# properties, with various attributes depending on the property.
[Bindable(true), Category("Appearance"), DefaultValue("80")] public short Size { get { return _size; } set { _size = value; } }
These properties are then used in the Render
method to write out HTML using the method’s HtmlTextWriter
parameter.
The Render
method begins by adding the default attributes to the render, ensuring that the size is within the valid range of 1 to 512, and initialises the gravatar URL:
AddAttributesToRender(output); // if the size property has been specified, ensure it is a short, and in the range // 1..512: try { // if it's not in the allowed range, throw an exception: if (Size < 1 || Size > 512) throw new ArgumentOutOfRangeException(); } catch { Size = 80; } // default the image url: string imageUrl = "http://www.gravatar.com/avatar.php?";
If an Email address has been supplied, the MD5CryptoServiceProvider
hashes the email and a StringBuilder
converts this to the required format:
if( !string.IsNullOrEmpty( Email)) { // build up image url, including MD5 hash for supplied email: MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); UTF8Encoding encoder = new UTF8Encoding(); MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider(); byte[] hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(Email)); StringBuilder sb = new StringBuilder(hashedBytes.Length * 2); for (int i = 0; i < hashedBytes.Length; i++) { sb.Append(hashedBytes[i].ToString("X2")); } // output parameters: imageUrl += "gravatar_id=" + sb.ToString().ToLower(); imageUrl += "&rating=" + MaxAllowedRating.ToString(); imageUrl += "&size=" + Size.ToString(); }
The final part of the method assigns a default image, if one has been specified, outputs the site ink, if required, outputs the required attributes and tags.
// output default parameter if specified if (!string.IsNullOrEmpty(DefaultImage)) { imageUrl += "&default=" + HttpUtility.UrlEncode(DefaultImage); } // if we need to output the site link: if (OutputGravatarSiteLink) { output.AddAttribute(HtmlTextWriterAttribute.Href, "http://www.gravatar.com"); output.AddAttribute(HtmlTextWriterAttribute.Title, LinkTitle); output.RenderBeginTag(HtmlTextWriterTag.A); } // output required attributes/img tag: output.AddAttribute(HtmlTextWriterAttribute.Width, Size.ToString()); output.AddAttribute(HtmlTextWriterAttribute.Height, Size.ToString()); output.AddAttribute(HtmlTextWriterAttribute.Src, imageUrl); output.AddAttribute(HtmlTextWriterAttribute.Alt, "Gravatar"); output.RenderBeginTag("img"); output.RenderEndTag(); // if we need to output the site link: if (OutputGravatarSiteLink) { output.RenderEndTag(); }
Using the control on your own projects
As previously mentioned, the download solution will not open properly in Express versions of Visual Studio, since it does not support control projects, but the control, included in the download is supported by all versions of Visual Studio, 2005 and later.
The easiest way to use the control is to add the control to the toolbox. To do this, ensure that you are in design mode (looking at a web page), and right click on the ‘Standard’ group header of the Toolbox. From the context menu, select “Choose Items” and browse to the assembly (Freshclickmedia.Web.dll), and click “OK” to add.
Once you’ve added the assembly, you should see the following:
From there, you can drag the control onto your page and start having fun!
First, thanks for posting your great source!
Second, I found that when this control was in a aspListView and the listview was posted back, the Email property wasn’t getting set because it was databound.
I added the following code to the Gravatar class and now the email property is saved in viewstate :):
protected override object SaveViewState()
{
return new Pair(base.SaveViewState(), _email );
}
protected override void LoadViewState(object savedState)
{
if (savedState != null)
{
Pair state = savedState as System.Web.UI.Pair;
if(state != null)
{
base.LoadViewState(state.First);
_email = (string)state.Second;
}
}
}
Thanks for your comment Kenneth. I’ll make the changes to my posted source when I get the chance, and credit you with the change.
I like this control. The source code is very clean and easily adaptable. I modified it only slightly to support ASP.NET 1.1 (my web site has been running on that for years) and am now using it on my Blog.
Thanks for making this available.
Thanks Shane for this control, and thanks Kenneth for posting the solution to the viewstate problem.
Thank you, I was looking for this code.
BIG ERROR!!!
System.Exception: Email should not be null or empty
But is not empty or NULL!!! this exception is throw when button click event is fired in FORMVIEW
i did go in degug to see if have email and it is there!!! please, help me…
@Ezequiel – Sorry to hear that you’re having problems with the control.
I tried putting the control in a formview, and couldn’t reproduce the error you mention.
Just to let you know, I created an object data source, which exposed several email addresses. This object data source was the data source for the form view control, and this form view control had a Gravatar control in it. I was able to page through the records without an issue.
Would you mind going into a little more detail?
Thanks for this, worked a treat.
I just tried your control on my ASP.NET MVC application is it works flawlessly! Great job! When I’m done with the site you’ll be added to the contributors. (By the way, it’s not being used on MVC Starter Kits) Thanks.
very good. but i want to ask you, which md5 you use?
Hi Mr.Cantus – I use the standard .NET MD5 class, to be found in the System.Security.Cryptography namespace.
Great control. I added a bool property UseSSL the defaults to false. Just after the declaration of string imgUrl, I added:
// if we use the secure URL for SSL:
if (UseSSL)
{
imageUrl = “https://secure.gravatar.com/avatar.php?”;
}
Now I can use it on secure (https) sites without the IE security warning.
Thanks for the contribution to the discussion SullivanDavid – it’s appreciated.
This is great, very easy to understand. Thanks so much.
Hi, Shane. Great control.
I was running into the same “System.Exception: Email should not be null or empty” error that Ezequiel reported above. In my case, the gravatar control was inside a repeater control on a page with a login control in the master. When a user logged out using the login control, I would get the error. The top of the stack looked like this:
FreshClickMedia.Web.UI.WebControls.Gravatar.Render(HtmlTextWriter output) +186
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
Here’s how I fixed it for me. My Page_Load looked like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Session[“Users”] = MembershipQueries.GetUsersWithRoles();
RepeaterUsers.DataSource = (IList)Session[“Users”];
RepeaterUsers.DataBind();
}
}
So, the repeater with the gravatar wasn’t rebinding on postback (which apparently occurs when the login control is used to logout), and I guess that’s how the email ended up being null. When I changed my Page_Load to this, the error went away:
protected void Page_Load(object sender, EventArgs e)
{
Session[“Users”] = MembershipQueries.GetUsersWithRoles();
RepeaterUsers.DataSource = (IList)Session[“Users”];
RepeaterUsers.DataBind();
}
Hope that will help someone else.
Hey Shane, I know it’s been around 4 years since you released this, but I just ran across it now and wanted to say thanks!
Time sure flies, but I always appreciate gratitude for my work. Glad you found it useful 🙂