diff --git a/src/Microsoft.AspNetCore.Mvc.Versioning/ReportApiVersionsAttribute.cs b/src/Microsoft.AspNetCore.Mvc.Versioning/ReportApiVersionsAttribute.cs index 9097b229..0da54801 100644 --- a/src/Microsoft.AspNetCore.Mvc.Versioning/ReportApiVersionsAttribute.cs +++ b/src/Microsoft.AspNetCore.Mvc.Versioning/ReportApiVersionsAttribute.cs @@ -30,12 +30,14 @@ public ReportApiVersionsAttribute( IReportApiVersions reportApiVersions ) } /// - /// Reports the discovered service API versions for the given context after an action has executed. + /// Reports the discovered service API versions for the given context before an action has executed. /// - /// The context for the executed action. + /// The context for the executing action. /// This method will write the "api-supported-versions" and "api-deprecated-versions" HTTP headers into the - /// response provided that there is a response and the executed action was not version-neutral. - public override void OnActionExecuted( ActionExecutedContext context ) + /// response provided the executing action is not version-neutral. This operation should be performed before the + /// action is executed instead of after as HTTP headers cannot be specified after the response body has started + /// streaming to the client. + public override void OnActionExecuting( ActionExecutingContext context ) { var response = context.HttpContext.Response; diff --git a/src/Microsoft.AspNetCore.Mvc.Versioning/Versioning/ActionDescriptorMatch.cs b/src/Microsoft.AspNetCore.Mvc.Versioning/Versioning/ActionDescriptorMatch.cs index 2a7d5eaf..ea22472a 100644 --- a/src/Microsoft.AspNetCore.Mvc.Versioning/Versioning/ActionDescriptorMatch.cs +++ b/src/Microsoft.AspNetCore.Mvc.Versioning/Versioning/ActionDescriptorMatch.cs @@ -64,11 +64,11 @@ public ActionDescriptorMatch( ActionDescriptor action, RouteData routeData ) /// True if the objects are equal; otherwise, false. public static bool operator ==( ActionDescriptorMatch match1, ActionDescriptorMatch match2 ) { - if ( ReferenceEquals( match1, null ) ) + if ( match1 is null ) { - return ReferenceEquals( match2, null ); + return match2 is null; } - else if ( ReferenceEquals( match2, null ) ) + else if ( match2 is null ) { return false; } @@ -84,11 +84,11 @@ public ActionDescriptorMatch( ActionDescriptor action, RouteData routeData ) /// True if the objects are not equal; otherwise, false. public static bool operator !=( ActionDescriptorMatch match1, ActionDescriptorMatch match2 ) { - if ( ReferenceEquals( match1, null ) ) + if ( match1 is null ) { - return !ReferenceEquals( match2, null ); + return !( match2 is null ); } - else if ( ReferenceEquals( match2, null ) ) + else if ( match2 is null ) { return true; } diff --git a/test/Microsoft.AspNetCore.Mvc.Versioning.Tests/ReportApiVersionsAttributeTest.cs b/test/Microsoft.AspNetCore.Mvc.Versioning.Tests/ReportApiVersionsAttributeTest.cs index ed27f6ee..ab754ab8 100644 --- a/test/Microsoft.AspNetCore.Mvc.Versioning.Tests/ReportApiVersionsAttributeTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Versioning.Tests/ReportApiVersionsAttributeTest.cs @@ -6,29 +6,33 @@ using FluentAssertions; using Http; using Moq; + using System.Collections.Generic; using System.Linq; using Versioning; using Xunit; public class ReportApiVersionsAttributeTest { - static ActionExecutedContext CreateContext( ApiVersionModel model ) + static ActionExecutingContext CreateContext( ApiVersionModel model ) { var headers = new HeaderDictionary(); var response = new Mock(); var httpContext = new Mock(); var action = new ActionDescriptor(); var actionContext = new ActionContext( httpContext.Object, new RouteData(), action ); + var filters = new IFilterMetadata[0]; + var actionArguments = new Dictionary(); + var controller = default( object ); response.SetupGet( r => r.Headers ).Returns( headers ); httpContext.SetupGet( c => c.Response ).Returns( response.Object ); action.SetProperty( model ); - return new ActionExecutedContext( actionContext, new IFilterMetadata[0], null ); + return new ActionExecutingContext( actionContext, filters, actionArguments, controller ); } [Fact] - public void on_action_executed_should_add_version_headers() + public void on_action_executing_should_add_version_headers() { // arrange var supported = new[] { new ApiVersion( 1, 0 ), new ApiVersion( 2, 0 ) }; @@ -38,7 +42,7 @@ public void on_action_executed_should_add_version_headers() var attribute = new ReportApiVersionsAttribute(); // act - attribute.OnActionExecuted( context ); + attribute.OnActionExecuting( context ); // assert context.HttpContext.Response.Headers["api-supported-versions"].Single().Should().Be( "1.0, 2.0" ); @@ -53,7 +57,7 @@ public void on_action_executing_should_not_add_headers_for_versionX2Dneutral_con var attribute = new ReportApiVersionsAttribute(); // act - attribute.OnActionExecuted( context ); + attribute.OnActionExecuting( context ); // assert