Skip to content

Commit f7bff84

Browse files
Chris Martinezcommonsensesoftware
Chris Martinez
authored andcommitted
Refactor to use API behaviors everywhere
1 parent 36b18b4 commit f7bff84

File tree

45 files changed

+105
-85
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+105
-85
lines changed

src/Microsoft.AspNetCore.Mvc.Versioning/Versioning/ApiVersioningApplicationModelProvider.cs

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
public class ApiVersioningApplicationModelProvider : IApplicationModelProvider
1818
{
1919
readonly IOptions<ApiVersioningOptions> options;
20+
readonly Lazy<Func<ControllerModel, bool>> isApiController = new Lazy<Func<ControllerModel, bool>>( NewIsApiControllerFunc );
2021

2122
/// <summary>
2223
/// Initializes a new instance of the <see cref="ApiVersioningApplicationModelProvider"/> class.
@@ -45,7 +46,12 @@ public virtual void OnProvidersExecuted( ApplicationModelProviderContext context
4546
var implicitVersionModel = new ApiVersionModel( Options.DefaultApiVersion );
4647
var conventionBuilder = Options.Conventions;
4748
var application = context.Result;
48-
var controllers = FilterControllers( application.Controllers );
49+
IEnumerable<ControllerModel> controllers = application.Controllers;
50+
51+
if ( Options.UseApiBehavior )
52+
{
53+
controllers = controllers.Where( isApiController.Value );
54+
}
4955

5056
foreach ( var controller in controllers )
5157
{
@@ -59,37 +65,6 @@ public virtual void OnProvidersExecuted( ApplicationModelProviderContext context
5965
/// <inheritdoc />
6066
public virtual void OnProvidersExecuting( ApplicationModelProviderContext context ) { }
6167

62-
IEnumerable<ControllerModel> FilterControllers( IEnumerable<ControllerModel> controllers )
63-
{
64-
Contract.Requires( controllers != null );
65-
Contract.Ensures( Contract.Result<IEnumerable<ControllerModel>>() != null );
66-
67-
if ( !Options.UseApiBehavior )
68-
{
69-
return controllers;
70-
}
71-
72-
var assembly = typeof( ControllerAttribute ).Assembly;
73-
var apiBehaviorSupported = assembly.ExportedTypes.Any( t => t.Name == "ApiControllerAttribute" );
74-
75-
return apiBehaviorSupported ? controllers.Where( IsApiController ) : controllers;
76-
}
77-
78-
static bool IsApiController( ControllerModel controller )
79-
{
80-
if ( controller.Attributes.Any( IsApiBehaviorMetadata ) )
81-
{
82-
return true;
83-
}
84-
85-
var controllerAssembly = controller.ControllerType.Assembly;
86-
var assemblyAttributes = controllerAssembly.GetCustomAttributes();
87-
88-
return assemblyAttributes.Any( IsApiBehaviorMetadata );
89-
}
90-
91-
static bool IsApiBehaviorMetadata( object attribute ) => attribute.GetType().GetInterfaces().Any( i => i.Name == "IApiBehaviorMetadata" );
92-
9368
static bool IsDecoratedWithAttributes( ControllerModel controller )
9469
{
9570
Contract.Requires( controller != null );
@@ -131,5 +106,12 @@ static void ApplyAttributeOrImplicitConventions( ControllerModel controller, Api
131106
ApplyImplicitConventions( controller, implicitVersionModel );
132107
}
133108
}
109+
110+
static Func<ControllerModel, bool> NewIsApiControllerFunc()
111+
{
112+
var type = Type.GetType( "Microsoft.AspNetCore.Mvc.ApplicationModels.ApiBehaviorApplicationModelProvider, Microsoft.AspNetCore.Mvc.Core", throwOnError: true );
113+
var method = type.GetRuntimeMethods().Single( m => m.Name == "IsApiController" );
114+
return (Func<ControllerModel, bool>) method.CreateDelegate( typeof( Func<ControllerModel, bool> ) );
115+
}
134116
}
135117
}

src/Microsoft.AspNetCore.Mvc.Versioning/Versioning/ApiVersioningOptions.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ public partial class ApiVersioningOptions
2121
/// <summary>
2222
/// Gets or sets a value indicating whether to use web API behaviors.
2323
/// </summary>
24-
/// <value>True to use web API behaviors; otherwise, false. The default value is <c>false</c>.</value>
25-
/// <remarks>Setting this property to <c>true</c> applies API versioning policies only to controllers that
26-
/// have the ApiControllerAttribute applied. A value of <c>true</c> is only effective when using ASP.NET Core
27-
/// 2.1 or above. The default value of <c>false</c> retains backward capability with the existing behaviors
28-
/// before the API behavior feature was introduced.</remarks>
29-
public bool UseApiBehavior { get; set; }
24+
/// <value>True to use web API behaviors; otherwise, false. The default value is <c>true</c>.</value>
25+
/// <remarks>When this property is set to <c>true</c>, API versioning policies only apply to controllers that
26+
/// have the ApiControllerAttribute applied. When this property is set to <c>false</c>, API versioning
27+
/// policies are considers for all controllers. This was default behavior prior to ASP.NET Core 2.2.</remarks>
28+
public bool UseApiBehavior { get; set; } = true;
3029
}
3130
}

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Basic/Controllers/HelloWorld2Controller.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
using Microsoft.AspNetCore.Mvc;
55
using System;
66

