diff --git a/CHANGELOG.md b/CHANGELOG.md
index fb85de5e..dac4f24d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,23 @@
+# 2.19.0 (07 October 2026)
+- [#1512](https://github.com/wiremock/WireMock.Net/pull/1512) - Use IDateTimeUtils in WireMockWebSocketContext [bug] contributed by [StefH](https://github.com/StefH)
+- [#1514](https://github.com/wiremock/WireMock.Net/pull/1514) - Fix DateTime in Response [bug] contributed by [StefH](https://github.com/StefH)
+- [#1511](https://github.com/wiremock/WireMock.Net/issues/1511) - Incorrect response datetime for mapped response [bug]
+
+# 2.18.0 (22 September 2026)
+- [#1510](https://github.com/wiremock/WireMock.Net/pull/1510) - WireMock.Net.OpenApiParser: fix depencency on RamlToOpenApiConverter.SourceOnly [bug] contributed by [StefH](https://github.com/StefH)
+- [#1508](https://github.com/wiremock/WireMock.Net/issues/1508) - Transitive Dependency Conflict with Microsoft.OpenApi in 2.16.0 [bug]
+
+# 2.17.0 (21 September 2026)
+- [#1509](https://github.com/wiremock/WireMock.Net/pull/1509) - Revert to RamlToOpenApiConverter.SourceOnly [bug] contributed by [StefH](https://github.com/StefH)
+
+# 2.16.0 (19 September 2026)
+- [#1502](https://github.com/wiremock/WireMock.Net/pull/1502) - Fix #1501: Generate WhenStateIs/WillSetStateTo correctly in ToCSharpCode contributed by [Bafyn](https://github.com/Bafyn)
+- [#1503](https://github.com/wiremock/WireMock.Net/pull/1503) - Fix FormUrlEncodedMatcher (+ refactor values / matchers logic) contributed by [StefH](https://github.com/StefH)
+- [#1504](https://github.com/wiremock/WireMock.Net/pull/1504) - Update SharpYaml package to version 2.5.1 [dependencies] contributed by [johnthcall](https://github.com/johnthcall)
+- [#1505](https://github.com/wiremock/WireMock.Net/pull/1505) - Upgrade dependency RamlToOpenApiConverter to version 0.40.0 [dependencies] contributed by [StefH](https://github.com/StefH)
+- [#1500](https://github.com/wiremock/WireMock.Net/issues/1500) - Sending a form-urlencoded body with a repeated field name returns HTTP 500 [bug]
+- [#1501](https://github.com/wiremock/WireMock.Net/issues/1501) - Generated C# code for stateful (Scenario) mappings does not compile and drops the WhenStateIs condition [bug]
+
# 2.15.0 (15 August 2026)
- [#1495](https://github.com/wiremock/WireMock.Net/pull/1495) - Fix #1494: `WithClientIP(MatchOperator, params IStringMatcher[])` ignores the MatchOperator argument [bug] contributed by [Bafyn](https://github.com/Bafyn)
- [#1497](https://github.com/wiremock/WireMock.Net/pull/1497) - Fix WithParam RejectOnMatch inverting the match result #1496 [bug] contributed by [Bafyn](https://github.com/Bafyn)
diff --git a/Directory.Build.props b/Directory.Build.props
index 79945350..3c7ff66d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -4,7 +4,7 @@
- 2.15.0
+ 2.19.0
WireMock.Net-Logo.png
https://github.com/wiremock/WireMock.Net
Apache-2.0
@@ -52,7 +52,7 @@
-
+
diff --git a/Generate-ReleaseNotes.cmd b/Generate-ReleaseNotes.cmd
index 58cbc00e..19fad88e 100644
--- a/Generate-ReleaseNotes.cmd
+++ b/Generate-ReleaseNotes.cmd
@@ -1,6 +1,6 @@
rem https://github.com/StefH/GitHubReleaseNotes
-SET version=2.15.0
+SET version=2.19.0
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels wontfix test question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
diff --git a/PackageReleaseNotes.txt b/PackageReleaseNotes.txt
index 40d63159..877be2da 100644
--- a/PackageReleaseNotes.txt
+++ b/PackageReleaseNotes.txt
@@ -1,8 +1,6 @@
-# 2.15.0 (15 August 2026)
-- #1495 Fix #1494: `WithClientIP(MatchOperator, params IStringMatcher[])` ignores the MatchOperator argument [bug]
-- #1497 Fix WithParam RejectOnMatch inverting the match result #1496 [bug]
-- #1499 Update Testcontainers [bug]
-- #1494 `WithClientIP(MatchOperator, params IStringMatcher[])` ignores the `MatchOperator` argument [bug]
-- #1496 `WithParam(key, MatchBehaviour.RejectOnMatch, values)` inverts the match result [bug]
+# 2.19.0 (07 October 2026)
+- #1512 Use IDateTimeUtils in WireMockWebSocketContext [bug]
+- #1514 Fix DateTime in Response [bug]
+- #1511 Incorrect response datetime for mapped response [bug]
The full release notes can be found here: https://github.com/wiremock/WireMock.Net/blob/master/CHANGELOG.md
\ No newline at end of file
diff --git a/examples/WireMock.Net.Client/Program.cs b/examples/WireMock.Net.Client/Program.cs
index f9651fbc..0f0c2f78 100644
--- a/examples/WireMock.Net.Client/Program.cs
+++ b/examples/WireMock.Net.Client/Program.cs
@@ -1,9 +1,7 @@
// Copyright © WireMock.Net
-using System;
using System.Net.Http.Headers;
using System.Text;
-using System.Threading.Tasks;
using Newtonsoft.Json;
using RestEase;
using WireMock.Admin.Settings;
diff --git a/examples/WireMock.Net.Console.NET8.WithCertificate/Program.cs b/examples/WireMock.Net.Console.NET8.WithCertificate/Program.cs
index c81eca17..a1488ea6 100644
--- a/examples/WireMock.Net.Console.NET8.WithCertificate/Program.cs
+++ b/examples/WireMock.Net.Console.NET8.WithCertificate/Program.cs
@@ -1,6 +1,5 @@
// Copyright © WireMock.Net
-using System.IO;
using WireMock.Logging;
using WireMock.Server;
using WireMock.Settings;
diff --git a/examples/WireMock.Net.Console.NET8/MainApp.cs b/examples/WireMock.Net.Console.NET8/MainApp.cs
index 9023b526..43fe8bb8 100644
--- a/examples/WireMock.Net.Console.NET8/MainApp.cs
+++ b/examples/WireMock.Net.Console.NET8/MainApp.cs
@@ -1,14 +1,9 @@
// Copyright © WireMock.Net
-using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.IO;
-using System.Linq;
using System.Net;
-using System.Threading.Tasks;
using Newtonsoft.Json;
-using SharpYaml.Model;
+using Scriban.Runtime;
using WireMock.Logging;
using WireMock.Matchers;
using WireMock.Models;
@@ -291,11 +286,21 @@ namespace WireMock.Net.ConsoleApplication
var server = WireMockServer.Start(new WireMockServerSettings
{
+ StartAdminInterface = true,
Logger = new WireMockConsoleLogger(),
-
Port = 9091
});
+ server
+ .WhenRequest(r => r
+ .WithPath("/test")
+ .UsingAnyMethod()
+ )
+ .ThenRespondWith(r => r
+ .WithStatusCode(HttpStatusCode.OK)
+ .WithBody("OK")
+ );
+
server
.WhenRequest(r => r
.WithPath("/Content-Length")
@@ -405,12 +410,26 @@ namespace WireMock.Net.ConsoleApplication
// handlebarsContext.RegisterHelper(transformer.Name, transformer.Render); TODO
},
+ ScribanRegistrationCallback = (scriptObject, fileSystemHandler) =>
+ {
+ var globals = (ScriptObject)scriptObject;
+ globals.Import("greet", new Func(name => $"Hello {name}"));
+ },
+
// Uncomment below if you want to use the CustomFileSystemFileHandler
// FileSystemHandler = new CustomFileSystemFileHandler()
});
System.Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));
server.SetBasicAuthentication("a", "b");
+
+ server
+ .Given(Request.Create().WithPath("/scriban/greet").UsingGet())
+ .RespondWith(Response.Create()
+ .WithBody("{{ greet 'WireMock.Net' }}")
+ .WithTransformer(TransformerType.Scriban)
+ );
+
//server.SetAzureADAuthentication(Environment.GetEnvironmentVariable("WIREMOCK_AAD_TENANT")!, "api://e083d51a-01a6-446c-8ad5-0c5c7f002208");
//var http = new HttpClient();
diff --git a/examples/WireMock.Net.Console.RequestLogTest/Program.cs b/examples/WireMock.Net.Console.RequestLogTest/Program.cs
index d1aeab3b..dbcdc04a 100644
--- a/examples/WireMock.Net.Console.RequestLogTest/Program.cs
+++ b/examples/WireMock.Net.Console.RequestLogTest/Program.cs
@@ -1,9 +1,5 @@
// Copyright © WireMock.Net
-using System;
-using System.Linq;
-using System.Net.Http;
-using System.Threading.Tasks;
using WireMock.Logging;
using WireMock.Net.StandAlone;
using WireMock.RequestBuilders;
diff --git a/examples/WireMock.Net.ConsoleApp.UsingNuGet/WireMock.Net.ConsoleApp.UsingNuGet.csproj b/examples/WireMock.Net.ConsoleApp.UsingNuGet/WireMock.Net.ConsoleApp.UsingNuGet.csproj
index 0836b3a1..f37fe696 100644
--- a/examples/WireMock.Net.ConsoleApp.UsingNuGet/WireMock.Net.ConsoleApp.UsingNuGet.csproj
+++ b/examples/WireMock.Net.ConsoleApp.UsingNuGet/WireMock.Net.ConsoleApp.UsingNuGet.csproj
@@ -16,7 +16,7 @@
-
+
\ No newline at end of file
diff --git a/examples/WireMock.Net.OpenApiParser.ConsoleApp/Program.cs b/examples/WireMock.Net.OpenApiParser.ConsoleApp/Program.cs
index 13230f90..4b0cc347 100644
--- a/examples/WireMock.Net.OpenApiParser.ConsoleApp/Program.cs
+++ b/examples/WireMock.Net.OpenApiParser.ConsoleApp/Program.cs
@@ -1,7 +1,5 @@
// Copyright © WireMock.Net
-using System;
-using System.IO;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
diff --git a/examples/WireMock.Net.OpenApiParser.ConsoleApp/WireMock.Net.OpenApiParser.ConsoleApp.csproj b/examples/WireMock.Net.OpenApiParser.ConsoleApp/WireMock.Net.OpenApiParser.ConsoleApp.csproj
index e35ba9fd..310ef063 100644
--- a/examples/WireMock.Net.OpenApiParser.ConsoleApp/WireMock.Net.OpenApiParser.ConsoleApp.csproj
+++ b/examples/WireMock.Net.OpenApiParser.ConsoleApp/WireMock.Net.OpenApiParser.ConsoleApp.csproj
@@ -6,15 +6,13 @@
-
-
-
+
diff --git a/src/WireMock.Net.Abstractions/IRequestMessage.cs b/src/WireMock.Net.Abstractions/IRequestMessage.cs
index 02a23b63..c60fbe8f 100644
--- a/src/WireMock.Net.Abstractions/IRequestMessage.cs
+++ b/src/WireMock.Net.Abstractions/IRequestMessage.cs
@@ -32,7 +32,7 @@ public interface IRequestMessage
string? ProxyUrl { get; set; }
///
- /// Gets the DateTime.
+ /// The DateTime when this request was done.
///
DateTime DateTime { get; }
diff --git a/src/WireMock.Net.Abstractions/IResponseMessage.cs b/src/WireMock.Net.Abstractions/IResponseMessage.cs
index 8abf4114..4993a649 100644
--- a/src/WireMock.Net.Abstractions/IResponseMessage.cs
+++ b/src/WireMock.Net.Abstractions/IResponseMessage.cs
@@ -52,7 +52,7 @@ public interface IResponseMessage
object? StatusCode { get; set; }
///
- /// Gets the DateTime.
+ /// The DateTime when this response was sent.
///
DateTime DateTime { get; }
diff --git a/src/WireMock.Net.Minimal/Extensions/HttpContextExtensions.cs b/src/WireMock.Net.Minimal/Extensions/HttpContextExtensions.cs
new file mode 100644
index 00000000..07ca7b81
--- /dev/null
+++ b/src/WireMock.Net.Minimal/Extensions/HttpContextExtensions.cs
@@ -0,0 +1,14 @@
+// Copyright © WireMock.Net
+
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.AspNetCore.Http;
+
+namespace WireMock.Extensions;
+
+internal static class HttpContextExtensions
+{
+ internal static bool TryGet(this HttpContext httpContext, [NotNullWhen(true)] out T? value)
+ {
+ return httpContext.Items.TryGetValue(nameof(T), out value);
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.Minimal/Owin/Mappers/OwinRequestMapper.cs b/src/WireMock.Net.Minimal/Owin/Mappers/OwinRequestMapper.cs
index 0db51eb4..a0d2c3c7 100644
--- a/src/WireMock.Net.Minimal/Owin/Mappers/OwinRequestMapper.cs
+++ b/src/WireMock.Net.Minimal/Owin/Mappers/OwinRequestMapper.cs
@@ -12,7 +12,7 @@ namespace WireMock.Owin.Mappers;
///
/// OwinRequestMapper
///
-internal class OwinRequestMapper : IOwinRequestMapper
+internal class OwinRequestMapper(IDateTimeUtils dateTimeUtils) : IOwinRequestMapper
{
///
public async Task MapAsync(HttpContext context, IWireMockMiddlewareOptions options)
@@ -72,7 +72,7 @@ internal class OwinRequestMapper : IOwinRequestMapper
await request.HttpContext.Connection.GetClientCertificateAsync()
)
{
- DateTime = DateTime.UtcNow
+ DateTime = dateTimeUtils.UtcNow
};
}
diff --git a/src/WireMock.Net.Minimal/Owin/WireMockMiddleware.cs b/src/WireMock.Net.Minimal/Owin/WireMockMiddleware.cs
index bd193e11..89528b3f 100644
--- a/src/WireMock.Net.Minimal/Owin/WireMockMiddleware.cs
+++ b/src/WireMock.Net.Minimal/Owin/WireMockMiddleware.cs
@@ -171,6 +171,12 @@ internal class WireMockMiddleware(
}
finally
{
+ // Set the DateTime from the Response to the current DateTime
+ if (response is ResponseMessage responseMessage)
+ {
+ responseMessage.DateTime = dateTimeUtils.UtcNow;
+ }
+
logger.LogRequestAndResponse(logRequest, request, response, result.Match, result.Partial, activity);
try
@@ -255,4 +261,4 @@ internal class WireMockMiddleware(
scenario.Finished = mapping.NextState == null;
});
}
-}
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.Minimal/Owin/WireMockMiddlewareLogger.cs b/src/WireMock.Net.Minimal/Owin/WireMockMiddlewareLogger.cs
index 2f35b2ce..d44eaf7d 100644
--- a/src/WireMock.Net.Minimal/Owin/WireMockMiddlewareLogger.cs
+++ b/src/WireMock.Net.Minimal/Owin/WireMockMiddlewareLogger.cs
@@ -73,20 +73,20 @@ internal class WireMockMiddlewareLogger(
var logEntries = options.LogEntries.ToList();
foreach (var logEntry in logEntries
- .OrderBy(le => le.RequestMessage?.DateTime ?? le.ResponseMessage?.DateTime)
+ .OrderBy(le => le.RequestMessage?.DateTime)
.Take(logEntries.Count - options.MaxRequestLogCount.Value))
{
TryRemoveLogEntry(logEntry);
}
}
- // In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the date.
+ // In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the RequestMessage date.
if (options.RequestLogExpirationDuration is > 0)
{
var logEntries = options.LogEntries.ToList();
var checkTime = dateTimeUtils.UtcNow.AddHours(-options.RequestLogExpirationDuration.Value);
- foreach (var logEntry in logEntries.Where(le => le.RequestMessage?.DateTime < checkTime || le.ResponseMessage?.DateTime < checkTime))
+ foreach (var logEntry in logEntries.Where(le => le.RequestMessage?.DateTime < checkTime))
{
TryRemoveLogEntry(logEntry);
}
diff --git a/src/WireMock.Net.Minimal/ResponseBuilders/Response.cs b/src/WireMock.Net.Minimal/ResponseBuilders/Response.cs
index 60151c0e..b14631f5 100644
--- a/src/WireMock.Net.Minimal/ResponseBuilders/Response.cs
+++ b/src/WireMock.Net.Minimal/ResponseBuilders/Response.cs
@@ -87,7 +87,7 @@ public partial class Response : IResponseBuilder
{
var message = responseMessage ?? new ResponseMessage
{
- DateTime = DateTime.UtcNow // We set it here to the current time.
+ DateTime = DateTime.UtcNow // Initially, this is set to the current time, but will be updated to the real time once the response has been sent.
};
return new Response(message);
diff --git a/src/WireMock.Net.Minimal/ResponseMessage.cs b/src/WireMock.Net.Minimal/ResponseMessage.cs
index 1b5d3f9c..70ae16c1 100644
--- a/src/WireMock.Net.Minimal/ResponseMessage.cs
+++ b/src/WireMock.Net.Minimal/ResponseMessage.cs
@@ -2,7 +2,6 @@
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
-using System.Linq;
using Stef.Validation;
using WireMock.ResponseBuilders;
using WireMock.Types;
diff --git a/src/WireMock.Net.Minimal/ResponseProviders/WebSocketResponseProvider.cs b/src/WireMock.Net.Minimal/ResponseProviders/WebSocketResponseProvider.cs
index 64460954..23a03bc6 100644
--- a/src/WireMock.Net.Minimal/ResponseProviders/WebSocketResponseProvider.cs
+++ b/src/WireMock.Net.Minimal/ResponseProviders/WebSocketResponseProvider.cs
@@ -67,7 +67,8 @@ internal class WebSocketResponseProvider(WebSocketBuilder builder, IGuidUtils gu
builder,
options,
logger,
- guidUtils
+ guidUtils,
+ dateTimeUtils
);
// Add to registry
diff --git a/src/WireMock.Net.Minimal/Settings/WireMockServerSettingsExtensions.cs b/src/WireMock.Net.Minimal/Settings/WireMockServerSettingsExtensions.cs
new file mode 100644
index 00000000..7e347be9
--- /dev/null
+++ b/src/WireMock.Net.Minimal/Settings/WireMockServerSettingsExtensions.cs
@@ -0,0 +1,40 @@
+// Copyright © WireMock.Net
+
+using JetBrains.Annotations;
+using Scriban.Runtime;
+using Stef.Validation;
+using WireMock.Handlers;
+
+namespace WireMock.Settings;
+
+///
+/// Extension methods for .
+///
+public static class WireMockServerSettingsExtensions
+{
+ ///
+ /// Adds a strongly typed Scriban registration to .
+ ///
+ ///
+ /// Members added to the are available as globals in Scriban and Scriban-DotLiquid templates.
+ /// When a callback is already configured, it is kept and invoked before .
+ ///
+ /// The settings.
+ /// The action which registers functions, objects or variables on the .
+ /// The same instance.
+ [PublicAPI]
+ public static WireMockServerSettings WithScribanRegistration(this WireMockServerSettings settings, Action registrationCallback)
+ {
+ Guard.NotNull(settings);
+ Guard.NotNull(registrationCallback);
+
+ var existingCallback = settings.ScribanRegistrationCallback;
+ settings.ScribanRegistrationCallback = (scriptObject, fileSystemHandler) =>
+ {
+ existingCallback?.Invoke(scriptObject, fileSystemHandler);
+ registrationCallback((ScriptObject)scriptObject, fileSystemHandler);
+ };
+
+ return settings;
+ }
+}
diff --git a/src/WireMock.Net.Minimal/Transformers/Scriban/ScribanContext.cs b/src/WireMock.Net.Minimal/Transformers/Scriban/ScribanContext.cs
index c54febbf..ea21cdee 100644
--- a/src/WireMock.Net.Minimal/Transformers/Scriban/ScribanContext.cs
+++ b/src/WireMock.Net.Minimal/Transformers/Scriban/ScribanContext.cs
@@ -1,6 +1,7 @@
// Copyright © WireMock.Net
using Scriban;
+using Scriban.Runtime;
using Stef.Validation;
using WireMock.Handlers;
using WireMock.Types;
@@ -9,21 +10,40 @@ namespace WireMock.Transformers.Scriban;
internal class ScribanContext : ITransformerContext
{
+ private static readonly MemberRenamerDelegate MemberRenamer = member => member.Name;
+
private readonly TransformerType _transformerType;
+ private readonly ScriptObject? _customGlobals;
public IFileSystemHandler FileSystemHandler { get; }
- public ScribanContext(IFileSystemHandler fileSystemHandler, TransformerType transformerType)
+ public ScribanContext(IFileSystemHandler fileSystemHandler, TransformerType transformerType, ScriptObject? customGlobals = null)
{
FileSystemHandler = Guard.NotNull(fileSystemHandler);
_transformerType = transformerType;
+ _customGlobals = customGlobals;
}
public string ParseAndRender(string text, object model)
{
- var template = _transformerType == TransformerType.ScribanDotLiquid ? Template.ParseLiquid(text) : Template.Parse(text);
+ var isLiquid = _transformerType == TransformerType.ScribanDotLiquid;
+ var template = isLiquid ? Template.ParseLiquid(text) : Template.Parse(text);
- return template.Render(model, member => member.Name);
+ if (_customGlobals is null)
+ {
+ return template.Render(model, MemberRenamer);
+ }
+
+ // Same as Template.Render(model, MemberRenamer), but with the custom globals pushed beneath the model so that the model takes precedence.
+ var context = isLiquid ? new LiquidTemplateContext() : new TemplateContext();
+ context.MemberRenamer = MemberRenamer;
+ context.PushGlobal(_customGlobals);
+
+ var modelGlobals = new ScriptObject();
+ modelGlobals.Import(model, renamer: MemberRenamer);
+ context.PushGlobal(modelGlobals);
+
+ return template.Render(context);
}
public object? ParseAndEvaluate(string text, object model)
diff --git a/src/WireMock.Net.Minimal/Transformers/Scriban/ScribanContextFactory.cs b/src/WireMock.Net.Minimal/Transformers/Scriban/ScribanContextFactory.cs
index 91db290c..1a829a5a 100644
--- a/src/WireMock.Net.Minimal/Transformers/Scriban/ScribanContextFactory.cs
+++ b/src/WireMock.Net.Minimal/Transformers/Scriban/ScribanContextFactory.cs
@@ -1,24 +1,32 @@
// Copyright © WireMock.Net
-using WireMock.Handlers;
-using WireMock.Types;
+using Scriban.Runtime;
using Stef.Validation;
+using WireMock.Settings;
+using WireMock.Types;
namespace WireMock.Transformers.Scriban;
internal class ScribanContextFactory : ITransformerContextFactory
{
- private readonly IFileSystemHandler _fileSystemHandler;
+ private readonly WireMockServerSettings _settings;
private readonly TransformerType _transformerType;
- public ScribanContextFactory(IFileSystemHandler fileSystemHandler, TransformerType transformerType)
+ public ScribanContextFactory(WireMockServerSettings settings, TransformerType transformerType)
{
- _fileSystemHandler = Guard.NotNull(fileSystemHandler);
+ _settings = Guard.NotNull(settings);
_transformerType = Guard.Condition(transformerType, t => t is TransformerType.Scriban or TransformerType.ScribanDotLiquid);
}
public ITransformerContext Create()
{
- return new ScribanContext(_fileSystemHandler, _transformerType);
+ ScriptObject? customGlobals = null;
+ if (_settings.ScribanRegistrationCallback is { } registrationCallback)
+ {
+ customGlobals = new ScriptObject();
+ registrationCallback(customGlobals, _settings.FileSystemHandler);
+ }
+
+ return new ScribanContext(_settings.FileSystemHandler, _transformerType, customGlobals);
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net.Minimal/Transformers/TransformerFactory.cs b/src/WireMock.Net.Minimal/Transformers/TransformerFactory.cs
index c398d140..7d390274 100644
--- a/src/WireMock.Net.Minimal/Transformers/TransformerFactory.cs
+++ b/src/WireMock.Net.Minimal/Transformers/TransformerFactory.cs
@@ -19,8 +19,8 @@ internal static class TransformerFactory
case TransformerType.Scriban:
case TransformerType.ScribanDotLiquid:
- var factoryDotLiquid = new ScribanContextFactory(settings.FileSystemHandler, transformerType);
- return new Transformer(settings, factoryDotLiquid);
+ var factoryScriban = new ScribanContextFactory(settings, transformerType);
+ return new Transformer(settings, factoryScriban);
default:
throw new NotSupportedException($"{nameof(TransformerType)} '{transformerType}' is not supported.");
diff --git a/src/WireMock.Net.Minimal/WebSockets/WireMockWebSocketContext.cs b/src/WireMock.Net.Minimal/WebSockets/WireMockWebSocketContext.cs
index 5486c292..e5a9d380 100644
--- a/src/WireMock.Net.Minimal/WebSockets/WireMockWebSocketContext.cs
+++ b/src/WireMock.Net.Minimal/WebSockets/WireMockWebSocketContext.cs
@@ -18,6 +18,8 @@ namespace WireMock.WebSockets;
///
public class WireMockWebSocketContext : IWebSocketContext
{
+ private readonly IDateTimeUtils _dateTimeUtils;
+
///
public Guid ConnectionId { get; }
@@ -50,7 +52,8 @@ public class WireMockWebSocketContext : IWebSocketContext
WebSocketBuilder builder,
IWireMockMiddlewareOptions options,
IWireMockMiddlewareLogger logger,
- IGuidUtils guidUtils
+ IGuidUtils guidUtils,
+ IDateTimeUtils dateTimeUtils
)
{
HttpContext = httpContext;
@@ -61,6 +64,7 @@ public class WireMockWebSocketContext : IWebSocketContext
Builder = builder;
Options = options;
Logger = logger;
+ _dateTimeUtils = dateTimeUtils;
ConnectionId = guidUtils.NewGuid();
}
@@ -169,7 +173,7 @@ public class WireMockWebSocketContext : IWebSocketContext
null
)
{
- DateTime = DateTime.UtcNow
+ DateTime = _dateTimeUtils.UtcNow
};
}
else
@@ -179,7 +183,7 @@ public class WireMockWebSocketContext : IWebSocketContext
{
Method = method,
BodyData = bodyData,
- DateTime = DateTime.UtcNow
+ DateTime = _dateTimeUtils.UtcNow
};
}
diff --git a/src/WireMock.Net.OpenApiParser/Extensions/DictionaryExtensions.cs b/src/WireMock.Net.OpenApiParser/Extensions/DictionaryExtensions.cs
index aec4ac2f..5a5ea0b8 100644
--- a/src/WireMock.Net.OpenApiParser/Extensions/DictionaryExtensions.cs
+++ b/src/WireMock.Net.OpenApiParser/Extensions/DictionaryExtensions.cs
@@ -1,8 +1,5 @@
// Copyright © WireMock.Net
-
-using System.Diagnostics.CodeAnalysis;
-
namespace System.Collections.Generic;
internal static class DictionaryExtensions
diff --git a/src/WireMock.Net.OpenApiParser/Extensions/WireMockServerExtensions.cs b/src/WireMock.Net.OpenApiParser/Extensions/WireMockServerExtensions.cs
index 7e763b55..bde12912 100644
--- a/src/WireMock.Net.OpenApiParser/Extensions/WireMockServerExtensions.cs
+++ b/src/WireMock.Net.OpenApiParser/Extensions/WireMockServerExtensions.cs
@@ -1,8 +1,8 @@
// Copyright © WireMock.Net
using JetBrains.Annotations;
-using Microsoft.OpenApi.Reader;
using Stef.Validation;
+using WireMock.Net.OpenApiParser.Models;
using WireMock.Net.OpenApiParser.Settings;
using WireMock.Server;
diff --git a/src/WireMock.Net.OpenApiParser/ILRepack.targets b/src/WireMock.Net.OpenApiParser/ILRepack.targets
new file mode 100644
index 00000000..71bd22d4
--- /dev/null
+++ b/src/WireMock.Net.OpenApiParser/ILRepack.targets
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/WireMock.Net.OpenApiParser/IWireMockOpenApiParser.cs b/src/WireMock.Net.OpenApiParser/IWireMockOpenApiParser.cs
index 7c451558..c09fa6e7 100644
--- a/src/WireMock.Net.OpenApiParser/IWireMockOpenApiParser.cs
+++ b/src/WireMock.Net.OpenApiParser/IWireMockOpenApiParser.cs
@@ -1,7 +1,7 @@
// Copyright © WireMock.Net
-using Microsoft.OpenApi.Reader;
using WireMock.Admin.Mappings;
+using WireMock.Net.OpenApiParser.Models;
using WireMock.Net.OpenApiParser.Settings;
namespace WireMock.Net.OpenApiParser;
diff --git a/src/WireMock.Net.OpenApiParser/Models/OpenApiDiagnostic.cs b/src/WireMock.Net.OpenApiParser/Models/OpenApiDiagnostic.cs
new file mode 100644
index 00000000..22093244
--- /dev/null
+++ b/src/WireMock.Net.OpenApiParser/Models/OpenApiDiagnostic.cs
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+namespace WireMock.Net.OpenApiParser.Models;
+
+///
+/// Object containing all diagnostic information related to Open API parsing.
+///
+public class OpenApiDiagnostic
+{
+ ///
+ /// List of all errors.
+ ///
+ public List Errors { get; set; } = [];
+
+ ///
+ /// List of all warnings
+ ///
+ public List Warnings { get; set; } = [];
+
+ ///
+ /// Open API specification version of the document parsed.
+ ///
+ public OpenApiSpecVersion SpecificationVersion { get; set; }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.OpenApiParser/Models/OpenApiError.cs b/src/WireMock.Net.OpenApiParser/Models/OpenApiError.cs
new file mode 100644
index 00000000..b3d8bbe0
--- /dev/null
+++ b/src/WireMock.Net.OpenApiParser/Models/OpenApiError.cs
@@ -0,0 +1,46 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+namespace WireMock.Net.OpenApiParser.Models;
+
+///
+/// Error related to the Open API Document.
+///
+public class OpenApiError
+{
+ ///
+ /// Initializes the class.
+ ///
+ public OpenApiError(string? pointer, string message)
+ {
+ Pointer = pointer;
+ Message = message;
+ }
+
+ ///
+ /// Initializes a copy of an object
+ ///
+ public OpenApiError(OpenApiError error)
+ {
+ Pointer = error.Pointer;
+ Message = error.Message;
+ }
+
+ ///
+ /// Message explaining the error.
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// Pointer to the location of the error.
+ ///
+ public string? Pointer { get; set; }
+
+ ///
+ /// Gets the string representation of .
+ ///
+ public override string ToString()
+ {
+ return Message + (!string.IsNullOrEmpty(Pointer) ? " [" + Pointer + "]" : "");
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.OpenApiParser/Models/OpenApiMapper.cs b/src/WireMock.Net.OpenApiParser/Models/OpenApiMapper.cs
new file mode 100644
index 00000000..b203c7f1
--- /dev/null
+++ b/src/WireMock.Net.OpenApiParser/Models/OpenApiMapper.cs
@@ -0,0 +1,23 @@
+// Copyright © WireMock.Net
+
+using MicrosoftOpenApiDiagnostic = Microsoft.OpenApi.Reader.OpenApiDiagnostic;
+
+namespace WireMock.Net.OpenApiParser.Models;
+
+internal static class OpenApiMapper
+{
+ internal static OpenApiDiagnostic? Map(MicrosoftOpenApiDiagnostic? openApiDiagnostic)
+ {
+ if (openApiDiagnostic == null)
+ {
+ return null;
+ }
+
+ return new OpenApiDiagnostic
+ {
+ Errors = openApiDiagnostic.Errors.Select(e => new OpenApiError(e.Pointer, e.Message)).ToList(),
+ Warnings = openApiDiagnostic.Warnings.Select(e => new OpenApiError(e.Pointer, e.Message)).ToList(),
+ SpecificationVersion = (OpenApiSpecVersion)openApiDiagnostic.SpecificationVersion
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.OpenApiParser/Models/OpenApiSpecVersion.cs b/src/WireMock.Net.OpenApiParser/Models/OpenApiSpecVersion.cs
new file mode 100644
index 00000000..31433dd4
--- /dev/null
+++ b/src/WireMock.Net.OpenApiParser/Models/OpenApiSpecVersion.cs
@@ -0,0 +1,29 @@
+// Copyright © WireMock.Net
+
+namespace WireMock.Net.OpenApiParser.Models;
+
+///
+/// Represents versions of OpenAPI specification.
+///
+public enum OpenApiSpecVersion
+{
+ ///
+ /// Represents OpenAPI V2.0 spec
+ ///
+ OpenApi2_0,
+
+ ///
+ /// Represents all patches of OpenAPI V3.0 spec (e.g. 3.0.0, 3.0.1)
+ ///
+ OpenApi3_0,
+
+ ///
+ /// Represents OpenAPI V3.1 spec
+ ///
+ OpenApi3_1,
+
+ ///
+ /// Represents OpenAPI V3.2 spec
+ ///
+ OpenApi3_2
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.OpenApiParser/Settings/IWireMockOpenApiParserExampleValues.cs b/src/WireMock.Net.OpenApiParser/Settings/IWireMockOpenApiParserExampleValues.cs
index 6c3b3953..68946953 100644
--- a/src/WireMock.Net.OpenApiParser/Settings/IWireMockOpenApiParserExampleValues.cs
+++ b/src/WireMock.Net.OpenApiParser/Settings/IWireMockOpenApiParserExampleValues.cs
@@ -1,6 +1,5 @@
// Copyright © WireMock.Net
-using System;
using Microsoft.OpenApi;
namespace WireMock.Net.OpenApiParser.Settings;
diff --git a/src/WireMock.Net.OpenApiParser/Settings/WireMockOpenApiParserDynamicExampleValues.cs b/src/WireMock.Net.OpenApiParser/Settings/WireMockOpenApiParserDynamicExampleValues.cs
index 0f27bf31..26ce5719 100644
--- a/src/WireMock.Net.OpenApiParser/Settings/WireMockOpenApiParserDynamicExampleValues.cs
+++ b/src/WireMock.Net.OpenApiParser/Settings/WireMockOpenApiParserDynamicExampleValues.cs
@@ -1,6 +1,5 @@
// Copyright © WireMock.Net
-using System;
using Microsoft.OpenApi;
using RandomDataGenerator.FieldOptions;
using RandomDataGenerator.Randomizers;
diff --git a/src/WireMock.Net.OpenApiParser/Settings/WireMockOpenApiParserExampleValues.cs b/src/WireMock.Net.OpenApiParser/Settings/WireMockOpenApiParserExampleValues.cs
index 5acec53a..132d86e1 100644
--- a/src/WireMock.Net.OpenApiParser/Settings/WireMockOpenApiParserExampleValues.cs
+++ b/src/WireMock.Net.OpenApiParser/Settings/WireMockOpenApiParserExampleValues.cs
@@ -1,6 +1,5 @@
// Copyright © WireMock.Net
-using System;
using Microsoft.OpenApi;
namespace WireMock.Net.OpenApiParser.Settings;
diff --git a/src/WireMock.Net.OpenApiParser/Utils/DateTimeUtils.cs b/src/WireMock.Net.OpenApiParser/Utils/DateTimeUtils.cs
index e3178549..40ac3380 100644
--- a/src/WireMock.Net.OpenApiParser/Utils/DateTimeUtils.cs
+++ b/src/WireMock.Net.OpenApiParser/Utils/DateTimeUtils.cs
@@ -1,6 +1,5 @@
// Copyright © WireMock.Net
-using System;
using System.Globalization;
namespace WireMock.Net.OpenApiParser.Utils;
diff --git a/src/WireMock.Net.OpenApiParser/Utils/ExampleValueGenerator.cs b/src/WireMock.Net.OpenApiParser/Utils/ExampleValueGenerator.cs
index 1ee9920f..6a09e874 100644
--- a/src/WireMock.Net.OpenApiParser/Utils/ExampleValueGenerator.cs
+++ b/src/WireMock.Net.OpenApiParser/Utils/ExampleValueGenerator.cs
@@ -1,7 +1,5 @@
// Copyright © WireMock.Net
-using System;
-using System.Linq;
using System.Text.Json.Nodes;
using Microsoft.OpenApi;
using Stef.Validation;
diff --git a/src/WireMock.Net.OpenApiParser/WireMock.Net.OpenApiParser.csproj b/src/WireMock.Net.OpenApiParser/WireMock.Net.OpenApiParser.csproj
index 3a603126..6e20755f 100644
--- a/src/WireMock.Net.OpenApiParser/WireMock.Net.OpenApiParser.csproj
+++ b/src/WireMock.Net.OpenApiParser/WireMock.Net.OpenApiParser.csproj
@@ -23,7 +23,7 @@
true
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -40,11 +40,27 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/WireMock.Net.OpenApiParser/WireMockOpenApiParser.cs b/src/WireMock.Net.OpenApiParser/WireMockOpenApiParser.cs
index 5d675ef3..379f6576 100644
--- a/src/WireMock.Net.OpenApiParser/WireMockOpenApiParser.cs
+++ b/src/WireMock.Net.OpenApiParser/WireMockOpenApiParser.cs
@@ -9,7 +9,9 @@ using Microsoft.OpenApi.YamlReader;
using RamlToOpenApiConverter;
using WireMock.Admin.Mappings;
using WireMock.Net.OpenApiParser.Mappers;
+using WireMock.Net.OpenApiParser.Models;
using WireMock.Net.OpenApiParser.Settings;
+using OpenApiDiagnostic = WireMock.Net.OpenApiParser.Models.OpenApiDiagnostic;
namespace WireMock.Net.OpenApiParser;
@@ -125,7 +127,7 @@ public class WireMockOpenApiParser : IWireMockOpenApiParser
var result = OpenApiDocument.Load(memoryStream, settings: _readerSettings);
- diagnostic = result.Diagnostic ?? new OpenApiDiagnostic();
+ diagnostic = OpenApiMapper.Map(result.Diagnostic) ?? new OpenApiDiagnostic();
openApiDocument = result.Document;
return openApiDocument != null && !diagnostic.Errors.Any();
}
diff --git a/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs b/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs
index e11f630c..941120eb 100644
--- a/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs
+++ b/src/WireMock.Net.Shared/Settings/WireMockServerSettings.cs
@@ -194,6 +194,20 @@ public class WireMockServerSettings
[JsonIgnore]
public Action? HandlebarsRegistrationCallback { get; set; }
+ ///
+ /// Action which can be used to add additional Scriban registrations (functions, objects or variables). [Optional]
+ ///
+ ///
+ /// The first argument is a Scriban.Runtime.ScriptObject from the Scriban.Signed package.
+ /// It is typed as so that this package does not depend on Scriban.
+ /// Members added to it are available as globals in and templates.
+ /// On a name clash the template model (request, response, mapping and data) takes precedence.
+ /// The action is invoked each time a transformer context is created.
+ ///
+ [PublicAPI]
+ [JsonIgnore]
+ public Action