Giter Club home page Giter Club logo

abp.settingui's Introduction

中文

Abp.SettingUi

ABP version NuGet NuGet Download Discord online GitHub stars

An ABP module used to manage ABP settings

demo

If you are using ABP version <2.1.1, please see Abp.SettingManagement.Mvc.UI

Features

  • Manage ABP setting values via UI
  • Support localization
  • Group settings
  • Display settings with appropriate input controls
  • Control display of settings by permissions

Installation

Add ABP packages with AbpHelper (Recommended)

Run following command in your ABP project root folder:

abphelper module add EasyAbp.Abp.SettingUi -acshlw

Add ABP packages manually

  1. Install the following NuGet packages.

    • EasyAbp.Abp.SettingUi.Application
    • EasyAbp.Abp.SettingUi.Application.Contracts
    • EasyAbp.Abp.SettingUi.Domain.Shared
    • EasyAbp.Abp.SettingUi.HttpApi
    • EasyAbp.Abp.SettingUi.HttpApi.Client (Only Tiered structure is needed)
    • EasyAbp.Abp.SettingUi.Web
  2. Add DependsOn(typeof(AbpSettingUiXxxModule)) attribute to configure the module dependencies. (see how)

Configure localization resource

In order to let SettingUi module use localization resources from this application, we need to add them to SettingUiResource:

  • MyAbpApp.Domain.Shared project - MyAbpAppDomainSharedModule class

    Configure<AbpLocalizationOptions>(options =>
    {
        ...
        options.Resources
            .Get<SettingUiResource>()
            .AddVirtualJson("/Localization/MyAbpApp");
    });

Usage

  1. Grant permission ("Setting UI" - "Show Setting Page")

    permission

  2. Refresh the browser then you can use "Administration" - "Settings" menu to see all ABP built-in settings

Manage custom settings

Beside ABP built-in settings, you can also use this module to manage your own settings.

  1. Define a setting

    • MyAbpApp.Domain project - Settings/MyAbpAppSettingDefinitionProvider class

      public class MyAbpAppSettingDefinitionProvider : SettingDefinitionProvider
      {
          public override void Define(ISettingDefinitionContext context)
          {
              context.Add(
                  new SettingDefinition(
                      "Connection.Ip", // Setting name
                      "127.0.0.1", // Default value
                      L("DisplayName:Connection.Ip"), // Display name
                      L("Description:Connection.Ip") // Description
                  ));
          }
      
          private static LocalizableString L(string name)
          {
              return LocalizableString.Create<MyAbpAppResource>(name);
          }
      }
      • The setting name is "Connection.Ip"
      • Provide a default value: "127.0.0.1"
      • Set the DisplayName and Description to a localizable string by using a helper method L. The format "DisplayName:{SettingName}" is the convention recommended by ABP

      For ABP setting system, please see Settings document

  2. Define localization resources for the setting, for demonstration purpose, we defined English and Chinese localization resources

    • MyAbpApp.Domain.Shared project

      • Localization/MyAbpApp/en.json

        {
            "culture": "en",
            "texts": {
                ...
                "DisplayName:Connection.Ip": "IP",
                "Description:Connection.Ip": "The IP address of the server."
            }
        }
      • Localization/MyAbpApp/zh-Hans.json

        {
            "culture": "zh-Hans",
            "texts": {
                ...
                "DisplayName:Connection.Ip": "IP",
                "Description:Connection.Ip": "服务器的IP地址."
            }
        }
  3. Relaunch the application, we can see the setting displayed, and the localization also works

    custom-setting

Grouping

You may notice that our custom setting is displayed in "Others" tab, and "Others" card, these are the default group display names called "Group1" and "Group2" respectively:

group

