Using the ASP.NET Chart Control With Multiple Web Roles In Windows Azure
May 20, 2010 In Development By Karsten JanuszewskiI use the ASP.NET Chart Control in Azure in an ASP.NET page with both markup and code-behind. I do this because the chart control overlays hrefs and tooltips on the chart. (Check out this post for a little more about how I use the charts: http://visitmix.com/LabNotes/ASPNET-Charts-and-ASPNET-MVC–Controller-vs-View.)
Things work fine if I configure the chart control to generate images in memory. But, with more than one web role, things break. This is expected, as the documentation states: “Do not use this [the memory storage] option in a server cluster or a multiple-process site.”
Somehow, I need to store the image to disk instead of memory, and then let the chart control know where to do it. Azure supports writing to disk through what they call a ‘local resource’, so I started using a LocalResource. But I kept hitting the following problem: I don’t know the path to the LocalResource until runtime, but the Chart Control expects this information to be in the Web.Config file. And, if I changed the Web.Config at runtime, Azure got very unhappy.
I looked into using XDrive, which is similar to using a LocalResource, but the same problem ensued. Each web role ended up mounting its own drive,and the drive letter became dynamic. I need to know it to pass that drive letter to Web.Config.
But I found a solution: I just implement my own instance of IChartStorageHandler and have it point to blob storage. Here’s what the code looks like:
public class ChartImageHandler : IChartStorageHandler
{
CloudStorageAccount account;
CloudBlobClient client;
CloudBlobContainer tweetContainer;
public ChartImageHandler()
{
//wire up azure
account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
client = account.CreateCloudBlobClient();
tweetContainer = client.GetContainerReference(Urls.archiveContainer);
}
#region IChartStorageHandler Members
public void Delete(string key)
{
CloudBlob image = tweetContainer.GetBlobReference(Urls.imageURL + key);
image.Delete();
}
public bool Exists(string key)
{
bool exists = true;
WebClient webClient = new WebClient();
try
{
using (Stream stream = webClient.OpenRead(Urls.imageURL + key))
{ }
}
catch (WebException)
{
exists = false;
}
return exists;
}
public byte[] Load(string key)
{
//sometimes load gets called before save is done
CloudBlob image = tweetContainer.GetBlobReference(Urls.imageURL + key);
byte[] imageArray;
try
{
imageArray = image.DownloadByteArray();
}
catch (Exception)
{
System.Threading.Thread.Sleep(1000);
imageArray = image.DownloadByteArray();
}
return imageArray;
}
public void Save(string key,byte[] data)
{
CloudBlob image = tweetContainer.GetBlobReference(Urls.imageURL + key);
image.UploadByteArray(data);
}
#endregion
}
Implementing this interface turns out to be pretty easy, especially because the Azure Storage Client CloudBlob class supports DownloadByteArray and UploadByteArray. Because the signature of the interface uses byte[] all over the place, this comes in real handy. Thanks Azure Storage Client!
You’ll note that I’m using this static Urls.imageURL for pointing to blob storage. This string is simply a path to a container in Azure.
The only tricky bit is that sometimes the Load method gets called before the Save function is finished. This is probably because of the latency with blob storage, which is going to be a little slower than writing to disk. I deal with this by adding try/catch. This simply puts a 1 second sleep delay in the call before trying to download the image. This solves the problem, and I’ve never seen the Save function take any longer than that.
I then update the web.config to specify that the ChartImageHandler key passed the fully qualified namespace and location of my handler, instead of the default handler.
And now I can use the ASP.NET Chart Control in Windows Azure with multiple web roles. Rockin.



Follow the Conversation
7 comments so far. You should leave one, too.
Thank you for sharing your learning Karsten. I feel, blob storage might incur some performance overheads in comparison to file storage under heavy load. I hope ASP.NET/ Chart team is reading your post and they will make charts ''Azure Compatible'' in next release :)
Thanks for the post but I was always inclined towards fancy graphs
Have you tried http://www.fusioncharts.com/aspnet/ (The product used by Google, FB and over 14000 top fellows) ... What I like the most is the simplicity it offers to the developers.
You post was offered as a solution on the Azure forum as it is seems to be the only way to get this to work (so Bravo!).
I would love to see some more code to help implement this (having not played with the Blob storage service), any chance you could provide a working example?
@Peter Grimshaw -- Check out all the code from The Archivist: http://archive.msdn.microsoft.com/archivist/Release/ProjectReleases.aspx?ReleaseId=4417
That's where I implement the charts as discussed above. For example, see any detail screen from The Archivist, aka: http://archivist.visitmix.com/irhetoric/131
The key file to check out is ArchivistWeb/Controllers/VisualizationController.cs -- in particular the GetChart() method. This is where I build up the chart (programmatically) and then save it out to storage and return it to the view:
MemoryStream imageStream = new MemoryStream();
chart.SaveImage(imageStream, ChartImageFormat.Png);
return File(imageStream.GetBuffer(), @"image/png");
I use a slightly different methodology for the "big charts", aka: http://archivist.visitmix.com/irhetoric/131/User
Here, the charts are declared in the ArchivistWeb/Views/*.aspx pages with code-behind in the view which is where the data is wired up.
Using Karsten's code as the basis, I have created some simple instructions for people wanting to implement this approach to display charts in Azure.
The post is here: http://social.msdn.microsoft.com/Forums/en-US/windowsazuredevelopment/thread/fe6ccbdf-ec70-49f5-aef4-aada217938ed
[...] to Karsten’s article: Using the ASP.NET Chart Control With Multiple Web Roles In Windows Azure. In this article you’ll find an example of a chart image handler written specifically to work [...]
One of the best sites for relevant facts on this niche !?!