mirror of https://github.com/abpframework/abp.git
committed by
GitHub
78 changed files with 1353 additions and 392 deletions
@ -0,0 +1,73 @@ |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.Versioning; |
|||
using Microsoft.AspNetCore.Mvc.Versioning.Conventions; |
|||
using Volo.Abp.ApiVersioning; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.Conventions; |
|||
using Volo.Abp.AspNetCore.Mvc.Versioning; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
public static class AbpApiVersioningOptionsExtensions |
|||
{ |
|||
public static void ConfigureAbp(this ApiVersioningOptions options, IServiceCollection services) |
|||
{ |
|||
//TODO: Use new builder will be released with Api Versioning 2.1 instead of reflection!
|
|||
|
|||
services.AddTransient<IRequestedApiVersion, HttpContextRequestedApiVersion>(); |
|||
|
|||
services.Configure<AbpAspNetCoreMvcOptions>(op => |
|||
{ |
|||
//TODO: Configuring api version should be done directly inside ConfigureAbp,
|
|||
//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) |
|||
{ |
|||
if (setting.ApiVersionConfigurer == null) |
|||
{ |
|||
ConfigureApiVersionsByConvention(options, setting); |
|||
} |
|||
else |
|||
{ |
|||
setting.ApiVersionConfigurer.Invoke(options); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private static void ConfigureApiVersionsByConvention(ApiVersioningOptions options, ConventionalControllerSetting setting) |
|||
{ |
|||
foreach (var controllerType in setting.ControllerTypes) |
|||
{ |
|||
var controllerBuilder = typeof(ApiVersionConventionBuilder) |
|||
.GetMethod(nameof(ApiVersionConventionBuilder.Controller), |
|||
BindingFlags.Instance | BindingFlags.Public) |
|||
.MakeGenericMethod(controllerType) |
|||
.Invoke(options.Conventions, null); |
|||
|
|||
if (setting.ApiVersions.Any()) |
|||
{ |
|||
foreach (var apiVersion in setting.ApiVersions) |
|||
{ |
|||
typeof(ControllerApiVersionConventionBuilder<>) |
|||
.MakeGenericType(controllerType) |
|||
.GetMethod("HasApiVersion") |
|||
.Invoke(controllerBuilder, new object[] {apiVersion}); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (!controllerType.IsDefined(typeof(ApiVersionAttribute), true)) |
|||
{ |
|||
typeof(ControllerApiVersionConventionBuilder<>) |
|||
.MakeGenericType(controllerType) |
|||
.GetMethod("IsApiVersionNeutral") |
|||
.Invoke(controllerBuilder, null); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,41 +0,0 @@ |
|||
using System.Reflection; |
|||
using Microsoft.AspNetCore.Mvc.Controllers; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Reflection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class AbpAppServiceControllerFeatureProvider : ControllerFeatureProvider |
|||
{ |
|||
private readonly IAbpApplication _application; |
|||
|
|||
public AbpAppServiceControllerFeatureProvider(IAbpApplication application) |
|||
{ |
|||
_application = application; |
|||
} |
|||
|
|||
protected override bool IsController(TypeInfo typeInfo) |
|||
{ |
|||
var type = typeInfo.AsType(); |
|||
|
|||
if (!typeof(IRemoteService).IsAssignableFrom(type) || |
|||
!typeInfo.IsPublic || typeInfo.IsAbstract || typeInfo.IsGenericType) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
var remoteServiceAttr = ReflectionHelper.GetSingleAttributeOrDefault<RemoteServiceAttribute>(typeInfo); |
|||
|
|||
if (remoteServiceAttr != null && !remoteServiceAttr.IsEnabledFor(type)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
//TODO: Move this to a lazy loaded field for efficiency.
|
|||
var configuration = _application.ServiceProvider.GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>().Value.AppServiceControllers.ControllerAssemblySettings.GetSettingOrNull(type); |
|||
return configuration != null && (configuration.TypePredicate == null || configuration.TypePredicate(type)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,12 +1,14 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
using Volo.Abp.AspNetCore.Mvc.Conventions; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class AbpAspNetCoreMvcOptions |
|||
{ |
|||
public AppServiceControllerOptions AppServiceControllers { get; } |
|||
public ConventionalControllerOptions ConventionalControllers { get; } |
|||
|
|||
public AbpAspNetCoreMvcOptions() |
|||
{ |
|||
AppServiceControllers = new AppServiceControllerOptions(); |
|||
ConventionalControllers = new ConventionalControllerOptions(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,36 +0,0 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class AbpControllerAssemblySetting |
|||
{ |
|||
[NotNull] |
|||
public Assembly Assembly { get; } |
|||
|
|||
[NotNull] |
|||
public string RootPath { get; } |
|||
|
|||
[CanBeNull] |
|||
public Func<Type, bool> TypePredicate { get; set; } |
|||
|
|||
[CanBeNull] |
|||
public Action<ControllerModel> ControllerModelConfigurer { get; set; } |
|||
|
|||
[CanBeNull] |
|||
public Func<UrlControllerNameNormalizerContext, string> UrlControllerNameNormalizer { get; set; } |
|||
|
|||
[CanBeNull] |
|||
public Func<UrlActionNameNormalizerContext, string> UrlActionNameNormalizer { get; set; } |
|||
|
|||
public AbpControllerAssemblySetting([NotNull] Assembly assembly, [NotNull] string rootPath) |
|||
{ |
|||
Check.NotNull(assembly, rootPath); |
|||
|
|||
Assembly = assembly; |
|||
RootPath = rootPath; |
|||
} |
|||
} |
|||
} |
|||
@ -1,39 +0,0 @@ |
|||
using System; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class AbpControllerAssemblySettingBuilder : IAbpControllerAssemblySettingBuilder |
|||
{ |
|||
private readonly AbpControllerAssemblySetting _setting; |
|||
|
|||
public AbpControllerAssemblySettingBuilder(AbpControllerAssemblySetting setting) |
|||
{ |
|||
_setting = setting; |
|||
} |
|||
|
|||
public AbpControllerAssemblySettingBuilder Where(Func<Type, bool> predicate) |
|||
{ |
|||
_setting.TypePredicate = predicate; |
|||
return this; |
|||
} |
|||
|
|||
public AbpControllerAssemblySettingBuilder ConfigureControllerModel(Action<ControllerModel> configurer) |
|||
{ |
|||
_setting.ControllerModelConfigurer = configurer; |
|||
return this; |
|||
} |
|||
|
|||
public AbpControllerAssemblySettingBuilder NormalizeControllerNameInUrl(Func<UrlControllerNameNormalizerContext, string> normalizer) |
|||
{ |
|||
_setting.UrlControllerNameNormalizer = normalizer; |
|||
return this; |
|||
} |
|||
|
|||
public AbpControllerAssemblySettingBuilder NormalizeActionNameInUrl(Func<UrlActionNameNormalizerContext, string> normalizer) |
|||
{ |
|||
_setting.UrlActionNameNormalizer = normalizer; |
|||
return this; |
|||
} |
|||
} |
|||
} |
|||
@ -1,32 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Volo.Abp.Http.Modeling; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class AppServiceControllerOptions |
|||
{ |
|||
public ControllerAssemblySettingList ControllerAssemblySettings { get; } |
|||
|
|||
public List<Type> FormBodyBindingIgnoredTypes { get; } |
|||
|
|||
public AppServiceControllerOptions() |
|||
{ |
|||
ControllerAssemblySettings = new ControllerAssemblySettingList(); |
|||
|
|||
FormBodyBindingIgnoredTypes = new List<Type> |
|||
{ |
|||
typeof(IFormFile) |
|||
}; |
|||
} |
|||
|
|||
public AbpControllerAssemblySettingBuilder CreateFor(Assembly assembly, string rootPath = ModuleApiDescriptionModel.DefaultRootPath) |
|||
{ |
|||
var setting = new AbpControllerAssemblySetting(assembly, rootPath); |
|||
ControllerAssemblySettings.Add(setting); |
|||
return new AbpControllerAssemblySettingBuilder(setting); |
|||
} |
|||
} |
|||
} |
|||
@ -1,16 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class ControllerAssemblySettingList : List<AbpControllerAssemblySetting> |
|||
{ |
|||
[CanBeNull] |
|||
public AbpControllerAssemblySetting GetSettingOrNull(Type controllerType) |
|||
{ |
|||
return this.FirstOrDefault(controllerSetting => controllerSetting.Assembly == controllerType.Assembly); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
using System.Reflection; |
|||
using Microsoft.AspNetCore.Mvc.Controllers; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Conventions |
|||
{ |
|||
public class AbpConventionalControllerFeatureProvider : ControllerFeatureProvider |
|||
{ |
|||
private readonly IAbpApplication _application; |
|||
|
|||
public AbpConventionalControllerFeatureProvider(IAbpApplication application) |
|||
{ |
|||
_application = application; |
|||
} |
|||
|
|||
protected override bool IsController(TypeInfo typeInfo) |
|||
{ |
|||
//TODO: Move this to a lazy loaded field for efficiency.
|
|||
var configuration = _application.ServiceProvider |
|||
.GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>().Value |
|||
.ConventionalControllers |
|||
.ConventionalControllerSettings |
|||
.GetSettingOrNull(typeInfo.AsType()); |
|||
|
|||
return configuration != null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Volo.Abp.Http.Modeling; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Conventions |
|||
{ |
|||
public class ConventionalControllerOptions |
|||
{ |
|||
public ConventionalControllerSettingList ConventionalControllerSettings { get; } |
|||
|
|||
public List<Type> FormBodyBindingIgnoredTypes { get; } |
|||
|
|||
public ConventionalControllerOptions() |
|||
{ |
|||
ConventionalControllerSettings = new ConventionalControllerSettingList(); |
|||
|
|||
FormBodyBindingIgnoredTypes = new List<Type> |
|||
{ |
|||
typeof(IFormFile) |
|||
}; |
|||
} |
|||
|
|||
public ConventionalControllerOptions Create(Assembly assembly, [CanBeNull] Action<ConventionalControllerSetting> optionsAction = null) |
|||
{ |
|||
var setting = new ConventionalControllerSetting(assembly, ModuleApiDescriptionModel.DefaultRootPath); |
|||
optionsAction?.Invoke(setting); |
|||
setting.Initialize(); |
|||
ConventionalControllerSettings.Add(setting); |
|||
return this; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
using Microsoft.AspNetCore.Mvc.Versioning; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Reflection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Conventions |
|||
{ |
|||
public class ConventionalControllerSetting |
|||
{ |
|||
[NotNull] |
|||
public Assembly Assembly { get; } |
|||
|
|||
[NotNull] |
|||
public HashSet<Type> ControllerTypes { get; } |
|||
|
|||
[NotNull] |
|||
public string RootPath |
|||
{ |
|||
get => _rootPath; |
|||
set |
|||
{ |
|||
Check.NotNull(value, nameof(value)); |
|||
_rootPath = value; |
|||
} |
|||
} |
|||
private string _rootPath; |
|||
|
|||
[CanBeNull] |
|||
public Func<Type, bool> TypePredicate { get; set; } |
|||
|
|||
[CanBeNull] |
|||
public Action<ControllerModel> ControllerModelConfigurer { get; set; } |
|||
|
|||
[CanBeNull] |
|||
public Func<UrlControllerNameNormalizerContext, string> UrlControllerNameNormalizer { get; set; } |
|||
|
|||
[CanBeNull] |
|||
public Func<UrlActionNameNormalizerContext, string> UrlActionNameNormalizer { get; set; } |
|||
|
|||
public List<ApiVersion> ApiVersions { get; } |
|||
|
|||
public Action<ApiVersioningOptions> ApiVersionConfigurer { get; set; } |
|||
|
|||
public ConventionalControllerSetting([NotNull] Assembly assembly, [NotNull] string rootPath) |
|||
{ |
|||
Check.NotNull(assembly, rootPath); |
|||
|
|||
Assembly = assembly; |
|||
RootPath = rootPath; |
|||
|
|||
ControllerTypes = new HashSet<Type>(); |
|||
|
|||
ApiVersions = new List<ApiVersion>(); |
|||
} |
|||
|
|||
public void Initialize() |
|||
{ |
|||
var types = Assembly.GetTypes() |
|||
.Where(IsRemoteService) |
|||
.WhereIf(TypePredicate != null, TypePredicate); |
|||
|
|||
foreach (var type in types) |
|||
{ |
|||
ControllerTypes.Add(type); |
|||
} |
|||
} |
|||
|
|||
private static bool IsRemoteService(Type type) |
|||
{ |
|||
if (!typeof(IRemoteService).IsAssignableFrom(type) || !type.IsPublic || type.IsAbstract || type.IsGenericType) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
var remoteServiceAttr = ReflectionHelper.GetSingleAttributeOrDefault<RemoteServiceAttribute>(type); |
|||
|
|||
if (remoteServiceAttr != null && !remoteServiceAttr.IsEnabledFor(type)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Conventions |
|||
{ |
|||
public class ConventionalControllerSettingList : List<ConventionalControllerSetting> |
|||
{ |
|||
[CanBeNull] |
|||
public ConventionalControllerSetting GetSettingOrNull(Type controllerType) |
|||
{ |
|||
return this.FirstOrDefault(controllerSetting => controllerSetting.ControllerTypes.Contains(controllerType)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Conventions |
|||
{ |
|||
public interface IAbpServiceConvention : IApplicationModelConvention |
|||
{ |
|||
} |
|||
} |
|||
@ -1,6 +1,6 @@ |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
namespace Volo.Abp.AspNetCore.Mvc.Conventions |
|||
{ |
|||
public class UrlActionNameNormalizerContext |
|||
{ |
|||
@ -0,0 +1,15 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.Conventions |
|||
{ |
|||
public class UrlControllerNameNormalizerContext |
|||
{ |
|||
public string RootPath { get; } |
|||
|
|||
public string ControllerName { get; } |
|||
|
|||
public UrlControllerNameNormalizerContext(string rootPath, string controllerName) |
|||
{ |
|||
RootPath = rootPath; |
|||
ControllerName = controllerName; |
|||
} |
|||
} |
|||
} |
|||
@ -1,8 +0,0 @@ |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public interface IAbpAppServiceConvention : IApplicationModelConvention |
|||
{ |
|||
} |
|||
} |
|||
@ -1,12 +0,0 @@ |
|||
using System; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public interface IAbpControllerAssemblySettingBuilder |
|||
{ |
|||
AbpControllerAssemblySettingBuilder Where(Func<Type, bool> predicate); |
|||
|
|||
AbpControllerAssemblySettingBuilder ConfigureControllerModel(Action<ControllerModel> configurer); |
|||
} |
|||
} |
|||
@ -1,24 +0,0 @@ |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
//TODO: Re-consider properties of this class.
|
|||
public class UrlControllerNameNormalizerContext |
|||
{ |
|||
public string RootPath { get; } |
|||
|
|||
public string ControllerName { get; } |
|||
|
|||
public ActionModel Action { get; } |
|||
|
|||
public string HttpMethod { get; } |
|||
|
|||
public UrlControllerNameNormalizerContext(string rootPath, string controllerName, ActionModel action, string httpMethod) |
|||
{ |
|||
RootPath = rootPath; |
|||
ControllerName = controllerName; |
|||
Action = action; |
|||
HttpMethod = httpMethod; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.ApiVersioning; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning |
|||
{ |
|||
public class HttpContextRequestedApiVersion : IRequestedApiVersion |
|||
{ |
|||
public string Current => _httpContextAccessor.HttpContext?.GetRequestedApiVersion().ToString(); |
|||
|
|||
private readonly IHttpContextAccessor _httpContextAccessor; |
|||
|
|||
public HttpContextRequestedApiVersion(IHttpContextAccessor httpContextAccessor) |
|||
{ |
|||
_httpContextAccessor = httpContextAccessor; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.Http.Client.DynamicProxying |
|||
{ |
|||
public class ApiVersionInfo //TODO: Rename to not conflict with api versioning apis
|
|||
{ |
|||
public string BindingSource { get; } |
|||
public string Version { get; } |
|||
|
|||
public ApiVersionInfo(string bindingSource, string version) |
|||
{ |
|||
BindingSource = bindingSource; |
|||
Version = version; |
|||
} |
|||
|
|||
public bool ShouldSendInQueryString() |
|||
{ |
|||
//TODO: Constant! TODO: Other sources!
|
|||
return !BindingSource.IsIn("Path"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Aspects; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Http.Modeling |
|||
{ |
|||
public class ApiDescriptionModelOptions |
|||
{ |
|||
public HashSet<Type> IgnoredInterfaces { get; } |
|||
|
|||
public ApiDescriptionModelOptions() |
|||
{ |
|||
IgnoredInterfaces = new HashSet<Type> |
|||
{ |
|||
typeof(IApplicationService), |
|||
typeof(IRemoteService), |
|||
typeof(ITransientDependency), |
|||
typeof(ISingletonDependency), |
|||
typeof(IDisposable), |
|||
typeof(IAvoidDuplicateCrossCuttingConcerns) |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
using System.Linq; |
|||
using Swashbuckle.AspNetCore.Swagger; |
|||
using Swashbuckle.AspNetCore.SwaggerGen; |
|||
|
|||
namespace Volo.Abp.Identity.HttpApi.Host |
|||
{ |
|||
/// <summary>
|
|||
/// Represents the Swagger/Swashbuckle operation filter used to document the implicit API version parameter.
|
|||
/// </summary>
|
|||
/// <remarks>This <see cref="IOperationFilter"/> is only required due to bugs in the <see cref="SwaggerGenerator"/>.
|
|||
/// Once they are fixed and published, this class can be removed.</remarks>
|
|||
public class SwaggerDefaultValues : IOperationFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Applies the filter to the specified operation using the given context.
|
|||
/// </summary>
|
|||
/// <param name="operation">The operation to apply the filter to.</param>
|
|||
/// <param name="context">The current operation filter context.</param>
|
|||
public void Apply(Operation operation, OperationFilterContext context) |
|||
{ |
|||
// REF: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/412
|
|||
// REF: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/413
|
|||
foreach (var parameter in operation.Parameters.OfType<NonBodyParameter>()) |
|||
{ |
|||
var description = context.ApiDescription.ParameterDescriptions.First(p => p.Name == parameter.Name); |
|||
|
|||
if (parameter.Description == null) |
|||
{ |
|||
parameter.Description = description.ModelMetadata.Description; |
|||
} |
|||
|
|||
if (parameter.Default == null) |
|||
{ |
|||
parameter.Default = description.RouteInfo?.DefaultValue; |
|||
} |
|||
|
|||
parameter.Required |= description.RouteInfo?.IsOptional == true; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,28 +0,0 @@ |
|||
using System.Collections.Generic; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace Volo.Abp.Identity.HttpApi.Host.VersioningTests |
|||
{ |
|||
[Route("api/calls")] |
|||
public class CallsController : AbpController |
|||
{ |
|||
private static List<CallDto> _calls = new List<CallDto> |
|||
{ |
|||
new CallDto {Id = 1, Number = "123456"}, |
|||
new CallDto { Id = 2, Number = "123457" } |
|||
}; |
|||
|
|||
[HttpGet] |
|||
public List<CallDto> GetList() |
|||
{ |
|||
return _calls; |
|||
} |
|||
} |
|||
|
|||
public class CallDto : EntityDto<int> |
|||
{ |
|||
public string Number { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace Volo.Abp.Identity.HttpApi.Host.VersioningTests.V1 |
|||
{ |
|||
public class CallDto : EntityDto<int> |
|||
{ |
|||
public string Number { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using System.Collections.Generic; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace Volo.Abp.Identity.HttpApi.Host.VersioningTests.V1 |
|||
{ |
|||
[ApiVersion("1.0")] |
|||
[Route("api/v{apiVersion:apiVersion}/calls")] |
|||
public class CallsController : AbpController, IRemoteService |
|||
{ |
|||
private static readonly List<CallDto> Calls = new List<CallDto> |
|||
{ |
|||
new CallDto {Id = 1, Number = "123456"}, |
|||
new CallDto { Id = 2, Number = "123457" } |
|||
}; |
|||
|
|||
[HttpGet] |
|||
public List<CallDto> GetList() |
|||
{ |
|||
return Calls; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.Identity.HttpApi.Host.VersioningTests.V1; |
|||
|
|||
namespace Volo.Abp.Identity.HttpApi.Host.VersioningTests.V2 |
|||
{ |
|||
[ApiVersion("2.0")] |
|||
[Route("api/v{apiVersion:apiVersion}/calls")] |
|||
public class CallsController : AbpController, IRemoteService |
|||
{ |
|||
private static List<CallDto> _calls = new List<CallDto> |
|||
{ |
|||
new CallDto {Id = 1, Number = "123456000"}, |
|||
new CallDto { Id = 2, Number = "123457000" } |
|||
}; |
|||
|
|||
[HttpGet] |
|||
public List<CallDto> GetList() |
|||
{ |
|||
return _calls; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("by-filter")] |
|||
public List<CallDto> GetList(string num) |
|||
{ |
|||
return _calls.Where(c => c.Number.Contains(num)).ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.ApiVersioning; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace Volo.Abp.Identity |
|||
{ |
|||
//TODO: This is just a test controller and will be removed later
|
|||
[ApiVersion("3.0")] |
|||
[ApiVersion("2.0", Deprecated = true)] |
|||
[Route("api/v{apiVersion:apiVersion}/identity/fixture")] |
|||
public class FixtureController : AbpController, IRemoteService |
|||
{ |
|||
private readonly IRequestedApiVersion _requestedApiVersion; |
|||
|
|||
public FixtureController(IRequestedApiVersion requestedApiVersion) |
|||
{ |
|||
_requestedApiVersion = requestedApiVersion; |
|||
} |
|||
|
|||
[HttpGet, MapToApiVersion("2.0")] |
|||
public string Get() |
|||
{ |
|||
return 41 + " - " + _requestedApiVersion.Current; |
|||
} |
|||
|
|||
[HttpGet, MapToApiVersion("3.0")] |
|||
public string Get3() |
|||
{ |
|||
return 42 + " - " + _requestedApiVersion.Current; |
|||
} |
|||
|
|||
[HttpPost] |
|||
public int Post() |
|||
{ |
|||
return 43; |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Route("{id}")] |
|||
public int Post(int id) |
|||
{ |
|||
return id; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.ApiVersioning; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace Volo.Abp.Identity.V4 |
|||
{ |
|||
//TODO: This is just a test controller and will be removed later
|
|||
[ApiVersion("4.0")] |
|||
[Route("api/v{apiVersion:apiVersion}/identity/fixture")] |
|||
public class FixtureController : AbpController, IRemoteService |
|||
{ |
|||
private readonly IRequestedApiVersion _requestedApiVersion; |
|||
|
|||
public FixtureController(IRequestedApiVersion requestedApiVersion) |
|||
{ |
|||
_requestedApiVersion = requestedApiVersion; |
|||
} |
|||
|
|||
[HttpGet] |
|||
public string Get() |
|||
{ |
|||
return 41 + " - " + _requestedApiVersion.Current; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace Volo.Abp.ApiVersioning |
|||
{ |
|||
public interface IRequestedApiVersion |
|||
{ |
|||
string Current { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
namespace Volo.Abp.ApiVersioning |
|||
{ |
|||
public class NullRequestedApiVersion : IRequestedApiVersion |
|||
{ |
|||
public static NullRequestedApiVersion Instance = new NullRequestedApiVersion(); |
|||
|
|||
public string Current => null; |
|||
|
|||
private NullRequestedApiVersion() |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp2.0</TargetFramework> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<AssemblyName>Volo.Abp.AspNetCore.Mvc.Versioning.Tests</AssemblyName> |
|||
<PackageId>Volo.Abp.AspNetCore.Mvc.Versioning.Tests</PackageId> |
|||
<PreserveCompilationContext>true</PreserveCompilationContext> |
|||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> |
|||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.AspNetCore.Mvc\Volo.Abp.AspNetCore.Mvc.csproj" /> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Tests\Volo.Abp.AspNetCore.Tests.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<!-- Below ItemGroup and Target tags are added according to https://github.com/aspnet/Hosting/issues/959#issuecomment-286351703 --> |
|||
|
|||
<!-- Solves Problem#2 (404 when executing service calls hosted in other assemblies) --> |
|||
<!-- https://github.com/Microsoft/vstest/issues/196.--> |
|||
<ItemGroup> |
|||
<None Update="xunit.runner.json"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
</ItemGroup> |
|||
|
|||
<!-- https://github.com/NuGet/Home/issues/4412. --> |
|||
<Target Name="CopyDepsFiles" AfterTargets="Build" Condition="'$(TargetFramework)'!=''"> |
|||
<ItemGroup> |
|||
<DepsFilePaths Include="$([System.IO.Path]::ChangeExtension('%(_ResolvedProjectReferencePaths.FullPath)', '.deps.json'))" /> |
|||
</ItemGroup> |
|||
|
|||
<Copy SourceFiles="%(DepsFilePaths.FullPath)" DestinationFolder="$(OutputPath)" Condition="Exists('%(DepsFilePaths.FullPath)')" /> |
|||
</Target> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,69 @@ |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.Versioning; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AspNetCore.Modularity; |
|||
using Volo.Abp.AspNetCore.TestBase; |
|||
using Volo.Abp.Autofac; |
|||
using Volo.Abp.Http.Client; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreTestBaseModule), |
|||
typeof(AbpAspNetCoreMvcModule), |
|||
typeof(AbpAutofacModule), |
|||
typeof(AbpHttpClientModule) |
|||
)] |
|||
public class AbpAspNetCoreMvcVersioningTestModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(IServiceCollection services) |
|||
{ |
|||
services.AddMvc(); |
|||
|
|||
services.Configure<AbpAspNetCoreMvcOptions>(options => |
|||
{ |
|||
//2.0 Version
|
|||
options.ConventionalControllers.Create(typeof(AbpAspNetCoreMvcVersioningTestModule).Assembly, opts => |
|||
{ |
|||
opts.TypePredicate = t => t.Namespace == typeof(Volo.Abp.AspNetCore.Mvc.Versioning.App.TodoAppService).Namespace; |
|||
opts.ApiVersions.Add(new ApiVersion(2, 0)); |
|||
}); |
|||
|
|||
//1.0 Compatability version
|
|||
options.ConventionalControllers.Create(typeof(AbpAspNetCoreMvcVersioningTestModule).Assembly, opts => |
|||
{ |
|||
opts.TypePredicate = t => t.Namespace == typeof(Volo.Abp.AspNetCore.Mvc.Versioning.App.Compat.TodoAppService).Namespace; |
|||
opts.ApiVersions.Add(new ApiVersion(1, 0)); |
|||
}); |
|||
}); |
|||
|
|||
services.AddApiVersioning(options => |
|||
{ |
|||
options.ReportApiVersions = true; |
|||
options.AssumeDefaultVersionWhenUnspecified = true; |
|||
|
|||
//options.ApiVersionReader = new HeaderApiVersionReader("api-version"); //Supports header too
|
|||
//options.ApiVersionReader = new MediaTypeApiVersionReader(); //Supports accept header too
|
|||
|
|||
options.ConfigureAbp(services); |
|||
}); |
|||
|
|||
services.AddAssemblyOf<AbpAspNetCoreMvcVersioningTestModule>(); |
|||
|
|||
services.AddHttpClientProxies(typeof(AbpAspNetCoreMvcVersioningTestModule).Assembly); |
|||
|
|||
services.Configure<RemoteServiceOptions>(options => |
|||
{ |
|||
options.RemoteServices.Default = new RemoteServiceConfiguration("/"); |
|||
}); |
|||
} |
|||
|
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var app = context.GetApplicationBuilder(); |
|||
app.UseMvcWithDefaultRoute(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning.App.Compat |
|||
{ |
|||
public interface ITodoAppService : IApplicationService |
|||
{ |
|||
string Get(int id); |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using Volo.Abp.ApiVersioning; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning.App.Compat |
|||
{ |
|||
public class TodoAppService : ITodoAppService |
|||
{ |
|||
private readonly IRequestedApiVersion _requestedApiVersion; |
|||
|
|||
public TodoAppService(IRequestedApiVersion requestedApiVersion) |
|||
{ |
|||
_requestedApiVersion = requestedApiVersion; |
|||
} |
|||
|
|||
public string Get(int id) |
|||
{ |
|||
return "Compat-" + id + "-" + GetVersionOrNone(); |
|||
} |
|||
|
|||
private string GetVersionOrNone() |
|||
{ |
|||
return _requestedApiVersion.Current ?? "NONE"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning.App |
|||
{ |
|||
[ApiVersion("1.0")] |
|||
[ApiVersion("2.0")] |
|||
[Route("api/v{apiVersion:apiVersion}/[controller]")]
|
|||
public class HelloController : AbpController, IHelloController |
|||
{ |
|||
[HttpPost] |
|||
public Task<string> PostAsync() |
|||
{ |
|||
return Task.FromResult($"42-{HttpContext.GetRequestedApiVersion().ToString()}"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning.App |
|||
{ |
|||
public interface IHelloController : IRemoteService |
|||
{ |
|||
Task<string> PostAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning.App |
|||
{ |
|||
public interface ITodoAppService : IApplicationService |
|||
{ |
|||
string Get(int id); |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using Volo.Abp.ApiVersioning; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning.App |
|||
{ |
|||
public class TodoAppService : ITodoAppService |
|||
{ |
|||
private readonly IRequestedApiVersion _requestedApiVersion; |
|||
|
|||
public TodoAppService(IRequestedApiVersion requestedApiVersion) |
|||
{ |
|||
_requestedApiVersion = requestedApiVersion; |
|||
} |
|||
|
|||
public string Get(int id) |
|||
{ |
|||
return id + "-" + GetVersionOrNone(); |
|||
} |
|||
|
|||
private string GetVersionOrNone() |
|||
{ |
|||
return _requestedApiVersion.Current ?? "NONE"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning |
|||
{ |
|||
public abstract class AspNetCoreMvcVersioningTestBase : AbpAspNetCoreTestBase<Startup> |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
using System; |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning |
|||
{ |
|||
public class Startup |
|||
{ |
|||
public IServiceProvider ConfigureServices(IServiceCollection services) |
|||
{ |
|||
services.AddApplication<AbpAspNetCoreMvcVersioningTestModule>(options => |
|||
{ |
|||
options.UseAutofac(); |
|||
}); |
|||
|
|||
//TODO: This is needed because ASP.NET Core does not use IServiceProviderFactory!
|
|||
return services.BuildServiceProviderFromFactory(); |
|||
} |
|||
|
|||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) |
|||
{ |
|||
app.InitializeApplication(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Volo.Abp.AspNetCore.Mvc.Versioning.App.Compat; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning.Test.Compat |
|||
{ |
|||
public class TodoAppService_Tests : AspNetCoreMvcVersioningTestBase |
|||
{ |
|||
private readonly ITodoAppService _todoAppService; |
|||
|
|||
public TodoAppService_Tests() |
|||
{ |
|||
_todoAppService = ServiceProvider.GetRequiredService<ITodoAppService>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Get() |
|||
{ |
|||
_todoAppService.Get(42).ShouldBe("Compat-42-1.0"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Volo.Abp.AspNetCore.Mvc.Versioning.App; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning.Test |
|||
{ |
|||
public class HelloController_Tests: AspNetCoreMvcVersioningTestBase |
|||
{ |
|||
private readonly IHelloController _todoAppService; |
|||
|
|||
public HelloController_Tests() |
|||
{ |
|||
_todoAppService = ServiceProvider.GetRequiredService<IHelloController>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task PostAsync() |
|||
{ |
|||
(await _todoAppService.PostAsync()).ShouldBe("42-2.0"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Volo.Abp.AspNetCore.Mvc.Versioning.App; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Versioning.Test |
|||
{ |
|||
public class TodoAppService_Tests : AspNetCoreMvcVersioningTestBase |
|||
{ |
|||
private readonly ITodoAppService _todoAppService; |
|||
|
|||
public TodoAppService_Tests() |
|||
{ |
|||
_todoAppService = ServiceProvider.GetRequiredService<ITodoAppService>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Get() |
|||
{ |
|||
_todoAppService.Get(42).ShouldBe("42-2.0"); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue