diff --git a/examples/WireMock.Net.ConsoleApplication/MainApp.cs b/examples/WireMock.Net.ConsoleApplication/MainApp.cs index 0627c020..0bf8fccd 100644 --- a/examples/WireMock.Net.ConsoleApplication/MainApp.cs +++ b/examples/WireMock.Net.ConsoleApplication/MainApp.cs @@ -160,18 +160,17 @@ namespace WireMock.Net.ConsoleApplication .RespondWith(Response.Create().WithStatusCode(200).WithBody("partial = 200")); // http://localhost:8080/any/any?start=1000&stop=1&stop=2 - //server - // .Given(Request.Create().WithPath("/*").UsingGet()) - // .WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05") - // .AtPriority(server.Mappings.Count() + 1) - // .RespondWith(Response.Create() - // .WithStatusCode(200) - // .WithHeader("Content-Type", "application/json") - // .WithHeader("Transformed-Postman-Token", "token is {{request.headers.Postman-Token}}") - // .WithBody(@"{""msg"": ""Hello world CATCH-ALL on /*, {{request.path}}, bykey={{request.query.start}}, bykey={{request.query.stop}}, byidx0={{request.query.stop.[0]}}, byidx1={{request.query.stop.[1]}}"" }") - // .WithTransformer() - // .WithDelay(TimeSpan.FromMilliseconds(100)) - // ); + server + .Given(Request.Create().WithPath("/trans").UsingGet()) + .WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05") + .RespondWith(Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", "application/json") + .WithHeader("Transformed-Postman-Token", "token is {{request.headers.Postman-Token}}") + .WithBody(@"{""msg"": ""Hello world CATCH-ALL on /*, {{request.path}}, bykey={{request.query.start}}, bykey={{request.query.stop}}, byidx0={{request.query.stop.[0]}}, byidx1={{request.query.stop.[1]}}"" }") + .WithTransformer() + .WithDelay(TimeSpan.FromMilliseconds(100)) + ); server .Given(Request.Create() diff --git a/src/WireMock.Net/Admin/Mappings/ResponseModel.cs b/src/WireMock.Net/Admin/Mappings/ResponseModel.cs index 5627ee82..5998d4e8 100644 --- a/src/WireMock.Net/Admin/Mappings/ResponseModel.cs +++ b/src/WireMock.Net/Admin/Mappings/ResponseModel.cs @@ -32,6 +32,11 @@ namespace WireMock.Admin.Mappings /// public object BodyAsJson { get; set; } + /// + /// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings. + /// + public bool? BodyAsJsonIndented { get; set; } + /// /// Gets or sets the body (as bytearray). /// diff --git a/src/WireMock.Net/Owin/OwinResponseMapper.cs b/src/WireMock.Net/Owin/OwinResponseMapper.cs index 471cfb58..4702dd2d 100644 --- a/src/WireMock.Net/Owin/OwinResponseMapper.cs +++ b/src/WireMock.Net/Owin/OwinResponseMapper.cs @@ -87,7 +87,8 @@ namespace WireMock.Owin if (responseMessage.BodyAsJson != null) { - string jsonBody = JsonConvert.SerializeObject(responseMessage.BodyAsJson, new JsonSerializerSettings { Formatting = Formatting.None, NullValueHandling = NullValueHandling.Ignore }); + Formatting formatting = responseMessage.BodyAsJsonIndented == true ? Formatting.Indented : Formatting.None; + string jsonBody = JsonConvert.SerializeObject(responseMessage.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore }); using (var writer = new StreamWriter(response.Body, responseMessage.BodyEncoding ?? _utf8NoBom)) { await writer.WriteAsync(jsonBody); diff --git a/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs b/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs index a3240938..b8613428 100644 --- a/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs +++ b/src/WireMock.Net/ResponseBuilders/IBodyResponseBuilder.cs @@ -43,8 +43,17 @@ namespace WireMock.ResponseBuilders /// /// The body. /// The body encoding. + /// Use JSON indented. /// A . - IResponseBuilder WithBodyAsJson([NotNull] object body, [CanBeNull] Encoding encoding = null); + IResponseBuilder WithBodyAsJson([NotNull] object body, [CanBeNull] Encoding encoding = null, bool? indented = null); + + /// + /// WithBody : Create a string response based on a object (which will be converted to a JSON string). + /// + /// The body. + /// Define whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings. + /// A . + IResponseBuilder WithBodyAsJson([NotNull] object body, bool indented); /// /// WithBody : Create a string response based on a Base64 string (which will be decoded to a normal string). diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs index 2fc52d9c..508894b8 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.cs @@ -258,18 +258,25 @@ namespace WireMock.ResponseBuilders return this; } - /// - public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null) + /// + public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null, bool? indented = null) { Check.NotNull(body, nameof(body)); ResponseMessage.BodyDestination = null; ResponseMessage.BodyAsJson = body; ResponseMessage.BodyEncoding = encoding; + ResponseMessage.BodyAsJsonIndented = indented; return this; } + /// + public IResponseBuilder WithBodyAsJson(object body, bool indented) + { + return WithBodyAsJson(body, null, indented); + } + /// public IResponseBuilder WithBodyFromBase64(string bodyAsbase64, Encoding encoding = null) { diff --git a/src/WireMock.Net/ResponseMessage.cs b/src/WireMock.Net/ResponseMessage.cs index cc1f5044..ccdce00d 100644 --- a/src/WireMock.Net/ResponseMessage.cs +++ b/src/WireMock.Net/ResponseMessage.cs @@ -42,6 +42,11 @@ namespace WireMock /// public object BodyAsJson { get; set; } + /// + /// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings. + /// + public bool? BodyAsJsonIndented { get; set; } + /// /// Gets or sets the body as bytes. /// diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs index 782dd8dd..8d0c1735 100644 --- a/src/WireMock.Net/Serialization/MappingConverter.cs +++ b/src/WireMock.Net/Serialization/MappingConverter.cs @@ -1,7 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using WireMock.Admin.Mappings; using WireMock.Matchers.Request; using WireMock.RequestBuilders; @@ -96,6 +94,7 @@ namespace WireMock.Serialization mappingModel.Response.Headers = null; mappingModel.Response.BodyDestination = null; mappingModel.Response.BodyAsJson = null; + mappingModel.Response.BodyAsJsonIndented = null; mappingModel.Response.Body = null; mappingModel.Response.BodyAsBytes = null; mappingModel.Response.BodyAsFile = null; @@ -110,6 +109,7 @@ namespace WireMock.Serialization mappingModel.Response.StatusCode = response.ResponseMessage.StatusCode; mappingModel.Response.Headers = Map(response.ResponseMessage.Headers); mappingModel.Response.BodyAsJson = response.ResponseMessage.BodyAsJson; + mappingModel.Response.BodyAsJsonIndented = response.ResponseMessage.BodyAsJsonIndented; mappingModel.Response.Body = response.ResponseMessage.Body; mappingModel.Response.BodyAsBytes = response.ResponseMessage.BodyAsBytes; mappingModel.Response.BodyAsFile = response.ResponseMessage.BodyAsFile; @@ -152,9 +152,9 @@ namespace WireMock.Serialization // return funcs?.Select(Map).Where(x => x != null).ToArray(); //} - private static string Map([CanBeNull] Func func) - { - return func?.ToString(); - } + //private static string Map([CanBeNull] Func func) + //{ + // return func?.ToString(); + //} } } \ No newline at end of file diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs index b34f09c6..c95bde84 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -266,17 +266,19 @@ namespace WireMock.Server private ResponseMessage SettingsUpdate(RequestMessage requestMessage) { - var settings = requestMessage.Body != null ? JsonConvert.DeserializeObject(requestMessage.Body) : ((JObject)requestMessage.BodyAsJson).ToObject(); - - if (settings.AllowPartialMapping != null) - _options.AllowPartialMapping = settings.AllowPartialMapping.Value; - + var settings = DeserializeObject(requestMessage); _options.MaxRequestLogCount = settings.MaxRequestLogCount; - _options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration; + if (settings.AllowPartialMapping != null) + { + _options.AllowPartialMapping = settings.AllowPartialMapping.Value; + } + if (settings.GlobalProcessingDelay != null) + { _options.RequestProcessingDelay = TimeSpan.FromMilliseconds(settings.GlobalProcessingDelay.Value); + } return new ResponseMessage { Body = "Settings updated" }; } @@ -303,7 +305,7 @@ namespace WireMock.Server { Guid guid = Guid.Parse(requestMessage.Path.TrimStart(AdminMappings.ToCharArray())); - MappingModel mappingModel = requestMessage.Body != null ? JsonConvert.DeserializeObject(requestMessage.Body) : ((JObject)requestMessage.BodyAsJson).ToObject(); + var mappingModel = DeserializeObject(requestMessage); DeserializeAndAddOrUpdateMapping(mappingModel, guid); return new ResponseMessage { Body = "Mapping added or updated" }; @@ -371,7 +373,7 @@ namespace WireMock.Server { try { - MappingModel mappingModel = requestMessage.Body != null ? JsonConvert.DeserializeObject(requestMessage.Body) : ((JObject)requestMessage.BodyAsJson).ToObject(); + var mappingModel = DeserializeObject(requestMessage); DeserializeAndAddOrUpdateMapping(mappingModel); } catch (ArgumentException a) @@ -552,7 +554,7 @@ namespace WireMock.Server #region Requests/find private ResponseMessage RequestsFind(RequestMessage requestMessage) { - var requestModel = requestMessage.Body != null ? JsonConvert.DeserializeObject(requestMessage.Body) : ((JObject)requestMessage.BodyAsJson).ToObject(); + var requestModel = DeserializeObject(requestMessage); var request = (Request)InitRequestBuilder(requestModel); @@ -598,8 +600,7 @@ namespace WireMock.Server if (requestModel.ClientIP != null) { - string clientIP = requestModel.ClientIP as string; - if (clientIP != null) + if (requestModel.ClientIP is string clientIP) { requestBuilder = requestBuilder.WithClientIP(clientIP); } @@ -615,8 +616,7 @@ namespace WireMock.Server if (requestModel.Path != null) { - string path = requestModel.Path as string; - if (path != null) + if (requestModel.Path is string path) { requestBuilder = requestBuilder.WithPath(path); } @@ -632,8 +632,7 @@ namespace WireMock.Server if (requestModel.Url != null) { - string url = requestModel.Url as string; - if (url != null) + if (requestModel.Url is string url) { requestBuilder = requestBuilder.WithUrl(url); } @@ -739,7 +738,7 @@ namespace WireMock.Server } else if (responseModel.BodyAsJson != null) { - responseBuilder = responseBuilder.WithBodyAsJson(responseModel.BodyAsJson, ToEncoding(responseModel.BodyEncoding)); + responseBuilder = responseBuilder.WithBodyAsJson(responseModel.BodyAsJson, ToEncoding(responseModel.BodyEncoding), responseModel.BodyAsJsonIndented == true); } else if (responseModel.BodyFromBase64 != null) { @@ -768,5 +767,12 @@ namespace WireMock.Server { return encodingModel != null ? Encoding.GetEncoding(encodingModel.CodePage) : null; } + + private T DeserializeObject(RequestMessage requestMessage) + { + return requestMessage.Body != null ? + JsonConvert.DeserializeObject(requestMessage.Body) : + ((JObject)requestMessage.BodyAsJson).ToObject(); + } } } \ No newline at end of file diff --git a/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs b/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs index 9dd58d8d..7e22ad35 100644 --- a/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs +++ b/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs @@ -21,7 +21,8 @@ namespace WireMock.Transformers var template = new { request = requestMessage }; // Body - string body = bodyIsJson ? JsonConvert.SerializeObject(original.BodyAsJson) : original.Body; + Formatting formatting = original.BodyAsJsonIndented == true ? Formatting.Indented : Formatting.None; + string body = bodyIsJson ? JsonConvert.SerializeObject(original.BodyAsJson, formatting) : original.Body; if (body != null) { var templateBody = Handlebars.Compile(body); diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.cs b/test/WireMock.Net.Tests/FluentMockServerTests.cs index 0c175999..533b852f 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs @@ -232,6 +232,40 @@ namespace WireMock.Net.Tests Check.That(response).IsEqualTo("Hello world!"); } + [Fact] + public async Task FluentMockServer_Should_respond_to_request_BodyAsJson() + { + // Assign + _server = FluentMockServer.Start(); + + _server + .Given(Request.Create().UsingAnyVerb()) + .RespondWith(Response.Create().WithBodyAsJson(new { message = "Hello" })); + + // Act + var response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0]); + + // Assert + Check.That(response).IsEqualTo("{\"message\":\"Hello\"}"); + } + + [Fact] + public async Task FluentMockServer_Should_respond_to_request_BodyAsJson_Indented() + { + // Assign + _server = FluentMockServer.Start(); + + _server + .Given(Request.Create().UsingAnyVerb()) + .RespondWith(Response.Create().WithBodyAsJson(new { message = "Hello" }, true)); + + // Act + var response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0]); + + // Assert + Check.That(response).IsEqualTo("{\r\n \"message\": \"Hello\"\r\n}"); + } + [Fact] public async Task FluentMockServer_Should_respond_to_request_bodyAsCallback() {