Creating a simple HTTP Communication class


This is a follow up to my last post about my first CodePlex project (http://shorturllibrary.codeplex.com/). As mentioned in that post, the short url API is part of a bigger project and will eventually lead to tweet on blog bits where the URL of the blog entry are automatically short urled according to your specs. This means there will be a factory pattern in there eventually (got your interest?).

The first step for me was to create a communication library.

Communication

When we communicate with the short url sites, the APIs are generally REST, JaSON or similar. Regardless of which of these they use, you will use HTTP Communication to reach the libraries. But, following proper practice, and so we can later test, let’s create a communication interface. It looks like this:

public interface ICommunicator
{
    WebResponse SendRequest(string requestUrl, RequestMethod requestMethod);
    WebResponse SendRequest(string requestUrl, RequestMethod requestMethod, string userName, string password);
}

Now, since I am using HTTP, I can go ahead and create the enumeration for RequestMethod (I may regret this later if I create something a bit more generic as a comm library, but it is great for now). The enumeration looks like this:

namespace CrazyCancer.Framework.Communication.Enums
{
    public enum RequestMethod
    {
        GET,
        POST
    }
}

Contract first development. What a novel concept! (For those not seeing I am being a bit sardonic here, Contract First development is a well established concept).

Now that I have a contract, let’s rough in the class:

public class HttpCommunicator : ICommunicator
{
}

If you add this to a project, you will see that the ICommunicator is not implemented, so Visual Studio complains at you. To fix this, I am going to create the two methods. Since the more explicit method makes more sense, I will have it actually run all of the code. When initially implemented, it will look like this:

public WebResponse SendRequest(string requestUrl, RequestMethod requestMethod)
{
    return SendRequest(requestUrl, requestMethod, null, null);
}

public WebResponse SendRequest(string requestUrl, RequestMethod requestMethod, string userName, string password)
{
    throw new NotImplementedException
}

At this time, I really should be using TDD, but it is late and inversion of control is not a wavelength I am able to maintain, so I will approach that when I get to the ShortUrl library post (which was developed using Test Driven Development – ADD moment, forgot to tell what TDD meant at first mention). As a side note, many of my dev buddies, who know I am a TDD advocate are probably having a snicker at this post. 😉

There are a couple of methods I know I need in addition to the interface methods. First, I need something to turn the enum into a string, as the WebRequest class expects a string. You might say, this is not necessary as you can simply ToString() the RequestMethod passed in. Good point, but I will not do this for two reasons:

  1. I may eventually add other communication protocols and having a separate method allows my to filter out bad results
  2. It breaks SOLID principles (no time to explain this right now)

Here is my code for this method (extremely simple):

private string GetResponseMethodAsString(RequestMethod requestMethod)
{
    switch (requestMethod)
    {
        case RequestMethod.POST: { return "POST"; }
        default: { return "GET"; }
    }
}

I also am going to create a method to get Network Credentials, if necessary. When I start using this library with Twitter, this will be useful. Right now, it is extraneous (and I have broken one principle of Agile – only code what you need today – another ADD moment?).

private NetworkCredential GetNetworkCredentials(string userName, string password)
{
    NetworkCredential credential = new NetworkCredential(userName, password);
    return credential;
}

There is a temptation to put this in the SendRequest method (which may be badly named – have to think about this – oh, too late, it is published), and I agree with this temptation based on TDD/Agile principles. I have chosen not to, as I am thinking ahead to a yet unrealized future.

Now to SendRequest(). I need a request object that uses a GET or POST. Simple enough, I set up something like this:

WebRequest request = WebRequest.Create(requestUrl);
request.Method = GetResponseMethodAsString(requestMethod);

I also have the possibility of having to set up network credentials, but only if the userName and password are not null. This looks like the following:

if((userName != null)&&(password!=null))
{
    request.Credentials = GetNetworkCredentials(userName, password);
}

Now, since we are currently consuming the web request from the routine, all I have to do is get the request and return it. I have this in two lines, as I like to be able to peek at the object in case of an error while developing. If you feel safer, you can return the object directly from request.

WebResponse response = request.GetResponse();
return response;

Communication Class

Here is the entire code for the HttpCommunicator class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using CrazyCancer.Framework.Communication.Enums;
using CrazyCancer.Framework.Communication.Interfaces;

namespace CrazyCancer.Framework.Communication
{
    public class HttpCommunicator : ICommunicator
    {
        /// <summary>
        /// Gets a response from an HTTP fronted API
        /// </summary>
        /// <param name="requestUrl">URL to communicate with</param>
        /// <param name="requestMethod">Method for getting response (GET or POST)</param>
        /// <returns></returns>
        public WebResponse SendRequest(string requestUrl, RequestMethod requestMethod)
        {
            return SendRequest(requestUrl, requestMethod, null, null);
        }

        public WebResponse SendRequest(string requestUrl, RequestMethod requestMethod, string userName, string password)
        {
            WebRequest request = WebRequest.Create(requestUrl);
            request.Method = GetResponseMethodAsString(requestMethod);

            if((userName != null)&&(password!=null))
            {
                request.Credentials = GetNetworkCredentials(userName, password);
            }

            WebResponse response = request.GetResponse();
            return response;
        }

        private string GetResponseMethodAsString(RequestMethod requestMethod)
        {
            switch (requestMethod)
            {
                case RequestMethod.POST: { return "POST"; }
                default: { return "GET"; }
            }
        }

        private NetworkCredential GetNetworkCredentials(string userName, string password)
        {
            NetworkCredential credential = new NetworkCredential(userName, password);
            return credential;
        }
    }
}

Not a lot of code, but this library will grow as we end up having to add headers. This is more for Twitter and I am not sure how I will easily handle this (some type of collection), but that is a subject for a later date.

Peace and Grace,
Greg

Twitter: @gbworld

Advertisements

2 Responses to Creating a simple HTTP Communication class

  1. Troy says:

    I’m not sure exactly how you’re planning to integrate with Twitter for your app, but you may want to take a look at a couple of existing libraries first. Such as: http://www.codeplex.com/LinqToTwitter

  2. Gregory says:

    Troy:I am looking at different libs. LINQ to Twitter currently looks pretty solid, so I will at least look at it for ideas. I have already separated out a communications library, so I will be using it for the actual communications plumbing.I would like LINQ to Twitter better if it were tiered out, but the author(s) do at least understand the concept of domain models, which is nice. I am probably going to create CrazyCancer.Framework.MicroBlog and hit Twitter, Plurk and Pownce to start with. I will not likely finish complete APIs immediately, of course.Peace and Grace,Greg

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 )

Google+ photo

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

Connecting to %s

%d bloggers like this: