Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 94042f0

Browse filesBrowse files
Add support for custom group name formatting
1 parent d3b2135 commit 94042f0
Copy full SHA for 94042f0

File tree

Expand file treeCollapse file tree

7 files changed

+578
-18
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+578
-18
lines changed

‎src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/ApiExplorerOptions.cs

Copy file name to clipboardExpand all lines: src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/ApiExplorerOptions.cs
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,13 @@ public IApiVersionParameterSource ApiVersionParameterSource
4646
/// </summary>
4747
/// <value>The name associated with the <see cref="ApiVersionRouteConstraint">API version route constraint</see>.</value>
4848
public string RouteConstraintName { get; set; } = string.Empty;
49+
50+
/// <summary>
51+
/// Gets or sets the function used to format the combination of a group name and API version.
52+
/// </summary>
53+
/// <value>The <see cref="FormatGroupNameCallback">callback</see> used to format the combination of
54+
/// a group name and API version. The default value is <c>null</c>.</value>
55+
/// <remarks>The specified callback will only be invoked if a group name has been configured. The API
56+
/// version will be provided formatted according to the <see cref="GroupNameFormat">group name format</see>.</remarks>
57+
public FormatGroupNameCallback? FormatGroupName { get; set; }
4958
}
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
3+
namespace Microsoft.AspNetCore.Builder;
4+
5+
using Asp.Versioning;
6+
using Asp.Versioning.ApiExplorer;
7+
using Microsoft.AspNetCore.Mvc.Infrastructure;
8+
using Microsoft.AspNetCore.Routing;
9+
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.Options;
11+
12+
internal sealed class ApiVersionDescriptionProviderFactory : IApiVersionDescriptionProviderFactory
13+
{
14+
private readonly IServiceProvider serviceProvider;
15+
private readonly Func<EndpointDataSource, IActionDescriptorCollectionProvider, ISunsetPolicyManager, IOptions<ApiExplorerOptions>, IApiVersionDescriptionProvider> activator;
16+
17+
public ApiVersionDescriptionProviderFactory(
18+
IServiceProvider serviceProvider,
19+
Func<EndpointDataSource, IActionDescriptorCollectionProvider, ISunsetPolicyManager, IOptions<ApiExplorerOptions>, IApiVersionDescriptionProvider> activator )
20+
{
21+
this.serviceProvider = serviceProvider;
22+
this.activator = activator;
23+
}
24+
25+
public IApiVersionDescriptionProvider Create( EndpointDataSource endpointDataSource )
26+
{
27+
var actionDescriptorCollectionProvider = serviceProvider.GetRequiredService<IActionDescriptorCollectionProvider>();
28+
var sunsetPolicyManager = serviceProvider.GetRequiredService<ISunsetPolicyManager>();
29+
var options = serviceProvider.GetRequiredService<IOptions<ApiExplorerOptions>>();
30+
return activator( endpointDataSource, actionDescriptorCollectionProvider, sunsetPolicyManager, options );
31+
}
32+
}

‎src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/DependencyInjection/IApiVersioningBuilderExtensions.cs

Copy file name to clipboardExpand all lines: src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/DependencyInjection/IApiVersioningBuilderExtensions.cs
+50-1Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ namespace Microsoft.Extensions.DependencyInjection;
44

55
using Asp.Versioning;
66
using Asp.Versioning.ApiExplorer;
7+
using Microsoft.AspNetCore.Builder;
78
using Microsoft.AspNetCore.Mvc.ApiExplorer;
9+
using Microsoft.AspNetCore.Mvc.Infrastructure;
810
using Microsoft.AspNetCore.Mvc.ModelBinding;
911
using Microsoft.AspNetCore.Routing;
1012
using Microsoft.Extensions.DependencyInjection.Extensions;
@@ -61,7 +63,8 @@ private static void AddApiExplorerServices( IServiceCollection services )
6163

