Logging Elmah Exceptions To Azure Storage

13 June 2013

I wanted to store the Elmah errors from a web application using Windows Azure Table Storage and came across this post by Dina Berry which outlines the steps required very nicely.

However, it was written in 2011 and the Windows Azure Table Storage client has moved on since then so some of the syntax is out of date.

Below is the code updated for the current Windows Azure Storage client (2.0) as of 13/06/2013.

I wanted to use the Azure Storage connection string that I already have set up in the Azure portal rather than exposing the username and password in the Elmah web.config settings so this code no longer uses the IDictionary config and instead has a reference to the ConnectionString via ConfigurationManager. 

using Elmah;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Microsoft.WindowsAzure.Storage.Table.DataServices;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TIROne.ElmahAzureStorage
    public class WindowsAzureErrorLogs : ErrorLog
         /// <summary>
        /// Table Name To Use In Windows Azure Storage
        /// </summary>
        private readonly string tableName = "ElmahExceptions";

        /// <summary>
        /// Cloud Table Client To Use When Accessing Windows Azure Storage
        /// </summary>
        private readonly CloudTableClient cloudTableClient;

        /// <summary>
        /// Initialize a new instance of the WindowsAzureErrorLogs class.
        /// </summary>
        /// <param name="config"></param>
        public WindowsAzureErrorLogs(IDictionary config)
            if (!(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString is string))
                throw new Elmah.ApplicationException("Connection string is missing for the Windows Azure error log.");

            if (string.IsNullOrWhiteSpace((string)ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString))
                throw new Elmah.ApplicationException("Connection string is missing for the Windows Azure error log.");

            CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);
            this.cloudTableClient = cloudStorageAccount.CreateCloudTableClient();

        /// <summary>
        /// </summary>
        /// <param name="error"></param>
        /// <returns></returns>
        public override string Log(Error error)
            ErrorEntity entity = new ErrorEntity(error.Time, Guid.NewGuid())
                HostName = error.HostName,
                Type = error.Type,
                ErrorXml = ErrorXml.EncodeString(error),
                Message = error.Message,
                StatusCode = error.StatusCode,
                User = error.User,
                Source = error.Source

            CloudTable table = this.cloudTableClient.GetTableReference(this.tableName);

            TableOperation insertOperation = TableOperation.Insert(entity);

            if (entity.RowKey != null && entity.PartitionKey != null)
                TableResult result = table.Execute(insertOperation);

            return entity.Id.ToString();

        /// <summary>
        /// Get a Error From Windows Azure Storage
        /// </summary>
        /// <param name="id">Error Identifier (Guid)</param>
        /// <returns>Error Fetched (or Null If Not Found)</returns>
        public override ErrorLogEntry GetError(string id)
             TableServiceContext tableServiceContext = this.cloudTableClient.GetTableServiceContext();

            var query = from entity in tableServiceContext.CreateQuery<ErrorEntity>(this.tableName).AsTableServiceQuery(tableServiceContext)
                        where ErrorEntity.GetRowKey(Guid.Parse(id)) == entity.RowKey
                        select entity;

            ErrorEntity errorEntity = query.FirstOrDefault();
            if (errorEntity == null)
                return null;

            return new ErrorLogEntry(this, id, ErrorXml.DecodeString(errorEntity.ErrorXml));


        public override int GetErrors(int pageIndex, int pageSize, System.Collections.IList errorEntryList)
            if (pageIndex < 0)
                throw new ArgumentOutOfRangeException("pageIndex", pageIndex, null);

            if (pageSize < 0)
                throw new ArgumentOutOfRangeException("pageSize", pageSize, null);

            TableServiceContext tableServiceContext = this.cloudTableClient.GetTableServiceContext();

            // WWB: Server Side Call To Get All Data
            ErrorEntity[] serverSideQuery = tableServiceContext.CreateQuery<ErrorEntity>(this.tableName).AsTableServiceQuery(tableServiceContext).Execute().ToArray();

            // WWB: Sorted in Reverse Order So Oldest are First
            var sorted = serverSideQuery.OrderByDescending(entity => entity.TimeUtc);

            // WWB: Trim To Just a Page From The End
            ErrorEntity[] page = sorted.Skip(pageIndex * pageSize).Take(pageSize).ToArray();

            // WWB: Convert To ErrorLogEntry classes From Windows Azure Table Entities
            IEnumerable<ErrorLogEntry> errorLogEntries = page.Select(errorEntity => new ErrorLogEntry(this, errorEntity.Id.ToString(), ErrorXml.DecodeString(errorEntity.ErrorXml)));

            // WWB: Stuff them into the class we were passed
            foreach (var errorLogEntry in errorLogEntries)

            return serverSideQuery.Length;


PayPal example project C# ASP.Net

01 December 2011