7+
[ApiController]
78
[ApiVersion( "2.0" )]
89
[Route( "api/v{version:apiVersion}/HelloWorld" )]
9-
public class HelloWorld2Controller : Controller
10+
public class HelloWorld2Controller : ControllerBase
1011
{
1112
[HttpGet]
1213
public IActionResult Get() => Ok( new { Controller = GetType().Name, Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Basic/Controllers/HelloWorldController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
using Microsoft.AspNetCore.Mvc;
55
using System;
66

7+
[ApiController]
78
[ApiVersion( "1.0" )]
89
[Route( "api/v{version:apiVersion}/[controller]" )]
9-
public class HelloWorldController : Controller
10+
public class HelloWorldController : ControllerBase
1011
{
1112
[HttpGet]
1213
public IActionResult Get() => Ok( new { Controller = GetType().Name, Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Basic/Controllers/OrdersController.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Microsoft.AspNetCore.Mvc;
44
using System;
55

6+
[ApiController]
67
[Route( "api/[controller]" )]
78
public class OrdersController : ControllerBase
89
{

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Basic/Controllers/OverlappingRouteTemplateController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
using Microsoft.AspNetCore.Mvc;
44
using System;
55

6+
[ApiController]
67
[ApiVersion( "1.0" )]
78
[Route( "api/v{version:apiVersion}/values" )]
8-
public class OverlappingRouteTemplateController : Controller
9+
public class OverlappingRouteTemplateController : ControllerBase
910
{
1011
[HttpGet( "{id:int}/{childId}" )]
1112
public IActionResult Get( int id, string childId ) => Ok( new { id, childId } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Basic/Controllers/PingController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
{
33
using System;
44

5+
[ApiController]
56
[ApiVersionNeutral]
67
[Route( "api/[controller]" )]
7-
public class PingController : Controller
8+
public class PingController : ControllerBase
89
{
910
[HttpGet]
1011
public IActionResult Get() => NoContent();

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Basic/Controllers/Values2Controller.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
using Microsoft.AspNetCore.Mvc;
44
using System;
55

6+
[ApiController]
67
[ApiVersion( "2.0" )]
78
[Route( "api/values" )]
8-
public class Values2Controller : Controller
9+
public class Values2Controller : ControllerBase
910
{
1011
[HttpGet]
1112
public IActionResult Get() => Ok( new { Controller = nameof( Values2Controller ), Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Basic/Controllers/ValuesController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
using Microsoft.AspNetCore.Mvc;
44
using System;
55

6+
[ApiController]
67
[ApiVersion( "1.0" )]
78
[Route( "api/[controller]" )]
8-
public class ValuesController : Controller
9+
public class ValuesController : ControllerBase
910
{
1011
[HttpGet]
1112
public IActionResult Get() => Ok( new { Controller = nameof( ValuesController ), Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Basic/Controllers/WithViewsUsingAttributes/HomeController.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
{
33
using System;
44

5-
[ApiVersionNeutral]
65
[Route( "" )]
76
[Route( "[controller]" )]
87
public class HomeController : Controller

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Basic/Controllers/WithViewsUsingConventions/HomeController.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
{
33
using System;
44

5-
[ApiVersionNeutral]
65
public class HomeController : Controller
76
{
87
public IActionResult Index() => View();

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/ByNamespace/Controllers/V1/AgreementsController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
{
33
using Models;
44

5-
public class AgreementsController : Controller
5+
[ApiController]
6+
public class AgreementsController : ControllerBase
67
{
78
[HttpGet]
89
public IActionResult Get( string accountId, ApiVersion apiVersion ) => Ok( new Agreement( GetType().FullName, accountId, apiVersion.ToString() ) );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/ByNamespace/Controllers/V2/AgreementsController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
{
33
using Models;
44

5-
public class AgreementsController : Controller
5+
[ApiController]
6+
public class AgreementsController : ControllerBase
67
{
78
[HttpGet]
89
public IActionResult Get( string accountId, ApiVersion apiVersion ) => Ok( new Agreement( GetType().FullName, accountId, apiVersion.ToString() ) );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/ByNamespace/Controllers/V3/AgreementsController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
{
33
using Models;
44

5-
public class AgreementsController : Controller
5+
[ApiController]
6+
public class AgreementsController : ControllerBase
67
{
78
[HttpGet]
89
public IActionResult Get( string accountId, ApiVersion apiVersion ) => Ok( new Agreement( GetType().FullName, accountId, apiVersion.ToString() ) );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Conventions/Controllers/HelloWorld2Controller.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
using Microsoft.AspNetCore.Mvc;
55
using System;
66

7+
[ApiController]
78
[Route( "api/v{version:apiVersion}/helloworld" )]
8-
public class HelloWorld2Controller : Controller
9+
public class HelloWorld2Controller : ControllerBase
910
{
1011
[HttpGet]
1112
public IActionResult Get() => Ok( new { Controller = nameof( HelloWorld2Controller ), Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Conventions/Controllers/HelloWorldController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
using Microsoft.AspNetCore.Mvc;
55
using System;
66

7+
[ApiController]
78
[Route( "api/v{version:apiVersion}/[controller]" )]
8-
public class HelloWorldController : Controller
9+
public class HelloWorldController : ControllerBase
910
{
1011
[HttpGet]
1112
public IActionResult Get() => Ok( new { Controller = nameof( HelloWorldController ), Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Conventions/Controllers/Values2Controller.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using System;
55

66
[Route( "api/values" )]
7-
public class Values2Controller : Controller
7+
public class Values2Controller : ControllerBase
88
{
99
[HttpGet]
1010
public IActionResult Get() => Ok( new { Controller = nameof( Values2Controller ), Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/Conventions/Controllers/ValuesController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using System;
55

66
[Route( "api/[controller]" )]
7-
public class ValuesController : Controller
7+
public class ValuesController : ControllerBase
88
{
99
[HttpGet]
1010
public IActionResult Get() => Ok( new { Controller = nameof( ValuesController ), Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/MediaTypeNegotiation/Controllers/HelloWorldController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
using System.Collections.Generic;
88

99
[Route( "api/[controller]" )]
10-
public class HelloWorldController : Controller
10+
public class HelloWorldController : ControllerBase
1111
{
1212
[HttpGet]
1313
public IActionResult Get() => Ok( new { Controller = nameof( HelloWorldController ), Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/MediaTypeNegotiation/Controllers/Values2Controller.cs

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

66
[ApiVersion( "2.0" )]
77
[Route( "api/values" )]
8-
public class Values2Controller : Controller
8+
public class Values2Controller : ControllerBase
99
{
1010
[HttpGet]
1111
public IActionResult Get() => Ok( new { Controller = nameof( Values2Controller ), Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Acceptance.Tests/Mvc/MediaTypeNegotiation/Controllers/ValuesController.cs

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

66
[ApiVersion( "1.0" )]
77
[Route( "api/[controller]" )]
8-
public class ValuesController : Controller
8+
public class ValuesController : ControllerBase
99
{
1010
[HttpGet]
1111
public IActionResult Get() => Ok( new { Controller = nameof( ValuesController ), Version = HttpContext.GetRequestedApiVersion().ToString() } );

test/Microsoft.AspNetCore.Mvc.Versioning.Tests/Simulators/AmbiguousController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
using System;
44
using System.Threading.Tasks;
55

6+
[ApiController]
67
[ApiVersion( "1.0" )]
7-
public sealed class AmbiguousController : Controller
8+
public sealed class AmbiguousController : ControllerBase
89
{
910
[HttpGet]
1011
public Task<string> Get() => Task.FromResult( "Test" );

test/Microsoft.AspNetCore.Mvc.Versioning.Tests/Simulators/AmbiguousNeutralController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
using System;
44
using System.Threading.Tasks;
55

6+
[ApiController]
67
[ApiVersionNeutral]
78
[ControllerName( "Ambiguous" )]
8-
public sealed class AmbiguousNeutralController : Controller
9+
public sealed class AmbiguousNeutralController : ControllerBase
910
{
1011
[HttpGet]
1112
public Task<string> Get() => Task.FromResult( "Test" );

test/Microsoft.AspNetCore.Mvc.Versioning.Tests/Simulators/AmbiguousToo2Controller.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
using System;
44
using System.Threading.Tasks;
55

6+
[ApiController]
67
[ApiVersion( "1.0" )]
78
[ControllerName( "AmbiguousToo" )]
8-
public sealed class AmbiguousToo2Controller : Controller
9+
public sealed class AmbiguousToo2Controller : ControllerBase
910
{
1011
[HttpGet]
1112
public Task<string> Get() => Task.FromResult( "Test" );

test/Microsoft.AspNetCore.Mvc.Versioning.Tests/Simulators/AmbiguousTooController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
using System;
44
using System.Threading.Tasks;
55

6+
[ApiController]
67
[ApiVersion( "1.0" )]
7-
public sealed class AmbiguousTooController : Controller
8+
public sealed class AmbiguousTooController : ControllerBase
89
{
910
[HttpGet]
1011
public Task<string> Get() => Task.FromResult( "Test" );

test/Microsoft.AspNetCore.Mvc.Versioning.Tests/Simulators/ApiVersionedRoute2Controller.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
using System;
44
using System.Threading.Tasks;
55

6+
[ApiController]
67
[ApiVersion( "5.0" )]
78
[ApiVersion( "4.0", Deprecated = true )]
89
[Route( "api/v{version:apiVersion}/attributed" )]
9-
public sealed class ApiVersionedRoute2Controller : Controller
10+
public sealed class ApiVersionedRoute2Controller : ControllerBase
1011
{
1112
[HttpGet]
1213
[MapToApiVersion( "4.0" )]

test/Microsoft.AspNetCore.Mvc.Versioning.Tests/Simulators/ApiVersionedRouteController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
using System;
44
using System.Threading.Tasks;
55

6+
[ApiController]
67
[ApiVersion( "1.0" )]
78
[ApiVersion( "2.0" )]
89
[ApiVersion( "3.0" )]
910
[Route( "api/v{version:apiVersion}/attributed" )]
10-
public sealed class ApiVersionedRouteController : Controller
11+
public sealed class ApiVersionedRouteController : ControllerBase
1112
{
1213
[HttpGet]
1314
public Task<string> Get() => Task.FromResult( "Test" );

test/Microsoft.AspNetCore.Mvc.Versioning.Tests/Simulators/AttributeRoutedAmbiguous2Controller.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
using System;
44
using System.Threading.Tasks;
55

6+
[ApiController]
67
[ApiVersion( "1.0" )]
78
[Route( "api/attributed/ambiguous" )]
8-
public sealed class AttributeRoutedAmbiguous2Controller : Controller
9+
public sealed class AttributeRoutedAmbiguous2Controller : ControllerBase
910
{
1011
[HttpGet]
1112
public Task<string> Get() => Task.FromResult( "Test" );

test/Microsoft.AspNetCore.Mvc.Versioning.Tests/Simulators/AttributeRoutedAmbiguous3Controller.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
using System;
44
using System.Threading.Tasks;
55

6+
[ApiController]
67
[ApiVersion( "1.0" )]
78
[Route( "api/attributed/ambiguous" )]
8-
public sealed class AttributeRoutedAmbiguous3Controller : Controller
9+
public sealed class AttributeRoutedAmbiguous3Controller : ControllerBase
910
{
1011
[HttpGet]
1112
public Task<string> Get() => Task.FromResult( "Test" );

test/Microsoft.AspNetCore.Mvc.Versioning.Tests/Simulators/AttributeRoutedAmbiguousController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
using System;
44
using System.Threading.Tasks;
55

6+
[ApiController]
67
[ApiVersion( "1.0" )]
78
[Route( "api/attributed-ambiguous" )]
8-
public sealed class AttributeRoutedAmbiguousController : Controller
9+
public sealed class AttributeRoutedAmbiguousController : ControllerBase
910
{
1011
[HttpGet]
1112
public Task<string> Get() => Task.FromResult( "Test" );

0 commit comments

Comments
 (0)