Creating a WebSurge Addin

West Wind WebSurge supports creating addins using .NET code which are placed in the Addins folder of the WebSurge installation.

Creating an addin involves an easy process of creating a .NET assembly, with a custom class that can hook into the request life cycle for a test run with events that are fired at the beginning and end of the test and events fired before and after each request is run.

Addins allow you to customize request processing for Web Surge tests either by modifying individual requests, or by customizing the request workflow dynamically at runtime for tasks like capturing request data on one request and passing it to subsequent requests.

Creating an Addin

The process to create an Addin involves the following steps:

  • Create a new .NET Class Library
  • Target the same .NET version as WebSurge.exe (.NET 4.6.1 at this time)
  • Add a reference to WebSurge.Core.dll
  • Use Properties on WebSurge.Core.dll and set Copy Local to false
  • Create a new .NET Class
  • Implement IWebSurgeExtensibility
  • or subclass WebSurgeExtensibilityBase
  • Implement desired OnXXX methods to intercept request processing
  • Compile your project
  • Place the final DLL (or build into) <WebSurgeInstall>\Addins

Debugging your Addins

Because you are building a plain .NET class library assembly you can easily debug your addin with Visual Studio by running it inside of WebSurge.

To do this:

  • Open your Addin project in Visual Studio
  • Go to Properties
  • On the Build tag send the output to <WebSurgeInstallFolder>
  • On the Debug Tab start WebSurge.exe in the <WebSurgeInstallFolder>

On the Build tab:

On the Debug Tab:

Permissions Required

You may have to change the permissions in the Addins folder temporarily in order to be able to build into the folder from Visual Studio. Add the INTERACTIVE user to the folder permissions and give it Full Rights in order to be able to have Visual Studio output into the Addins folder.

With this setup you should just be able to start debugging in Visual Studio by setting breakpoints:

How it works

When WebSurge starts it looks for assemblies in the Addins folder that implement IWebSurgeExtensibility and loads them. You can add multiple addins into a single assembly and WebSurge will find them and hook them into the processing chain.

When a test is run or you test an invididual request, the addin's OnXXXX methods are fired as requests are processed. The addin is applied to individual requests when you click the Test button, or when you run a full test using the Start button.

Request Threading

Note that requests are fired on isolated threads so if you decide to access any UI functionality in WebSurge you have to explicitly marshal the thread back to the UI thread.

The request data that is provided to a given request is thread safe and you can safely read and write the request data. However, any other data structures are potentially subject to thread state changes, so use care when working with WebSurge's state. Also if you write to files on disk make sure you either use locks to prevent multiple threads writing simultaneously, or else use retry logic to catch and avoid file sharing failures.

Simple Examples

Here are a couple of very simple examples that demonstrate what addin classes can look like.

Logging Request Event Hooks

The first is a simple logging addin that explicitly logs a small message for each request that is made:

public class LogPlugIn : IWebSurgeExtensibility
{
    public bool OnBeforeRequestSent(HttpRequestData data)
    {
        logRequests(data, 0);
        return true;
    }

    public void OnAfterRequestSent(HttpRequestData data)
    {
        logRequests(data, 1);
    }

    public bool OnLoadTestStarted(IList<HttpRequestData> requests)
    {
        LogString("Starting test with " + requests.Count + " in Session.");
        return true;
    }

    public void OnLoadTestCompleted(IList<HttpRequestData> results, int timeTakenForTestMs)
    {
        LogString("Completed test with " + results.Count + " requests processed.");
    }

    private void logRequests(HttpRequestData data, int mode = 0)
    {
        string output;

        // Check for a non-success response/errors
        bool isErorr = data.IsError;

        if (mode != 0)
            output = data.StatusCode + " " + data.HttpVerb + " " + data.Url + " " + data.TimeTakenMs;
        else
            output = data.HttpVerb + " " + data.Url;

        LogString(output);
    }

    public static object syncLock = new object();

    private void LogString(string message)
    {
        lock (syncLock)
        {
            StreamWriter streamWriter = new StreamWriter(Environment.CurrentDirectory + "\\requestlog.txt", true);
            streamWriter.WriteLine(DateTime.Now.ToString() + " - " + message);
            streamWriter.Close();
        }
    }
}

Modifying Request Data

The following example modifies request data by searching for a known value in the data and modifying it when the request comes in:

public class ModifyContentPlugIn : WebSurgeExtensibilityBase
{
    public override bool OnBeforeRequestSent(HttpRequestData data)
    {
        var header = new HttpRequestHeader
        {
            Name = "x-request-time",
            Value = DateTime.UtcNow.ToString("o")
        };
        data.Headers.Add(header);


        if (!string.IsNullOrEmpty(data.RequestContent))
        {
            // do something here to get your unique value
            var userId = new Random().Next().ToString();

            // then embed it into the content
            data.RequestContent = data.RequestContent.Replace("##UserId##", "USER_" + userId);
        }

        return true;
    }
}

© West Wind Technologies, 2014, 2014-2019 • Updated: 04/19/19
Comment or report problem with topic