A few weeks ago I spent some time integrating PayPal Express Checkout into http://bookhashtags.com so that I could take payments for the featured book spot.

Whilst PayPal produces a lot of documentation and provides some tools to help generate code these were not always that helpful. For example the code wizard produces code that doesn't build and uses a very old version of the API which means that a lot of the things you can now do according to the documentation just didn't work and it wasn't immediately obvious why.

I have put together a bare bones Visual Studio 2010 project that will give you a quick understanding of the basics of the three Express Checkout calls (SetExpressCheckout, GetExpressCheckoutDetails and DoExpressCheckout) you need to make to get things working.

To get the project to run you will need to set up a PayPal sandbox account here - https://developer.paypal.com

You will need to add your sandbox account username, password and signature in the NVPAPICaller class.

Once that is done just press play, change the default values on the default.aspx page and hit the Pay button.

The example only adds one item and doesn't handle shipping costs. For more information on parameter names etc. see the PayPal Express Checkout Integration pdf

Download the project



Trouble shooting SPWeb object closed or disposed

22 May 2009

I recently came across an issue on a WCM site where the following error was being shown whenever a dropdown selection was changed on a custom web part:
SPException: Trying to use an SPWeb object that has been closed or disposed and is no longer valid 

This looked like the SPWeb object was being incorrectly disposed of but careful inspection of the web part showed that best practices for disposal of SPObjects had been followed .
To try and track down the cause of the error and to really satisfy myself that it wasn't the web part causing the issue I removed all references to SPWeb from the custom web part. The error was still appearing so this ruled out bad coding practice in this control.
The next step was to take a look at the other controls on the page. As this was a WCM site there were a number of custom controls being used for navigation and other functionality.
It didn't take too long to track down the culprit in a control being used to set the site title in the browser title bar. This contained the following:
using(SPWeb web = SPContext.Current.Web)
   //some code
When the dropdown selection was changed a postback was fired and this piece of code brought the site crashing down.
This was because both the using statement and the use of SPContext handle garbage collection so the SPWeb object was being disposed of twice and as it didn't exist on the second dispose the error above was thrown.
Once corrected the code looked like this:
SPWeb web = SPContext.Current.Web;
//some code 

Most of the links about this error on the web will point you towards the issue being incorrect disposal of objects but what is learnt here is that it might not be a coding issue in the control that seems to be causing the problem. In this case it was the postback being fired by the control rather than the control itself that was triggering the error. The root cause was actually a completely different web part on the page.

Twitter SharePoint web part - another update!

10 February 2009

** Update June 2010 - new Twitter web part using OAuth rather than Basic Auth **

When I mentioned that I was developing a Twitter web part to Mirjam van Olst she asked if it would be possible to work on it with me. So thanks to Mirjam, in the true spirit of international collaboration, we are now able to bring you an updated version of the web part which is more secure and easier to deploy.

Improvements include -

  • The password input now uses a password textbox to protect the Twitter credentials
  • TwitterLib.dll has been added to the wsp for easier deployment

Download the new and improved Dutch/British/Euro version here: TwitterPublicTimeline.wsp (24.25 kb)

Twitter SharePoint web part update

06 February 2009

** Update June 2010 - new Twitter web part using OAuth rather than Basic Auth **

Original post with deployment instructions

 The Twitter public timeline web part has now been updated with the following:

  • URLs in Tweets are displayed as active links
  • The user's screename links to their Twitter page
  • If @screename appears in the Tweet it is displayed as a link to the user's Twitter page

TwitterPublicTimeline.wsp (24.25kb)

Twitter SharePoint web part

04 February 2009

** Update June 2010 - new Twitter web part using OAuth rather than Basic Auth **

I thought I would have a go at creating a web part to display a Twitter public timeline within SharePoint. The reason for creating this web part is so that it can be used by project teams that are spread over several offices/countries to stay in touch and feel more connected without having to invest a lot of time emailing each other or talking on the phone. Twitter is ideal for this kind of light weight communication as it restricts the user to sending short, to the point messages.

Before starting I had a quick look on the web to see if I was reinventing the wheel. Michael Gannotti suggests this solution using javascript and the CEWP but I wanted something that we would have a little more control over in terms of html markup and branding and that wasn't limited to the CEWP being available. I also wanted to have the possibility of extending the web part to include other functionality in the future such as not just being able to display tweets but to also send them.

The web part is configurable using two custom attributes - username and password. This allows you to display any users public timeline assuming you have the password. To set it up for use with a project team public timeline you should create a Twitter account for the project and then follow the members of the team to see a timeline that displays tweets from each of the members. 

At the bottom of this post there are links to the .wsp file which can be deployed to SharePoint using stsadm.exe and a .css file so that you can see how I chose to style the web part but obviously you could brand it any way you want.

**Update by request - more detail on deploying solutions