So how can we custom the group of the setting? There are two ways:

  1. Use WithProperty method

    The WithProperty method is a method provided by ABP SettingDefinition class, we can directly use it in setting defining:

    • MyAbpApp.Domain project - Settings/MyAbpAppSettingDefinitionProvider class

      context.Add(
          new SettingDefinition(
                  "Connection.Ip", // Setting name
                  "127.0.0.1", // Default value
                  L("DisplayName:Connection.Ip"), // Display name
                  L("Description:Connection.Ip") // Description
              )
              .WithProperty(SettingUiConst.Group1, "Server")
              .WithProperty(SettingUiConst.Group2, "Connection")
      );
      • The constants Group1 and Group2 are defined in the SettingUiConst class
      • Set the "Server" to "Group1", and "Connection" to "Group2"

    Then we should provide the localization resource for these two group names:

    • MyAbpApp.Domain.Shared project

      • Localization/MyAbpApp/en.json

        {
            "culture": "en",
            "texts": {
                ...
                "Server": "Server",
                "Connection": "Connection"
            }
        }
      • Localization/MyAbpApp/zh-Hans.json

        {
            "culture": "zh-Hans",
            "texts": {
                ...
                "Server": "服务器",
                "Connection": "连接"
            }
        }

    Relaunch the application and see if the group names are correctly set

    group-name

  2. Use setting property file

    Another way of setting group is use the setting property file, which is provided by the SettingUi module. It's useful when you can not easily modify the setting definition, or you want to put the grouping information into one single place.

    For demonstration in this way, let's define a new setting:

    • MyAbpApp.Domain project - Settings/MyAbpAppSettingDefinitionProvider class

      new SettingDefinition(
          "Connection.Port",
          8080.ToString(),
          L("DisplayName:Connection.Port"),
          L("Description:Connection.Port")
      )

    The steps of adding localization for this setting are omitted.

    Then we need to create a new json file with arbitrary filename, however the path must be "/SettingProperties", because SettingUi module will look for the setting property files from this path.

    • MyAbpApp.Domain.Shared project - /SettingProperties/MySettingProperties.json file

      {
          "Connection.Port": {
              "Group1": "Server",
              "Group2": "Connection"
          }
      }
      • The setting name Connection.Port as the key of the JSON object
      • Use "Group1" and "Group2" to set the grouping names
    • Relaunch the application to see the new grouped setting

      group-by-setting-property-file

Setting types

By default a setting value is string type, which will be rendered as a text input control in UI. We can custom it simply by providing a setting property "Type":

  • MyAbpApp.Domain.Shared project - /SettingProperties/MySettingProperties.json file

    {
        "Connection.Port": {
            "Group1": "Server",
            "Group2": "Connection",
            "Type": "number"
        }
    }
    • Set the "Connection.Port" setting type to "number"

No need to relaunch the application, just press F5 to refresh the browser, you should be able to see the effect immediately:

type-number

Now the input type changed to "number", and the frontend validations also work.

The setting types can also be configured through WithProperty method, like WithProperty("Type", "number")

For now SettingUi supports following setting types:

  • text (default)
  • number
  • checkbox
  • select
    • Needs an additional property "Options" to provide select options, which is a string separated by a vertical bar (|)

      "Connection.Protocol": {
          "Group1": "Server",
          "Group2": "Connection",
          "Type": "select",
          "Options": "|HTTP|TCP|RDP|FTP|SFTP"
      }
      

      The render result:

      selection

This is the end of the tutorial. Through this tutorial, you should be able to easily manage your settings using SettingUi. The source of the tutorial can be found in the sample folder.

Localization

The SettingUi module uses ABP's localization system to display the localization information of the settings.The languages currently supported are:

  • en
  • zh-Hans
  • tr

The localization resource files are under /Localization/SettingUi of the EasyAbp.Abp.SettingUi.Domain.Shared project.

You can add more resource files to make this module support more languages. Welcome PRs 😊 .

For ABP's localization system, please see the document

Permissions

SettingUi controls whether to display SettingUi's page by checking the SettingUi.ShowSettingPage permission.

As long as the permission is granted, all settings in the system can be modified through SettingUi.

But sometimes, we don't want users to see certain settings in SettingUi, which can be achieved by defining specific permissions.

For example, if we need to hide the "system" group from users, then we need to add a child permission of SettingUi.ShowSettingPage, the name of the permission is SettingUi.System. The code is as follows:

public override void Define(IPermissionDefinitionContext context)
{
    var settingUiPage = context.GetPermissionOrNull(SettingUiPermissions.ShowSettingPage);  // Get ShowSettingPage permission
    var systemGroup = settingUiPage.AddChild("SettingUi.System", L("Permission:SettingUi.System")); // Add display permission of Group1: System
}

