Creating custom IHttpBody classes for coded web tests

If you've recorded a web test and generated code, you've probably noticed the FormPostHttpBody class.  You might have even seen the StringHttpBody class if you had web service requests in your web test.  These are the only two built-in classes for generating HTTP request bodies, so what do you do if you need to send requests containing something other than form parameters and strings?  You just implement your own IHttpBody class.

I'm going to paste in a sample IHttpBody called BinaryHttpBody at the end of this post.  This class can be used in coded web tests to send requests with specific binary data in the request body.  You might use this if you want to send binary data in a PUT request body, for example.  Another use would be if you wanted to load pre-generated request bodies from files on disk.  As you can see, the constructor for BinaryHttpBody accepts either a byte array or a Stream.

To send an array of bytes, you would use BinaryHttpBody like this:

 WebTestRequest request1 = new WebTestRequest("https://localhost/test.aspx");
request1.Method = "POST";
BinaryHttpBody binaryBody = new BinaryHttpBody("application/octet-stream", 
        new byte[] { 0x01, 0x02, 0x03 });
request1.Body = binaryBody;
yield return request1;

The following code for BinaryHttpBody should be compatible with the July CTP and later.

 using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.VisualStudio.TestTools.WebTesting;

namespace TestProject1 {
    public class BinaryHttpBody : IHttpBody {
        private string _contentType;
        private Stream _stream;

        public BinaryHttpBody(string contentType, byte[] bytes)
            : this(contentType, new MemoryStream(bytes, false)) {

        }

        public BinaryHttpBody(string contentType, Stream stream) {
            _contentType = contentType;
            _stream = stream;
        }

        public BinaryHttpBody() {

        }

        public string ContentType {
            get { return _contentType; }
            set { _contentType = value; }
        }

        public Stream Stream {
            get { return _stream; }
            set { _stream = value; }
        }

        public void WriteHttpBody(WebTestRequest request, System.IO.Stream bodyStream) {
            if (_stream != null && _stream.CanRead) {
                try {
                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    while ((bytesRead = _stream.Read(buffer, 0, buffer.Length)) > 0) {
                        bodyStream.Write(buffer, 0, bytesRead);
                    }
                } finally {
                    _stream.Close();
                }
            }
        }

        public object Clone() {
            throw new NotImplementedException();
        }
    }
}

This is just one example of an extensibility point web tests provide. I plan to demonstrate custom validation and extraction rules next.