diff --git a/Directory.Build.props b/Directory.Build.props index 17dd053..7c9542e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -18,6 +18,6 @@ MIT True - 0.6.0 + 0.6.1 \ No newline at end of file diff --git a/ModEndpoints.sln b/ModEndpoints.sln index 78e7e70..e084eec 100644 --- a/ModEndpoints.sln +++ b/ModEndpoints.sln @@ -26,8 +26,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowcaseWebApi", "samples\S EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BenchmarkWebApi", "samples\BenchmarkWebApi\BenchmarkWebApi.csproj", "{BEE453CA-1ECC-4205-B4E6-D911C10F3155}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "samples\Client\Client.csproj", "{78546E80-4971-4C23-B8CE-D64FCB34F1A1}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModEndpoints.Core", "src\ModEndpoints.Core\ModEndpoints.Core.csproj", "{3AE2AB1C-C9CE-4F1D-8D73-2BD13864F0D5}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModEndpoints", "src\ModEndpoints\ModEndpoints.csproj", "{0F89CC73-32D4-4347-B284-41804A8A54A9}" @@ -38,6 +36,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModEndpoints.RemoteServices EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowcaseWebApi.FeatureContracts", "samples\ShowcaseWebApi.FeatureContracts\ShowcaseWebApi.FeatureContracts.csproj", "{DE3AA974-14C3-402F-93F4-A4A5D3DC0131}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceEndpointClient", "samples\ServiceEndpointClient\ServiceEndpointClient.csproj", "{286D2D88-E9F9-EB56-64BA-76C95D7ED0D8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -52,10 +52,6 @@ Global {BEE453CA-1ECC-4205-B4E6-D911C10F3155}.Debug|Any CPU.Build.0 = Debug|Any CPU {BEE453CA-1ECC-4205-B4E6-D911C10F3155}.Release|Any CPU.ActiveCfg = Release|Any CPU {BEE453CA-1ECC-4205-B4E6-D911C10F3155}.Release|Any CPU.Build.0 = Release|Any CPU - {78546E80-4971-4C23-B8CE-D64FCB34F1A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78546E80-4971-4C23-B8CE-D64FCB34F1A1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78546E80-4971-4C23-B8CE-D64FCB34F1A1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78546E80-4971-4C23-B8CE-D64FCB34F1A1}.Release|Any CPU.Build.0 = Release|Any CPU {3AE2AB1C-C9CE-4F1D-8D73-2BD13864F0D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3AE2AB1C-C9CE-4F1D-8D73-2BD13864F0D5}.Debug|Any CPU.Build.0 = Debug|Any CPU {3AE2AB1C-C9CE-4F1D-8D73-2BD13864F0D5}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -76,6 +72,10 @@ Global {DE3AA974-14C3-402F-93F4-A4A5D3DC0131}.Debug|Any CPU.Build.0 = Debug|Any CPU {DE3AA974-14C3-402F-93F4-A4A5D3DC0131}.Release|Any CPU.ActiveCfg = Release|Any CPU {DE3AA974-14C3-402F-93F4-A4A5D3DC0131}.Release|Any CPU.Build.0 = Release|Any CPU + {286D2D88-E9F9-EB56-64BA-76C95D7ED0D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {286D2D88-E9F9-EB56-64BA-76C95D7ED0D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {286D2D88-E9F9-EB56-64BA-76C95D7ED0D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {286D2D88-E9F9-EB56-64BA-76C95D7ED0D8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -84,11 +84,14 @@ Global {A860F9D9-9138-424F-9E97-C7A13F922F08} = {F7C9837C-EAE9-4189-8F0C-2F196B81F701} {BEF40F6B-9F44-43BD-867B-C3638DC3DC6C} = {74B81852-D3A9-49BA-A62F-A653FBB36665} {BEE453CA-1ECC-4205-B4E6-D911C10F3155} = {74B81852-D3A9-49BA-A62F-A653FBB36665} - {78546E80-4971-4C23-B8CE-D64FCB34F1A1} = {74B81852-D3A9-49BA-A62F-A653FBB36665} {3AE2AB1C-C9CE-4F1D-8D73-2BD13864F0D5} = {04A4BF42-A7C5-4D83-A137-90D6C3E68A00} {0F89CC73-32D4-4347-B284-41804A8A54A9} = {04A4BF42-A7C5-4D83-A137-90D6C3E68A00} {80C3DA6D-EDBE-47A5-BC6B-93BC334BEF67} = {04A4BF42-A7C5-4D83-A137-90D6C3E68A00} {3CDE6A69-09BA-4714-8DCD-D934BA27EBEB} = {04A4BF42-A7C5-4D83-A137-90D6C3E68A00} {DE3AA974-14C3-402F-93F4-A4A5D3DC0131} = {74B81852-D3A9-49BA-A62F-A653FBB36665} + {286D2D88-E9F9-EB56-64BA-76C95D7ED0D8} = {74B81852-D3A9-49BA-A62F-A653FBB36665} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8AD0451A-6029-4173-B7C5-737D09139323} EndGlobalSection EndGlobal diff --git a/samples/Client/Program.cs b/samples/ServiceEndpointClient/Program.cs similarity index 94% rename from samples/Client/Program.cs rename to samples/ServiceEndpointClient/Program.cs index 3209c36..205cef1 100644 --- a/samples/Client/Program.cs +++ b/samples/ServiceEndpointClient/Program.cs @@ -50,8 +50,8 @@ static async Task CallRemoteServicesAsync(IServiceProvider hostProvider) //send request over channel to remote ServiceResultEndpoint var listResult = await channel.SendAsync( new ListStoresRequest(), - default, - endpointUriPrefix: "v1/storesWithServiceEndpoint/"); + "v1/storesWithServiceEndpoint/", + default); if (listResult.IsOk) { @@ -62,8 +62,8 @@ static async Task CallRemoteServicesAsync(IServiceProvider hostProvider) //send request over channel to remote ServiceResultEndpoint var getResult = await channel.SendAsync( new GetStoreByIdRequest(Id: id.Value), - default, - endpointUriPrefix: "v1/storesWithServiceEndpoint/"); + "v1/storesWithServiceEndpoint/", + default); if (getResult.IsOk) { Console.WriteLine(getResult.Value); diff --git a/samples/Client/Client.csproj b/samples/ServiceEndpointClient/ServiceEndpointClient.csproj similarity index 100% rename from samples/Client/Client.csproj rename to samples/ServiceEndpointClient/ServiceEndpointClient.csproj diff --git a/src/ModEndpoints.RemoteServices/DefaultServiceChannel.cs b/src/ModEndpoints.RemoteServices/DefaultServiceChannel.cs index 82fc44e..4b6ab29 100644 --- a/src/ModEndpoints.RemoteServices/DefaultServiceChannel.cs +++ b/src/ModEndpoints.RemoteServices/DefaultServiceChannel.cs @@ -11,12 +11,19 @@ public class DefaultServiceChannel( { private const string NoChannelRegistrationFound = "No channel registration found for request type {0}."; + public async Task> SendAsync(TRequest req, CancellationToken ct) + where TRequest : IServiceRequest + where TResponse : notnull + { + return await SendAsync(req, null, ct); + } + public async Task> SendAsync( TRequest req, + string? endpointUriPrefix, CancellationToken ct, - string? endpointUriPrefix = null, - Func? processHttpRequest = null, - Func? processHttpResponse = null, + Func? httpRequestInterceptor = null, + Func? httpResponseInterceptor = null, string? uriResolverName = null, string? serializerName = null) where TRequest : IServiceRequest @@ -44,16 +51,16 @@ public async Task> SendAsync( Combine(endpointUriPrefix, requestUriResult.Value))) { httpReq.Content = await serializer.CreateContentAsync(req, ct); - if (processHttpRequest is not null) + if (httpRequestInterceptor is not null) { - await processHttpRequest(scope.ServiceProvider, httpReq, ct); + await httpRequestInterceptor(scope.ServiceProvider, httpReq, ct); } var client = clientFactory.CreateClient(clientName); using (var httpResponse = await client.SendAsync(httpReq, ct)) { - if (processHttpResponse is not null) + if (httpResponseInterceptor is not null) { - await processHttpResponse(scope.ServiceProvider, httpResponse, ct); + await httpResponseInterceptor(scope.ServiceProvider, httpResponse, ct); } return await serializer.DeserializeResultAsync(httpResponse, ct); } @@ -66,12 +73,17 @@ public async Task> SendAsync( } } + public async Task SendAsync(TRequest req, CancellationToken ct) where TRequest : IServiceRequest + { + return await SendAsync(req, null, ct); + } + public async Task SendAsync( TRequest req, + string? endpointUriPrefix, CancellationToken ct, - string? endpointUriPrefix = null, - Func? processHttpRequest = null, - Func? processHttpResponse = null, + Func? httpRequestInterceptor = null, + Func? httpResponseInterceptor = null, string? uriResolverName = null, string? serializerName = null) where TRequest : IServiceRequest @@ -98,16 +110,16 @@ public async Task SendAsync( Combine(endpointUriPrefix, requestUriResult.Value))) { httpReq.Content = await serializer.CreateContentAsync(req, ct); - if (processHttpRequest is not null) + if (httpRequestInterceptor is not null) { - await processHttpRequest(scope.ServiceProvider, httpReq, ct); + await httpRequestInterceptor(scope.ServiceProvider, httpReq, ct); } var client = clientFactory.CreateClient(clientName); using (var httpResponse = await client.SendAsync(httpReq, ct)) { - if (processHttpResponse is not null) + if (httpResponseInterceptor is not null) { - await processHttpResponse(scope.ServiceProvider, httpResponse, ct); + await httpResponseInterceptor(scope.ServiceProvider, httpResponse, ct); } return await serializer.DeserializeResultAsync(httpResponse, ct); } diff --git a/src/ModEndpoints.RemoteServices/IServiceChannel.cs b/src/ModEndpoints.RemoteServices/IServiceChannel.cs index 4758628..883d7e1 100644 --- a/src/ModEndpoints.RemoteServices/IServiceChannel.cs +++ b/src/ModEndpoints.RemoteServices/IServiceChannel.cs @@ -15,18 +15,32 @@ public interface IServiceChannel /// ServiceEndpoint response type. /// Request to be sent. /// The to cancel operation. + /// Response of remote service endpoint or failure result. + Task> SendAsync( + TRequest req, + CancellationToken ct) + where TRequest : IServiceRequest + where TResponse : notnull; + + /// + /// Sends request to remote service endpoint. + /// + /// Type of ServiceEndpoint request that will be sent. + /// ServiceEndpoint response type. + /// Request to be sent. /// Path to append as prefix to resolved enpoint uri. Usually used to add path segments to configured client's base address. - /// Delegate to further configure created HTTP request message (headers, etc) before sending to ServiceEndpoint. - /// Delegate to process received HTTP response message of ServiceEndpoint before deserialization. + /// The to cancel operation. + /// Delegate to further configure created HTTP request message (headers, etc) before sending to ServiceEndpoint. + /// Delegate to process received HTTP response message of ServiceEndpoint before deserialization. /// name to be used to resolve ServiceEnpoint Uri. /// name to be used to resolve ServiceEnpoint Uri. /// Response of remote service endpoint or failure result. Task> SendAsync( TRequest req, + string? endpointUriPrefix, CancellationToken ct, - string? endpointUriPrefix = null, - Func? processHttpRequest = null, - Func? processHttpResponse = null, + Func? httpRequestInterceptor = null, + Func? httpResponseInterceptor = null, string? uriResolverName = null, string? serializerName = null) where TRequest : IServiceRequest @@ -38,18 +52,30 @@ Task> SendAsync( /// Type of ServiceEndpoint request that will be sent. /// Request to be sent. /// The to cancel operation. + /// Response of remote service endpoint or failure result. + Task SendAsync( + TRequest req, + CancellationToken ct) + where TRequest : IServiceRequest; + + /// + /// Sends request to remote service endpoint. + /// + /// Type of ServiceEndpoint request that will be sent. + /// Request to be sent. /// Path to append as prefix to resolved enpoint uri. Usually used to add path segments to configured client's base address. - /// Delegate to further configure created HTTP request message (headers, etc) before sending to ServiceEndpoint. - /// Delegate to process received HTTP response message of ServiceEndpoint before deserialization. + /// The to cancel operation. + /// Delegate to further configure created HTTP request message (headers, etc) before sending to ServiceEndpoint. + /// Delegate to process received HTTP response message of ServiceEndpoint before deserialization. /// name to be used to resolve ServiceEnpoint Uri. /// name to be used to resolve ServiceEnpoint Uri. /// Response of remote service endpoint or failure result. Task SendAsync( TRequest req, + string? endpointUriPrefix, CancellationToken ct, - string? endpointUriPrefix = null, - Func? processHttpRequest = null, - Func? processHttpResponse = null, + Func? httpRequestInterceptor = null, + Func? httpResponseInterceptor = null, string? uriResolverName = null, string? serializerName = null) where TRequest : IServiceRequest;