In this way, when SettingUi enumerates the settings, if a permission in the form of SettingUi.Group1 is found, the Group1 will only be displayed after the permission is explicitly granted.

You can also use the SettingUiPermissions.GroupName variable. The effect is the same as the above code. The code is as follows:

public override void Define(IPermissionDefinitionContext context)
{
    var settingUiPage = context.GetPermissionOrNull(SettingUiPermissions.ShowSettingPage);  // Get ShowSettingPage permission
    var systemGroup = settingUiPage.AddChild(SettingUiPermissions.GroupName + ".System", L("Permission:SettingUi.System")); // Add display permission of Group1: System
}

We can continue to add permissions to control Group2, such as "System" -> "Password" group, we need to add a permission with the Group2 name as the suffix, the code is as follows:

public override void Define(IPermissionDefinitionContext context)
{
    ...
    var passwordGroup = systemGroup.AddChild("SettingUi.System.Password", L("Permission:SettingUi.System.Password"));   // Add display permission of Group2: Password
}

In this way, when SettingUi enumerates the settings, if a permission in the form of SettingUi.Group1.Group2 is found, the Group2 in Group1 will only be displayed after the permission is explicitly granted.

Of course, we can also continue to add a permission to precisely control a specified setting, such as "System" -> "Password" -> "Required Length", we need to add a permission with the setting name as the suffix, the code is as follows:

public override void Define(IPermissionDefinitionContext context)
{
    ...
    var requiredLength = passwordGroup.AddChild("SettingUi.System.Password.Abp.Identity.Password.RequiredLength", L("Permission:SettingUi.System.Password.RequiredLength"));    // Add display permission of Abp.Identity.Password.RequiredLength
}

In this way, when SettingUi enumerates the settings, if a permission in the form of SettingUi.Group1.Group2.SettingName is found, the setting in Group2 in Group1 will only be displayed after the permission is explicitly granted.

Through the above three-level permission definition way, we can arbitrarily control the display of settings in SettingUi.

The following figure is a screenshot of Setting Ui permissions, and the displayed result:

setting_permission

For ABP's permission system, please see the document

abp.settingui's People

Contributors

blackwins avatar cihangll avatar dependabot[bot] avatar gdlcf88 avatar hueifeng avatar jadynwong avatar linch90 avatar wakuflair avatar washyn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

abp.settingui's Issues

Disabling Abp settings on tenants

Hi!

Thanks for providing this awesome module.

I am seeking advice around disabling the default Abp settings from displaying for tenants.

For example i would like the host admin to control System and Mail settings and not the individual users or tenant admins.

image

Is it possible accomplish this in the current version 1.1.10?

Perform setting save validation

Hello!

What should we override to perform validation when saving settings through this module?
Ideally we can override and check if the setting group is x then perform some validation

Localizable strings for setting groups

Hello!

Currently the SettingDefinition takes localizable strings for our settings, however the .WithProperty method does not, so how do we get localized strings into our group headers for settings?

image

image

what's the plan to implement the support for UserSettingManagementProvider

and can you support the below function:

the smart property recognition for the following codes,
for example: the boolean property should smart work with si.WithProperty(SettingUiConst.Type, bool) ;

private List<SettingInfo> SetSettingDefinitionProperties(IDictionary<string, IDictionary<string, string>> settingProperties)
        {
            var settingInfos = new List<SettingInfo>();
            var settingDefinitions = _settingDefinitionManager.GetAll();
            foreach (var settingDefinition in settingDefinitions)
            {
                var si = CreateSettingInfo(settingDefinition);
                if (settingProperties.ContainsKey(si.Name))
                {
                    // This Setting is defined in the property file,
                    // set its property values from the dictionary
                    var properties = settingProperties[si.Name];
                    foreach (var kv in properties)
                    {
                        // Do not assign the property if it has already been set by the user.
                        if (!si.Properties.ContainsKey(kv.Key))
                        {
                            si.WithProperty(kv.Key, kv.Value);
                        }
                    }
                }

                // Default group1: Others
                if (!si.Properties.ContainsKey(SettingUiConst.Group1))
                {
                    si.WithProperty(SettingUiConst.Group1, SettingUiConst.DefaultGroup);
                }

                // Default group2: Others
                if (!si.Properties.ContainsKey(SettingUiConst.Group2))
                {
                    si.WithProperty(SettingUiConst.Group2, SettingUiConst.DefaultGroup);
                }

                // Default type: text
                if (!si.Properties.ContainsKey(SettingUiConst.Type))
                {
                    si.WithProperty(SettingUiConst.Type, SettingUiConst.DefaultType);
                }

                settingInfos.Add(si);
            }

            return settingInfos;
        }

