Asynchronously Calling REST Services From a Windows Azure Role

February 23, 2013 — Leave a comment

I regularly consume REST services from code running in Web Roles and Worker Roles. The best practice when it comes to anything going over the network, is to use the The Transient Fault Handling Application Block. The RestClient from this post is a Fluent REST Client that uses the HttpTransientErrorDetectionStrategy and a RetryPolicy to be tolerant of transient faults. Find out more about the HttpTransientErrorDetectionStrategy in an earlier post.

Take some time to get to know the characteristics of good REST services. They are part of an established convention that help us to rapidly understand and consume new REST services. 

The code from this Post is part of the Brisebois.WindowsAzure NuGet Package

To install Brisebois.WindowsAzure, run the following command in the Package Manager Console

PM> Install-Package Brisebois.WindowsAzure

Get more details about the Nuget Package.

 

Calling HTTP GET on a REST Endpoint

Making a HTTP GET request is done by specifying a Uri. Then by calling the GetAsync method with a lambda for the onError parameter. This lambda will be called when exceptions occur during the requests to the endpoint. The request gets initiated when the GetAsync method is called.

The code below defaults to 10 retries if transient Http Status Codes are returned by the endpoint.

Action<Uri, HttpStatusCode, string> onError = (uri, code, message) =>
    {
        Console.WriteLine(code.ToString());
    };

var result = await RestClient.Uri("http://localhost:81/testWebApi/api/values")
                             .GetAsync(onError);

The onError parameter of the GetAsync method can also be a private method. This is where you can react to specific Http Status Codes. For example, if the REST service returns a 401 Unauthorized, you can log the active user off of your application.

private void OnError(Uri uri, HttpStatusCode statusCode, string content)
{
    switch (statusCode)
    {
        case HttpStatusCode.NotFound:
            {
                // TODO: do something
            }
            break;
        case HttpStatusCode.Unauthorized:
            {
                // TODO: log user out
            }
            break;
        default:
            {
                var message = string.Format("{1}{0}{0}{2}", 
                                            Environment.NewLine, 
                                            uri, 
                                            content);

                throw new RestClientException(statusCode, message);
            }
    }
}

The RestClientException above is a great way to propagate RestClient related exceptions. In most cases, the most important part of an error response from a REST service is the Http Status Code. You can use this exception to communicate the code in order to show the right error messages to your end users.

 

Calling HTTP GET on a REST Endpoint With Tracing

Activating the trace on requests for logging or debug purposes can be done by passing a Progress<string> instance to the GetAsync method. An example of a trace can be found below the following code.

var progress = new Progress<string>(Console.WriteLine);

Action<Uri, HttpStatusCode, string> onError = (uri, code, message) =>
    {
        Console.WriteLine(code.ToString());
    };

var result = await RestClient.Uri("http://localhost:81/testWebApi/api/values")
                             .GetAsync(onError, progress);

Trace

2013-02-24_03h05_20

 

Considering Http Status Code 404 Not Found as Transient

If you are trying to call a REST service hosted on Windows Azure, it can be very convenient to consider a 404 Http Status Code to be transient. Roles can become unavailable for a number of reasons and this can happen at any time. But in most circumstances, this is temporary and having code that is able to retry calling the REST services goes a long way in dealing with these unplanned interruptions.

var progress = new Progress<string>(Console.WriteLine);

Action<Uri, HttpStatusCode, string> onError = (uri, code, message) =>
    {
        //Do nothing
    };

const bool notFoundIsTransient = true;

var result = await RestClient.Uri("http://localhost:81/testWebApi/api/404")
                             .Retry(3, notFoundIsTransient)
                             .GetAsync(onError, progress);

Trace

2013-02-24_03h52_33

This trace shows what happens when the 404 Not Found Http Status Code is considered to be transient. The code will retry until the it reaches the requested number of attempts. Then it will throws the exception so that it can be handled accordingly.

 

Calling HTTP POST on a REST Endpoint With Tracing

Making a HTTP POST request is done by specifying a Uri. Build the QueryString by adding Parameters, then set the Content and it’s Content Type. Call the PostAsync method with a lambda for the onError parameter. This lambda will be called when exceptions occur during the requests to the endpoint. The request gets initiated when the PostAsync method is called.

var r = new Resource
    {
        Name = "Alexandre Brisebois",
        Values = new Dictionary<string, string>
            {
                {"specialty", "Windows Azure"}
            }
    };

var progress = new Progress<string>(Console.WriteLine);

var resul = await RestClient.Uri("http://localhost:81/testWebApi/api/values")
                        .Retry(2, true)
                        .Parameter("_token", Guid.NewGuid().ToString())
                        .Content(JsonConvert.SerializeObject(r))
                        .ContentType("application/json; charset=utf-8")
                        .PostAsync(OnError, progress);

Trace

2013-02-24_03h57_29

 

Calling HTTP PUT on a REST Endpoint With Tracing

Making a HTTP PUT request is done by specifying a Uri. Build the QueryString by adding Parameters, then set the Content and it’s Content Type. Call the PutAsync method with a lambda for the onError parameter. This lambda will be called when exceptions occur during the requests to the endpoint. The request gets initiated when the PutAsync method is called.

var r = new Resource
    {
        Name = "Alexandre Brisebois",
        Values = new Dictionary<string, string>
            {
                {"specialty", "Windows Azure"}
            }
    };

var progress = new Progress<string>(Console.WriteLine);

var result = await RestClient.Uri("http://localhost:81/testWebApi/api/values")
                                .Retry(2, true)
                                .Content(JsonConvert.SerializeObject(r))
                                .ContentType("application/json; charset=utf-8")
                                .PutAsync(OnError, progress);

Trace

2013-02-24_04h35_15

 

Calling HTTP DELETE on a REST Endpoint With Tracing

Making a HTTP DELETE request is done by specifying a Uri. Call the DeleteAsync method with a lambda for the onError parameter. This lambda will be called when exceptions occur during the requests to the endpoint. The request gets initiated when the DeleteAsync method is called.

var progress = new Progress<string>(Console.WriteLine);

var result = await RestClient.Uri("http://localhost:81/testWebApi/api/values")
                             .Retry(2, true)
                             .DeleteAsync(OnError, progress);

Trace

2013-02-24_05h45_18

No Comments

Be the first to start the conversation!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.