Skip to content

Commit

Permalink
Merge pull request #671 from leancodepl/feature/override-default-rout…
Browse files Browse the repository at this point in the history
…evalues-in-api-description

Allow overriding default RouteValues in CQRS API description
  • Loading branch information
Dragemil authored May 14, 2024
2 parents b72e167 + 0491e58 commit efe1735
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 6 deletions.
6 changes: 6 additions & 0 deletions docs/external_integrations/api_explorer/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ public override void ConfigureServices(IServiceCollection services)
}
```

The `AddCQRSApiExplorer` method has an optional parameter that accepts a configuration override.
For now, it only allows to set a custom mapping of the `RouteValues` parameter,
which is used by OpenAPI generation tools to pass some metadata, by which the endpoints
could be grouped on the OpenAPI UI, for example. Usage of this metadata varies between
different OpenAPI UI implementations, so please check the tools documentation before overriding it.

## JSON Casing

Every integration uses different configuration for the generated payload types. It is highly probable that the default configuration of JSON serializer for these integrations will use wrong property casing. Unfortunately, every tool is configured differently.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Frozen;
using Microsoft.AspNetCore.Routing;

namespace LeanCode.CQRS.AspNetCore.Registration;

public class CQRSApiDescriptionConfiguration
{
// Required by Swagger (Swashbuckle)
public static readonly FrozenDictionary<string, string?> DefaultRouteValues = new Dictionary<string, string?>
{
["controller"] = "CQRS"
}.ToFrozenDictionary();

public Func<RouteEndpoint, IDictionary<string, string?>> RouteValuesMapping { get; init; } =
_ => DefaultRouteValues;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ internal sealed class CQRSApiDescriptionProvider : IApiDescriptionProvider
private const string ApplicationJson = "application/json";

private readonly EndpointDataSource endpointDataSource;
private readonly CQRSApiDescriptionConfiguration configuration;

public int Order => -1200;

public CQRSApiDescriptionProvider(EndpointDataSource endpointDataSource)
public CQRSApiDescriptionProvider(
EndpointDataSource endpointDataSource,
CQRSApiDescriptionConfiguration configuration
)
{
this.endpointDataSource = endpointDataSource;
this.configuration = configuration;
}

public void OnProvidersExecuting(ApiDescriptionProviderContext context)
Expand All @@ -40,7 +45,7 @@ endpoint is RouteEndpoint routeEndpoint

public void OnProvidersExecuted(ApiDescriptionProviderContext context) { }

private static ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, CQRSObjectMetadata metadata)
private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, CQRSObjectMetadata metadata)
{
var apiDescription = new ApiDescription
{
Expand All @@ -50,7 +55,7 @@ private static ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint,
ActionDescriptor = new ActionDescriptor
{
DisplayName = routeEndpoint.DisplayName,
RouteValues = { ["controller"] = "CQRS", }, // Required by Swagger (Swashbuckle)
RouteValues = configuration.RouteValuesMapping(routeEndpoint),
},
};
apiDescription.SupportedRequestFormats.Add(new() { MediaType = ApplicationJson });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using LeanCode.CQRS.Security;
using LeanCode.CQRS.Validation;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

Expand Down Expand Up @@ -36,9 +37,14 @@ TypesCatalog handlersCatalog
return new CQRSServicesBuilder(serviceCollection, objectsSource);
}

public static IServiceCollection AddCQRSApiExplorer(this IServiceCollection serviceCollection)
public static IServiceCollection AddCQRSApiExplorer(
this IServiceCollection serviceCollection,
CQRSApiDescriptionConfiguration? configuration = null
)
{
serviceCollection.AddTransient<IApiDescriptionProvider, CQRSApiDescriptionProvider>();
serviceCollection.AddTransient<IApiDescriptionProvider, CQRSApiDescriptionProvider>(sp =>
new(sp.GetRequiredService<EndpointDataSource>(), configuration ?? new())
);
return serviceCollection;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ private static List<ApiDescription> ListApis(Type forObject)
{
var dataSource = CreateDataSource(forObject);
var context = new ApiDescriptionProviderContext([]);
new CQRSApiDescriptionProvider(dataSource).OnProvidersExecuting(context);
new CQRSApiDescriptionProvider(dataSource, new()).OnProvidersExecuting(context);
return context.Results.ToList();
}

Expand Down

0 comments on commit efe1735

Please sign in to comment.