Resolves #703 API Versioning tests failing after .net core 2.2 upgrade

pull/1140/head
lonwern 7 years ago
parent 7366294ab1
commit bb8bcaafd5

@ -1,5 +1,7 @@
using System.Linq; using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Versioning; using Microsoft.AspNetCore.Mvc.Versioning;
using Volo.Abp.ApiVersioning; using Volo.Abp.ApiVersioning;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
@ -8,31 +10,31 @@ using Volo.Abp.AspNetCore.Mvc.Versioning;
namespace Microsoft.Extensions.DependencyInjection namespace Microsoft.Extensions.DependencyInjection
{ {
public static class AbpApiVersioningOptionsExtensions public static class AbpApiVersioningExtensions
{ {
public static void ConfigureAbp(this ApiVersioningOptions options, IServiceCollection services) public static IServiceCollection AddAbpApiVersioning(this IServiceCollection services, Action<ApiVersioningOptions> setupAction)
{ {
//TODO: Use new builder will be released with Api Versioning 2.1 instead of reflection!
services.AddTransient<IRequestedApiVersion, HttpContextRequestedApiVersion>(); services.AddTransient<IRequestedApiVersion, HttpContextRequestedApiVersion>();
services.AddTransient<IApiControllerSpecification, AbpConventionalApiControllerSpecification>();
services.Configure<AbpAspNetCoreMvcOptions>(op => services.AddApiVersioning(setupAction);
{
//TODO: Configuring api version should be done directly inside ConfigureAbp, return services;
//TODO: not in a callback that will be called by MVC later! For that, we immediately need to controllerAssemblySettings }
foreach (var setting in op.ConventionalControllers.ConventionalControllerSettings) public static void ConfigureAbp(this ApiVersioningOptions options, AbpAspNetCoreMvcOptions mvcOptions)
{
foreach (var setting in mvcOptions.ConventionalControllers.ConventionalControllerSettings)
{
if (setting.ApiVersionConfigurer == null)
{ {
if (setting.ApiVersionConfigurer == null) ConfigureApiVersionsByConvention(options, setting);
{
ConfigureApiVersionsByConvention(options, setting);
}
else
{
setting.ApiVersionConfigurer.Invoke(options);
}
} }
}); else
{
setting.ApiVersionConfigurer.Invoke(options);
}
}
} }
private static void ConfigureApiVersionsByConvention(ApiVersioningOptions options, ConventionalControllerSetting setting) private static void ConfigureApiVersionsByConvention(ApiVersioningOptions options, ConventionalControllerSetting setting)

@ -85,7 +85,7 @@ namespace Volo.Abp.AspNetCore.Mvc
method, method,
apiDescription.RelativePath, apiDescription.RelativePath,
apiDescription.HttpMethod, apiDescription.HttpMethod,
setting?.ApiVersions.Select(v => v.ToString()).ToList() ?? new List<string>() //TODO: Also get from ApiVersion attributes if available..? GetSupportedVersions(controllerType, method, setting)
)); ));
AddParameterDescriptionsToModel(actionModel, method, apiDescription); AddParameterDescriptionsToModel(actionModel, method, apiDescription);
@ -126,6 +126,29 @@ namespace Volo.Abp.AspNetCore.Mvc
return methodNameBuilder.ToString(); return methodNameBuilder.ToString();
} }
private static List<string> GetSupportedVersions(Type controllerType, MethodInfo method, ConventionalControllerSetting setting)
{
var supportedVersions = new List<ApiVersion>();
var mapToAttributes = method.GetCustomAttributes<MapToApiVersionAttribute>().ToArray();
if (mapToAttributes.Any())
{
supportedVersions.AddRange(
mapToAttributes.SelectMany(a => a.Versions)
);
}
else
{
supportedVersions.AddRange(
controllerType.GetCustomAttributes<ApiVersionAttribute>().SelectMany(a => a.Versions)
);
setting?.ApiVersions.ForEach(supportedVersions.Add);
}
return supportedVersions.Select(v => v.ToString()).Distinct().ToList();
}
private void AddParameterDescriptionsToModel(ActionApiDescriptionModel actionModel, MethodInfo method, ApiDescription apiDescription) private void AddParameterDescriptionsToModel(ActionApiDescriptionModel actionModel, MethodInfo method, ApiDescription apiDescription)
{ {
if (!apiDescription.ParameterDescriptions.Any()) if (!apiDescription.ParameterDescriptions.Any())

@ -0,0 +1,25 @@
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.Options;
namespace Volo.Abp.AspNetCore.Mvc.Conventions
{
public class AbpConventionalApiControllerSpecification : IApiControllerSpecification
{
private readonly AbpAspNetCoreMvcOptions _options;
public AbpConventionalApiControllerSpecification(IOptions<AbpAspNetCoreMvcOptions> options)
{
_options = options.Value;
}
public bool IsSatisfiedBy(ControllerModel controller)
{
var configuration = _options
.ConventionalControllers
.ConventionalControllerSettings
.GetSettingOrNull(controller.ControllerType.AsType());
return configuration != null;
}
}
}

@ -16,26 +16,34 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning
)] )]
public class AbpAspNetCoreMvcVersioningTestModule : AbpModule public class AbpAspNetCoreMvcVersioningTestModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void PreConfigureServices(ServiceConfigurationContext context)
{ {
Configure<AbpAspNetCoreMvcOptions>(options => PreConfigure<AbpAspNetCoreMvcOptions>(options =>
{ {
//2.0 Version //2.0 Version
options.ConventionalControllers.Create(typeof(AbpAspNetCoreMvcVersioningTestModule).Assembly, opts => options.ConventionalControllers.Create(typeof(AbpAspNetCoreMvcVersioningTestModule).Assembly, opts =>
{ {
opts.TypePredicate = t => t.Namespace == typeof(Volo.Abp.AspNetCore.Mvc.Versioning.App.TodoAppService).Namespace; opts.TypePredicate = t => t.Namespace == typeof(Volo.Abp.AspNetCore.Mvc.Versioning.App.v2.TodoAppService).Namespace;
opts.ApiVersions.Add(new ApiVersion(2, 0)); opts.ApiVersions.Add(new ApiVersion(2, 0));
}); });
//1.0 Compatibility version //1.0 Compatibility version
options.ConventionalControllers.Create(typeof(AbpAspNetCoreMvcVersioningTestModule).Assembly, opts => options.ConventionalControllers.Create(typeof(AbpAspNetCoreMvcVersioningTestModule).Assembly, opts =>
{ {
opts.TypePredicate = t => t.Namespace == typeof(Volo.Abp.AspNetCore.Mvc.Versioning.App.Compat.TodoAppService).Namespace; opts.TypePredicate = t => t.Namespace == typeof(Volo.Abp.AspNetCore.Mvc.Versioning.App.v1.TodoAppService).Namespace;
opts.ApiVersions.Add(new ApiVersion(1, 0)); opts.ApiVersions.Add(new ApiVersion(1, 0));
}); });
}); });
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
context.Services.ExecutePreConfiguredActions(options);
});
context.Services.AddApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
@ -43,7 +51,8 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning
//options.ApiVersionReader = new HeaderApiVersionReader("api-version"); //Supports header too //options.ApiVersionReader = new HeaderApiVersionReader("api-version"); //Supports header too
//options.ApiVersionReader = new MediaTypeApiVersionReader(); //Supports accept header too //options.ApiVersionReader = new MediaTypeApiVersionReader(); //Supports accept header too
options.ConfigureAbp(context.Services); var mvcOptions = context.Services.ExecutePreConfiguredActions<AbpAspNetCoreMvcOptions>();
options.ConfigureAbp(mvcOptions);
}); });
context.Services.AddHttpClientProxies(typeof(AbpAspNetCoreMvcVersioningTestModule).Assembly); context.Services.AddHttpClientProxies(typeof(AbpAspNetCoreMvcVersioningTestModule).Assembly);

