Creating a WebSurge Addin with .NET
Creating an addin involves an easy process of creating a .NET 6 assembly, with a custom class that can hook into the WebSurge 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.
Addin Execution is disabled by Default
By default addins are not allowed to execute, as they represent a potential execution threat to your application. You have to explicitly enable them via the
AllowAddinExecution
in the File -> Settings Configuration.
Creating an Addin
The process to create an Addin involves the following steps:
- Target the same .NET version as
WebSurge.exe
(net60-windows
at this time) - Add a reference to
WebSurge.Core.dll
from the WebSurge Install folder - Use Properties on
WebSurge.Core.dll
and set Copy Local tofalse
- Create a new .NET Class
- Implement
IWebSurgeAddin
- or subclass
WebSurgeAddinBase
- Implement desired
OnXXX
methods to intercept request processing - Compile your project
- Place the final DLL (or build into)
<WebSurgeInstall>\Addins
Project Layout
The easiest way to configure a project for a WebSurge is to manually edit the project file and add the base references (adjusted for your install folder):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<UseWPF>true</UseWPF> <!-- only if you hook into UI features -->
</PropertyGroup>
<ItemGroup>
<Reference Include="WebSurge.Core">
<HintPath>c:\Program Files\West Wind WebSurge\WebSurge.Core.dll</HintPath>
<CopyLocal>False</CopyLocal>
</Reference>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<!--
* Copy main output assembly and any non-WebSurge dependencies to Addins folder
* If using `Program Files` you may have to change folder permissions to allow
you to write the new file(s) to the target folder or manually copy with Admin
-->
<Exec Command="copy "$(TargetDir)SampleAddin.dll" "C:\Program Files\West Wind WebSurge\Addins\SampleAddin.dll"" />
</Target>
</Project>
This code builds into the default compilation folder and then explicitly copies all assemblies that are non-WebSurge related to the Addins
folder. Any depedencies on libraries that WebSurge uses don't need to be copied but any additional libraries you add have to be copied.
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 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 theINTERACTIVE
user to the folder permissions and give it Full Rights in order to be able to have Visual Studio output into theAddins
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 IWebSurgeAddin
and loads them. You can add multiple addins into a single assembly and WebSurge will find them or look through all assemblies in the Addins
folder 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 fired during tests for OnBeforeRequestSent
and OnAfterRequestSent
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 using the WPF Dispatcher.CurrentDispatcher
.
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 including the passed in StressTester
instance, as well as any other structures re 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 LogAddin : IWebSurgeAddin
{
public override bool OnBeforeRequestSent(HttpRequestData httpRequest, StressTester stressTester)
{
logRequests(request, 0);
return true;
}
public override void OnAfterRequestSent(HttpRequestData request, StressTester stressTester)
{
logRequests(request, 1);
}
public override void OnAfterRequestSent(HttpRequestData request, StressTester stressTester)
{
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.");
}
public override void OnLoadTestCompleted(IList<HttpRequestData> requests, TestResultView results, StressTester stressTester)
{
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 ModifyContentAddin : WebSurgeAddinBase
{
public override bool OnBeforeRequestSent(HttpRequestData data, StressTester stressTester)
{
data.AddHeader("x-request-time", DateTime.UtcNow.ToString("o"))
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);
}
// change request content conditionally
if (data.Url.Contains("/somerequest"))
{
data.RequestContent = "<custom content>";
}
return true;
}
}
See also
Create WebSurge .NET Addins to extend Functionality© West Wind Technologies, 2014-2023 • Updated: 02/06/22
Comment or report problem with topic