Skip to content

Commit 94d7f8c

Browse files
Updates responses to return 400 instead of 404 when a required version for a valid resource is not specified. Resolves #61 and fixes #62. (#63)
1 parent ad5b96b commit 94d7f8c

File tree

26 files changed

+294
-78
lines changed

26 files changed

+294
-78
lines changed

ApiVersioning.sln

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1919
ProjectSection(SolutionItems) = preProject
2020
.gitattributes = .gitattributes
2121
.gitignore = .gitignore
22+
appveyor.yml = appveyor.yml
23+
global.json = global.json
2224
LICENSE = LICENSE
2325
pack.ps1 = pack.ps1
2426
README.md = README.md

global.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"projects": [ "src", "test" ]
2+
"projects": [ "src", "test" ],
3+
"sdk": { "version": "1.0.0-preview2-003121" }
34
}

src/Microsoft.AspNet.OData.Versioning/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
"dependencies": {
1010
"Microsoft.AspNet.OData": "[5.9.1,6.0.0)",
11-
"Microsoft.AspNet.WebApi.Versioning": "2.0.2-*"
11+
"Microsoft.AspNet.WebApi.Versioning": "2.0.3-*"
1212
},
1313

1414
"frameworks": {

src/Microsoft.AspNet.WebApi.Versioning/Controllers/ActionSelectorCacheItem.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ private static HttpResponseMessage CreateBadRequestResponse( HttpControllerConte
226226

227227
var request = controllerContext.Request;
228228
var exceptionFactory = new HttpResponseExceptionFactory( request );
229-
return exceptionFactory.CreateBadRequestResponseForUnsupportedApiVersion( request.GetRequestedApiVersion() );
229+
return exceptionFactory.CreateBadRequestResponse( request.GetRequestedApiVersion() );
230230
}
231231

232232
[SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Caller is responsible for disposing of response instance." )]

src/Microsoft.AspNet.WebApi.Versioning/Dispatcher/ControllerSelectionResult.cs

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,16 @@
55

66
internal sealed class ControllerSelectionResult
77
{
8-
internal HttpControllerDescriptor Controller
9-
{
10-
get;
11-
set;
12-
}
8+
internal HttpControllerDescriptor Controller { get; set; }
139

14-
internal string ControllerName
15-
{
16-
get;
17-
set;
18-
}
10+
internal string ControllerName { get; set; }
1911

20-
internal bool Succeeded
21-
{
22-
get
23-
{
24-
return this.Controller != null;
25-
}
26-
}
12+
internal bool Succeeded => Controller != null;
2713

28-
internal bool CouldMatchVersion
29-
{
30-
get
31-
{
32-
return this.HasCandidates && this.RequestedVersion != null;
33-
}
34-
}
14+
internal bool CouldMatchVersion => HasCandidates;
3515

36-
internal bool HasCandidates
37-
{
38-
get;
39-
set;
40-
}
16+
internal bool HasCandidates { get; set; }
4117

42-
internal ApiVersion RequestedVersion
43-
{
44-
get;
45-
set;
46-
}
18+
internal ApiVersion RequestedVersion { get; set; }
4719
}
48-
}
20+
}

src/Microsoft.AspNet.WebApi.Versioning/Dispatcher/HttpResponseExceptionFactory.cs

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ internal sealed class HttpResponseExceptionFactory
1818
internal HttpResponseExceptionFactory( HttpRequestMessage request )
1919
{
2020
Contract.Requires( request != null );
21-
2221
this.request = request;
2322
}
2423

@@ -28,33 +27,17 @@ internal HttpResponseExceptionFactory( HttpRequestMessage request )
2827