@ -5,13 +5,33 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning.App
{ {
[ApiVersion("1.0")] [ApiVersion("1.0")]
[ApiVersion("2.0")] [ApiVersion("2.0")]
[ApiController]
[Route("api/v{apiVersion:apiVersion}/[controller]")] [Route("api/v{apiVersion:apiVersion}/[controller]")]
public class HelloController : AbpController, IHelloController public class HelloController : AbpController, IHelloController
{ {
[HttpGet]
public Task<string> GetAsync()
{
return Task.FromResult($"Get-{HttpContext.GetRequestedApiVersion().ToString()}");
}
[HttpPost]
[MapToApiVersion("1.0")]
public Task<string> PostAsyncV1()
{
return PostAsync();
}
[HttpPost] [HttpPost]
public Task<string> PostAsync() [MapToApiVersion("2.0")]
public Task<string> PostAsyncV2()
{
return PostAsync();
}
private Task<string> PostAsync()
{ {
return Task.FromResult($"42-{HttpContext.GetRequestedApiVersion().ToString()}"); return Task.FromResult($"Post-{HttpContext.GetRequestedApiVersion().ToString()}");
} }
} }
} }

@ -4,6 +4,10 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning.App
{ {
public interface IHelloController : IRemoteService public interface IHelloController : IRemoteService
{ {
Task<string> PostAsync(); Task<string> GetAsync();
Task<string> PostAsyncV1();
Task<string> PostAsyncV2();
} }
} }