6264
services.AddMvcCore().AddApiExplorer();
6365
services.TryAddSingleton<IOptionsFactory<ApiExplorerOptions>, ApiExplorerOptionsFactory<ApiExplorerOptions>>();
64-
services.TryAddSingleton<IApiVersionDescriptionProvider, DefaultApiVersionDescriptionProvider>();
66+
services.TryAddTransient( ResolveApiVersionDescriptionProviderFactory );
67+
services.TryAddSingleton( ResolveApiVersionDescriptionProvider );
6568

6669
// use internal constructor until ASP.NET Core fixes their bug
6770
// BUG: https://github.com/dotnet/aspnetcore/issues/41773
@@ -73,4 +76,50 @@ private static void AddApiExplorerServices( IServiceCollection services )
7376
sp.GetRequiredService<IInlineConstraintResolver>(),
7477
sp.GetRequiredService<IOptions<ApiExplorerOptions>>() ) ) );
7578
}
79+
80+
private static IApiVersionDescriptionProviderFactory ResolveApiVersionDescriptionProviderFactory( IServiceProvider serviceProvider )
81+
{
82+
var options = serviceProvider.GetRequiredService<IOptions<ApiExplorerOptions>>();
83+
var mightUseCustomGroups = options.Value.FormatGroupName is not null;
84+
85+
return new ApiVersionDescriptionProviderFactory( serviceProvider, mightUseCustomGroups ? NewGroupedProvider : NewDefaultProvider );
86+
87+
static IApiVersionDescriptionProvider NewDefaultProvider(
88+
EndpointDataSource endpointDataSource,
89+
IActionDescriptorCollectionProvider actionDescriptorCollectionProvider,
90+
ISunsetPolicyManager sunsetPolicyManager,
91+
IOptions<ApiExplorerOptions> apiExplorerOptions ) =>
92+
new DefaultApiVersionDescriptionProvider( endpointDataSource, actionDescriptorCollectionProvider, sunsetPolicyManager, apiExplorerOptions );
93+
94+
static IApiVersionDescriptionProvider NewGroupedProvider(
95+
EndpointDataSource endpointDataSource,
96+
IActionDescriptorCollectionProvider actionDescriptorCollectionProvider,
97+
ISunsetPolicyManager sunsetPolicyManager,
98+
IOptions<ApiExplorerOptions> apiExplorerOptions ) =>
99+
new GroupedApiVersionDescriptionProvider( endpointDataSource, actionDescriptorCollectionProvider, sunsetPolicyManager, apiExplorerOptions );
100+
}
101+
102+
private static IApiVersionDescriptionProvider ResolveApiVersionDescriptionProvider( IServiceProvider serviceProvider )
103+
{
104+
var endpointDataSource = serviceProvider.GetRequiredService<EndpointDataSource>();
105+
var actionDescriptorCollectionProvider = serviceProvider.GetRequiredService<IActionDescriptorCollectionProvider>();
106+
var sunsetPolicyManager = serviceProvider.GetRequiredService<ISunsetPolicyManager>();
107+
var options = serviceProvider.GetRequiredService<IOptions<ApiExplorerOptions>>();
108+
var mightUseCustomGroups = options.Value.FormatGroupName is not null;
109+
110+
if ( mightUseCustomGroups )
111+
{
112+
return new GroupedApiVersionDescriptionProvider(
113+
endpointDataSource,
114+
actionDescriptorCollectionProvider,
115+
sunsetPolicyManager,
116+
options );
117+
}
118+
119+
return new DefaultApiVersionDescriptionProvider(
120+
endpointDataSource,
121+
actionDescriptorCollectionProvider,
122+
sunsetPolicyManager,
123+
options );
124+
}
76125
}
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
3+
namespace Asp.Versioning.ApiExplorer;
4+
5+
/// <summary>
6+
/// Represents a callback function used to format a group name.
7+
/// </summary>
8+
/// <param name="groupName">The associated group name.</param>
9+
/// <param name="apiVersion">A formatted API version.</param>
10+
/// <returns>The format result.</returns>
11+
public delegate string FormatGroupNameCallback( string groupName, string apiVersion );

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.