views:

42

answers:

3

I'd like to get a list of all the Azure Table errors and figure out a clean way to handle them in a try...catch block.

For example, I'd like to not have to directly code and compare the InnerException message to String.Contains("The specified entity already exists"). What is the right way to trap these errors?

alt text

+1  A: 

You could try looking at the values in the Response, rather that the inner exception. This is an example of one of my try catch blocks:

try {
    return query.FirstOrDefault();
}
catch (System.Data.Services.Client.DataServiceQueryException ex)
{
    if (ex.Response.StatusCode == (int)System.Net.HttpStatusCode.NotFound) {
        return null;
    }
    throw;
}

Obviously this is just for the item doesn't exist error, but I'm sure you can expand on this concept by looking at the list of Azure error codes.

knightpfhor
+2  A: 

See my code here: http://blog.smarx.com/posts/testing-existence-of-a-windows-azure-blob. The pattern is to catch a StorageClientException, and then use the .ErrorCode property to match against the constants in StorageErrorCode.

smarx
Thanks! What exceptions are commonly associated with: context.RetryPolicy? ..TimeOut? ..Expect100Continue? ..UsePostTunneling? ...MergeOption? ...servicepoint.ConnectionLimit? A guide would be quite helpful when creating robust applications.
MakerOfThings7
Seems that Table will throw "System.Data.Services.Client.DataServiceQueryException" instead of "StorageClientException" mentioned on your blog. This will change my handler implementation... to what, I'm not sure yet.
MakerOfThings7
+1  A: 

Here is code that is provided in the Azure Table Whitepaper, but I'm not sure if this gives any value over smark's reply.

   /*
         From Azure table whitepaper

         When an exception occurs, you can extract the sequence number (highlighted above) of the command that caused the transaction to fail as follows:

try
{
    // ... save changes 
}
catch (InvalidOperationException e)
{
    DataServiceClientException dsce = e.InnerException as DataServiceClientException;
    int? commandIndex;
    string errorMessage;

    ParseErrorDetails(dsce, out commandIndex, out errorMessage);
}


          */

-

    void ParseErrorDetails( DataServiceClientException e, out string errorCode, out int? commandIndex, out string errorMessage)
    {

        GetErrorInformation(e.Message, out errorCode, out errorMessage);

        commandIndex = null;
        int indexOfSeparator = errorMessage.IndexOf(':');
        if (indexOfSeparator > 0)
        {
            int temp;
            if (Int32.TryParse(errorMessage.Substring(0, indexOfSeparator), out temp))
            {
                commandIndex = temp;
                errorMessage = errorMessage.Substring(indexOfSeparator + 1);
            }
        }
    }

    void GetErrorInformation(  string xmlErrorMessage,  out string errorCode, out string message)
    {
        message = null;
        errorCode = null;

        XName xnErrorCode = XName.Get("code", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
        XName xnMessage = XName.Get  ( "message",    "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");

        using (StringReader reader = new StringReader(xmlErrorMessage))
        {
            XDocument xDocument = null;
            try
            {
                xDocument = XDocument.Load(reader);
            }
            catch (XmlException)
            {
                // The XML could not be parsed. This could happen either because the connection 
                // could not be made to the server, or if the response did not contain the
                // error details (for example, if the response status code was neither a failure
                // nor a success, but a 3XX code such as NotModified.
                return;
            }

            XElement errorCodeElement =   xDocument.Descendants(xnErrorCode).FirstOrDefault();

            if (errorCodeElement == null)
            {
                return;
            }

            errorCode = errorCodeElement.Value;

            XElement messageElement =   xDocument.Descendants(xnMessage).FirstOrDefault();

            if (messageElement != null)
            {
                message = messageElement.Value;
            }
        }
    }
MakerOfThings7