Grouping configuration improvement.

I saw the grouping demo:

context.Add(
    new SettingDefinition(
            "Connection.Ip", // Setting name
            "127.0.0.1", // Default value
            L("DisplayName:Connection.Ip"), // Display name
            L("Description:Connection.Ip") // Description
        )
        .WithProperty(SettingUiConst.Group1, "Server")
        .WithProperty(SettingUiConst.Group2, "Connection")
);

"SettingUiConst.Group$n" cannot express the hierarchy well, maybe this is a better way:

context.Add(
    new SettingDefinition(
            "Connection.Ip", // Setting name
            "127.0.0.1", // Default value
            L("DisplayName:Connection.Ip"), // Display name
            L("Description:Connection.Ip") // Description
        )
        .WithProperty("SettingGroup", "Server:Connection")  // More then 2 levels support
        .WithProperty("SettingType", "number") // Original name is: Type
);

Sorting settings

Hi,

I think settings can be sorted on the UI with Weight / Order property.

We can use like this (code side);

context.Add(
  new SettingDefinition(
     ...  
  )
  .WithProperty(SettingUiConst.Weight, "5")
  ...
);

or like this (xml side);

"Setting1": {
    ...
   "Weight": "5"
}

Code Example
SettingInfo

public class SettingInfo
{    
    public short Weight { get; set; }
    ...
}

Default value can be set zero.

SettingUiAppService

... SetSettingDefinitionPropertiesAsync(...) {
    ...
    // Default weight: 0
    if(!si.Properties.ContainsKey(SettingUiConst.Weight))
    {
        si.WithProperty(SettingUiConst.Weight, "0");
    }
    ...
}

in SettingUiAppService.GroupSettingDefinitions:

settingInfos.OrderByDescending(si => (short) si.Properties[SettingUiConst.Weight]).ToList();

Usage with MultiTenancy

Hi, just started using your module, its awesome!

What is the roadmap for implementing the tenant provider and giving ability to control settings for tenants?

Thanks

A way to make settings required or default when blank?

Hello,

First of all, great module! I was just about to make mine and I found yours and used it instead.

I was wondering if there is a way to make settings required? If a user deletes the content of a setting, it will be saved as blank in the DB. This overrides the default value with "nothing".

I see 2 possible solutions:

  1. Make settings required, users must provide a value.
  2. If the user deletes the content of a setting, it's set to the default value instead.

What do you think?
Thank you!

Admin can be locked out

If admin changes the Setting to required confirm of email/phone - and then logs out - the admin can no longer log back in!! :-)

Suggest that Admin account should be except from requiring confirm?

How to Remove Existing "Emailing" Settings?

I followed the instructions and installed using
abphelper module add EasyAbp.Abp.SettingUi -acshlw

