diff --git a/RESTFulSense.Tests.Acceptance/Tests/RestfulApiClientTests.SendHttpRequest.cs b/RESTFulSense.Tests.Acceptance/Tests/RestfulApiClientTests.SendHttpRequest.cs new file mode 100644 index 00000000..94659954 --- /dev/null +++ b/RESTFulSense.Tests.Acceptance/Tests/RestfulApiClientTests.SendHttpRequest.cs @@ -0,0 +1,89 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.Threading.Tasks; +using FluentAssertions; +using Newtonsoft.Json; +using RESTFulSense.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.Tests.Acceptance.Tests +{ + public partial class RestfulApiClientTests + { + + [Fact] + private void ShouldSendContentWithNoResponseAndDeserializeContent() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity inputTEntity = randomTEntity; + TEntity expectedTEntity = inputTEntity; + string mediaType = "application/json"; + bool ignoreDefaultValues = false; + string randomHttpMethodName = GetRandomHttpMethodName(); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingMethod(randomHttpMethodName)) + .RespondWith(Response.Create() + .WithStatusCode(200)); + + // when + Action actualResponseResult = async () => + await this.restfulApiClient.SendHttpRequestAsync( + method: randomHttpMethodName, + relativeUrl: relativeUrl, + content: inputTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction); + + // then + actualResponseResult.Should().NotBeNull(); + } + + [Fact] + private async Task ShouldSendContentWithTContentReturnsTResultAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity inputTEntity = randomTEntity; + TEntity expectedTEntity = inputTEntity; + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + string randomHttpMethodName = GetRandomHttpMethodName(); + + string expectedBody = + JsonConvert.SerializeObject(randomTEntity); + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingMethod(randomHttpMethodName)) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.restfulApiClient.SendHttpRequestAsync( + method: randomHttpMethodName, + relativeUrl: relativeUrl, + content: inputTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.Tests.Acceptance/Tests/RestfulApiClientTests.cs b/RESTFulSense.Tests.Acceptance/Tests/RestfulApiClientTests.cs index f825e372..583d4efc 100644 --- a/RESTFulSense.Tests.Acceptance/Tests/RestfulApiClientTests.cs +++ b/RESTFulSense.Tests.Acceptance/Tests/RestfulApiClientTests.cs @@ -65,6 +65,9 @@ await Task.FromResult(JsonSerializer.Deserialize( private static TEntity GetRandomTEntity() => CreateTEntityFiller(GetTestDateTimeOffset()).Create(); + private static string GetRandomHttpMethodName() => + new MnemonicString().GetValue(); + private static DateTimeOffset GetTestDateTimeOffset() => new DateTimeOffset(DateTime.Now); diff --git a/RESTFulSense.Tests.Acceptance/Tests/RestfulSenseApiFactoryTests.SendHttpRequest.cs b/RESTFulSense.Tests.Acceptance/Tests/RestfulSenseApiFactoryTests.SendHttpRequest.cs new file mode 100644 index 00000000..64c13357 --- /dev/null +++ b/RESTFulSense.Tests.Acceptance/Tests/RestfulSenseApiFactoryTests.SendHttpRequest.cs @@ -0,0 +1,88 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.Threading.Tasks; +using FluentAssertions; +using Newtonsoft.Json; +using RESTFulSense.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.Tests.Acceptance.Tests +{ + public partial class RestfulSenseApiFactoryTests + { + [Fact] + private void ShouldSendContentWithNoResponseAndDeserializeContent() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity inputTEntity = randomTEntity; + TEntity expectedTEntity = inputTEntity; + string mediaType = "application/json"; + bool ignoreDefaultValues = false; + string randomHttpMethodName = GetRandomHttpMethodName(); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingMethod(randomHttpMethodName)) + .RespondWith(Response.Create() + .WithStatusCode(200)); + + // when + Action actualResponseResult = async () => + await this.factoryClient.SendHttpRequestAsync( + method: randomHttpMethodName, + relativeUrl: relativeUrl, + content: inputTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction); + + // then + actualResponseResult.Should().NotBeNull(); + } + + [Fact] + private async Task ShouldSendContentWithTContentReturnsTResultAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity inputTEntity = randomTEntity; + TEntity expectedTEntity = inputTEntity; + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + string randomHttpMethodName = GetRandomHttpMethodName(); + + string expectedBody = + JsonConvert.SerializeObject(randomTEntity); + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingMethod(randomHttpMethodName)) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.factoryClient.SendHttpRequestAsync( + method: randomHttpMethodName, + relativeUrl: relativeUrl, + content: inputTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: ContentDeserializationFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.Tests.Acceptance/Tests/RestfulSenseApiFactoryTests.cs b/RESTFulSense.Tests.Acceptance/Tests/RestfulSenseApiFactoryTests.cs index db2f14af..fbe37027 100644 --- a/RESTFulSense.Tests.Acceptance/Tests/RestfulSenseApiFactoryTests.cs +++ b/RESTFulSense.Tests.Acceptance/Tests/RestfulSenseApiFactoryTests.cs @@ -68,6 +68,9 @@ await Task.FromResult(JsonSerializer.Deserialize( private static TEntity GetRandomTEntity() => CreateTEntityFiller(GetTestDateTimeOffset()).Create(); + private static string GetRandomHttpMethodName() => + new MnemonicString().GetValue(); + private static DateTimeOffset GetTestDateTimeOffset() => new DateTimeOffset(DateTime.Now); diff --git a/RESTFulSense.WebAssembly/Clients/IRESTFulApiClient.cs b/RESTFulSense.WebAssembly/Clients/IRESTFulApiClient.cs index c2c187ce..1678cd35 100644 --- a/RESTFulSense.WebAssembly/Clients/IRESTFulApiClient.cs +++ b/RESTFulSense.WebAssembly/Clients/IRESTFulApiClient.cs @@ -144,5 +144,29 @@ ValueTask DeleteContentAsync( ValueTask ExecuteHttpCallAsync( Task function); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + CancellationToken cancellationToken, + Func> deserailizationFunction = null); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + T content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + TContent content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null); } } diff --git a/RESTFulSense.WebAssembly/Clients/IRESTFulApiFactoryClient.cs b/RESTFulSense.WebAssembly/Clients/IRESTFulApiFactoryClient.cs index 6ec3b357..498a34b6 100644 --- a/RESTFulSense.WebAssembly/Clients/IRESTFulApiFactoryClient.cs +++ b/RESTFulSense.WebAssembly/Clients/IRESTFulApiFactoryClient.cs @@ -135,5 +135,29 @@ ValueTask DeleteContentAsync( ValueTask ExecuteHttpCallAsync( Task function); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + CancellationToken cancellationToken, + Func> deserailizationFunction = null); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + T content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + TContent content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null); } } \ No newline at end of file diff --git a/RESTFulSense.WebAssembly/Clients/RESTFulApiClient.cs b/RESTFulSense.WebAssembly/Clients/RESTFulApiClient.cs index 1674a1b7..b355e84f 100644 --- a/RESTFulSense.WebAssembly/Clients/RESTFulApiClient.cs +++ b/RESTFulSense.WebAssembly/Clients/RESTFulApiClient.cs @@ -425,5 +425,90 @@ public async ValueTask ExecuteHttpCallAsync( return httpResponseMessage; } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + CancellationToken cancellationToken, + Func> deserializationFunction = null) + { + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await SendAsync( + request: new HttpRequestMessage(httpMethod, relativeUrl), + cancellationToken: cancellationToken); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, deserializationFunction); + } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + T content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null) + { + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); + + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await SendAsync( + request: new HttpRequestMessage + { + Method = httpMethod, + RequestUri = new Uri(relativeUrl), + Content = contentString + }); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); + } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + TContent content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null) + { + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); + + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await SendAsync( + request: new HttpRequestMessage(httpMethod, relativeUrl) + { + Content = contentString + }); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); + } } } \ No newline at end of file diff --git a/RESTFulSense.WebAssembly/Clients/RESTFulApiFactoryClient.cs b/RESTFulSense.WebAssembly/Clients/RESTFulApiFactoryClient.cs index 7303d0fd..1151117b 100644 --- a/RESTFulSense.WebAssembly/Clients/RESTFulApiFactoryClient.cs +++ b/RESTFulSense.WebAssembly/Clients/RESTFulApiFactoryClient.cs @@ -456,5 +456,90 @@ public async ValueTask ExecuteHttpCallAsync( return httpResponseMessage; } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + CancellationToken cancellationToken, + Func> deserializationFunction = null) + { + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await this.httpClient.SendAsync( + request: new HttpRequestMessage(httpMethod, relativeUrl), + cancellationToken: cancellationToken); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, deserializationFunction); + } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + T content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null) + { + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); + + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await this.httpClient.SendAsync( + request: new HttpRequestMessage + { + Method = httpMethod, + RequestUri = new Uri(relativeUrl), + Content = contentString + }); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); + } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + TContent content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null) + { + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); + + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await this.httpClient.SendAsync( + request: new HttpRequestMessage(httpMethod, relativeUrl) + { + Content = contentString + }); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); + } } } \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.SendHttpRequest.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.SendHttpRequest.cs new file mode 100644 index 00000000..68b9117e --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.SendHttpRequest.cs @@ -0,0 +1,88 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.Threading.Tasks; +using FluentAssertions; +using Newtonsoft.Json; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyApiClientTests + { + [Fact] + private void ShouldSendContentWithNoResponseAndDeserializeContent() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity inputTEntity = randomTEntity; + TEntity expectedTEntity = inputTEntity; + string mediaType = "application/json"; + bool ignoreDefaultValues = false; + string randomHttpMethodName = GetRandomHttpMethodName(); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingMethod(randomHttpMethodName)) + .RespondWith(Response.Create() + .WithStatusCode(200)); + + // when + Action actualResponseResult = async () => + await this.restfulWebAssemblyApiClient.SendHttpRequestAsync( + method: randomHttpMethodName, + relativeUrl: relativeUrl, + content: inputTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction); + + // then + actualResponseResult.Should().NotBeNull(); + } + + [Fact] + private async Task ShouldSendContentWithTContentReturnsTResultAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity inputTEntity = randomTEntity; + TEntity expectedTEntity = inputTEntity; + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + string randomHttpMethodName = GetRandomHttpMethodName(); + + string expectedBody = + JsonConvert.SerializeObject(randomTEntity); + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingMethod(randomHttpMethodName)) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.restfulWebAssemblyApiClient.SendHttpRequestAsync( + method: randomHttpMethodName, + relativeUrl: relativeUrl, + content: inputTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: DeserializationContentFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.cs index c69d86b3..8781da5b 100644 --- a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.cs +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyApiClientTests.cs @@ -65,6 +65,9 @@ await Task.FromResult(JsonSerializer.Deserialize( private static TEntity GetRandomTEntity() => CreateTEntityFiller(GetTestDateTimeOffset()).Create(); + private static string GetRandomHttpMethodName() => + new MnemonicString().GetValue(); + private static DateTimeOffset GetTestDateTimeOffset() => new DateTimeOffset(DateTime.Now); diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.SendHttpRequest.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.SendHttpRequest.cs new file mode 100644 index 00000000..08db0e86 --- /dev/null +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.SendHttpRequest.cs @@ -0,0 +1,88 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.Threading.Tasks; +using FluentAssertions; +using Newtonsoft.Json; +using RESTFulSense.WebAssenbly.Tests.Acceptance.Models; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using Xunit; + +namespace RESTFulSense.WebAssenbly.Tests.Acceptance.Tests +{ + public partial class RestfulSenseWebAssemblyFactoryApiClientTests + { + [Fact] + private void ShouldSendContentWithNoResponseAndDeserializeContent() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity inputTEntity = randomTEntity; + TEntity expectedTEntity = inputTEntity; + string mediaType = "application/json"; + bool ignoreDefaultValues = false; + string randomHttpMethodName = GetRandomHttpMethodName(); + + this.wiremockServer.Given(Request.Create() + .WithPath(relativeUrl) + .UsingMethod(randomHttpMethodName)) + .RespondWith(Response.Create() + .WithStatusCode(200)); + + // when + Action actualResponseResult = async () => + await this.webAssemblyApiFactoryClient.SendHttpRequestAsync( + method: randomHttpMethodName, + relativeUrl: relativeUrl, + content: inputTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction); + + // then + actualResponseResult.Should().NotBeNull(); + } + + [Fact] + private async Task ShouldSendContentWithTContentReturnsTResultAsync() + { + // given + TEntity randomTEntity = GetRandomTEntity(); + TEntity inputTEntity = randomTEntity; + TEntity expectedTEntity = inputTEntity; + string mediaType = "text/json"; + bool ignoreDefaultValues = false; + string randomHttpMethodName = GetRandomHttpMethodName(); + + string expectedBody = + JsonConvert.SerializeObject(randomTEntity); + + this.wiremockServer.Given( + Request.Create() + .WithPath(relativeUrl) + .UsingMethod(randomHttpMethodName)) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithHeader("Content-Type", mediaType) + .WithBody(expectedBody)); + + // when + TEntity actualTEntity = + await this.webAssemblyApiFactoryClient.SendHttpRequestAsync( + method: randomHttpMethodName, + relativeUrl: relativeUrl, + content: inputTEntity, + mediaType: mediaType, + ignoreDefaultValues: ignoreDefaultValues, + serializationFunction: SerializationContentFunction, + deserializationFunction: ContentDeserializationFunction); + + // then + actualTEntity.Should().BeEquivalentTo(expectedTEntity); + } + } +} \ No newline at end of file diff --git a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.cs b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.cs index 108f5b1f..c62d6f21 100644 --- a/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.cs +++ b/RESTFulSense.WebAssenbly.Tests.Acceptance/Tests/RestfulSenseWebAssemblyFactoryApiClientTests.cs @@ -68,6 +68,9 @@ await Task.FromResult(JsonSerializer.Deserialize( private static TEntity GetRandomTEntity() => CreateTEntityFiller(GetTestDateTimeOffset()).Create(); + private static string GetRandomHttpMethodName() => + new MnemonicString().GetValue(); + private static DateTimeOffset GetTestDateTimeOffset() => new DateTimeOffset(DateTime.Now); diff --git a/RESTFulSense/Clients/IRESTFulApiClient.cs b/RESTFulSense/Clients/IRESTFulApiClient.cs index 54325ebf..a8f250bb 100644 --- a/RESTFulSense/Clients/IRESTFulApiClient.cs +++ b/RESTFulSense/Clients/IRESTFulApiClient.cs @@ -16,8 +16,7 @@ public interface IRESTFulApiClient { ValueTask GetContentAsync( string relativeUrl, - Func> deserializationFunction = null); + Func> deserializationFunction = null); ValueTask GetContentAsync( string relativeUrl, @@ -145,5 +144,29 @@ ValueTask DeleteContentAsync( ValueTask ExecuteHttpCallAsync( Task function); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + CancellationToken cancellationToken, + Func> deserailizationFunction = null); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + T content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + TContent content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null); } } \ No newline at end of file diff --git a/RESTFulSense/Clients/IRESTFulApiFactoryClient.cs b/RESTFulSense/Clients/IRESTFulApiFactoryClient.cs index 4de60aa0..018417cd 100644 --- a/RESTFulSense/Clients/IRESTFulApiFactoryClient.cs +++ b/RESTFulSense/Clients/IRESTFulApiFactoryClient.cs @@ -143,5 +143,29 @@ ValueTask DeleteContentAsync( ValueTask ExecuteHttpCallAsync( Task function); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + CancellationToken cancellationToken, + Func> deserailizationFunction = null); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + T content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null); + + ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + TContent content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null); } } \ No newline at end of file diff --git a/RESTFulSense/Clients/RESTFulApiClient.cs b/RESTFulSense/Clients/RESTFulApiClient.cs index b06fafc6..a9a5db1e 100644 --- a/RESTFulSense/Clients/RESTFulApiClient.cs +++ b/RESTFulSense/Clients/RESTFulApiClient.cs @@ -453,5 +453,88 @@ public async ValueTask ExecuteHttpCallAsync( return httpResponseMessage; } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + CancellationToken cancellationToken, + Func> deserializationFunction = null) + { + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await SendAsync( + request: new HttpRequestMessage(httpMethod, relativeUrl), + cancellationToken: cancellationToken); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, deserializationFunction); + } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + T content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null) + { + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); + + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await SendAsync( + request: new HttpRequestMessage(httpMethod, relativeUrl) + { + Content = contentString + }); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); + } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + TContent content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null) + { + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); + + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await SendAsync( + request: new HttpRequestMessage(httpMethod, relativeUrl) + { + Content = contentString + }); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); + } } } \ No newline at end of file diff --git a/RESTFulSense/Clients/RESTFulApiFactoryClient.cs b/RESTFulSense/Clients/RESTFulApiFactoryClient.cs index 179bb113..14a315e7 100644 --- a/RESTFulSense/Clients/RESTFulApiFactoryClient.cs +++ b/RESTFulSense/Clients/RESTFulApiFactoryClient.cs @@ -492,5 +492,90 @@ public async ValueTask ExecuteHttpCallAsync( return httpResponseMessage; } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + CancellationToken cancellationToken, + Func> deserializationFunction = null) + { + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await this.httpClient.SendAsync( + request: new HttpRequestMessage(httpMethod, relativeUrl), + cancellationToken: cancellationToken); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, deserializationFunction); + } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + T content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null) + { + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); + + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await this.httpClient.SendAsync( + request: new HttpRequestMessage + { + Method = httpMethod, + RequestUri = new Uri(relativeUrl), + Content = contentString + }); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); + } + + public async ValueTask SendHttpRequestAsync( + string method, + string relativeUrl, + TContent content, + string mediaType = "text/json", + bool ignoreDefaultValues = false, + Func> serializationFunction = null, + Func> deserializationFunction = null) + { + HttpContent contentString = + await ConvertToHttpContent( + content, + mediaType, + ignoreDefaultValues, + serializationFunction); + + var httpMethod = new HttpMethod(method); + + HttpResponseMessage responseMessage = + await this.httpClient.SendAsync( + request: new HttpRequestMessage(httpMethod, relativeUrl) + { + Content = contentString + }); + + await ValidationService.ValidateHttpResponseAsync(responseMessage); + + return await DeserializeResponseContent( + responseMessage, + deserializationFunction); + } } } \ No newline at end of file diff --git a/RESTFulSense/Models/Attributes/HttpCustomAttribute.cs b/RESTFulSense/Models/Attributes/HttpCustomAttribute.cs new file mode 100644 index 00000000..d5038d99 --- /dev/null +++ b/RESTFulSense/Models/Attributes/HttpCustomAttribute.cs @@ -0,0 +1,14 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using Microsoft.AspNetCore.Mvc.Routing; + +namespace RESTFulSense.Models.Attributes +{ + public class HttpCustomAttribute : HttpMethodAttribute + { + public HttpCustomAttribute(string httpVerb) + : base(new[] { httpVerb }) { } + } +}