4
\$\begingroup\$

I'm in QA Automation, and C# isn't my first language. I've written a small class of methods for GETting and POSTing to web URLs. I use these when I want to test certain things that really fall outside the jurisdiction of Selenium, but are still roughly "black box" type testing. Link scanning, and culling data from POSTBIN, are a few examples.

I was wondering if you C# gurus might like to look the code over, and let me know if there are better ways to do what I've done, or if there's any potential gotcha's I haven't thought of:

public class RawHttp
{
    public static string Url = null;

    public RawHttp(string url)
    {
        Url = url;
    }

    public HttpStatusCode GetStatusCode(string url = null)
    {
        HttpStatusCode result = default(HttpStatusCode);
        string activeUrl = url ?? Url;

        var request = WebRequest.Create(activeUrl);
        request.Method = "HEAD";
        using (var response = request.GetResponse() as HttpWebResponse)
        {
            if (response != null)
            {
                result = response.StatusCode;
                //var headers = response.Headers;
                response.Close();
            }
        }
        return result;
    }

    public string GetBody(string url = null)
    {
        string activeUrl = url ?? Url;

        var request = (HttpWebRequest)WebRequest.Create(activeUrl);
        request.Method = "GET";
        // Set some reasonable limits on resources used by this request
        request.MaximumAutomaticRedirections = 4;
        request.MaximumResponseHeadersLength = 4;
        // Set credentials to use for this request.
        request.Credentials = CredentialCache.DefaultCredentials;
        var response = (HttpWebResponse)request.GetResponse();

        //Console.WriteLine("Content length is {0}", response.ContentLength);
        //Console.WriteLine("Content type is {0}", response.ContentType);

        // Get the stream associated with the response.
        Stream receiveStream = response.GetResponseStream();
        // Pipes the stream to a higher level stream reader with the required encoding format. 
        var readStream = new StreamReader(receiveStream, Encoding.UTF8);
        var body = readStream.ReadToEnd();
        response.Close();
        readStream.Close();
        return body;
    }

    public string Post(string url = null, string parameters = "")
    {
        string activeUrl = url ?? Url;

        var req = WebRequest.Create(activeUrl);
        req.ContentType = "application/x-www-form-urlencoded";
        req.Method = "POST";
        byte[] bytes = Encoding.ASCII.GetBytes(parameters);
        req.ContentLength = bytes.Length;
        Stream os = req.GetRequestStream();
        os.Write(bytes, 0, bytes.Length); //Push it out there
        os.Close();
        var resp = req.GetResponse();
        //if (resp == null) {return null;}
        var sr = new System.IO.StreamReader(resp.GetResponseStream());
        return sr.ReadToEnd().Trim();
    }
}  

Thanks!

\$\endgroup\$
  • 1
    \$\begingroup\$ Hello Greg. Is this strictly used as a utility? Do you test repeated things, like test a=status code success and then b = check something in the body? Also, you are switching between the static "Url" variable and the actual instance (the class is instance based and not static), what is the use case you are shooting for? Is there any other forms of functionality that you want to add onto this in the future? Is this code being included in something else (i.e. how does it interact with your test suite)? \$\endgroup\$ – Randy Apr 5 '12 at 0:01
  • \$\begingroup\$ Thanks for the questions, Randy. I suppose I should have supplied some examples when I created this question. I've not had a lot of time to revisit this, though. I'm sorry for that. I'll respond in more detail later this week. \$\endgroup\$ – Greg Gauthier Apr 11 '12 at 21:53
1
\$\begingroup\$

It's probably fine for test code. There are a few things I noticed. None of these are necessarily a problem. They may never affect your tests. But they're not ideal either.

  1. You're not calling Dispose() on everything that you strictly should (eg, Streams).
  2. You're always encoding your post parameters in ASCII, but reading the responses in UTF8. If you're sticking to basic English characters that'll be fine, but if you try other languages/character sets it may be problematic.
  3. the GetStatusCode() function is using the HEAD method. Not all endpoints will respond properly to the HEAD method, or is the same way that they would to GET or POST.

If you're going to be doing a lot of this then you may want to look at the WebClient class. It's a little bit simpler to use, and may be sufficient for your needs.

\$\endgroup\$
  • \$\begingroup\$ Using using is even better than calling .Dispose(). \$\endgroup\$ – Leonid Apr 5 '12 at 19:56
  • 2
    \$\begingroup\$ From a disposal standpoint they're equivalent, though using is frequently more convenient. At any rate, he's not doing either of them in several cases. \$\endgroup\$ – breischl Apr 5 '12 at 20:07
  • \$\begingroup\$ Thanks @breischl, these are really good tips. Sorry I haven't responded sooner. Things have been busy here. \$\endgroup\$ – Greg Gauthier Apr 11 '12 at 21:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.