However I see the original `Emailing' Settings are still there in the UI.
image

Is there a way to remove it?

it is a duplicate for the better Mail settings that come with Easy Abp
thanks

Cannot compact with the setting management page for abp commercial 4.3.0-rc.1

When open the setting management page, it thrown below exception:

Volo.Abp.Http.Client.AbpRemoteCallException: 对不起,在处理你的请求期间,产生了一个服务器内部错误!
at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor1.ThrowExceptionForResponseAsync(HttpResponseMessage response) at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor1.MakeRequestAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor1.MakeRequestAndGetResultAsync[T](IAbpMethodInvocation invocation) at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor1.GetResultAsync(Task task, Type resultType)
at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor1.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync()
at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed)
at EasyAbp.Abp.SettingUi.Web.Pages.SettingUiPageContributor.ConfigureAsync(SettingPageCreationContext context)
at Volo.Abp.SettingManagement.Web.Pages.SettingManagement.IndexModel.OnGetAsync()
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory.GenericTaskHandlerMethod.Convert[T](Object taskAsObject)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory.GenericTaskHandlerMethod.Execute(Object receiver, Object[] arguments)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync()
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync()
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Volo.Abp.AspNetCore.Serilog.AbpSerilogMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<b__1>d.MoveNext()
--- End of stack trace from previous location ---

An exception occurred when the setting was saved

image

If (custom group1) is in the first place, the form that saves the right card will throw an exception.

Logs:

System.NullReferenceException: Object reference not set to an instance of an object.
   at AspNetCoreGeneratedDocument.Pages_SettingManagement_Index.<ExecuteAsync>b__12_5()
   at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync()
   at AspNetCoreGeneratedDocument.Pages_SettingManagement_Index.<ExecuteAsync>b__12_1()
   at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync()
   at AspNetCoreGeneratedDocument.Pages_SettingManagement_Index.ExecuteAsync()
   at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
   at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)
   at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
   at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
   at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Volo.Abp.AspNetCore.Serilog.AbpSerilogMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Volo.Abp.AspNetCore.Uow.AbpUnitOfWorkMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Builder.ApplicationBuilderAbpOpenIddictMiddlewareExtension.<>c__DisplayClass0_0.<<UseAbpOpenIddictValidation>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Volo.Abp.AspNetCore.Tracing.AbpCorrelationIdMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.RequestLocalization.AbpRequestLocalizationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

设置布尔类型的时候,会报错

image

details: "验证时发现以下错误.\r\n - The JSON value could not be converted to System.Collections.Generic.Dictionary`2[System.String,System.String]. Path: $.Setting_Abp_Identity_Lockout_AllowedForNewUsers | LineNumber: 0 | BytePositionInLine: 55.\r\n"
message: "你的请求无效!"

Basic Theme NullReferenceException

Hi,
The following error occurs when using basic theme.

NullReferenceException: Object reference not set to an instance of an object.
AspNetCoreGeneratedDocument.Pages_SettingManagement_Index.b__12_5()

Does this module work well under multi tenancy

Hi
First of all, great module! I was just about to make mine and I found yours and used it instead.

I have a problem
Does this module work well under multi tenancy?

I try use this module in multi tenancy,login with tenancy and update setting ,all settings ProviderName are set to 'G'

Tks

本地调试可以,部署后swagger正常,但是页面访问不了

image

Antiforgery token validation failed. The antiforgery token could not be decrypted.
Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The antiforgery token could not be decrypted.
---> System.Security.Cryptography.CryptographicException: The payload was invalid. For more information go to http://aka.ms/dataprotectionwarning
at Microsoft.AspNetCore.DataProtection.Cng.CbcAuthenticatedEncryptor.DecryptImpl(Byte* pbCiphertext, UInt32 cbCiphertext, Byte* pbAdditionalAuthenticatedData, UInt32 cbAdditionalAuthenticatedData)
at Microsoft.AspNetCore.DataProtection.Cng.Internal.CngAuthenticatedEncryptorBase.Decrypt(ArraySegment1 ciphertext, ArraySegment1 additionalAuthenticatedData)
at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus& status)
at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[] protectedData)
at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgeryTokenSerializer.Deserialize(String serializedToken)
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgeryTokenSerializer.Deserialize(String serializedToken)
at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.DeserializeTokens(HttpContext httpContext, AntiforgeryTokenSet antiforgeryTokenSet, AntiforgeryToken& cookieToken, AntiforgeryToken& requestToken)
at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateTokens(HttpContext httpContext, AntiforgeryTokenSet antiforgeryTokenSet)
at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext)
at Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.ValidateAntiforgeryTokenAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context)

KeyNotFoundException: The given key 'Group1' was not present in the dictionary.

##错误描述:

KeyNotFoundException: The given key 'Group1' was not present in the dictionary.

##版本:

1.3.1

##问题分析原因:

调试代码在EasyAbp.Abp.SettingUi.Web.Pages.Components中发现取Group1对应属性值,而SettingInfo并未对Properties进行赋值,导致取值错误。默认是否应该调用WithProperty方法,设置Group1,Group2 的Value?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.