diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj index e190116b2f..e564dec738 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj @@ -21,6 +21,7 @@ + diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index e3cee4e72b..88a81fa1ec 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -10,14 +10,12 @@ using Microsoft.Extensions.Options; using Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Net; using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.DataAnnotations; -using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; using Microsoft.AspNetCore.Routing; @@ -34,6 +32,7 @@ using Volo.Abp.AspNetCore.VirtualFileSystem; using Volo.Abp.DependencyInjection; using Volo.Abp.Http; using Volo.Abp.DynamicProxy; +using Volo.Abp.GlobalFeatures; using Volo.Abp.Http.Modeling; using Volo.Abp.Localization; using Volo.Abp.Modularity; @@ -46,7 +45,8 @@ namespace Volo.Abp.AspNetCore.Mvc typeof(AbpLocalizationModule), typeof(AbpApiVersioningAbstractionsModule), typeof(AbpAspNetCoreMvcContractsModule), - typeof(AbpUiModule) + typeof(AbpUiModule), + typeof(AbpGlobalFeaturesModule) )] public class AbpAspNetCoreMvcModule : AbpModule { @@ -168,7 +168,7 @@ namespace Volo.Abp.AspNetCore.Mvc context.Services.Replace(ServiceDescriptor.Singleton()); context.Services.AddSingleton(); - + Configure(mvcOptions => { mvcOptions.AddAbp(context.Services); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs index 0254a6022b..166640fe00 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.Extensions.Options; using Volo.Abp.Application.Services; using Volo.Abp.DependencyInjection; +using Volo.Abp.GlobalFeatures; using Volo.Abp.Http; using Volo.Abp.Http.Modeling; using Volo.Abp.Http.ProxyScripting.Generators; @@ -142,18 +143,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions if (controller.ApiExplorer.IsVisible == null) { - var controllerType = controller.ControllerType.AsType(); - var remoteServiceAtt = ReflectionHelper.GetSingleAttributeOrDefault(controllerType.GetTypeInfo()); - if (remoteServiceAtt != null) - { - controller.ApiExplorer.IsVisible = - remoteServiceAtt.IsEnabledFor(controllerType) && - remoteServiceAtt.IsMetadataEnabledFor(controllerType); - } - else - { - controller.ApiExplorer.IsVisible = true; - } + controller.ApiExplorer.IsVisible = IsVisibleRemoteService(controller.ControllerType); } foreach (var action in controller.Actions) @@ -164,16 +154,18 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions protected virtual void ConfigureApiExplorer(ActionModel action) { - if (action.ApiExplorer.IsVisible == null) + if (action.ApiExplorer.IsVisible != null) { - var remoteServiceAtt = ReflectionHelper.GetSingleAttributeOrDefault(action.ActionMethod); - if (remoteServiceAtt != null) - { - action.ApiExplorer.IsVisible = - remoteServiceAtt.IsEnabledFor(action.ActionMethod) && - remoteServiceAtt.IsMetadataEnabledFor(action.ActionMethod); - } + return; } + + var visible = IsVisibleRemoteServiceMethod(action.ActionMethod); + if (visible == null) + { + return; + } + + action.ApiExplorer.IsVisible = visible; } protected virtual void ConfigureSelector(ControllerModel controller, [CanBeNull] ConventionalControllerSetting configuration) @@ -397,5 +389,45 @@ namespace Volo.Abp.AspNetCore.Mvc.Conventions { return typeof(IRemoteService).GetTypeInfo().IsAssignableFrom(controllerType); } + + protected virtual bool IsVisibleRemoteService(Type controllerType) + { + if (!IsGlobalFeatureEnabled(controllerType)) + { + return false; + } + + var attribute = ReflectionHelper.GetSingleAttributeOrDefault(controllerType); + if (attribute == null) + { + return true; + } + + return attribute.IsEnabledFor(controllerType) && + attribute.IsMetadataEnabledFor(controllerType); + } + + protected virtual bool? IsVisibleRemoteServiceMethod(MethodInfo method) + { + var attribute = ReflectionHelper.GetSingleAttributeOrDefault(method); + if (attribute == null) + { + return null; + } + + return attribute.IsEnabledFor(method) && + attribute.IsMetadataEnabledFor(method); + } + + protected virtual bool IsGlobalFeatureEnabled(Type controllerType) + { + var attribute = ReflectionHelper.GetSingleAttributeOrDefault(controllerType); + if (attribute == null) + { + return true; + } + + return GlobalFeatureManager.Instance.IsEnabled(attribute.FeatureType); + } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureManager.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureManager.cs index 79badfe4e7..19a48a9da3 100644 --- a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureManager.cs +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureManager.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; + using System.Collections.Generic; using JetBrains.Annotations; namespace Volo.Abp.GlobalFeatures @@ -30,6 +31,11 @@ namespace Volo.Abp.GlobalFeatures return IsEnabled(GlobalFeatureNameAttribute.GetName()); } + public virtual bool IsEnabled([NotNull] Type featureType) + { + return IsEnabled(GlobalFeatureNameAttribute.GetName(featureType)); + } + public virtual bool IsEnabled(string featureName) { return EnabledFeatures.Contains(featureName); diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureNameAttribute.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureNameAttribute.cs index 0563712899..2b987f6cb1 100644 --- a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureNameAttribute.cs +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureNameAttribute.cs @@ -23,8 +23,10 @@ namespace Volo.Abp.GlobalFeatures } [NotNull] - public static string GetName(Type type) + public static string GetName([NotNull] Type type) { + Check.NotNull(type, nameof(type)); + var attribute = type .GetCustomAttributes() .FirstOrDefault(); diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/RequiresGlobalFeatureAttribute.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/RequiresGlobalFeatureAttribute.cs new file mode 100644 index 0000000000..23ea10be81 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/RequiresGlobalFeatureAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace Volo.Abp.GlobalFeatures +{ + [AttributeUsage(AttributeTargets.Class)] + public class RequiresGlobalFeatureAttribute : Attribute + { + public Type FeatureType { get; } + + public RequiresGlobalFeatureAttribute(Type featureType) + { + FeatureType = featureType; + } + } +}