-
Notifications
You must be signed in to change notification settings - Fork 716
Expand file tree
/
Copy pathApiVersionUrlHelper.cs
More file actions
134 lines (111 loc) · 4.11 KB
/
ApiVersionUrlHelper.cs
File metadata and controls
134 lines (111 loc) · 4.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright (c) .NET Foundation and contributors. All rights reserved.
namespace Asp.Versioning.Routing;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
/// <summary>
/// Represents an API version aware <see cref="IUrlHelper">URL helper</see>.
/// </summary>
[CLSCompliant( false )]
public class ApiVersionUrlHelper : IUrlHelper
{
private readonly IApiVersioningFeature feature;
/// <summary>
/// Initializes a new instance of the <see cref="ApiVersionUrlHelper"/> class.
/// </summary>
/// <param name="actionContext">The current <see cref="ActionContext">action context</see>.</param>
/// <param name="url">The inner <see cref="IUrlHelper">URL helper</see>.</param>
public ApiVersionUrlHelper( ActionContext actionContext, IUrlHelper url )
{
ActionContext = actionContext ?? throw new ArgumentNullException( nameof( actionContext ) );
Url = url;
feature = actionContext.HttpContext.ApiVersioningFeature();
}
/// <summary>
/// Gets the inner URL helper.
/// </summary>
/// <value>The inner <see cref="IUrlHelper">URL helper</see>.</value>
protected IUrlHelper Url { get; }
/// <summary>
/// Gets the name of the API version route parameter.
/// </summary>
/// <value>The API version route parameter name.</value>
protected string? RouteParameter => feature.RouteParameter;
/// <summary>
/// Gets the API version value.
/// </summary>
/// <value>The raw API version value.</value>
protected string? ApiVersion => feature.RawRequestedApiVersion;
/// <inheritdoc />
public ActionContext ActionContext { get; }
/// <inheritdoc />
public virtual string? Action( UrlActionContext actionContext )
{
ArgumentNullException.ThrowIfNull( actionContext );
actionContext.Values = AddApiVersionRouteValueIfNecessary( actionContext.Values );
return Url.Action( actionContext );
}
/// <inheritdoc />
public virtual string? Content( string? contentPath ) => Url.Content( contentPath );
/// <inheritdoc />
public virtual string? Link( string? routeName, object? values ) =>
Url.Link( routeName, AddApiVersionRouteValueIfNecessary( values ) );
/// <inheritdoc />
#pragma warning disable IDE0079
#pragma warning disable CA1054 // URI-like parameters should not be strings
public virtual bool IsLocalUrl( string? url ) => Url.IsLocalUrl( url );
#pragma warning restore CA1054 // URI-like parameters should not be strings
#pragma warning restore IDE0079
/// <inheritdoc />
#pragma warning disable IDE0079
#pragma warning disable CA1055 // URI-like return values should not be strings
public virtual string? RouteUrl( UrlRouteContext routeContext )
#pragma warning restore CA1055 // URI-like return values should not be strings
#pragma warning restore IDE0079
{
ArgumentNullException.ThrowIfNull( routeContext );
routeContext.Values = AddApiVersionRouteValueIfNecessary( routeContext.Values );
return Url.RouteUrl( routeContext );
}
private object? AddApiVersionRouteValueIfNecessary( object? current )
{
var key = RouteParameter;
if ( string.IsNullOrEmpty( key ) )
{
return current;
}
var value = ApiVersion;
if ( string.IsNullOrEmpty( value ) )
{
return current;
}
RouteValueDictionary values;
if ( current is null )
{
values = new() { { key, value } };
return values;
}
if ( current is RouteValueDictionary dictionary )
{
values = dictionary;
}
else if ( current is IEnumerable<KeyValuePair<string, object?>> kvps )
{
values = [];
foreach ( var kvp in kvps )
{
values.Add( kvp.Key, kvp.Value );
}
}
else
{
return current;
}
if ( !values.ContainsKey( key ) )
{
values.Add( key, value );
}
return values;
}
}