My solution uses Twitterlib.dll which is an open source .Net wrapper for the Twitter API and was created by the developers at Witty. This is a link to the Witty project on Google code. 

Download the wsp for the Twitter web part: TwitterPublicTimeline.wsp (24 kb)

For a styling suggestion try this css: twitter.css (302.00 bytes)

Generic CSV or SQL data importer for SharePoint list

10 September 2008


I finally got bored of rewriting the same console application to move data from a csv or a sql table into a SharePoint list! The result is a generic console application that is capable of importing either a CSV file or some SQL data from a stored procedure. The app uses the object model so it needs to be run on the SharePoint server farm. I may get round to rewriting it using web services at some point. The CSV import parses the file so that things like line breaks and commas within fields are handled nicely. Any blank fields in the CSV do need to be filled using find and replace on blank space otherwise data ends up in the wrong columns.

To import a CSV the first row of the of the CSV file is used to define which columns the data will import to. Eg. A CSV that has one column with a header of Title will import the data into the Title column of the specified list. Modify the App.Config file to include the URL of your site collection, the list name, the path to the CSV and whether or not you want to delete all items in the list before importing.

To import SQL data create a stored procedure that returns the data as the names of the site columns

Eg. Select Name AS Title from tblPerson - will return one column of data that will import into the Title column of a list. Modify the App.Config to include the name of the stored procedure and the SQL connection string and run the app.

You can download the project from the following link:


This application is supplied as is and offers no guarantees feel free to use as you wish all I ask is that if you make any improvements then you share them in the comments or by email.

Web part custom property - dropdown list

19 December 2007

It isn't immediately obvious how to include a drop down list as a custom property on a web part. To do this you simply use an enum.


//create enum

public enum ProductByEnum

{Type = 0,



//create get/set for the property

protected ProductByEnum productsBy;

[Personalizable(PersonalizationScope.User),WebBrowsable, WebDisplayName("Products By"),WebDescription("Use this property to change web part grouping")]public ProductByEnum ProductsBy


get { return productsBy; }

set { productsBy = value; }


A dropdown list will now appear in the miscellaneous section of your web part custom properties containing the enum values.


Creating XHTML compliant ASP.Net server controls

12 December 2007

ASP.Net is great but many of the controls use table tags when they render. I am currently in the process of developing some Internet sites using MOSS 2007 which need to meet accessibility guidelines so these controls, in their out of the box state, are no use to me. We have tried applying the CSS adapters that get rid of the tables but this also had the effect of removing tables from the site settings screens making them difficult to use.

The solution we are going for is to create new controls that inherit from the base control. The new control then overrides the render event to remove the non-compliant tags and replaces them with compliant ones.

We are also using this method to add script to the master pages which removes table tags from web part zones etc.

DISCLAIMER - I have created a non-tabular control for the SPGridView. You could argue that the SPGridView presents tabular data so does not need any changes to the rendered HTML, you would probably be right but this example shows what can be done. :-)

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web.UI;
using System.Text.RegularExpressions;
using System.IO;

namespace XHTMLCompliantMOSSControls
    public class CompliantSPGridView : SPGridView
        protected override void RenderContents(HtmlTextWriter output)
            //get the rendered HTML
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            HtmlTextWriter hw = new HtmlTextWriter(sw);

            //remove tables
            string str = sb.ToString();
            str = Regex.Replace(str, "<table[^>]*>", "<div class=\"mainSPGridView\">");
            str = Regex.Replace(str, "<tr>", "<div class=\"normalSPGridView\">");
            str = Regex.Replace(str, "<tr class=\"ms-alternating\">", "<div class=\"alternatingSPGridView\">");
            str = Regex.Replace(str, "</tr>", "</div>");
            str = Regex.Replace(str, "<td[^>]*>", "<div class=\"itemSPGridView\">");
            str = Regex.Replace(str, "</td>", "</div>");
            str = Regex.Replace(str, "<tr class=\"ms-viewheadertr\">", "<div class=\"headerSPGridView\">");
            str = Regex.Replace(str, "<th class=\"ms-vh2-nofilter ms-vh2-gridview\" scope=\"col\">", "<div class=\"itemSPGridView\">");
            str = Regex.Replace(str, "</th>", "</div>");

If you then apply a bit of CSS using the classes that have been added it is possible to get it looking just like the tabular SPGridView.

This approach could be used with any server control to make it compliant with XHTML.

Excellent post about making SharePoint xhtml compliant

11 December 2007
For anyone using the web content management components of MOSS 2007 to produce Internet sites this is essential reading. SharePoint uses a lot of ASP.Net controls which render using tables and non compliant html. To get rid of this there are a few things you can do which are explained in this blog post http://zac.provoke.co.nz/archive/2007/04/19/guide-to-making-sharepoint-xhtml-compliant.aspx