diff --git a/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs b/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
index 5e7180a72..74aac829c 100644
--- a/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
+++ b/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
@@ -12,6 +12,7 @@
using WireMock.Server;
using WireMock.Settings;
using WireMock.Util;
+using System.Threading.Tasks;
namespace WireMock.Net.ConsoleApplication
{
@@ -521,9 +522,29 @@ public static void Run()
.WithBodyAsJson(new { Id = "5bdf076c-5654-4b3e-842c-7caf1fabf8c9" }));
server
.Given(Request.Create().WithPath("/random200or505").UsingGet())
- .RespondWith(Response.Create().WithCallback(request => new ResponseMessage
+ .RespondWith(Response.Create().WithCallback(request =>
{
- StatusCode = new Random().Next(1, 100) == 1 ? 504 : 200
+ int code = new Random().Next(1, 2) == 1 ? 505 : 200;
+ return new ResponseMessage
+ {
+ BodyData = new BodyData { BodyAsString = "random200or505:" + code, DetectedBodyType = Types.BodyType.String },
+ StatusCode = code
+ };
+ }));
+
+ server
+ .Given(Request.Create().WithPath("/random200or505async").UsingGet())
+ .RespondWith(Response.Create().WithCallback(async request =>
+ {
+ await Task.Delay(1);
+
+ int code = new Random().Next(1, 2) == 1 ? 505 : 200;
+
+ return new ResponseMessage
+ {
+ BodyData = new BodyData { BodyAsString = "random200or505async:" + code, DetectedBodyType = Types.BodyType.String },
+ StatusCode = code
+ };
}));
System.Console.WriteLine(JsonConvert.SerializeObject(server.MappingModels, Formatting.Indented));
diff --git a/src/WireMock.Net/ResponseBuilders/ICallbackResponseBuilder.cs b/src/WireMock.Net/ResponseBuilders/ICallbackResponseBuilder.cs
index bd06ef902..27ddec154 100644
--- a/src/WireMock.Net/ResponseBuilders/ICallbackResponseBuilder.cs
+++ b/src/WireMock.Net/ResponseBuilders/ICallbackResponseBuilder.cs
@@ -1,19 +1,27 @@
-using System;
-using JetBrains.Annotations;
-using WireMock.ResponseProviders;
-
-namespace WireMock.ResponseBuilders
-{
- ///
- /// The CallbackResponseBuilder interface.
- ///
- public interface ICallbackResponseBuilder : IResponseProvider
- {
- ///
- /// The callback builder
- ///
- /// The .
- [PublicAPI]
- IResponseBuilder WithCallback([NotNull] Func callbackHandler);
- }
+using System;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+using WireMock.ResponseProviders;
+
+namespace WireMock.ResponseBuilders
+{
+ ///
+ /// The CallbackResponseBuilder interface.
+ ///
+ public interface ICallbackResponseBuilder : IResponseProvider
+ {
+ ///
+ /// The callback builder
+ ///
+ /// The .
+ [PublicAPI]
+ IResponseBuilder WithCallback([NotNull] Func callbackHandler);
+
+ ///
+ /// The async callback builder
+ ///
+ /// The .
+ [PublicAPI]
+ IResponseBuilder WithCallback([NotNull] Func> callbackHandler);
+ }
}
\ No newline at end of file
diff --git a/src/WireMock.Net/ResponseBuilders/Response.WithCallback.cs b/src/WireMock.Net/ResponseBuilders/Response.WithCallback.cs
new file mode 100644
index 000000000..34e68931b
--- /dev/null
+++ b/src/WireMock.Net/ResponseBuilders/Response.WithCallback.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Threading.Tasks;
+using WireMock.Validation;
+
+namespace WireMock.ResponseBuilders
+{
+ public partial class Response
+ {
+ ///
+ /// A delegate to execute to generate the response.
+ ///
+ public Func Callback { get; private set; }
+
+ ///
+ /// A delegate to execute to generate the response async.
+ ///
+ public Func> CallbackAsync { get; private set; }
+
+ ///
+ /// Defines if the method WithCallback(...) is used.
+ ///
+ public bool WithCallbackUsed { get; private set; }
+
+ ///
+ public IResponseBuilder WithCallback(Func callbackHandler)
+ {
+ Check.NotNull(callbackHandler, nameof(callbackHandler));
+
+ return WithCallbackInternal(true, callbackHandler);
+ }
+
+ ///
+ public IResponseBuilder WithCallback(Func> callbackHandler)
+ {
+ Check.NotNull(callbackHandler, nameof(callbackHandler));
+
+ return WithCallbackInternal(true, callbackHandler);
+ }
+
+ private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func callbackHandler)
+ {
+ Check.NotNull(callbackHandler, nameof(callbackHandler));
+
+ WithCallbackUsed = withCallbackUsed;
+ Callback = callbackHandler;
+
+ return this;
+ }
+
+ private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func> callbackHandler)
+ {
+ Check.NotNull(callbackHandler, nameof(callbackHandler));
+
+ WithCallbackUsed = withCallbackUsed;
+ CallbackAsync = callbackHandler;
+
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs
index ee6715b98..061552b88 100644
--- a/src/WireMock.Net/ResponseBuilders/Response.cs
+++ b/src/WireMock.Net/ResponseBuilders/Response.cs
@@ -42,16 +42,6 @@ public partial class Response : IResponseBuilder
///
public ResponseMessage ResponseMessage { get; }
- ///
- /// A delegate to execute to generate the response.
- ///
- public Func Callback { get; private set; }
-
- ///
- /// Defines if the method WithCallback(...) is used.
- ///
- public bool WithCallbackUsed { get; private set; }
-
///
/// Creates this instance.
///
@@ -311,25 +301,6 @@ public IResponseBuilder WithDelay(int milliseconds)
return WithDelay(TimeSpan.FromMilliseconds(milliseconds));
}
- ///
- public IResponseBuilder WithCallback(Func callbackHandler)
- {
- Check.NotNull(callbackHandler, nameof(callbackHandler));
-
- return WithCallbackInternal(true, callbackHandler);
- }
-
- ///
- private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func callbackHandler)
- {
- Check.NotNull(callbackHandler, nameof(callbackHandler));
-
- WithCallbackUsed = withCallbackUsed;
- Callback = callbackHandler;
-
- return this;
- }
-
///
public async Task ProvideResponseAsync(RequestMessage requestMessage, IWireMockServerSettings settings)
{
@@ -365,13 +336,20 @@ string RemoveFirstOccurrence(string source, string find)
}
ResponseMessage responseMessage;
- if (Callback == null)
+ if (Callback == null && CallbackAsync == null)
{
responseMessage = ResponseMessage;
}
else
{
- responseMessage = Callback(requestMessage);
+ if (Callback != null)
+ {
+ responseMessage = Callback(requestMessage);
+ }
+ else
+ {
+ responseMessage = await CallbackAsync(requestMessage);
+ }
if (!WithCallbackUsed)
{
diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs
index 510b5f1b1..1fbe3f791 100644
--- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs
+++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithCallbackTests.cs
@@ -13,6 +13,35 @@ public class ResponseWithCallbackTests
{
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
+ [Fact]
+ public async Task Response_WithCallbackAsync()
+ {
+ // Assign
+ var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+ var response = Response.Create()
+ .WithCallback(async request =>
+ {
+ await Task.Delay(1);
+
+ return new ResponseMessage
+ {
+ BodyData = new BodyData
+ {
+ DetectedBodyType = BodyType.String,
+ BodyAsString = request.Path + "Bar"
+ },
+ StatusCode = 302
+ };
+ });
+
+ // Act
+ var responseMessage = await response.ProvideResponseAsync(requestMessage, _settings);
+
+ // Assert
+ responseMessage.BodyData.BodyAsString.Should().Be("/fooBar");
+ responseMessage.StatusCode.Should().Be(302);
+ }
+
[Fact]
public async Task Response_WithCallback()
{