Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ namespace Asp.Versioning;
/// <summary>
/// Represents API version parser from a type namespace.
/// </summary>
/// <remarks>
/// The namespace identifier can use 'v', 'V', or '_' as a prefix. The '_' prefix is useful when
/// a folder starts with a number because Visual Studio automatically prefixes it with an underscore.
/// For example, <c>Contoso.Api._2018_04_01.Controllers</c> is equivalent to <c>Contoso.Api.v2018_04_01.Controllers</c>.
/// </remarks>
public class NamespaceParser
{
private const string CompactDateFormat = "yyyyMMdd";
Expand Down Expand Up @@ -142,7 +147,8 @@ public IReadOnlyList<ApiVersion> Parse( Type type )
/// <summary>
/// Attempts to parse an API version from the specified namespace identifier.
/// </summary>
/// <param name="identifier">The namespace identifier to parse.</param>
/// <param name="identifier">The namespace identifier to parse. The identifier must start with
/// 'v', 'V', or '_' followed by the version components.</param>
/// <param name="apiVersion">The parsed <see cref="ApiVersion">API version</see> or <c>null</c>.</param>
/// <returns>True if parsing is successful; otherwise, false.</returns>
protected virtual bool TryParse( Text identifier, out ApiVersion? apiVersion )
Expand All @@ -157,16 +163,22 @@ protected virtual bool TryParse( Text identifier, out ApiVersion? apiVersion )
return false;
}

// 'v' | 'V' : [<year> : ['_'] : <month> : ['_'] : <day>] : ['_'] : [<major> ['_' : <minor>]] : ['_'] : [<status>]
// 'v' | 'V' | '_' : [<year> : ['_'] : <month> : ['_'] : <day>] : ['_'] : [<major> ['_' : <minor>]] : ['_'] : [<status>]
//
// - v1
// - v1_1
// - v2_0_Beta
// - v20180401
// - v2018_04_01_1_1_Beta
// - _1
// - _1_1
// - _20180401
// - _2018_04_01
// - _2018_04_01_Beta
// - _2018_04_01_1_0_Beta
var ch = identifier[0];

if ( ch != 'v' && ch != 'V' )
if ( ch != 'v' && ch != 'V' && ch != '_' )
{
apiVersion = default;
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@ public void parse_should_return_no_versions()
{ "Contoso.Api.v2018_04_01_1_0_Beta.Controllers", "2018-04-01.1.0-Beta" },
{ "MyRestaurant.Vegetarian.Food.v1_1.Controllers", "1.1" },
{ "VersioningSample.V5.Controllers", "5.0" },
{ "_1", "1" },
{ "_1_1", "1.1" },
{ "_0_9_Beta", "0.9-Beta" },
{ "_20180401", "2018-04-01" },
{ "_2018_04_01", "2018-04-01" },
{ "_20180401_Beta", "2018-04-01-Beta" },
{ "_2018_04_01_Beta", "2018-04-01-Beta" },
{ "_2018_04_01_1_0_Beta", "2018-04-01.1.0-Beta" },
{ "Contoso.Api._1.Controllers", "1" },
{ "Contoso.Api._2018_04_01.Controllers", "2018-04-01" },
{ "Contoso.Api._2018_04_01_Beta.Controllers", "2018-04-01-Beta" },
};

public static TheoryData<string, string[]> NamespaceWithMultipleVersions => new()
Expand Down