Skip to content
Merged

Dev #10

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>

<Version>0.6.0</Version>
<Version>0.6.1</Version>
</PropertyGroup>
</Project>
17 changes: 10 additions & 7 deletions ModEndpoints.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ static async Task CallRemoteServicesAsync(IServiceProvider hostProvider)
//send request over channel to remote ServiceResultEndpoint
var listResult = await channel.SendAsync<ListStoresRequest, ListStoresResponse>(
new ListStoresRequest(),
default,
endpointUriPrefix: "v1/storesWithServiceEndpoint/");
"v1/storesWithServiceEndpoint/",
default);

if (listResult.IsOk)
{
Expand All @@ -62,8 +62,8 @@ static async Task CallRemoteServicesAsync(IServiceProvider hostProvider)
//send request over channel to remote ServiceResultEndpoint
var getResult = await channel.SendAsync<GetStoreByIdRequest, GetStoreByIdResponse>(
new GetStoreByIdRequest(Id: id.Value),
default,
endpointUriPrefix: "v1/storesWithServiceEndpoint/");
"v1/storesWithServiceEndpoint/",
default);
if (getResult.IsOk)
{
Console.WriteLine(getResult.Value);
Expand Down
40 changes: 26 additions & 14 deletions src/ModEndpoints.RemoteServices/DefaultServiceChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@ public class DefaultServiceChannel(
{
private const string NoChannelRegistrationFound = "No channel registration found for request type {0}.";

public async Task<Result<TResponse>> SendAsync<TRequest, TResponse>(TRequest req, CancellationToken ct)
where TRequest : IServiceRequest<TResponse>
where TResponse : notnull
{
return await SendAsync<TRequest, TResponse>(req, null, ct);
}

public async Task<Result<TResponse>> SendAsync<TRequest, TResponse>(
TRequest req,
string? endpointUriPrefix,
CancellationToken ct,
string? endpointUriPrefix = null,
Func<IServiceProvider, HttpRequestMessage, CancellationToken, Task>? processHttpRequest = null,
Func<IServiceProvider, HttpResponseMessage, CancellationToken, Task>? processHttpResponse = null,
Func<IServiceProvider, HttpRequestMessage, CancellationToken, Task>? httpRequestInterceptor = null,
Func<IServiceProvider, HttpResponseMessage, CancellationToken, Task>? httpResponseInterceptor = null,
string? uriResolverName = null,
string? serializerName = null)
where TRequest : IServiceRequest<TResponse>
Expand Down Expand Up @@ -44,16 +51,16 @@ public async Task<Result<TResponse>> SendAsync<TRequest, TResponse>(
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<TResponse>(httpResponse, ct);
}
Expand All @@ -66,12 +73,17 @@ public async Task<Result<TResponse>> SendAsync<TRequest, TResponse>(
}
}

public async Task<Result> SendAsync<TRequest>(TRequest req, CancellationToken ct) where TRequest : IServiceRequest
{
return await SendAsync<TRequest>(req, null, ct);
}

public async Task<Result> SendAsync<TRequest>(
TRequest req,
string? endpointUriPrefix,
CancellationToken ct,
string? endpointUriPrefix = null,
Func<IServiceProvider, HttpRequestMessage, CancellationToken, Task>? processHttpRequest = null,
Func<IServiceProvider, HttpResponseMessage, CancellationToken, Task>? processHttpResponse = null,
Func<IServiceProvider, HttpRequestMessage, CancellationToken, Task>? httpRequestInterceptor = null,
Func<IServiceProvider, HttpResponseMessage, CancellationToken, Task>? httpResponseInterceptor = null,
string? uriResolverName = null,
string? serializerName = null)
where TRequest : IServiceRequest
Expand All @@ -98,16 +110,16 @@ public async Task<Result> SendAsync<TRequest>(
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);
}
Expand Down
46 changes: 36 additions & 10 deletions src/ModEndpoints.RemoteServices/IServiceChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,32 @@ public interface IServiceChannel
/// <typeparam name="TResponse">ServiceEndpoint response type.</typeparam>
/// <param name="req">Request to be sent.</param>
/// <param name="ct">The <see cref="CancellationToken"/> to cancel operation.</param>
/// <returns>Response of remote service endpoint or failure result.</returns>
Task<Result<TResponse>> SendAsync<TRequest, TResponse>(
TRequest req,
CancellationToken ct)
where TRequest : IServiceRequest<TResponse>
where TResponse : notnull;

/// <summary>
/// Sends request to remote service endpoint.
/// </summary>
/// <typeparam name="TRequest">Type of ServiceEndpoint request that will be sent.</typeparam>
/// <typeparam name="TResponse">ServiceEndpoint response type.</typeparam>
/// <param name="req">Request to be sent.</param>
/// <param name="endpointUriPrefix">Path to append as prefix to resolved enpoint uri. Usually used to add path segments to configured client's base address.</param>
/// <param name="processHttpRequest">Delegate to further configure created HTTP request message (headers, etc) before sending to ServiceEndpoint.</param>
/// <param name="processHttpResponse">Delegate to process received HTTP response message of ServiceEndpoint before deserialization.</param>
/// <param name="ct">The <see cref="CancellationToken"/> to cancel operation.</param>
/// <param name="httpRequestInterceptor">Delegate to further configure created HTTP request message (headers, etc) before sending to ServiceEndpoint.</param>
/// <param name="httpResponseInterceptor">Delegate to process received HTTP response message of ServiceEndpoint before deserialization.</param>
/// <param name="uriResolverName"><see cref="IServiceEndpointUriResolver"/> name to be used to resolve ServiceEnpoint Uri.</param>
/// <param name="serializerName"><see cref="IServiceChannelSerializer"/> name to be used to resolve ServiceEnpoint Uri.</param>
/// <returns>Response of remote service endpoint or failure result.</returns>
Task<Result<TResponse>> SendAsync<TRequest, TResponse>(
TRequest req,
string? endpointUriPrefix,
CancellationToken ct,
string? endpointUriPrefix = null,
Func<IServiceProvider, HttpRequestMessage, CancellationToken, Task>? processHttpRequest = null,
Func<IServiceProvider, HttpResponseMessage, CancellationToken, Task>? processHttpResponse = null,
Func<IServiceProvider, HttpRequestMessage, CancellationToken, Task>? httpRequestInterceptor = null,
Func<IServiceProvider, HttpResponseMessage, CancellationToken, Task>? httpResponseInterceptor = null,
string? uriResolverName = null,
string? serializerName = null)
where TRequest : IServiceRequest<TResponse>
Expand All @@ -38,18 +52,30 @@ Task<Result<TResponse>> SendAsync<TRequest, TResponse>(
/// <typeparam name="TRequest">Type of ServiceEndpoint request that will be sent.</typeparam>
/// <param name="req">Request to be sent.</param>
/// <param name="ct">The <see cref="CancellationToken"/> to cancel operation.</param>
/// <returns>Response of remote service endpoint or failure result.</returns>
Task<Result> SendAsync<TRequest>(
TRequest req,
CancellationToken ct)
where TRequest : IServiceRequest;

/// <summary>
/// Sends request to remote service endpoint.
/// </summary>
/// <typeparam name="TRequest">Type of ServiceEndpoint request that will be sent.</typeparam>
/// <param name="req">Request to be sent.</param>
/// <param name="endpointUriPrefix">Path to append as prefix to resolved enpoint uri. Usually used to add path segments to configured client's base address.</param>
/// <param name="processHttpRequest">Delegate to further configure created HTTP request message (headers, etc) before sending to ServiceEndpoint.</param>
/// <param name="processHttpResponse">Delegate to process received HTTP response message of ServiceEndpoint before deserialization.</param>
/// <param name="ct">The <see cref="CancellationToken"/> to cancel operation.</param>
/// <param name="httpRequestInterceptor">Delegate to further configure created HTTP request message (headers, etc) before sending to ServiceEndpoint.</param>
/// <param name="httpResponseInterceptor">Delegate to process received HTTP response message of ServiceEndpoint before deserialization.</param>
/// <param name="uriResolverName"><see cref="IServiceEndpointUriResolver"/> name to be used to resolve ServiceEnpoint Uri.</param>
/// <param name="serializerName"><see cref="IServiceChannelSerializer"/> name to be used to resolve ServiceEnpoint Uri.</param>
/// <returns>Response of remote service endpoint or failure result.</returns>
Task<Result> SendAsync<TRequest>(
TRequest req,
string? endpointUriPrefix,
CancellationToken ct,
string? endpointUriPrefix = null,
Func<IServiceProvider, HttpRequestMessage, CancellationToken, Task>? processHttpRequest = null,
Func<IServiceProvider, HttpResponseMessage, CancellationToken, Task>? processHttpResponse = null,
Func<IServiceProvider, HttpRequestMessage, CancellationToken, Task>? httpRequestInterceptor = null,
Func<IServiceProvider, HttpResponseMessage, CancellationToken, Task>? httpResponseInterceptor = null,
string? uriResolverName = null,
string? serializerName = null)
where TRequest : IServiceRequest;
Expand Down