@ -1,6 +1,6 @@
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
namespace Volo.Abp.AspNetCore.Mvc.Versioning.App namespace Volo.Abp.AspNetCore.Mvc.Versioning.App.v1
{ {
public interface ITodoAppService : IApplicationService public interface ITodoAppService : IApplicationService
{ {

@ -1,7 +1,7 @@
using Volo.Abp.ApiVersioning; using Volo.Abp.ApiVersioning;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
namespace Volo.Abp.AspNetCore.Mvc.Versioning.App.Compat namespace Volo.Abp.AspNetCore.Mvc.Versioning.App.v1
{ {
public class TodoAppService : ApplicationService, ITodoAppService public class TodoAppService : ApplicationService, ITodoAppService
{ {
@ -14,7 +14,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning.App.Compat
public string Get(int id) public string Get(int id)
{ {
return "Compat-" + id + "-" + GetVersionOrNone(); return $"Compat-{id}-{GetVersionOrNone()}";
} }
private string GetVersionOrNone() private string GetVersionOrNone()

@ -1,6 +1,6 @@
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
namespace Volo.Abp.AspNetCore.Mvc.Versioning.App.Compat namespace Volo.Abp.AspNetCore.Mvc.Versioning.App.v2
{ {
public interface ITodoAppService : IApplicationService public interface ITodoAppService : IApplicationService
{ {

@ -1,7 +1,7 @@
using Volo.Abp.ApiVersioning; using Volo.Abp.ApiVersioning;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
namespace Volo.Abp.AspNetCore.Mvc.Versioning.App namespace Volo.Abp.AspNetCore.Mvc.Versioning.App.v2
{ {
public class TodoAppService : ApplicationService, ITodoAppService public class TodoAppService : ApplicationService, ITodoAppService
{ {

@ -8,17 +8,29 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning.Test
{ {
public class HelloController_Tests: AspNetCoreMvcVersioningTestBase public class HelloController_Tests: AspNetCoreMvcVersioningTestBase
{ {
private readonly IHelloController _todoAppService; private readonly IHelloController _helloController;
public HelloController_Tests() public HelloController_Tests()
{ {
_todoAppService = ServiceProvider.GetRequiredService<IHelloController>(); _helloController = ServiceProvider.GetRequiredService<IHelloController>();
} }
[Fact] [Fact]
public async Task PostAsync() public async Task GetAsync()
{ {
(await _todoAppService.PostAsync()).ShouldBe("42-2.0"); (await _helloController.GetAsync()).ShouldBe("Get-2.0");
}
[Fact]
public async Task PostAsyncV1()
{
(await _helloController.PostAsyncV1()).ShouldBe("Post-1.0");
}
[Fact]
public async Task PostAsyncV2()
{
(await _helloController.PostAsyncV2()).ShouldBe("Post-2.0");
} }
} }
} }

@ -1,9 +1,9 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Shouldly; using Shouldly;
using Volo.Abp.AspNetCore.Mvc.Versioning.App.Compat; using Volo.Abp.AspNetCore.Mvc.Versioning.App.v1;
using Xunit; using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Versioning.Test.Compat namespace Volo.Abp.AspNetCore.Mvc.Versioning.Test.v1
{ {
public class TodoAppService_Tests : AspNetCoreMvcVersioningTestBase public class TodoAppService_Tests : AspNetCoreMvcVersioningTestBase
{ {
@ -14,7 +14,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning.Test.Compat
_todoAppService = ServiceProvider.GetRequiredService<ITodoAppService>(); _todoAppService = ServiceProvider.GetRequiredService<ITodoAppService>();
} }
[Fact(Skip = "It stopped working after ASP.NET Core 2.2 Upgrade. Should work on that.")] [Fact]
public void Get() public void Get()
{ {
_todoAppService.Get(42).ShouldBe("Compat-42-1.0"); _todoAppService.Get(42).ShouldBe("Compat-42-1.0");

@ -1,9 +1,9 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Shouldly; using Shouldly;
using Volo.Abp.AspNetCore.Mvc.Versioning.App; using Volo.Abp.AspNetCore.Mvc.Versioning.App.v2;
using Xunit; using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Versioning.Test namespace Volo.Abp.AspNetCore.Mvc.Versioning.Test.v2
{ {
public class TodoAppService_Tests : AspNetCoreMvcVersioningTestBase public class TodoAppService_Tests : AspNetCoreMvcVersioningTestBase
{ {
@ -14,7 +14,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning.Test
_todoAppService = ServiceProvider.GetRequiredService<ITodoAppService>(); _todoAppService = ServiceProvider.GetRequiredService<ITodoAppService>();
} }
[Fact(Skip = "It stopped working after ASP.NET Core 2.2 Upgrade. Should work on that.")] [Fact]
public void Get() public void Get()
{ {
_todoAppService.Get(42).ShouldBe("42-2.0"); _todoAppService.Get(42).ShouldBe("42-2.0");
Loading…
Cancel
Save