2928
[SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Created exception cannot be disposed. Handled by the caller." )]
3029
internal HttpResponseException NewNotFoundOrBadRequestException( ControllerSelectionResult conventionRouteResult, ControllerSelectionResult directRouteResult ) =>
31-
CreateBadRequestForUnsupportedApiVersion( conventionRouteResult, directRouteResult ) ?? CreateBadRequestForInvalidApiVersion() ?? CreateNotFound( conventionRouteResult );
30+
CreateBadRequest( conventionRouteResult, directRouteResult ) ?? CreateNotFound( conventionRouteResult );
3231

3332
[SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Created exception cannot be disposed. Handled by the caller." )]
34-
internal HttpResponseMessage CreateBadRequestResponseForUnsupportedApiVersion( ApiVersion requestedVersion )
35-
{
36-
Contract.Requires( requestedVersion != null );
37-
Contract.Ensures( Contract.Result<HttpResponseMessage>() != null );
38-
39-
var message = SR.VersionedResourceNotSupported.FormatDefault( request.RequestUri, requestedVersion );
40-
var messageDetail = SR.VersionedControllerNameNotFound.FormatDefault( request.RequestUri, requestedVersion );
41-
42-
TraceWriter.Info( request, ControllerSelectorCategory, message );
43-
44-
return Options.CreateBadRequest( request, "UnsupportedApiVersion", message, messageDetail );
45-
}
33+
internal HttpResponseMessage CreateBadRequestResponse( ApiVersion requestedVersion ) =>
34+
requestedVersion == null ? CreateBadRequestForUnspecifiedApiVersionOrInvalidApiVersion() : CreateBadRequestForUnsupportedApiVersion( requestedVersion );
4635

4736
[SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Created exception cannot be disposed. Handled by the caller." )]
48-
internal HttpResponseException CreateBadRequestForUnsupportedApiVersion( ApiVersion requestedVersion )
49-
{
50-
Contract.Requires( requestedVersion != null );
51-
Contract.Ensures( Contract.Result<HttpResponseException>() != null );
52-
53-
return new HttpResponseException( CreateBadRequestResponseForUnsupportedApiVersion( requestedVersion ) );
54-
}
37+
internal HttpResponseException CreateBadRequest( ApiVersion requestedVersion ) => new HttpResponseException( CreateBadRequestResponse( requestedVersion ) );
5538

5639
[SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Created exception cannot be disposed. Handled by the caller." )]
57-
private HttpResponseException CreateBadRequestForUnsupportedApiVersion( ControllerSelectionResult conventionRouteResult, ControllerSelectionResult directRouteResult )
40+
private HttpResponseException CreateBadRequest( ControllerSelectionResult conventionRouteResult, ControllerSelectionResult directRouteResult )
5841
{
5942
Contract.Requires( conventionRouteResult != null );
6043

@@ -73,26 +56,47 @@ private HttpResponseException CreateBadRequestForUnsupportedApiVersion( Controll
7356
return null;
7457
}
7558

76-
return CreateBadRequestForUnsupportedApiVersion( requestedVersion );
59+
return CreateBadRequest( requestedVersion );
7760
}
7861

7962
[SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Created exception cannot be disposed. Handled by the caller." )]
80-
private HttpResponseException CreateBadRequestForInvalidApiVersion()
63+
private HttpResponseMessage CreateBadRequestForUnspecifiedApiVersionOrInvalidApiVersion()
8164
{
8265
var requestedVersion = request.GetRawRequestedApiVersion();
8366
var parsedVersion = default( ApiVersion );
67+
var message = default( string );
8468

85-
if ( string.IsNullOrEmpty( requestedVersion ) || TryParse( requestedVersion, out parsedVersion ) )
69+
if ( string.IsNullOrEmpty( requestedVersion ) )
70+
{
71+
message = SR.ApiVersionUnspecified;
72+
TraceWriter.Info( request, ControllerSelectorCategory, message );
73+
return Options.CreateBadRequest( request, "ApiVersionUnspecified", message, messageDetail: null );
74+
}
75+
else if ( TryParse( requestedVersion, out parsedVersion ) )
8676
{
8777
return null;
8878
}
8979

80+
message = SR.VersionedResourceNotSupported.FormatDefault( request.RequestUri, requestedVersion );
81+
var messageDetail = SR.VersionedControllerNameNotFound.FormatDefault( request.RequestUri, requestedVersion );
82+
83+
TraceWriter.Info( request, ControllerSelectorCategory, message );
84+
85+
return Options.CreateBadRequest( request, "InvalidApiVersion", message, messageDetail );
86+
}
87+
88+
[SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Created exception cannot be disposed. Handled by the caller." )]
89+
private HttpResponseMessage CreateBadRequestForUnsupportedApiVersion( ApiVersion requestedVersion )
90+
{
91+
Contract.Requires( requestedVersion != null );
92+
Contract.Ensures( Contract.Result<HttpResponseMessage>() != null );
93+
9094
var message = SR.VersionedResourceNotSupported.FormatDefault( request.RequestUri, requestedVersion );
9195
var messageDetail = SR.VersionedControllerNameNotFound.FormatDefault( request.RequestUri, requestedVersion );
9296

9397
TraceWriter.Info( request, ControllerSelectorCategory, message );
9498

95-
return new HttpResponseException( Options.CreateBadRequest( request, "InvalidApiVersion", message, messageDetail ) );
99+
return Options.CreateBadRequest( request, "UnsupportedApiVersion", message, messageDetail );
96100
}
97101

98102
[SuppressMessage( "Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Created exception cannot be disposed. Handled by the caller." )]

src/Microsoft.AspNet.WebApi.Versioning/SR.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Microsoft.AspNet.WebApi.Versioning/SR.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@
147147
<data name="ApiVersionNotSupported" xml:space="preserve">
148148
<value>The requested API version '{0}' is not supported.</value>
149149
</data>
150+
<data name="ApiVersionUnspecified" xml:space="preserve">
151+
<value>An API version is required, but was not specified.</value>
152+
</data>
150153
<data name="ControllerNameNotFound" xml:space="preserve">
151154
<value>No route providing a controller name was found to match request URI '{0}'.</value>
152155
</data>

src/Microsoft.AspNet.WebApi.Versioning/project.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "2.0.2-*",
2+
"version": "2.0.3-*",
33
"authors": [ "Microsoft" ],
44
"title": "Microsoft ASP.NET Web API Versioning",
55
"copyright": "Copyright \u00A9 2016. Microsoft Corporation. All rights reserved.",
@@ -26,7 +26,7 @@
2626
"summary": "Provides API versioning for RESTful services created using ASP.NET Web API",
2727
"tags": [ "Microsoft", "AspNet", "AspNetWebAPI", "Versioning" ],
2828
"owners": [ "Microsoft" ],
29-
"releaseNotes": "\u2022 Fixed mapping of API-versioned actions by convention (Issue #55)",
29+
"releaseNotes": " Fixed responses when a version is unspecified (Issue #62)",
3030
"iconUrl": "http://go.microsoft.com/fwlink/?LinkID=288890",
3131
"licenseUrl": "https://raw.githubusercontent.com/Microsoft/aspnet-api-versioning/master/LICENSE",
3232
"requireLicenseAcceptance": true,

src/Microsoft.AspNetCore.Mvc.Versioning/SR.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)