diff --git a/examples/WireMock.Net.Client/Program.cs b/examples/WireMock.Net.Client/Program.cs index 6d1f7224..a6ccf781 100644 --- a/examples/WireMock.Net.Client/Program.cs +++ b/examples/WireMock.Net.Client/Program.cs @@ -1,78 +1,125 @@ -using Newtonsoft.Json; -using RestEase; using System; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; +using Newtonsoft.Json; +using RestEase; using WireMock.Admin.Settings; using WireMock.Client; +using WireMock.Client.Extensions; -namespace WireMock.Net.Client +namespace WireMock.Net.Client; + +class Program { - class Program + static async Task Main(string[] args) { - static async Task Main(string[] args) + // Create an implementation of the IWireMockAdminApi and pass in the base URL for the API. + var api = RestClient.For("http://localhost:9091"); + + // await api.ResetMappingsAsync().ConfigureAwait(false); + + var mappingBuilder = api.GetMappingBuilder(); + mappingBuilder.Given(m => m + .WithTitle("This is my title 1") + .WithRequest(req => req + .UsingGet() + .WithPath("/bla1") + ) + .WithResponse(rsp => rsp + .WithBody("x1") + .WithHeaders(h => h.Add("h1", "v1")) + ) + ); + + mappingBuilder.Given(m => m + .WithTitle("This is my title 2") + .WithRequest(req => req + .UsingGet() + .WithPath("/bla2") + ) + .WithResponse(rsp => rsp + .WithBody("x2") + .WithHeaders(h => h.Add("h2", "v2")) + ) + ); + + mappingBuilder.Given(m => m + .WithTitle("This is my title 3") + .WithRequest(req => req + .UsingGet() + .WithPath("/bla3") + ) + .WithResponse(rsp => rsp + .WithBodyAsJson(new + { + x = "test" + }, true) + ) + ); + + var result = await mappingBuilder.BuildAndPostAsync().ConfigureAwait(false); + Console.WriteLine($"result = {JsonConvert.SerializeObject(result)}"); + + var mappings = await api.GetMappingsAsync(); + Console.WriteLine($"mappings = {JsonConvert.SerializeObject(mappings)}"); + + // Set BASIC Auth + var value = Convert.ToBase64String(Encoding.ASCII.GetBytes("a:b")); + api.Authorization = new AuthenticationHeaderValue("Basic", value); + + var settings1 = await api.GetSettingsAsync(); + Console.WriteLine($"settings1 = {JsonConvert.SerializeObject(settings1)}"); + + var settingsViaBuilder = new SettingsModelBuilder() + .WithGlobalProcessingDelay(1077) + .WithoutGlobalProcessingDelay() + .Build(); + + settings1.GlobalProcessingDelay = 1077; + api.PostSettingsAsync(settings1).Wait(); + + var settings2 = await api.GetSettingsAsync(); + Console.WriteLine($"settings2 = {JsonConvert.SerializeObject(settings2)}"); + + mappings = await api.GetMappingsAsync(); + Console.WriteLine($"mappings = {JsonConvert.SerializeObject(mappings)}"); + + try { - // Create an implementation of the IWireMockAdminApi and pass in the base URL for the API. - var api = RestClient.For("http://localhost:9091"); - - // Set BASIC Auth - var value = Convert.ToBase64String(Encoding.ASCII.GetBytes("a:b")); - api.Authorization = new AuthenticationHeaderValue("Basic", value); - - var settings1 = await api.GetSettingsAsync(); - Console.WriteLine($"settings1 = {JsonConvert.SerializeObject(settings1)}"); - - var settingsViaBuilder = new SettingsModelBuilder() - .WithGlobalProcessingDelay(1077) - .WithoutGlobalProcessingDelay() - .Build(); - - settings1.GlobalProcessingDelay = 1077; - api.PostSettingsAsync(settings1).Wait(); - - var settings2 = await api.GetSettingsAsync(); - Console.WriteLine($"settings2 = {JsonConvert.SerializeObject(settings2)}"); - - var mappings = await api.GetMappingsAsync(); - Console.WriteLine($"mappings = {JsonConvert.SerializeObject(mappings)}"); - - try - { - var guid = Guid.Parse("11111110-a633-40e8-a244-5cb80bc0ab66"); - var mapping = await api.GetMappingAsync(guid); - Console.WriteLine($"mapping = {JsonConvert.SerializeObject(mapping)}"); - } - catch (Exception e) - { - } - - var request = await api.GetRequestsAsync(); - Console.WriteLine($"request = {JsonConvert.SerializeObject(request)}"); - - //var deleteRequestsAsync = api.DeleteRequestsAsync().Result; - //Console.WriteLine($"DeleteRequestsAsync = {deleteRequestsAsync.Status}"); - - //var resetRequestsAsync = api.ResetRequestsAsync().Result; - //Console.WriteLine($"ResetRequestsAsync = {resetRequestsAsync.Status}"); - - var scenarioStates = await api.GetScenariosAsync(); - Console.WriteLine($"GetScenariosAsync = {JsonConvert.SerializeObject(scenarioStates)}"); - - var postFileResult = await api.PostFileAsync("1.cs", "C# Hello"); - Console.WriteLine($"postFileResult = {JsonConvert.SerializeObject(postFileResult)}"); - - var getFileResult = await api.GetFileAsync("1.cs"); - Console.WriteLine($"getFileResult = {getFileResult}"); - - var resetMappingsAsync = await api.ResetMappingsAsync(); - Console.WriteLine($"resetMappingsAsync = {resetMappingsAsync.Status}"); - - var resetMappingsAndReloadStaticMappingsAsync = await api.ResetMappingsAsync(true); - Console.WriteLine($"resetMappingsAndReloadStaticMappingsAsync = {resetMappingsAndReloadStaticMappingsAsync.Status}"); - - Console.WriteLine("Press any key to quit"); - Console.ReadKey(); + var guid = Guid.Parse("11111110-a633-40e8-a244-5cb80bc0ab66"); + var mapping = await api.GetMappingAsync(guid); + Console.WriteLine($"mapping = {JsonConvert.SerializeObject(mapping)}"); } + catch (Exception e) + { + } + + var request = await api.GetRequestsAsync(); + Console.WriteLine($"request = {JsonConvert.SerializeObject(request)}"); + + //var deleteRequestsAsync = api.DeleteRequestsAsync().Result; + //Console.WriteLine($"DeleteRequestsAsync = {deleteRequestsAsync.Status}"); + + //var resetRequestsAsync = api.ResetRequestsAsync().Result; + //Console.WriteLine($"ResetRequestsAsync = {resetRequestsAsync.Status}"); + + var scenarioStates = await api.GetScenariosAsync(); + Console.WriteLine($"GetScenariosAsync = {JsonConvert.SerializeObject(scenarioStates)}"); + + var postFileResult = await api.PostFileAsync("1.cs", "C# Hello"); + Console.WriteLine($"postFileResult = {JsonConvert.SerializeObject(postFileResult)}"); + + var getFileResult = await api.GetFileAsync("1.cs"); + Console.WriteLine($"getFileResult = {getFileResult}"); + + var resetMappingsAsync = await api.ResetMappingsAsync(); + Console.WriteLine($"resetMappingsAsync = {resetMappingsAsync.Status}"); + + var resetMappingsAndReloadStaticMappingsAsync = await api.ResetMappingsAsync(true); + Console.WriteLine($"resetMappingsAndReloadStaticMappingsAsync = {resetMappingsAndReloadStaticMappingsAsync.Status}"); + + Console.WriteLine("Press any key to quit"); + Console.ReadKey(); } } \ No newline at end of file diff --git a/examples/WireMock.Net.Client/WireMock.Net.Client.csproj b/examples/WireMock.Net.Client/WireMock.Net.Client.csproj index bb713b33..5515959f 100644 --- a/examples/WireMock.Net.Client/WireMock.Net.Client.csproj +++ b/examples/WireMock.Net.Client/WireMock.Net.Client.csproj @@ -1,19 +1,13 @@ - - Exe - net6.0 - ../../resources/WireMock.Net-Logo.ico - + + Exe + net7.0 + ../../resources/WireMock.Net-Logo.ico + - - - - - - - - - + + + \ No newline at end of file diff --git a/src/WireMock.Net.Abstractions/BuilderExtensions/RequestModelBuilder.cs b/src/WireMock.Net.Abstractions/BuilderExtensions/RequestModelBuilder.cs new file mode 100644 index 00000000..418e740c --- /dev/null +++ b/src/WireMock.Net.Abstractions/BuilderExtensions/RequestModelBuilder.cs @@ -0,0 +1,139 @@ +using System; + +// ReSharper disable once CheckNamespace +namespace WireMock.Admin.Mappings; + +/// +/// RequestModelBuilder +/// +public partial class RequestModelBuilder +{ + /// + /// UsingConnect: add HTTP Method matching on `CONNECT`. + /// + /// The . + public RequestModelBuilder UsingConnect() => WithMethods("CONNECT"); + + /// + /// UsingDelete: add HTTP Method matching on `DELETE`. + /// + /// The . + public RequestModelBuilder UsingDelete() => WithMethods("DELETE"); + + /// + /// UsingGet: add HTTP Method matching on `GET`. + /// + /// The . + public RequestModelBuilder UsingGet() => WithMethods("GET"); + + /// + /// UsingHead: Add HTTP Method matching on `HEAD`. + /// + /// The . + public RequestModelBuilder UsingHead() => WithMethods("HEAD"); + + /// + /// UsingPost: add HTTP Method matching on `POST`. + /// + /// The . + public RequestModelBuilder UsingPost() => WithMethods("POST"); + + /// + /// UsingPatch: add HTTP Method matching on `PATCH`. + /// + /// The . + public RequestModelBuilder UsingPatch() => WithMethods("PATCH"); + + /// + /// UsingPut: add HTTP Method matching on `OPTIONS`. + /// + /// The . + public RequestModelBuilder UsingOptions() => WithMethods("OPTIONS"); + + /// + /// UsingPut: add HTTP Method matching on `PUT`. + /// + /// The . + public RequestModelBuilder UsingPut() => WithMethods("PUT"); + + /// + /// UsingTrace: add HTTP Method matching on `TRACE`. + /// + /// The . + public RequestModelBuilder UsingTrace() => WithMethods("TRACE"); + + /// + /// UsingAnyMethod: add HTTP Method matching on any method. + /// + /// The . + public RequestModelBuilder UsingAnyMethod() => this; + + /// + /// Set the ClientIP. + /// + public RequestModelBuilder WithClientIP(string value) => WithClientIP(() => value); + + /// + /// Set the ClientIP. + /// + public RequestModelBuilder WithClientIP(ClientIPModel value) => WithClientIP(() => value); + + /// + /// Set the ClientIP. + /// + public RequestModelBuilder WithClientIP(Action action) + { + return WithClientIP(() => + { + var builder = new ClientIPModelBuilder(); + action(builder); + return builder.Build(); + }); + } + + /// + /// Set the Path. + /// + public RequestModelBuilder WithPath(string value) => WithPath(() => value); + + /// + /// Set the Path. + /// + public RequestModelBuilder WithPath(PathModel value) => WithPath(() => value); + + /// + /// Set the Path. + /// + public RequestModelBuilder WithPath(Action action) + { + return WithPath(() => + { + var builder = new PathModelBuilder(); + action(builder); + return builder.Build(); + }); + } + + /// + /// Set the Url. + /// + public RequestModelBuilder WithUrl(string value) => WithUrl(() => value); + + /// + /// Set the Url. + /// + public RequestModelBuilder WithUrl(UrlModel value) => WithUrl(() => value); + + /// + /// Set the Url. + /// + public RequestModelBuilder WithUrl(Action action) + { + return WithUrl(() => + { + var builder = new UrlModelBuilder(); + action(builder); + return builder.Build(); + }); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.Abstractions/BuilderExtensions/ResponseModelBuilder.cs b/src/WireMock.Net.Abstractions/BuilderExtensions/ResponseModelBuilder.cs new file mode 100644 index 00000000..5f38dbbf --- /dev/null +++ b/src/WireMock.Net.Abstractions/BuilderExtensions/ResponseModelBuilder.cs @@ -0,0 +1,36 @@ +using System; +using System.Net; + +// ReSharper disable once CheckNamespace +namespace WireMock.Admin.Mappings; + +/// +/// ResponseModelBuilder +/// +public partial class ResponseModelBuilder +{ + /// + /// Set the StatusCode. + /// + public ResponseModelBuilder WithStatusCode(int value) => WithStatusCode(() => value); + + /// + /// Set the StatusCode. + /// + public ResponseModelBuilder WithStatusCode(HttpStatusCode value) => WithStatusCode(() => value); + + /// + /// Set the Delay. + /// + public ResponseModelBuilder WithDelay(TimeSpan value) => WithDelay((int) value.TotalMilliseconds); + + /// + /// Set the MinimumRandomDelay. + /// + public ResponseModelBuilder WithMinimumRandomDelay(TimeSpan value) => WithMinimumRandomDelay((int)value.TotalMilliseconds); + + /// + /// Set the MaximumRandomDelay. + /// + public ResponseModelBuilder WithMaximumRandomDelay(TimeSpan value) => WithMaximumRandomDelay((int)value.TotalMilliseconds); +} \ No newline at end of file diff --git a/src/WireMock.Net.RestClient/Builders/ApiMappingModelBuilder.cs b/src/WireMock.Net.RestClient/Builders/ApiMappingModelBuilder.cs new file mode 100644 index 00000000..8084819b --- /dev/null +++ b/src/WireMock.Net.RestClient/Builders/ApiMappingModelBuilder.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Stef.Validation; +using WireMock.Admin.Mappings; + +namespace WireMock.Client.Builders; + +/// +/// AdminApiMappingBuilder +/// +public class AdminApiMappingBuilder +{ + private readonly List> _mappingModelBuilderActions = new(); + + private readonly IWireMockAdminApi _api; + + /// + /// AdminApiMappingBuilder + /// + /// The . + public AdminApiMappingBuilder(IWireMockAdminApi api) + { + _api = Guard.NotNull(api); + } + + /// + /// The Given + /// + /// The action. + public void Given(Action mappingModelBuilderAction) + { + _mappingModelBuilderActions.Add(Guard.NotNull(mappingModelBuilderAction)); + } + + /// + /// Build the mappings and post these using the to the WireMock.Net server. + /// + /// The optional CancellationToken. + /// + public Task BuildAndPostAsync(CancellationToken cancellationToken = default) + { + var modelMappings = new List(); + + foreach (var mappingModelBuilderAction in _mappingModelBuilderActions) + { + cancellationToken.ThrowIfCancellationRequested(); + + var mappingModelBuilder = new MappingModelBuilder(); + mappingModelBuilderAction(mappingModelBuilder); + + modelMappings.Add(mappingModelBuilder.Build()); + } + + return _api.PostMappingsAsync(modelMappings, cancellationToken); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.RestClient/Extensions/ResponseModelBuilderExtensions.cs b/src/WireMock.Net.RestClient/Extensions/ResponseModelBuilderExtensions.cs new file mode 100644 index 00000000..b7553550 --- /dev/null +++ b/src/WireMock.Net.RestClient/Extensions/ResponseModelBuilderExtensions.cs @@ -0,0 +1,46 @@ +using System.Text; +using JsonConverter.Abstractions; +using JsonConverter.Newtonsoft.Json; +using WireMock.Admin.Mappings; + +namespace WireMock.Client.Extensions; + +/// +/// ResponseModelBuilder +/// +public static class ResponseModelBuilderExtensions +{ + private static readonly Encoding Utf8NoBom = new UTF8Encoding(false); + private static readonly IJsonConverter JsonConverter = new NewtonsoftJsonConverter(); + + /// + /// WithBodyAsJson + /// + /// The ResponseModelBuilder. + /// The body. + /// The body encoding. + /// Define whether child objects to be indented. + public static ResponseModelBuilder WithBodyAsJson(this ResponseModelBuilder builder, object body, Encoding? encoding = null, bool? indented = null) + { + return builder.WithBodyAsBytes(() => + { + var options = new JsonConverterOptions + { + WriteIndented = indented == true + }; + var jsonBody = JsonConverter.Serialize(body, options); + return (encoding ?? Utf8NoBom).GetBytes(jsonBody); + }); + } + + /// + /// WithBodyAsJson + /// + /// The ResponseModelBuilder. + /// The body. + /// Define whether child objects to be indented. + public static ResponseModelBuilder WithBodyAsJson(this ResponseModelBuilder builder, object body, bool indented) + { + return builder.WithBodyAsJson(body, null, indented); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.RestClient/Extensions/WireMockAdminApiExtensions.cs b/src/WireMock.Net.RestClient/Extensions/WireMockAdminApiExtensions.cs new file mode 100644 index 00000000..3165b4b7 --- /dev/null +++ b/src/WireMock.Net.RestClient/Extensions/WireMockAdminApiExtensions.cs @@ -0,0 +1,19 @@ +using WireMock.Client.Builders; + +namespace WireMock.Client.Extensions; + +/// +/// Some extensions for . +/// +public static class WireMockAdminApiExtensions +{ + /// + /// Get a new for the . + /// + /// See . + /// + public static AdminApiMappingBuilder GetMappingBuilder(this IWireMockAdminApi api) + { + return new AdminApiMappingBuilder(api); + } +} \ No newline at end of file diff --git a/src/WireMock.Net.RestClient/IWireMockAdminApi.cs b/src/WireMock.Net.RestClient/IWireMockAdminApi.cs index 39c9ac86..d304e9db 100644 --- a/src/WireMock.Net.RestClient/IWireMockAdminApi.cs +++ b/src/WireMock.Net.RestClient/IWireMockAdminApi.cs @@ -1,250 +1,283 @@ -using RestEase; using System; using System.Collections.Generic; using System.Net.Http.Headers; +using System.Threading; using System.Threading.Tasks; +using RestEase; using WireMock.Admin.Mappings; using WireMock.Admin.Requests; using WireMock.Admin.Scenarios; using WireMock.Admin.Settings; using WireMock.Types; -namespace WireMock.Client +namespace WireMock.Client; + +/// +/// The RestEase interface which defines all admin commands. +/// +[BasePath("__admin")] +public interface IWireMockAdminApi { /// - /// The RestEase interface which defines all admin commands. + /// Authentication header /// - [BasePath("__admin")] - public interface IWireMockAdminApi - { - /// - /// Authentication header - /// - [Header("Authorization")] - AuthenticationHeaderValue Authorization { get; set; } + [Header("Authorization")] + AuthenticationHeaderValue Authorization { get; set; } - /// - /// Get the settings. - /// - /// SettingsModel - [Get("settings")] - Task GetSettingsAsync(); + /// + /// Get the settings. + /// + /// SettingsModel + [Get("settings")] + Task GetSettingsAsync(); - /// - /// Update the settings. - /// - /// SettingsModel - [Put("settings")] - [Header("Content-Type", "application/json")] - Task PutSettingsAsync([Body] SettingsModel settings); + /// + /// Update the settings. + /// + /// SettingsModel + /// The optional cancellationToken. + [Put("settings")] + [Header("Content-Type", "application/json")] + Task PutSettingsAsync([Body] SettingsModel settings, CancellationToken cancellationToken = default); - /// - /// Update the settings - /// - /// SettingsModel - [Post("settings")] - [Header("Content-Type", "application/json")] - Task PostSettingsAsync([Body] SettingsModel settings); + /// + /// Update the settings + /// + /// SettingsModel + /// The optional cancellationToken. + [Post("settings")] + [Header("Content-Type", "application/json")] + Task PostSettingsAsync([Body] SettingsModel settings, CancellationToken cancellationToken = default); - /// - /// Get the mappings. - /// - /// MappingModels - [Get("mappings")] - Task> GetMappingsAsync(); + /// + /// Get the mappings. + /// + /// MappingModels + /// The optional cancellationToken. + [Get("mappings")] + Task> GetMappingsAsync(CancellationToken cancellationToken = default); - /// - /// Get the C# code from all mappings - /// - /// C# code - [Get("mappings/code")] - Task GetMappingsCodeAsync([Query] MappingConverterType mappingConverterType = MappingConverterType.Server); - - /// - /// Add a new mapping. - /// - /// MappingModel - [Post("mappings")] - [Header("Content-Type", "application/json")] - Task PostMappingAsync([Body] MappingModel mapping); + /// + /// Get the C# code from all mappings + /// + /// C# code + /// The , default is Server. + /// The optional cancellationToken. + [Get("mappings/code")] + Task GetMappingsCodeAsync([Query] MappingConverterType mappingConverterType = MappingConverterType.Server, CancellationToken cancellationToken = default); - /// - /// Add new mappings. - /// - /// MappingModels - [Post("mappings")] - [Header("Content-Type", "application/json")] - Task PostMappingsAsync([Body] IList mappings); + /// + /// Add a new mapping. + /// + /// MappingModel + /// The optional cancellationToken. + [Post("mappings")] + [Header("Content-Type", "application/json")] + Task PostMappingAsync([Body] MappingModel mapping, CancellationToken cancellationToken = default); - /// - /// Delete all mappings. - /// - [Delete("mappings")] - Task DeleteMappingsAsync(); + /// + /// Add new mappings. + /// + /// MappingModels + /// The optional cancellationToken. + [Post("mappings")] + [Header("Content-Type", "application/json")] + Task PostMappingsAsync([Body] IList mappings, CancellationToken cancellationToken = default); - /// - /// Delete mappings according to GUIDs - /// - /// MappingModels - [Delete("mappings")] - [Header("Content-Type", "application/json")] - Task DeleteMappingsAsync([Body] IList mappings); + /// + /// Delete all mappings. + /// + /// The optional cancellationToken. + [Delete("mappings")] + Task DeleteMappingsAsync(CancellationToken cancellationToken = default); - /// - /// Delete (reset) all mappings. - /// - /// A value indicating whether to reload the static mappings after the reset. - [Post("mappings/reset")] - Task ResetMappingsAsync(bool? reloadStaticMappings = false); + /// + /// Delete mappings according to GUIDs + /// + /// MappingModels + /// The optional cancellationToken. + [Delete("mappings")] + [Header("Content-Type", "application/json")] + Task DeleteMappingsAsync([Body] IList mappings, CancellationToken cancellationToken = default); - /// - /// Get a mapping based on the guid - /// - /// The Guid - /// MappingModel - [Get("mappings/{guid}")] - Task GetMappingAsync([Path] Guid guid); + /// + /// Delete (reset) all mappings. + /// + /// A value indicating whether to reload the static mappings after the reset. + /// The optional cancellationToken. + [Post("mappings/reset")] + Task ResetMappingsAsync(bool? reloadStaticMappings = false, CancellationToken cancellationToken = default); - /// - /// Get the C# code from a mapping based on the guid - /// - /// The Guid - /// The optional mappingConverterType (can be Server or Builder) - /// C# code - [Get("mappings/code/{guid}")] - Task GetMappingCodeAsync([Path] Guid guid, [Query] MappingConverterType mappingConverterType = MappingConverterType.Server); - - /// - /// Update a mapping based on the guid - /// - /// The Guid - /// MappingModel - [Put("mappings/{guid}")] - [Header("Content-Type", "application/json")] - Task PutMappingAsync([Path] Guid guid, [Body] MappingModel mapping); + /// + /// Get a mapping based on the guid + /// + /// The Guid + /// MappingModel + /// The optional cancellationToken. + [Get("mappings/{guid}")] + Task GetMappingAsync([Path] Guid guid, CancellationToken cancellationToken = default); - /// - /// Delete a mapping based on the guid - /// - /// The Guid - [Delete("mappings/{guid}")] - Task DeleteMappingAsync([Path] Guid guid); + /// + /// Get the C# code from a mapping based on the guid + /// + /// The Guid + /// The optional mappingConverterType (can be Server or Builder) + /// C# code + /// The optional cancellationToken. + [Get("mappings/code/{guid}")] + Task GetMappingCodeAsync([Path] Guid guid, [Query] MappingConverterType mappingConverterType = MappingConverterType.Server, CancellationToken cancellationToken = default); - /// - /// Save the mappings - /// - [Post("mappings/save")] - Task SaveMappingAsync(); + /// + /// Update a mapping based on the guid + /// + /// The Guid + /// MappingModel + /// The optional cancellationToken. + [Put("mappings/{guid}")] + [Header("Content-Type", "application/json")] + Task PutMappingAsync([Path] Guid guid, [Body] MappingModel mapping, CancellationToken cancellationToken = default); - /// - /// Get the requests. - /// - /// LogRequestModels - [Get("requests")] - Task> GetRequestsAsync(); + /// + /// Delete a mapping based on the guid + /// + /// The Guid + /// The optional cancellationToken. + [Delete("mappings/{guid}")] + Task DeleteMappingAsync([Path] Guid guid, CancellationToken cancellationToken = default); - /// - /// Delete all requests. - /// - [Delete("requests")] - Task DeleteRequestsAsync(); + /// + /// Save the mappings + /// + /// The optional cancellationToken. + [Post("mappings/save")] + Task SaveMappingAsync(CancellationToken cancellationToken = default); - /// - /// Delete (reset) all requests. - /// - [Post("requests/reset")] - Task ResetRequestsAsync(); + /// + /// Get the requests. + /// + /// LogRequestModels + /// The optional cancellationToken. + [Get("requests")] + Task> GetRequestsAsync(CancellationToken cancellationToken = default); - /// - /// Get a request based on the guid - /// - /// The Guid - /// MappingModel - [Get("requests/{guid}")] - Task GetRequestAsync([Path] Guid guid); + /// + /// Delete all requests. + /// + /// The optional cancellationToken. + [Delete("requests")] + Task DeleteRequestsAsync(CancellationToken cancellationToken = default); - /// - /// Delete a request based on the guid - /// - /// The Guid - [Delete("requests/{guid}")] - Task DeleteRequestAsync([Path] Guid guid); + /// + /// Delete (reset) all requests. + /// + /// The optional cancellationToken. + [Post("requests/reset")] + Task ResetRequestsAsync(CancellationToken cancellationToken = default); - /// - /// Find a request based on the criteria - /// - /// The RequestModel - [Post("requests/find")] - [Header("Content-Type", "application/json")] - Task> FindRequestsAsync([Body] RequestModel model); + /// + /// Get a request based on the guid + /// + /// The Guid + /// MappingModel + /// The optional cancellationToken. + [Get("requests/{guid}")] + Task GetRequestAsync([Path] Guid guid, CancellationToken cancellationToken = default); - /// - /// Get all scenarios - /// - [Get("scenarios")] - Task> GetScenariosAsync(); + /// + /// Delete a request based on the guid + /// + /// The Guid + /// The optional cancellationToken. + [Delete("requests/{guid}")] + Task DeleteRequestAsync([Path] Guid guid, CancellationToken cancellationToken = default); - /// - /// Delete (reset) all scenarios - /// - [Delete("scenarios")] - Task DeleteScenariosAsync(); + /// + /// Find a request based on the criteria + /// + /// The RequestModel + /// The optional cancellationToken. + [Post("requests/find")] + [Header("Content-Type", "application/json")] + Task> FindRequestsAsync([Body] RequestModel model, CancellationToken cancellationToken = default); - /// - /// Delete (reset) all scenarios - /// - [Post("scenarios")] - Task ResetScenariosAsync(); + /// + /// Get all scenarios + /// + /// The optional cancellationToken. + [Get("scenarios")] + Task> GetScenariosAsync(CancellationToken cancellationToken = default); - /// - /// Delete (reset) a specific scenario - /// - [Delete("scenarios/{name}")] - [AllowAnyStatusCode] - Task DeleteScenarioAsync([Path] string name); + /// + /// Delete (reset) all scenarios + /// + /// The optional cancellationToken. + [Delete("scenarios")] + Task DeleteScenariosAsync(CancellationToken cancellationToken = default); - /// - /// Delete (reset) all scenarios - /// - [Post("scenarios/{name}/reset")] - [AllowAnyStatusCode] - Task ResetScenarioAsync([Path] string name); + /// + /// Delete (reset) all scenarios + /// + /// The optional cancellationToken. + [Post("scenarios")] + Task ResetScenariosAsync(CancellationToken cancellationToken = default); - /// - /// Create a new File - /// - /// The filename - /// The body - [Post("files/{filename}")] - Task PostFileAsync([Path] string filename, [Body] string body); + /// + /// Delete (reset) a specific scenario + /// + /// Scenario name. + /// The optional cancellationToken. + [Delete("scenarios/{name}")] + [AllowAnyStatusCode] + Task DeleteScenarioAsync([Path] string name, CancellationToken cancellationToken = default); - /// - /// Update an existing File - /// - /// The filename - /// The body - [Put("files/{filename}")] - Task PutFileAsync([Path] string filename, [Body] string body); + /// + /// Delete (reset) all scenarios + /// + /// Scenario name. + /// The optional cancellationToken. + [Post("scenarios/{name}/reset")] + [AllowAnyStatusCode] + Task ResetScenarioAsync([Path] string name, CancellationToken cancellationToken = default); - /// - /// Get the content of an existing File - /// - /// The filename - [Get("files/{filename}")] - Task GetFileAsync([Path] string filename); + /// + /// Create a new File + /// + /// The filename + /// The body + /// The optional cancellationToken. + [Post("files/{filename}")] + Task PostFileAsync([Path] string filename, [Body] string body, CancellationToken cancellationToken = default); - /// - /// Delete an existing File - /// - /// The filename - [Delete("files/{filename}")] - Task DeleteFileAsync([Path] string filename); + /// + /// Update an existing File + /// + /// The filename + /// The body + /// The optional cancellationToken. + [Put("files/{filename}")] + Task PutFileAsync([Path] string filename, [Body] string body, CancellationToken cancellationToken = default); - /// - /// Check if a file exists - /// - /// The filename - [Head("files/{filename}")] - Task FileExistsAsync([Path] string filename); - } + /// + /// Get the content of an existing File + /// + /// The filename + /// The optional cancellationToken. + [Get("files/{filename}")] + Task GetFileAsync([Path] string filename, CancellationToken cancellationToken = default); + + /// + /// Delete an existing File + /// + /// The filename + /// The optional cancellationToken. + [Delete("files/{filename}")] + Task DeleteFileAsync([Path] string filename, CancellationToken cancellationToken = default); + + /// + /// Check if a file exists + /// + /// The filename + /// The optional cancellationToken. + [Head("files/{filename}")] + Task FileExistsAsync([Path] string filename, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/WireMock.Net.RestClient/WireMock.Net.RestClient.csproj b/src/WireMock.Net.RestClient/WireMock.Net.RestClient.csproj index bf7112a4..84295df1 100644 --- a/src/WireMock.Net.RestClient/WireMock.Net.RestClient.csproj +++ b/src/WireMock.Net.RestClient/WireMock.Net.RestClient.csproj @@ -30,8 +30,10 @@ + + diff --git a/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs b/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs index e138822e..a9946f25 100644 --- a/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs +++ b/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs @@ -51,7 +51,7 @@ public interface IBodyResponseBuilder : IFaultResponseBuilder /// /// The body. /// The body encoding. - /// Use JSON indented. + /// Define whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings. /// A . IResponseBuilder WithBodyAsJson(object body, Encoding? encoding = null, bool? indented = null);