Browse Source

Merge pull request #10 from abpframework/master

merge
pull/847/head
Marcelo Mohr Maciel 7 years ago
committed by GitHub
parent
commit
86fcd94787
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo.Abp.AspNetCore.Mvc.Client.csproj
  2. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs
  3. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs
  4. 13
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClientExtensions.cs
  5. 70
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs
  6. 33
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs
  7. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs
  8. 11
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationSettingConfigurationDto.cs
  9. 88
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs
  10. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs
  11. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs
  12. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs
  13. 27
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs
  14. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownTagHelperService.cs
  15. 20
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/ModelExplorerExtensions.cs
  16. 20
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperContextExtensions.cs
  17. 41
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs
  18. 18
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperOutputExtensions.cs
  19. 19
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs
  20. 65
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs
  21. 20
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs
  22. 53
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs
  23. 44
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Grid/AbpColumnTagHelperService.cs
  24. 11
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Label/AbpLabelTagHelper.cs
  25. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Label/AbpLabelTagHelperService.cs
  26. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs
  27. 14
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Popover/AbpPopoverTagHelperService.cs
  28. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/ProgressBar/AbpProgressGroupTagHelperService.cs
  29. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabDropdownTagHelperService.cs
  30. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabLinkTagHelperService.cs
  31. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs
  32. 19
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js
  33. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs
  34. 37
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
  35. 13
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
  36. 43
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreCorrelationIdProvider.cs
  37. 58
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs
  38. 49
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AspNetCoreCorrelationIdProvider.cs
  39. 6
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs
  40. 2
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditLogInfo.cs
  41. 2
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingHelper.cs
  42. 12
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/NullCorrelationIdProvider.cs
  43. 4
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs
  44. 22
      framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
  45. 9
      framework/src/Volo.Abp.Core/Volo/Abp/Tracing/CorrelationIdOptions.cs
  46. 18
      framework/src/Volo.Abp.Core/Volo/Abp/Tracing/DefaultCorrelationIdProvider.cs
  47. 5
      framework/src/Volo.Abp.Core/Volo/Abp/Tracing/ICorrelationIdProvider.cs
  48. 1
      framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj
  49. 17
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/AbpDddApplicationModule.cs
  50. 2
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs
  51. 101
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs
  52. 3
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs
  53. 10
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderConfiguration.cs
  54. 10
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSenderConfiguration.cs
  55. 1
      framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj
  56. 9
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs
  57. 92
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
  58. 3
      framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelRemoteServiceHttpClientAuthenticator.cs
  59. 2
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageProviderExtensions.cs
  60. 1
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo.Abp.MultiTenancy.Abstractions.csproj
  61. 19
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AbpMultiTenancyAbstractionsModule.cs
  62. 45
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantSettingValueProvider.cs
  63. 1
      framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj
  64. 16
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/AbpSettingsModule.cs
  65. 14
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/DefaultValueSettingValueProvider.cs
  66. 12
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/GlobalSettingValueProvider.cs
  67. 2
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingDefinitionManager.cs
  68. 13
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingProvider.cs
  69. 15
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingStore.cs
  70. 8
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingValueProvider.cs
  71. 31
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs
  72. 31
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerExtensions.cs
  73. 34
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerSyncExtensions.cs
  74. 6
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingOptions.cs
  75. 101
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingProvider.cs
  76. 56
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingProviderExtensions.cs
  77. 5
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValue.cs
  78. 6
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProvider.cs
  79. 25
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/TenantSettingValueProvider.cs
  80. 30
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/UserSettingValueProvider.cs
  81. 1
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
  82. 53
      framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingManager_Tests.cs
  83. 30
      framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingProvider_Tests.cs
  84. 14
      framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/TestSettingValueProvider.cs
  85. 4
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml
  86. 2
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs
  87. 2
      modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/AuditLogConsts.cs
  88. 4
      modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs
  89. 1
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingtDbContextModelBuilderExtensions.cs
  90. 4
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityPermissionDefinitionProvider.cs
  91. 3
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityPermissions.cs
  92. 4
      modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs
  93. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj
  94. 33
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsFactory.cs
  95. 10
      modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityOptions_Tests.cs
  96. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbModule.cs
  97. 4
      modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs
  98. 4
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo.Abp.PermissionManagement.Domain.Shared.csproj
  99. 16
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/AbpPermissionManagementDomainSharedModule.cs
  100. 10
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/AbpPermissionManagementResource.cs

1
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo.Abp.AspNetCore.Mvc.Client.csproj

@ -17,6 +17,7 @@
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Contracts\Volo.Abp.AspNetCore.Mvc.Contracts.csproj" />
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.csproj" />
<ProjectReference Include="..\Volo.Abp.Http.Client\Volo.Abp.Http.Client.csproj" />
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
</ItemGroup>
</Project>

9
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs

@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Caching;
using Volo.Abp.Http.Client;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.Client
@ -8,7 +9,8 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
[DependsOn(
typeof(AbpHttpClientModule),
typeof(AbpAspNetCoreMvcContractsModule),
typeof(AbpCachingModule)
typeof(AbpCachingModule),
typeof(AbpLocalizationModule)
)]
public class AbpAspNetCoreMvcClientModule : AbpModule
{
@ -21,6 +23,11 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
RemoteServiceName,
asDefaultServices: false
);
Configure<AbpLocalizationOptions>(options =>
{
options.GlobalContributors.Add<RemoteLocalizationContributor>();
});
}
}
}

5
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs

@ -1,4 +1,5 @@
using System;
using System.Globalization;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
@ -45,7 +46,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
async () => await Proxy.Service.GetAsync(),
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(5)
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60) //TODO: Should be configurable. Default value should be higher (5 mins would be good).
}
);
@ -59,7 +60,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
protected virtual string CreateCacheKey()
{
return $"ApplicationConfiguration_{CurrentUser.Id?.ToString("N") ?? "Anonymous"}";
return $"ApplicationConfiguration_{CurrentUser.Id?.ToString("N") ?? "Anonymous"}_{CultureInfo.CurrentUICulture.Name}";
}
}
}

13
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClientExtensions.cs

@ -0,0 +1,13 @@
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.Threading;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
public static class CachedApplicationConfigurationClientExtensions
{
public static ApplicationConfigurationDto Get(this ICachedApplicationConfigurationClient client)
{
return AsyncHelper.RunSync(client.GetAsync);
}
}
}

70
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs

@ -0,0 +1,70 @@
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
public class RemoteLocalizationContributor : ILocalizationResourceContributor
{
private LocalizationResource _resource;
private ICachedApplicationConfigurationClient _applicationConfigurationClient;
private ILogger<RemoteLocalizationContributor> _logger;
public void Initialize(LocalizationResourceInitializationContext context)
{
_resource = context.Resource;
_applicationConfigurationClient = context.ServiceProvider.GetRequiredService<ICachedApplicationConfigurationClient>();
_logger = context.ServiceProvider.GetService<ILogger<RemoteLocalizationContributor>>()
?? NullLogger<RemoteLocalizationContributor>.Instance;
}
public LocalizedString GetOrNull(string cultureName, string name)
{
var resource = GetResourceOrNull();
if (resource == null)
{
return null;
}
var value = resource.GetOrDefault(name);
if (value == null)
{
return null;
}
return new LocalizedString(name, value);
}
public void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary)
{
var resource = GetResourceOrNull();
if (resource == null)
{
return;
}
foreach (var keyValue in resource)
{
dictionary[keyValue.Key] = new LocalizedString(keyValue.Key, keyValue.Value);
}
}
private Dictionary<string, string> GetResourceOrNull()
{
var resource = _applicationConfigurationClient
.Get()
.Localization.Values
.GetOrDefault(_resource.ResourceName);
if (resource == null)
{
_logger.LogWarning($"Could not find the localization resource {_resource.ResourceName} on the remote server!");
}
return resource;
}
}
}

33
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs

@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Settings;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
public class RemoteSettingProvider : ISettingProvider, ITransientDependency
{
protected ICachedApplicationConfigurationClient ConfigurationClient { get; }
public RemoteSettingProvider(ICachedApplicationConfigurationClient configurationClient)
{
ConfigurationClient = configurationClient;
}
public async Task<string> GetOrNullAsync(string name)
{
var configuration = await ConfigurationClient.GetAsync();
return configuration.Setting.Values.GetOrDefault(name);
}
public async Task<List<SettingValue>> GetAllAsync()
{
var configuration = await ConfigurationClient.GetAsync();
return configuration
.Setting.Values
.Select(s => new SettingValue(s.Key, s.Value))
.ToList();
}
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs

@ -9,6 +9,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
public ApplicationAuthConfigurationDto Auth { get; set; }
public ApplicationSettingConfigurationDto Setting { get; set; }
public CurrentUserDto CurrentUser { get; set; }
}
}

11
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationSettingConfigurationDto.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{
[Serializable]
public class ApplicationSettingConfigurationDto
{
public Dictionary<string, string> Values { get; set; }
}
}

88
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs

@ -56,93 +56,5 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers
Process(context, output);
return Task.CompletedTask;
}
protected virtual TagHelperOutput GetInnerTagHelper(TagHelperAttributeList attributeList, TagHelperContext context, TagHelper tagHelper, string tagName = "div", TagMode tagMode = TagMode.SelfClosing, bool runAsync = false)
{
var innerOutput = new TagHelperOutput(tagName, attributeList, (useCachedResult, encoder) => Task.Run<TagHelperContent>(() => new DefaultTagHelperContent()))
{
TagMode = tagMode
};
var innerContext = new TagHelperContext(attributeList, context.Items, Guid.NewGuid().ToString());
tagHelper.Init(context);
if (runAsync)
{
AsyncHelper.RunSync(() => tagHelper.ProcessAsync(innerContext, innerOutput));
}
else
{
tagHelper.Process(innerContext, innerOutput);
}
return innerOutput;
}
protected virtual string RenderTagHelper(TagHelperAttributeList attributeList, TagHelperContext context, TagHelper tagHelper, HtmlEncoder htmlEncoder, string tagName = "div", TagMode tagMode = TagMode.SelfClosing, bool runAsync = false)
{
var innerOutput = GetInnerTagHelper(attributeList, context, tagHelper, tagName, tagMode, runAsync);
return RenderTagHelperOutput(innerOutput, htmlEncoder);
}
protected virtual string RenderTagHelperOutput(TagHelperOutput output, HtmlEncoder htmlEncoder)
{
using (var writer = new StringWriter())
{
output.WriteTo(writer, htmlEncoder);
return writer.ToString();
}
}
protected virtual T GetAttribute<T>(ModelExplorer property) where T : Attribute
{
return property?.Metadata?.ContainerType?.GetTypeInfo()?.GetProperty(property.Metadata.PropertyName)?.GetCustomAttribute<T>();
}
protected virtual List<FormGroupItem> GetFormGroupContentsList(TagHelperContext context, out bool surpress)
{
var items = GetValueFromContext<List<FormGroupItem>>(context, FormGroupContents);
surpress = items != null;
return items ?? new List<FormGroupItem>();
}
protected virtual T GetValueFromContext<T>(TagHelperContext context, string key)
{
if (!context.Items.ContainsKey(key))
{
return default(T);
}
return (T)context.Items[key];
}
protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag)
{
var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id");
return idAttr != null ? "for=\"" + idAttr.Value + "\"" : "";
}
protected virtual int GetInputOrder(ModelExplorer explorer)
{
return GetAttribute<DisplayOrder>(explorer)?.Number ?? DisplayOrder.Default;
}
protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool surpress)
{
var list = GetFormGroupContentsList(context, out surpress);
if (list != null && !list.Any(igc => igc.HtmlContent.Contains("id=\"" + propertyName.Replace('.', '_') + "\"")))
{
list.Add(new FormGroupItem
{
HtmlContent = html,
Order = order
});
}
}
}
}

5
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs

@ -2,6 +2,7 @@
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb
{
@ -20,13 +21,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb
output.Attributes.AddClass("breadcrumb-item");
output.Attributes.AddClass(AbpBreadcrumbItemActivePlaceholder);
var list = GetValueFromContext<List<BreadcrumbItem>>(context, BreadcrumbItemsContent);
var list = context.GetValue<List<BreadcrumbItem>>(BreadcrumbItemsContent);
output.Content.SetHtmlContent(GetInnerHtml(context, output));
list.Add(new BreadcrumbItem
{
Html = RenderTagHelperOutput(output, _encoder),
Html = output.Render(_encoder),
Active = TagHelper.Active
});

5
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs

@ -3,6 +3,7 @@ using System.Text;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel
{
@ -32,9 +33,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel
private void AddToContext(TagHelperContext context, TagHelperOutput output)
{
var getOutputAsHtml = RenderTagHelperOutput(output, _encoder);
var getOutputAsHtml = output.Render(_encoder);
var itemList = GetValueFromContext<List<CarouselItem>>(context, CarouselItemsContent);
var itemList = context.GetValue<List<CarouselItem>>(CarouselItemsContent);
itemList.Add(new CarouselItem(getOutputAsHtml, TagHelper.Active ?? false));
}

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse
{
@ -15,7 +16,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse
var html = GetAccordionHeaderItem(context, output) + GetAccordionContentItem(context, output, innerContent);
var tabHeaderItems = GetValueFromContext<List<string>>(context, AccordionItems);
var tabHeaderItems = context.GetValue<List<string>>(AccordionItems);
tabHeaderItems.Add(html);

27
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs

@ -1,10 +1,12 @@
using System;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
{
@ -22,22 +24,25 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
_serviceProvider = serviceProvider;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var buttonsAsHtml = GetButtonsAsHtml(context, output);
var content = await output.GetChildContentAsync();
var buttonsAsHtml = GetButtonsAsHtml(context, output, content);
output.PreElement.SetHtmlContent(buttonsAsHtml);
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
output.Content.SetContent("");
output.Attributes.Clear();
}
protected virtual string GetButtonsAsHtml(TagHelperContext context, TagHelperOutput output)
protected virtual string GetButtonsAsHtml(TagHelperContext context, TagHelperOutput output, TagHelperContent content)
{
var buttonBuilder = new StringBuilder("");
var mainButton = GetMainButton(context, output);
var mainButton = GetMainButton(context, output, content);
buttonBuilder.AppendLine(mainButton);
@ -51,10 +56,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
return buttonBuilder.ToString();
}
protected virtual string GetMainButton(TagHelperContext context, TagHelperOutput output)
protected virtual string GetMainButton(TagHelperContext context, TagHelperOutput output, TagHelperContent content)
{
var abpButtonTagHelper = _serviceProvider.GetRequiredService<AbpButtonTagHelper>();
abpButtonTagHelper.Icon = TagHelper.Icon;
abpButtonTagHelper.Text = TagHelper.Text;
abpButtonTagHelper.IconType = TagHelper.IconType;
@ -62,15 +67,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
abpButtonTagHelper.ButtonType = TagHelper.ButtonType;
var attributes = GetAttributesForMainButton(context, output);
var buttonTag = GetInnerTagHelper(attributes, context, abpButtonTagHelper, "button", TagMode.StartTagAndEndTag);
var buttonTag = abpButtonTagHelper.ProcessAndGetOutput(attributes, context, "button", TagMode.StartTagAndEndTag);
buttonTag.PreContent.SetHtmlContent(content.GetContent());
if ((TagHelper.NavLink ?? false) || (TagHelper.Link ?? false))
{
var linkTag = ConvertButtonToLink(buttonTag);
return RenderTagHelperOutput(linkTag, _htmlEncoder);
return linkTag.Render(_htmlEncoder);
}
return RenderTagHelperOutput(buttonTag, _htmlEncoder);
return buttonTag.Render(_htmlEncoder);
}
protected virtual string GetSplitButton(TagHelperContext context, TagHelperOutput output)
@ -81,7 +88,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
abpButtonTagHelper.ButtonType = TagHelper.ButtonType;
var attributes = GetAttributesForSplitButton(context, output);
return RenderTagHelper(attributes, context, abpButtonTagHelper, _htmlEncoder, "button", TagMode.StartTagAndEndTag);
return abpButtonTagHelper.Render(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag);
}
protected virtual TagHelperAttributeList GetAttributesForMainButton(TagHelperContext context, TagHelperOutput output)

1
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownTagHelperService.cs

@ -8,6 +8,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
output.Attributes.AddClass("dropdown");
output.Attributes.AddClass("btn-group");
SetDirection(context, output);

20
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/ModelExplorerExtensions.cs

@ -0,0 +1,20 @@
using System;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions
{
public static class ModelExplorerExtensions
{
public static T GetAttribute<T>(this ModelExplorer property) where T : Attribute
{
return property?.Metadata?.ContainerType?.GetTypeInfo()?.GetProperty(property.Metadata.PropertyName)?.GetCustomAttribute<T>();
}
public static int GetDisplayOrder(this ModelExplorer explorer)
{
return GetAttribute<DisplayOrder>(explorer)?.Number ?? DisplayOrder.Default;
}
}
}

20
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperContextExtensions.cs

@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions
{
public static class TagHelperContextExtensions
{
public static T GetValue<T>(this TagHelperContext context, string key)
{
if (!context.Items.ContainsKey(key))
{
return default(T);
}
return (T)context.Items[key];
}
}
}

41
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs

@ -0,0 +1,41 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Text.Encodings.Web;
using Volo.Abp.Threading;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions
{
public static class TagHelperExtensions
{
public static TagHelperOutput ProcessAndGetOutput(this TagHelper tagHelper, TagHelperAttributeList attributeList, TagHelperContext context, string tagName = "div", TagMode tagMode = TagMode.SelfClosing, bool runAsync = false)
{
var innerOutput = new TagHelperOutput(tagName, attributeList, (useCachedResult, encoder) => Task.Run<TagHelperContent>(() => new DefaultTagHelperContent()))
{
TagMode = tagMode
};
var innerContext = new TagHelperContext(attributeList, context.Items, Guid.NewGuid().ToString());
tagHelper.Init(context);
if (runAsync)
{
AsyncHelper.RunSync(() => tagHelper.ProcessAsync(innerContext, innerOutput));
}
else
{
tagHelper.Process(innerContext, innerOutput);
}
return innerOutput;
}
public static string Render(this TagHelper tagHelper, TagHelperAttributeList attributeList, TagHelperContext context, HtmlEncoder htmlEncoder, string tagName = "div", TagMode tagMode = TagMode.SelfClosing, bool runAsync = false)
{
var innerOutput = tagHelper.ProcessAndGetOutput(attributeList, context, tagName, tagMode, runAsync);
return innerOutput.Render(htmlEncoder);
}
}
}

18
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperOutputExtensions.cs

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.IO;
using System.Text.Encodings.Web;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions
{
public static class TagHelperOutputExtensions
{
public static string Render(this TagHelperOutput output, HtmlEncoder htmlEncoder)
{
using (var writer = new StringWriter())
{
output.WriteTo(writer, htmlEncoder);
return writer.ToString();
}
}
}
}

19
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs

@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
@ -66,7 +67,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
ViewContext = TagHelper.ViewContext
};
var formTagOutput = GetInnerTagHelper(output.Attributes, context, formTagHelper, "form", TagMode.StartTagAndEndTag);
var formTagOutput = formTagHelper.ProcessAndGetOutput(output.Attributes, context, "form", TagMode.StartTagAndEndTag);
await formTagOutput.GetChildContentAsync();
@ -146,7 +147,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
var abpSelectTagHelper = GetSelectGroupTagHelper(context, output, model);
RenderTagHelper(new TagHelperAttributeList(), context, abpSelectTagHelper, _htmlEncoder, "div", TagMode.StartTagAndEndTag);
abpSelectTagHelper.Render(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag);
}
protected virtual AbpTagHelper GetSelectGroupTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model)
@ -156,7 +157,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
GetSelectTagHelper(model);
}
private AbpTagHelper GetSelectTagHelper(ModelExpression model)
protected virtual AbpTagHelper GetSelectTagHelper(ModelExpression model)
{
var abpSelectTagHelper = _serviceProvider.GetRequiredService<AbpSelectTagHelper>();
abpSelectTagHelper.AspFor = model;
@ -165,9 +166,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return abpSelectTagHelper;
}
private AbpTagHelper GetAbpRadioInputTagHelper(ModelExpression model)
protected virtual AbpTagHelper GetAbpRadioInputTagHelper(ModelExpression model)
{
var radioButtonAttribute = GetAttribute<AbpRadioButton>(model.ModelExplorer);
var radioButtonAttribute = model.ModelExplorer.GetAttribute<AbpRadioButton>();
var abpRadioInputTagHelper = _serviceProvider.GetRequiredService<AbpRadioInputTagHelper>();
abpRadioInputTagHelper.AspFor = model;
abpRadioInputTagHelper.AspItems = null;
@ -184,7 +185,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
abpButtonTagHelper.Text = "Submit";
abpButtonTagHelper.ButtonType = AbpButtonType.Primary;
return RenderTagHelper(attributes, context, abpButtonTagHelper, _htmlEncoder, "button", TagMode.StartTagAndEndTag);
return abpButtonTagHelper.Render(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag);
}
protected virtual void ProcessInputGroup(TagHelperContext context, TagHelperOutput output, ModelExpression model)
@ -194,7 +195,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
abpInputTagHelper.ViewContext = TagHelper.ViewContext;
abpInputTagHelper.DisplayRequiredSymbol = TagHelper.RequiredSymbols ?? true;
RenderTagHelper(new TagHelperAttributeList(), context, abpInputTagHelper, _htmlEncoder, "div", TagMode.StartTagAndEndTag);
abpInputTagHelper.Render(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag);
}
protected virtual List<ModelExpression> GetModels(TagHelperContext context, TagHelperOutput output)
@ -280,12 +281,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual bool AreSelectItemsProvided(ModelExplorer explorer)
{
return GetAttribute<SelectItems>(explorer) != null;
return explorer.GetAttribute<SelectItems>() != null;
}
protected virtual bool IsRadioGroup(ModelExplorer explorer)
{
return GetAttribute<AbpRadioButton>(explorer) != null;
return explorer.GetAttribute<AbpRadioButton>() != null;
}
}
}

65
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Encodings.Web;
@ -6,6 +7,7 @@ using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
@ -26,7 +28,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
var innerHtml = GetFormInputGroupAsHtml(context, output, out var isCheckbox);
var order = GetInputOrder(TagHelper.AspFor.ModelExplorer);
var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder();
AddGroupToFormGroupContents(
context,
@ -45,7 +47,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
output.TagMode = TagMode.StartTagAndEndTag;
output.TagName = "div";
LeaveOnlyGroupAttributes(context, output);
output.Attributes.AddClass(isCheckbox ? "form-check" : "form-group");
output.Attributes.AddClass(isCheckbox ? "custom-checkbox" : "form-group");
output.Attributes.AddClass(isCheckbox ? "custom-control" : "");
output.Attributes.AddClass(isCheckbox ? "mb-2" : "");
output.Content.SetHtmlContent(output.Content.GetContent() + innerHtml);
}
@ -54,8 +57,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual string GetFormInputGroupAsHtml(TagHelperContext context, TagHelperOutput output, out bool isCheckbox)
{
var inputTag = GetInputTagHelperOutput(context, output, out isCheckbox);
var inputHtml = RenderTagHelperOutput(inputTag, _encoder);
var inputHtml = inputTag.Render(_encoder);
var label = GetLabelAsHtml(context, output, inputTag, isCheckbox);
var info = GetInfoAsHtml(context, output, inputTag, isCheckbox);
var validation = isCheckbox ? "" : GetValidationAsHtml(context, output, inputTag);
@ -78,7 +81,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
var attributeList = new TagHelperAttributeList { { "class", "text-danger" } };
return RenderTagHelper(attributeList, context, validationMessageTagHelper, _encoder, "span", TagMode.StartTagAndEndTag, true);
return validationMessageTagHelper.Render(attributeList, context, _encoder, "span", TagMode.StartTagAndEndTag, true);
}
protected virtual string GetContent(TagHelperContext context, TagHelperOutput output, string label, string inputHtml, string validation, string infoHtml, bool isCheckbox)
@ -92,14 +95,14 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual string SurroundInnerHtmlAndGet(TagHelperContext context, TagHelperOutput output, string innerHtml, bool isCheckbox)
{
return "<div class=\"" + (isCheckbox ? "form-check" : "form-group") + "\">" +
return "<div class=\"" + (isCheckbox ? "custom-checkbox custom-control" : "form-group") + "\">" +
Environment.NewLine + innerHtml + Environment.NewLine +
"</div>";
}
protected virtual TagHelper GetInputTagHelper(TagHelperContext context, TagHelperOutput output)
{
var textAreaAttribute = GetAttribute<TextArea>(TagHelper.AspFor.ModelExplorer);
var textAreaAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<TextArea>();
if (textAreaAttribute != null)
{
@ -121,7 +124,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
var tagHelper = GetInputTagHelper(context, output);
var inputTagHelperOutput = GetInnerTagHelper(GetInputAttributes(context, output), context, tagHelper, "input");
var inputTagHelperOutput = tagHelper.ProcessAndGetOutput(GetInputAttributes(context, output), context, "input");
ConvertToTextAreaIfTextArea(inputTagHelperOutput);
AddDisabledAttribute(inputTagHelperOutput);
@ -141,7 +144,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
if (isCheckbox)
{
className = "form-check-input";
className = "custom-control-input";
}
inputTagHelperOutput.Attributes.AddClass(className + " " + GetSize(context, output));
@ -158,7 +161,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual void AddDisabledAttribute(TagHelperOutput inputTagHelperOutput)
{
if (inputTagHelperOutput.Attributes.ContainsName("disabled") == false &&
(TagHelper.IsDisabled || GetAttribute<DisabledInput>(TagHelper.AspFor.ModelExplorer) != null))
(TagHelper.IsDisabled || TagHelper.AspFor.ModelExplorer.GetAttribute<DisabledInput>() != null))
{
inputTagHelperOutput.Attributes.Add("disabled", "");
}
@ -167,7 +170,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual void AddReadOnlyAttribute(TagHelperOutput inputTagHelperOutput)
{
if (inputTagHelperOutput.Attributes.ContainsName("readonly") == false &&
(TagHelper.IsReadonly != false || GetAttribute<ReadOnlyInput>(TagHelper.AspFor.ModelExplorer) != null))
(TagHelper.IsReadonly != false || TagHelper.AspFor.ModelExplorer.GetAttribute<ReadOnlyInput>() != null))
{
inputTagHelperOutput.Attributes.Add("readonly", "");
}
@ -180,7 +183,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return;
}
var attribute = GetAttribute<Placeholder>(TagHelper.AspFor.ModelExplorer);
var attribute = TagHelper.AspFor.ModelExplorer.GetAttribute<Placeholder>();
if (attribute != null)
{
@ -192,7 +195,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual void AddInfoTextId(TagHelperOutput inputTagHelperOutput)
{
if (GetAttribute<InputInfoText>(TagHelper.AspFor.ModelExplorer) == null)
if (TagHelper.AspFor.ModelExplorer.GetAttribute<InputInfoText>() == null)
{
return;
}
@ -226,7 +229,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return GetLabelAsHtmlUsingTagHelper(context, output, isCheckbox) + GetRequiredSymbol(context, output, inputTag);
}
var checkboxClass = isCheckbox ? "class=\"form-check-label\" " : "";
var checkboxClass = isCheckbox ? "class=\"custom-control-label\" " : "";
return "<label " + checkboxClass + GetIdAttributeAsString(inputTag) + ">"
+ TagHelper.Label +
@ -240,7 +243,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return "";
}
return GetAttribute<RequiredAttribute>(TagHelper.AspFor.ModelExplorer) != null ? "<span> * </span>":"";
return TagHelper.AspFor.ModelExplorer.GetAttribute<RequiredAttribute>() != null ? "<span> * </span>":"";
}
protected virtual string GetInfoAsHtml(TagHelperContext context, TagHelperOutput output, TagHelperOutput inputTag, bool isCheckbox)
@ -263,7 +266,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
}
else
{
var infoAttribute = GetAttribute<InputInfoText>(TagHelper.AspFor.ModelExplorer);
var infoAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<InputInfoText>();
if (infoAttribute != null)
{
text = infoAttribute.Text;
@ -294,15 +297,15 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
if (isCheckbox)
{
attributeList.AddClass("form-check-label");
attributeList.AddClass("custom-control-label");
}
return RenderTagHelper(attributeList, context, labelTagHelper, _encoder, "label", TagMode.StartTagAndEndTag, true);
return labelTagHelper.Render(attributeList, context, _encoder, "label", TagMode.StartTagAndEndTag, true);
}
protected virtual void ConvertToTextAreaIfTextArea(TagHelperOutput tagHelperOutput)
{
var textAreaAttribute = GetAttribute<TextArea>(TagHelper.AspFor.ModelExplorer);
var textAreaAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<TextArea>();
if (textAreaAttribute == null)
{
@ -354,7 +357,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual string GetSize(TagHelperContext context, TagHelperOutput output)
{
var attribute = GetAttribute<FormControlSize>(TagHelper.AspFor.ModelExplorer);
var attribute = TagHelper.AspFor.ModelExplorer.GetAttribute<FormControlSize>();
if (attribute != null)
{
@ -378,5 +381,27 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
return inputTag.Attributes.Any(a => a.Name.ToLowerInvariant() == "type" && a.Value.ToString().ToLowerInvariant() == "hidden");
}
protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag)
{
var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id");
return idAttr != null ? "for=\"" + idAttr.Value + "\"" : "";
}
protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool surpress)
{
var list = context.GetValue<List<FormGroupItem>>(FormGroupContents) ?? new List<FormGroupItem>();
surpress = list != null;
if (list != null && !list.Any(igc => igc.HtmlContent.Contains("id=\"" + propertyName.Replace('.', '_') + "\"")))
{
list.Add(new FormGroupItem
{
HtmlContent = html,
Order = order
});
}
}
}
}

20
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
@ -24,7 +25,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
var selectItems = GetSelectItems(context,output);
SetSelectedValue(context, output, selectItems);
var order = GetInputOrder(TagHelper.AspFor.ModelExplorer);
var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder();
var html = GetHtml(context, output, selectItems);
@ -78,7 +79,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return GetSelectItemsFromEnum(context, output, TagHelper.AspFor.ModelExplorer);
}
var selectItemsAttribute = GetAttribute<SelectItems>(TagHelper.AspFor.ModelExplorer);
var selectItemsAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<SelectItems>();
if (selectItemsAttribute != null)
{
return GetSelectItemsFromAttribute(selectItemsAttribute, TagHelper.AspFor.ModelExplorer);
@ -155,5 +156,20 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return TagHelper.AspFor.ModelExplorer.Model?.ToString();
}
protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool surpress)
{
var list = context.GetValue<List<FormGroupItem>>(FormGroupContents) ?? new List<FormGroupItem>();
surpress = list != null;
if (list != null && !list.Any(igc => igc.HtmlContent.Contains("id=\"" + propertyName.Replace('.', '_') + "\"")))
{
list.Add(new FormGroupItem
{
HtmlContent = html,
Order = order
});
}
}
}
}

53
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs

@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
@ -30,7 +31,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
var innerHtml = GetFormInputGroupAsHtml(context, output);
var order = GetInputOrder(TagHelper.AspFor.ModelExplorer);
var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder();
AddGroupToFormGroupContents(context, TagHelper.AspFor.Name, SurroundInnerHtmlAndGet(context, output, innerHtml), order, out var surpress);
@ -51,7 +52,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual string GetFormInputGroupAsHtml(TagHelperContext context, TagHelperOutput output)
{
var selectTag = GetSelectTag(context, output);
var selectAsHtml = RenderTagHelperOutput(selectTag, _encoder);
var selectAsHtml = selectTag.Render(_encoder);
var label = GetLabelAsHtml(context, output, selectTag);
var validation = GetValidationAsHtml(context, output, selectTag);
var infoText = GetInfoAsHtml(context, output, selectTag);
@ -73,7 +74,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
ViewContext = TagHelper.ViewContext
};
var selectTagHelperOutput = GetInnerTagHelper(GetInputAttributes(context, output), context, selectTagHelper, "select", TagMode.StartTagAndEndTag);
var selectTagHelperOutput = selectTagHelper.ProcessAndGetOutput(GetInputAttributes(context, output), context, "select", TagMode.StartTagAndEndTag);
selectTagHelperOutput.Attributes.AddClass("form-control");
selectTagHelperOutput.Attributes.AddClass(GetSize(context, output));
@ -85,7 +86,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual void AddDisabledAttribute(TagHelperOutput inputTagHelperOutput)
{
var disabledAttribute = GetAttribute<DisabledInput>(TagHelper.AspFor.ModelExplorer);
var disabledAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<DisabledInput>();
if (disabledAttribute != null && !inputTagHelperOutput.Attributes.ContainsName("disabled"))
{
@ -105,7 +106,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return GetSelectItemsFromEnum(context, output, TagHelper.AspFor.ModelExplorer);
}
var selectItemsAttribute = GetAttribute<SelectItems>(TagHelper.AspFor.ModelExplorer);
var selectItemsAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<SelectItems>();
if (selectItemsAttribute != null)
{
return GetSelectItemsFromAttribute(selectItemsAttribute, TagHelper.AspFor.ModelExplorer);
@ -132,12 +133,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return "";
}
return GetAttribute<RequiredAttribute>(TagHelper.AspFor.ModelExplorer) != null ? "<span> * </span>" : "";
return TagHelper.AspFor.ModelExplorer.GetAttribute<RequiredAttribute>() != null ? "<span> * </span>" : "";
}
protected virtual void AddInfoTextId(TagHelperOutput inputTagHelperOutput)
{
if (GetAttribute<InputInfoText>(TagHelper.AspFor.ModelExplorer) == null)
if (TagHelper.AspFor.ModelExplorer.GetAttribute<InputInfoText>() == null)
{
return;
}
@ -164,7 +165,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
}
else
{
var infoAttribute = GetAttribute<InputInfoText>(TagHelper.AspFor.ModelExplorer);
var infoAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<InputInfoText>();
if (infoAttribute != null)
{
text = infoAttribute.Text;
@ -227,7 +228,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
ViewContext = TagHelper.ViewContext
};
return RenderTagHelper(new TagHelperAttributeList(), context, labelTagHelper, _encoder, "label", TagMode.StartTagAndEndTag, true);
return labelTagHelper.Render(new TagHelperAttributeList(), context, _encoder, "label", TagMode.StartTagAndEndTag, true);
}
protected virtual string GetValidationAsHtml(TagHelperContext context, TagHelperOutput output, TagHelperOutput inputTag)
@ -240,12 +241,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
var attributeList = new TagHelperAttributeList { { "class", "text-danger" } };
return RenderTagHelper(attributeList, context, validationMessageTagHelper, _encoder, "span", TagMode.StartTagAndEndTag, true);
return validationMessageTagHelper.Render(attributeList, context, _encoder, "span", TagMode.StartTagAndEndTag, true);
}
protected virtual string GetSize(TagHelperContext context, TagHelperOutput output)
{
var attribute = GetAttribute<FormControlSize>(TagHelper.AspFor.ModelExplorer);
var attribute = TagHelper.AspFor.ModelExplorer.GetAttribute<FormControlSize>();
if (attribute != null)
{
@ -255,11 +256,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
switch (TagHelper.Size)
{
case AbpFormControlSize.Small:
return "form-control-sm";
return "custom-select-sm";
case AbpFormControlSize.Medium:
return "form-control-md";
return "custom-select-md";
case AbpFormControlSize.Large:
return "form-control-lg";
return "custom-select-lg";
}
return "";
@ -277,6 +278,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
attrList.Add(tagHelperAttribute);
}
attrList.AddClass("custom-select");
return attrList;
}
@ -294,5 +297,27 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
output.Attributes.Add(newAttritube);
}
}
protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag)
{
var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id");
return idAttr != null ? "for=\"" + idAttr.Value + "\"" : "";
}
protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool surpress)
{
var list = context.GetValue<List<FormGroupItem>>(FormGroupContents) ?? new List<FormGroupItem>();
surpress = list != null;
if (list != null && !list.Any(igc => igc.HtmlContent.Contains("id=\"" + propertyName.Replace('.', '_') + "\"")))
{
list.Add(new FormGroupItem
{
HtmlContent = html,
Order = order
});
}
}
}
}

44
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Grid/AbpColumnTagHelperService.cs

@ -10,23 +10,31 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid
output.TagName = "div";
output.Attributes.AddClass("col");
ProcessSizeClass(output, TagHelper.Size, "");
ProcessSizeClass(output, TagHelper.SizeSm, "-sm");
ProcessSizeClass(output, TagHelper.SizeMd, "-md");
ProcessSizeClass(output, TagHelper.SizeLg, "-lg");
ProcessSizeClass(output, TagHelper.SizeXl, "-xl");
ProcessOffsetClass(output, TagHelper.Offset, "");
ProcessOffsetClass(output, TagHelper.OffsetSm, "-sm");
ProcessOffsetClass(output, TagHelper.OffsetMd, "-md");
ProcessOffsetClass(output, TagHelper.OffsetLg, "-lg");
ProcessOffsetClass(output, TagHelper.OffsetXl, "-xl");
ProcessColumnOrder(output);
ProcessVerticalAlign(output);
ProcessSizeClasses(context, output);
ProcessOffsetClasses(context, output);
ProcessColumnOrder(context, output);
ProcessVerticalAlign(context, output);
}
protected virtual void ProcessSizeClass(TagHelperOutput output, ColumnSize size, string breakpoint)
protected virtual void ProcessSizeClasses(TagHelperContext context, TagHelperOutput output)
{
ProcessSizeClass(context, output, TagHelper.Size, "");
ProcessSizeClass(context, output, TagHelper.SizeSm, "-sm");
ProcessSizeClass(context, output, TagHelper.SizeMd, "-md");
ProcessSizeClass(context, output, TagHelper.SizeLg, "-lg");
ProcessSizeClass(context, output, TagHelper.SizeXl, "-xl");
}
protected virtual void ProcessOffsetClasses(TagHelperContext context, TagHelperOutput output)
{
ProcessOffsetClass(context, output, TagHelper.Offset, "");
ProcessOffsetClass(context, output, TagHelper.OffsetSm, "-sm");
ProcessOffsetClass(context, output, TagHelper.OffsetMd, "-md");
ProcessOffsetClass(context, output, TagHelper.OffsetLg, "-lg");
ProcessOffsetClass(context, output, TagHelper.OffsetXl, "-xl");
}
protected virtual void ProcessSizeClass(TagHelperContext context, TagHelperOutput output, ColumnSize size, string breakpoint)
{
if (size == ColumnSize.Undefined)
{
@ -47,7 +55,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid
output.Attributes.AddClass(classString);
}
protected virtual void ProcessOffsetClass(TagHelperOutput output, ColumnSize size, string breakpoint)
protected virtual void ProcessOffsetClass(TagHelperContext context, TagHelperOutput output, ColumnSize size, string breakpoint)
{
if (size == ColumnSize.Undefined)
{
@ -68,7 +76,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid
output.Attributes.AddClass(classString);
}
protected virtual void ProcessVerticalAlign(TagHelperOutput output)
protected virtual void ProcessVerticalAlign(TagHelperContext context, TagHelperOutput output)
{
if (TagHelper.VAlign == VerticalAlign.Default)
{
@ -78,7 +86,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid
output.Attributes.AddClass("align-self-" + TagHelper.VAlign.ToString().ToLowerInvariant());
}
protected virtual void ProcessColumnOrder(TagHelperOutput output)
protected virtual void ProcessColumnOrder(TagHelperContext context, TagHelperOutput output)
{
if (TagHelper.ColumnOrder == ColumnOrder.Undefined)
{

11
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Label/AbpLabelTagHelper.cs

@ -1,11 +0,0 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Label
{
public class AbpLabelTagHelper : AbpTagHelper<AbpLabelTagHelper, AbpLabelTagHelperService>
{
public AbpLabelTagHelper(AbpLabelTagHelperService tagHelperService)
: base(tagHelperService)
{
}
}
}

12
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Label/AbpLabelTagHelperService.cs

@ -1,12 +0,0 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Label
{
public class AbpLabelTagHelperService : AbpTagHelperService<AbpLabelTagHelper>
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
//TODO: fill
}
}
}

5
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs

@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
{
@ -121,11 +122,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
var anchorTagHelper = GetAnchorTagHelper(currentPage, out var attributeList);
var tagHelperOutput = GetInnerTagHelper(attributeList, context, anchorTagHelper, "a", TagMode.StartTagAndEndTag);
var tagHelperOutput = anchorTagHelper.ProcessAndGetOutput(attributeList, context, "a", TagMode.StartTagAndEndTag);
tagHelperOutput.Content.SetHtmlContent(localizer[localizationKey]);
var renderedHtml = RenderTagHelperOutput(tagHelperOutput, _encoder);
var renderedHtml = tagHelperOutput.Render(_encoder);
return renderedHtml;
}

14
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Popover/AbpPopoverTagHelperService.cs

@ -7,7 +7,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Popover
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (!TagHelper.Disabled??true)
if (!TagHelper.Disabled ?? true)
{
SetDataToggle(context, output);
SetDataPlacement(context, output);
@ -16,21 +16,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Popover
}
else
{
SetDisabled(context,output);
SetDisabled(context, output);
}
}
protected virtual void SetDisabled(TagHelperContext context, TagHelperOutput output)
{
var triggerAsHtml = TagHelper.Dismissible ?? false ? "datatrigger=\"focus\" " : "";
var dataPlacementAsHtml = "data-placement=\"" +GetDirectory().ToString().ToLowerInvariant() + "\" ";
var dataPlacementAsHtml = "data-placement=\"" + GetDirectory().ToString().ToLowerInvariant() + "\" ";
var titleAttribute = output.Attributes.FirstOrDefault(at => at.Name == "title");
var titleAsHtml = titleAttribute == null? "":"title=\""+ titleAttribute.Value +"\" ";
var preElementHtml = "<span class=\"d-inline-block\" "+ titleAsHtml + triggerAsHtml + dataPlacementAsHtml + "data-toggle=\"popover\" data-content=\"" +GetDataContent()+"\">";
var titleAsHtml = titleAttribute == null ? "" : "title=\"" + titleAttribute.Value + "\" ";
var preElementHtml = "<span class=\"d-inline-block\" " + titleAsHtml + triggerAsHtml + dataPlacementAsHtml + "data-toggle=\"popover\" data-content=\"" + GetDataContent() + "\">";
var postElementHtml = "</span>";
output.PreElement.SetHtmlContent(preElementHtml);

1
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/ProgressBar/AbpProgressGroupTagHelperService.cs

@ -10,6 +10,5 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.ProgressBar
output.Attributes.AddClass("progress");
output.TagName = "div";
}
}
}

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabDropdownTagHelperService.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
{
@ -17,7 +18,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
await output.GetChildContentAsync();
var tabHeader = GetTabHeaderItem(context, output);
var tabHeaderItems = GetValueFromContext<List<TabItem>>(context, TabItems);
var tabHeaderItems = context.GetValue<List<TabItem>>(TabItems);
tabHeaderItems.Add(new TabItem(tabHeader, "", false, TagHelper.Name, "", true));

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabLinkTagHelperService.cs

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
{
@ -12,7 +13,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
var tabHeader = GetTabHeaderItem(context, output);
var tabHeaderItems = GetValueFromContext<List<TabItem>>(context, TabItems);
var tabHeaderItems = context.GetValue<List<TabItem>>(TabItems);
tabHeaderItems.Add(new TabItem(tabHeader, "", false, TagHelper.Name, TagHelper.ParentDropdownName, false));

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
{
@ -14,7 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
var tabHeader = GetTabHeaderItem(context, output);
var tabContent = GetTabContentItem(innerContent.GetContent());
var tabHeaderItems = GetValueFromContext<List<TabItem>>(context, TabItems);
var tabHeaderItems = context.GetValue<List<TabItem>>(TabItems);
var active = TagHelper.Active ?? false;

19
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js

@ -52,7 +52,7 @@
*************************************************************************/
var localize = function (key) {
return abp.localization.getResource('AbpUi')(key);
}
};
var recordActions = function () {
if (!$.fn.dataTableExt) {
@ -69,7 +69,7 @@
} else {
return visibilityField;
}
}
};
var _createDropdownItem = function (record, fieldItem) {
var $li = $('<li/>');
@ -83,7 +83,7 @@
$a.append($("<i>").addClass("fa fa-" + fieldItem.icon + " mr-1"));
} else if (fieldItem.iconClass) {
$a.append($("<i>").addClass(fieldItem.iconClass + " mr-1"));
}
}
$a.append(fieldItem.text);
}
@ -109,7 +109,7 @@
$a.appendTo($li);
return $li;
}
};
var _createButtonDropdown = function (record, field) {
var $container = $('<div/>')
@ -200,11 +200,11 @@
}
throw "DTE#1: Cannot create row action. Either set element or items fields!";
}
};
var hideColumnWithoutRedraw = function (tableInstance, colIndex) {
tableInstance.fnSetColumnVis(colIndex, false, false);
}
};
var hideEmptyColumn = function (cellContent, tableInstance, colIndex) {
if (cellContent == "") {
@ -307,8 +307,8 @@
});
});
}
}
}
};
};
}();
/************************************************************************
@ -338,9 +338,10 @@
}
}
configuration.dom = '<"dataTable_filters"f>rt<"row dataTable_footer"<"col-auto"l><"col-auto"i><"col"p>>';
return configuration;
}
};
}();

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs

@ -60,7 +60,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.RazorPages
public ICurrentTenant CurrentTenant { get; set; }
public ISettingManager SettingManager { get; set; }
public ISettingProvider SettingProvider { get; set; }
public IModelStateValidator ModelValidator { get; set; }

37
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs

@ -4,10 +4,12 @@ using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Authorization;
using Volo.Abp.Localization;
using Volo.Abp.Settings;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
@ -19,18 +21,24 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
private readonly IAbpAuthorizationPolicyProvider _abpAuthorizationPolicyProvider;
private readonly IAuthorizationService _authorizationService;
private readonly ICurrentUser _currentUser;
private readonly ISettingProvider _settingProvider;
private readonly ISettingDefinitionManager _settingDefinitionManager;
public AbpApplicationConfigurationAppService(
IOptions<AbpLocalizationOptions> localizationOptions,
IServiceProvider serviceProvider,
IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider,
IAuthorizationService authorizationService,
ICurrentUser currentUser)
ICurrentUser currentUser,
ISettingProvider settingProvider,
SettingDefinitionManager settingDefinitionManager)
{
_serviceProvider = serviceProvider;
_abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider;
_authorizationService = authorizationService;
_currentUser = currentUser;
_settingProvider = settingProvider;
_settingDefinitionManager = settingDefinitionManager;
_localizationOptions = localizationOptions.Value;
}
@ -40,9 +48,10 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
return new ApplicationConfigurationDto
{
Auth = await GetAuthConfig(),
Auth = await GetAuthConfigAsync(),
Localization = GetLocalizationConfig(),
CurrentUser = GetCurrentUser()
CurrentUser = GetCurrentUser(),
Setting = await GetSettingConfigAsync()
};
}
@ -57,7 +66,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
};
}
protected virtual async Task<ApplicationAuthConfigurationDto> GetAuthConfig()
protected virtual async Task<ApplicationAuthConfigurationDto> GetAuthConfigAsync()
{
var authConfig = new ApplicationAuthConfigurationDto();
@ -97,5 +106,25 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
return localizationConfig;
}
private async Task<ApplicationSettingConfigurationDto> GetSettingConfigAsync()
{
var result = new ApplicationSettingConfigurationDto
{
Values = new Dictionary<string, string>()
};
foreach (var settingDefinition in _settingDefinitionManager.GetAll())
{
if (!settingDefinition.IsVisibleToClients)
{
continue;
}
result.Values[settingDefinition.Name] = await _settingProvider.GetOrNullAsync(settingDefinition.Name);
}
return result;
}
}
}

13
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs

@ -7,6 +7,7 @@ using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.Tracing;
using Volo.Abp.AspNetCore.Uow;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
@ -40,6 +41,12 @@ namespace Microsoft.AspNetCore.Builder
.UseMiddleware<AbpUnitOfWorkMiddleware>();
}
public static IApplicationBuilder UseCorrelationId(this IApplicationBuilder app)
{
return app
.UseMiddleware<AbpCorrelationIdMiddleware>();
}
public static IApplicationBuilder UseAbpRequestLocalization(this IApplicationBuilder app)
{
IReadOnlyList<LanguageInfo> languages;
@ -48,10 +55,10 @@ namespace Microsoft.AspNetCore.Builder
using (var scope = app.ApplicationServices.CreateScope())
{
var languageProvider = scope.ServiceProvider.GetRequiredService<ILanguageProvider>();
var settingManager = scope.ServiceProvider.GetRequiredService<ISettingManager>();
languages = languageProvider.GetLanguages();
languages = AsyncHelper.RunSync(() => languageProvider.GetLanguagesAsync());
defaultLanguage = settingManager.GetOrNull(LocalizationSettingNames.DefaultLanguage);
var settingProvider = scope.ServiceProvider.GetRequiredService<ISettingProvider>();
defaultLanguage = settingProvider.GetOrNull(LocalizationSettingNames.DefaultLanguage);
}
if (!languages.Any())

43
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreCorrelationIdProvider.cs

@ -1,43 +0,0 @@
using System;
using Microsoft.AspNetCore.Http;
using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Auditing
{
[Dependency(ReplaceServices = true)]
public class AspNetCoreCorrelationIdProvider : ICorrelationIdProvider, ITransientDependency
{
public const string CorrelationIdKey = "_CorrelationId";
protected IHttpContextAccessor HttpContextAccessor { get; }
public AspNetCoreCorrelationIdProvider(IHttpContextAccessor httpContextAccessor)
{
HttpContextAccessor = httpContextAccessor;
}
public virtual string Get()
{
if (HttpContextAccessor.HttpContext?.Request?.Headers == null)
{
return CreateNewCorrelationId();
}
string correlationId = HttpContextAccessor.HttpContext.Request.Headers[CorrelationIdKey];
if (correlationId.IsNullOrEmpty())
{
correlationId = CreateNewCorrelationId();
HttpContextAccessor.HttpContext.Request.Headers[CorrelationIdKey] = correlationId;
}
return correlationId;
}
protected virtual string CreateNewCorrelationId()
{
return Guid.NewGuid().ToString("N");
}
}
}

58
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs

@ -0,0 +1,58 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using Volo.Abp.Tracing;
namespace Volo.Abp.AspNetCore.Tracing
{
public class AbpCorrelationIdMiddleware
{
private readonly RequestDelegate _next;
public AbpCorrelationIdMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(
HttpContext httpContext,
IOptions<CorrelationIdOptions> options,
ICorrelationIdProvider correlationIdProvider)
{
var correlationId = correlationIdProvider.Get();
var optionsValue = options.Value;
try
{
await _next(httpContext);
}
finally
{
CheckAndSetCorrelationIdOnResponse(httpContext, optionsValue, correlationId);
}
}
protected virtual void CheckAndSetCorrelationIdOnResponse(
HttpContext httpContext,
CorrelationIdOptions options,
string correlationId)
{
if (httpContext.Response.HasStarted)
{
return;
}
if (!options.SetResponseHeader)
{
return;
}
if (httpContext.Response.Headers.ContainsKey(options.HttpHeaderName))
{
return;
}
httpContext.Response.Headers[options.HttpHeaderName] = correlationId;
}
}
}

49
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AspNetCoreCorrelationIdProvider.cs

@ -0,0 +1,49 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Tracing;
namespace Volo.Abp.AspNetCore.Tracing
{
[Dependency(ReplaceServices = true)]
public class AspNetCoreCorrelationIdProvider : ICorrelationIdProvider, ITransientDependency
{
protected IHttpContextAccessor HttpContextAccessor { get; }
protected CorrelationIdOptions Options { get; }
public AspNetCoreCorrelationIdProvider(
IHttpContextAccessor httpContextAccessor,
IOptions<CorrelationIdOptions> options)
{
HttpContextAccessor = httpContextAccessor;
Options = options.Value;
}
public virtual string Get()
{
if (HttpContextAccessor.HttpContext?.Request?.Headers == null)
{
return CreateNewCorrelationId();
}
lock (HttpContextAccessor.HttpContext.Request.Headers)
{
string correlationId = HttpContextAccessor.HttpContext.Request.Headers[Options.HttpHeaderName];
if (correlationId.IsNullOrEmpty())
{
correlationId = CreateNewCorrelationId();
HttpContextAccessor.HttpContext.Request.Headers[Options.HttpHeaderName] = correlationId;
}
return correlationId;
}
}
protected virtual string CreateNewCorrelationId()
{
return Guid.NewGuid().ToString("N");
}
}
}

6
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs

@ -14,6 +14,12 @@ namespace Volo.Abp.Auditing
/// </summary>
public bool IsEnabled { get; set; }
/// <summary>
/// The name of the application or service writing audit logs.
/// Default: null.
/// </summary>
public string ApplicationName { get; set; }
/// <summary>
/// Default: true.
/// </summary>

2
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditLogInfo.cs

@ -10,6 +10,8 @@ namespace Volo.Abp.Auditing
//TODO: Make serializable!
public class AuditLogInfo : IMultiTenant, IHasExtraProperties
{
public string ApplicationName { get; set; }
public Guid? UserId { get; set; }
public string UserName { get; set; }

2
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingHelper.cs

@ -9,6 +9,7 @@ using Volo.Abp.Clients;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Timing;
using Volo.Abp.Tracing;
using Volo.Abp.Users;
namespace Volo.Abp.Auditing
@ -89,6 +90,7 @@ namespace Volo.Abp.Auditing
{
var auditInfo = new AuditLogInfo
{
ApplicationName = Options.ApplicationName,
TenantId = CurrentTenant.Id,
UserId = CurrentUser.Id,
UserName = CurrentUser.UserName,

12
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/NullCorrelationIdProvider.cs

@ -1,12 +0,0 @@
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Auditing
{
public class NullCorrelationIdProvider : ICorrelationIdProvider, ISingletonDependency
{
public string Get()
{
return null;
}
}
}

4
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs

@ -18,6 +18,10 @@ namespace Volo.Abp.Authorization.Permissions
/// </summary>
public PermissionDefinition Parent { get; private set; }
/// <summary>
/// A list of allowed providers to get/set value of this permission.
/// An empty list indicates that all providers are allowed.
/// </summary>
public List<string> Providers { get; }
public ILocalizableString DisplayName

22
framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs

@ -103,6 +103,7 @@ namespace Volo.Abp.Caching
Logger.LogException(ex, LogLevel.Warning);
return null;
}
throw;
}
@ -194,13 +195,13 @@ namespace Volo.Abp.Caching
}
}
public virtual Task SetAsync(string key, TCacheItem value, DistributedCacheEntryOptions options = null, bool? hideErrors = null, CancellationToken token = default)
public virtual async Task SetAsync(string key, TCacheItem value, DistributedCacheEntryOptions options = null, bool? hideErrors = null, CancellationToken token = default)
{
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
try
{
return Cache.SetAsync(
await Cache.SetAsync(
NormalizeKey(key),
ObjectSerializer.Serialize(value),
options ?? DefaultCacheOptions,
@ -212,8 +213,9 @@ namespace Volo.Abp.Caching
if ((bool)hideErrors)
{
Logger.LogException(ex, LogLevel.Warning);
return Task.CompletedTask;
return;
}
throw;
}
}
@ -238,21 +240,22 @@ namespace Volo.Abp.Caching
}
}
public virtual Task RefreshAsync(string key, bool? hideErrors = null, CancellationToken token = default)
public virtual async Task RefreshAsync(string key, bool? hideErrors = null, CancellationToken token = default)
{
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
try
{
return Cache.RefreshAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token));
await Cache.RefreshAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token));
}
catch (Exception ex)
{
if ((bool)hideErrors)
{
Logger.LogException(ex, LogLevel.Warning);
return Task.CompletedTask;
return;
}
throw;
}
}
@ -276,21 +279,22 @@ namespace Volo.Abp.Caching
}
}
public virtual Task RemoveAsync(string key, bool? hideErrors = null, CancellationToken token = default)
public virtual async Task RemoveAsync(string key, bool? hideErrors = null, CancellationToken token = default)
{
hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
try
{
return Cache.RemoveAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token));
await Cache.RemoveAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token));
}
catch (Exception ex)
{
if ((bool)hideErrors)
{
Logger.LogException(ex, LogLevel.Warning);
return Task.CompletedTask;
return;
}
throw;
}
}

9
framework/src/Volo.Abp.Core/Volo/Abp/Tracing/CorrelationIdOptions.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.Tracing
{
public class CorrelationIdOptions
{
public string HttpHeaderName { get; set; } = "X-Correlation-Id";
public bool SetResponseHeader { get; set; } = true;
}
}

18
framework/src/Volo.Abp.Core/Volo/Abp/Tracing/DefaultCorrelationIdProvider.cs

@ -0,0 +1,18 @@
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Tracing
{
public class DefaultCorrelationIdProvider : ICorrelationIdProvider, ISingletonDependency
{
public string Get()
{
return CreateNewCorrelationId();
}
protected virtual string CreateNewCorrelationId()
{
return Guid.NewGuid().ToString("N");
}
}
}

5
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/ICorrelationIdProvider.cs → framework/src/Volo.Abp.Core/Volo/Abp/Tracing/ICorrelationIdProvider.cs

@ -1,7 +1,10 @@
namespace Volo.Abp.Auditing
using JetBrains.Annotations;
namespace Volo.Abp.Tracing
{
public interface ICorrelationIdProvider
{
[NotNull]
string Get();
}
}

1
framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj

@ -20,6 +20,7 @@
<ProjectReference Include="..\Volo.Abp.Http.Abstractions\Volo.Abp.Http.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />
<ProjectReference Include="..\Volo.Abp.Validation\Volo.Abp.Validation.csproj" />
</ItemGroup>

17
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/AbpDddApplicationModule.cs

@ -1,5 +1,4 @@
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application.Services;
using Volo.Abp.Authorization;
using Volo.Abp.Domain;
@ -8,17 +7,21 @@ using Volo.Abp.Http.Modeling;
using Volo.Abp.Modularity;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Security;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
using Volo.Abp.Validation;
namespace Volo.Abp.Application
{
[DependsOn(typeof(AbpDddDomainModule))]
[DependsOn(typeof(AbpSecurityModule))]
[DependsOn(typeof(AbpObjectMappingModule))]
[DependsOn(typeof(AbpValidationModule))]
[DependsOn(typeof(AbpAuthorizationModule))]
[DependsOn(typeof(AbpHttpAbstractionsModule))]
[DependsOn(
typeof(AbpDddDomainModule),
typeof(AbpSecurityModule),
typeof(AbpObjectMappingModule),
typeof(AbpValidationModule),
typeof(AbpAuthorizationModule),
typeof(AbpHttpAbstractionsModule),
typeof(AbpSettingsModule)
)]
public class AbpDddApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)

2
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs

@ -45,7 +45,7 @@ namespace Volo.Abp.Application.Services
public ICurrentUser CurrentUser { get; set; }
public ISettingManager SettingManager { get; set; }
public ISettingProvider SettingProvider { get; set; }
public IClock Clock { get; set; }

101
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs

@ -1,98 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Volo.Abp.Domain.Values
{
//Inspired from https://blogs.msdn.microsoft.com/cesardelatorre/2011/06/06/implementing-a-value-object-base-class-supertype-patternddd-patterns-related/
/// <summary>
/// Base class for value objects.
/// </summary>
/// <typeparam name="TValueObject">The type of the value object.</typeparam>
public abstract class ValueObject<TValueObject> : IEquatable<TValueObject>
where TValueObject : ValueObject<TValueObject>
//Inspired from https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/implement-value-objects
public abstract class ValueObject
{
public bool Equals(TValueObject other)
protected static bool EqualOperator(ValueObject left, ValueObject right)
{
if ((object)other == null)
if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))
{
return false;
}
return ReferenceEquals(left, null) || left.Equals(right);
}
var publicProperties = GetType().GetTypeInfo().GetProperties();
if (!publicProperties.Any())
{
return true;
}
return publicProperties.All(property => Equals(property.GetValue(this, null), property.GetValue(other, null)));
protected static bool NotEqualOperator(ValueObject left, ValueObject right)
{
return !(EqualOperator(left, right));
}
protected abstract IEnumerable<object> GetAtomicValues();
public override bool Equals(object obj)
{
if (obj == null)
if (obj == null || obj.GetType() != GetType())
{
return false;
}
var item = obj as ValueObject<TValueObject>;
return (object)item != null && Equals((TValueObject)item);
}
public override int GetHashCode()
{
//TODO: Can we cache the hash value assuming value objects are always immutable? We can make a Reset-like method to reset it's mutated.
const int index = 1;
const int initialHasCode = 31;
var publicProperties = GetType().GetTypeInfo().GetProperties();
if (!publicProperties.Any())
ValueObject other = (ValueObject)obj;
IEnumerator<object> thisValues = GetAtomicValues().GetEnumerator();
IEnumerator<object> otherValues = other.GetAtomicValues().GetEnumerator();
while (thisValues.MoveNext() && otherValues.MoveNext())
{
return initialHasCode;
}
var hashCode = initialHasCode;
var changeMultiplier = false;
foreach (var property in publicProperties)
{
var value = property.GetValue(this, null);
if (value == null)
if (ReferenceEquals(thisValues.Current, null) ^
ReferenceEquals(otherValues.Current, null))
{
//support {"a",null,null,"a"} != {null,"a","a",null}
hashCode = hashCode ^ (index * 13);
continue;
return false;
}
hashCode = hashCode * (changeMultiplier ? 59 : 114) + value.GetHashCode();
changeMultiplier = !changeMultiplier;
}
return hashCode;
}
public static bool operator ==(ValueObject<TValueObject> x, ValueObject<TValueObject> y)
{
if (ReferenceEquals(x, y))
{
return true;
}
if (((object)x == null) || ((object)y == null))
{
return false;
if (thisValues.Current != null &&
!thisValues.Current.Equals(otherValues.Current))
{
return false;
}
}
return x.Equals(y);
return !thisValues.MoveNext() && !otherValues.MoveNext();
}
public static bool operator !=(ValueObject<TValueObject> x, ValueObject<TValueObject> y)
public override int GetHashCode()
{
return !(x == y);
return GetAtomicValues()
.Select(x => x != null ? x.GetHashCode() : 0)
.Aggregate((x, y) => x ^ y);
}
// Other utilility methods
}
}

3
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs

@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Emailing.Templates;
using Volo.Abp.Emailing.Templates.Virtual;
using Volo.Abp.Localization;

10
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderConfiguration.cs

@ -11,16 +11,16 @@ namespace Volo.Abp.Emailing
{
public virtual string DefaultFromAddress => GetNotEmptySettingValue(EmailSettingNames.DefaultFromAddress);
public virtual string DefaultFromDisplayName => SettingManager.GetOrNull(EmailSettingNames.DefaultFromDisplayName);
public virtual string DefaultFromDisplayName => SettingProvider.GetOrNull(EmailSettingNames.DefaultFromDisplayName);
protected readonly ISettingManager SettingManager;
protected readonly ISettingProvider SettingProvider;
/// <summary>
/// Creates a new <see cref="EmailSenderConfiguration"/>.
/// </summary>
protected EmailSenderConfiguration(ISettingManager settingManager)
protected EmailSenderConfiguration(ISettingProvider settingProvider)
{
SettingManager = settingManager;
SettingProvider = settingProvider;
}
/// <summary>
@ -30,7 +30,7 @@ namespace Volo.Abp.Emailing
/// <returns>Value of the setting</returns>
protected string GetNotEmptySettingValue(string name)
{
var value = SettingManager.GetOrNull(name);
var value = SettingProvider.GetOrNull(name);
if (value.IsNullOrEmpty())
{

10
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Smtp/SmtpEmailSenderConfiguration.cs

@ -18,14 +18,14 @@ namespace Volo.Abp.Emailing.Smtp
public virtual string Password => GetNotEmptySettingValue(EmailSettingNames.Smtp.Password);
public virtual string Domain => SettingManager.GetOrNull(EmailSettingNames.Smtp.Domain);
public virtual string Domain => SettingProvider.GetOrNull(EmailSettingNames.Smtp.Domain);
public virtual bool EnableSsl => SettingManager.GetOrNull(EmailSettingNames.Smtp.EnableSsl).To<bool>();
public virtual bool EnableSsl => SettingProvider.GetOrNull(EmailSettingNames.Smtp.EnableSsl).To<bool>();
public virtual bool UseDefaultCredentials => SettingManager.GetOrNull(EmailSettingNames.Smtp.UseDefaultCredentials).To<bool>();
public virtual bool UseDefaultCredentials => SettingProvider.GetOrNull(EmailSettingNames.Smtp.UseDefaultCredentials).To<bool>();
public SmtpEmailSenderConfiguration(ISettingManager settingManager)
: base(settingManager)
public SmtpEmailSenderConfiguration(ISettingProvider settingProvider)
: base(settingProvider)
{
}

1
framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj

@ -20,6 +20,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Castle.Core\Volo.Abp.Castle.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.Http\Volo.Abp.Http.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
</ItemGroup>
</Project>

9
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs

@ -1,17 +1,20 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Castle;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;
namespace Volo.Abp.Http.Client
{
[DependsOn(typeof(AbpHttpModule))]
[DependsOn(typeof(AbpCastleCoreModule))]
[DependsOn(
typeof(AbpHttpModule),
typeof(AbpCastleCoreModule),
typeof(AbpThreadingModule)
)]
public class AbpHttpClientModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<RemoteServiceOptions>(configuration);
}
}

92
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@ -15,21 +16,25 @@ using Volo.Abp.Http.ProxyScripting.Generators;
using Volo.Abp.Json;
using Volo.Abp.Reflection;
using Volo.Abp.Threading;
using Volo.Abp.Tracing;
namespace Volo.Abp.Http.Client.DynamicProxying
{
//TODO: Somehow capture cancellationtoken and pass to other methods...?
public class DynamicHttpProxyInterceptor<TService> : AbpInterceptor, ITransientDependency
{
private static MethodInfo GenericInterceptAsyncMethod { get; }
// ReSharper disable once StaticMemberInGenericType
protected static MethodInfo GenericInterceptAsyncMethod { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected ICorrelationIdProvider CorrelationIdProvider { get; }
protected CorrelationIdOptions CorrelationIdOptions { get; }
protected IDynamicProxyHttpClientFactory HttpClientFactory { get; }
protected IApiDescriptionFinder ApiDescriptionFinder { get; }
protected RemoteServiceOptions RemoteServiceOptions { get; }
protected AbpHttpClientOptions ClientOptions { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IRemoteServiceHttpClientAuthenticator ClientAuthenticator { get; }
private readonly IDynamicProxyHttpClientFactory _httpClientFactory;
private readonly IApiDescriptionFinder _apiDescriptionFinder;
private readonly RemoteServiceOptions _remoteServiceOptions;
private readonly AbpHttpClientOptions _clientOptions;
private readonly IJsonSerializer _jsonSerializer;
private readonly IRemoteServiceHttpClientAuthenticator _clientAuthenticator;
public ILogger<DynamicHttpProxyInterceptor<TService>> Logger { get; set; }
@ -46,14 +51,20 @@ namespace Volo.Abp.Http.Client.DynamicProxying
IOptionsSnapshot<RemoteServiceOptions> remoteServiceOptions,
IApiDescriptionFinder apiDescriptionFinder,
IJsonSerializer jsonSerializer,
IRemoteServiceHttpClientAuthenticator clientAuthenticator)
IRemoteServiceHttpClientAuthenticator clientAuthenticator,
ICancellationTokenProvider cancellationTokenProvider,
ICorrelationIdProvider correlationIdProvider,
IOptions<CorrelationIdOptions> correlationIdOptions)
{
_httpClientFactory = httpClientFactory;
_apiDescriptionFinder = apiDescriptionFinder;
_jsonSerializer = jsonSerializer;
_clientAuthenticator = clientAuthenticator;
_clientOptions = clientOptions.Value;
_remoteServiceOptions = remoteServiceOptions.Value;
CancellationTokenProvider = cancellationTokenProvider;
CorrelationIdProvider = correlationIdProvider;
CorrelationIdOptions = correlationIdOptions.Value;
HttpClientFactory = httpClientFactory;
ApiDescriptionFinder = apiDescriptionFinder;
JsonSerializer = jsonSerializer;
ClientAuthenticator = clientAuthenticator;
ClientOptions = clientOptions.Value;
RemoteServiceOptions = remoteServiceOptions.Value;
Logger = NullLogger<DynamicHttpProxyInterceptor<TService>>.Instance;
}
@ -62,11 +73,11 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{
if (invocation.Method.ReturnType == typeof(void))
{
AsyncHelper.RunSync(() => MakeRequest(invocation));
AsyncHelper.RunSync(() => MakeRequestAsync(invocation));
}
else
{
var responseAsString = AsyncHelper.RunSync(() => MakeRequest(invocation));
var responseAsString = AsyncHelper.RunSync(() => MakeRequestAsync(invocation));
//TODO: Think on that
if (TypeHelper.IsPrimitiveExtended(invocation.Method.ReturnType, true))
@ -75,7 +86,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
}
else
{
invocation.ReturnValue = _jsonSerializer.Deserialize(
invocation.ReturnValue = JsonSerializer.Deserialize(
invocation.Method.ReturnType,
responseAsString
);
@ -87,7 +98,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{
if (invocation.Method.ReturnType.GenericTypeArguments.IsNullOrEmpty())
{
return MakeRequest(invocation);
return MakeRequestAsync(invocation);
}
invocation.ReturnValue = GenericInterceptAsyncMethod
@ -99,7 +110,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
private async Task<T> MakeRequestAndGetResultAsync<T>(IAbpMethodInvocation invocation)
{
var responseAsString = await MakeRequest(invocation);
var responseAsString = await MakeRequestAsync(invocation);
//TODO: Think on that
if (TypeHelper.IsPrimitiveExtended(typeof(T), true))
@ -107,28 +118,28 @@ namespace Volo.Abp.Http.Client.DynamicProxying
return (T)Convert.ChangeType(responseAsString, typeof(T));
}
return _jsonSerializer.Deserialize<T>(responseAsString);
return JsonSerializer.Deserialize<T>(responseAsString);
}
private async Task<string> MakeRequest(IAbpMethodInvocation invocation)
private async Task<string> MakeRequestAsync(IAbpMethodInvocation invocation)
{
using (var client = _httpClientFactory.Create())
using (var client = HttpClientFactory.Create())
{
var clientConfig = _clientOptions.HttpClientProxies.GetOrDefault(typeof(TService)) ?? throw new AbpException($"Could not get DynamicHttpClientProxyConfig for {typeof(TService).FullName}.");
var remoteServiceConfig = _remoteServiceOptions.RemoteServices.GetConfigurationOrDefault(clientConfig.RemoteServiceName);
var clientConfig = ClientOptions.HttpClientProxies.GetOrDefault(typeof(TService)) ?? throw new AbpException($"Could not get DynamicHttpClientProxyConfig for {typeof(TService).FullName}.");
var remoteServiceConfig = RemoteServiceOptions.RemoteServices.GetConfigurationOrDefault(clientConfig.RemoteServiceName);
var action = await _apiDescriptionFinder.FindActionAsync(remoteServiceConfig.BaseUrl, typeof(TService), invocation.Method);
var action = await ApiDescriptionFinder.FindActionAsync(remoteServiceConfig.BaseUrl, typeof(TService), invocation.Method);
var apiVersion = GetApiVersionInfo(action);
var url = remoteServiceConfig.BaseUrl + UrlBuilder.GenerateUrlWithParameters(action, invocation.ArgumentsDictionary, apiVersion);
var requestMessage = new HttpRequestMessage(action.GetHttpMethod(), url)
{
Content = RequestPayloadBuilder.BuildContent(action, invocation.ArgumentsDictionary, _jsonSerializer, apiVersion)
Content = RequestPayloadBuilder.BuildContent(action, invocation.ArgumentsDictionary, JsonSerializer, apiVersion)
};
AddHeaders(invocation, action, requestMessage, apiVersion);
await _clientAuthenticator.Authenticate(
await ClientAuthenticator.Authenticate(
new RemoteServiceHttpClientAuthenticateContext(
client,
requestMessage,
@ -137,7 +148,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
)
);
var response = await client.SendAsync(requestMessage);
var response = await client.SendAsync(requestMessage, GetCancellationToken());
if (!response.IsSuccessStatusCode)
{
@ -176,8 +187,9 @@ namespace Volo.Abp.Http.Client.DynamicProxying
return action.SupportedVersions.Last(); //TODO: Ensure to get the latest version!
}
private static void AddHeaders(IAbpMethodInvocation invocation, ActionApiDescriptionModel action, HttpRequestMessage requestMessage, ApiVersionInfo apiVersion)
protected virtual void AddHeaders(IAbpMethodInvocation invocation, ActionApiDescriptionModel action, HttpRequestMessage requestMessage, ApiVersionInfo apiVersion)
{
//API Version
if (!apiVersion.Version.IsNullOrEmpty())
{
//TODO: What about other media types?
@ -186,8 +198,8 @@ namespace Volo.Abp.Http.Client.DynamicProxying
requestMessage.Headers.Add("api-version", apiVersion.Version);
}
//Header parameters
var headers = action.Parameters.Where(p => p.BindingSourceId == ParameterBindingSources.Header).ToArray();
foreach (var headerParameter in headers)
{
var value = HttpActionParameterHelper.FindParameterValue(invocation.ArgumentsDictionary, headerParameter);
@ -196,22 +208,25 @@ namespace Volo.Abp.Http.Client.DynamicProxying
requestMessage.Headers.Add(headerParameter.Name, value.ToString());
}
}
//CorrelationId
requestMessage.Headers.Add(CorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get());
}
private string GetConfiguredApiVersion()
{
var clientConfig = _clientOptions.HttpClientProxies.GetOrDefault(typeof(TService))
var clientConfig = ClientOptions.HttpClientProxies.GetOrDefault(typeof(TService))
?? throw new AbpException($"Could not get DynamicHttpClientProxyConfig for {typeof(TService).FullName}.");
return _remoteServiceOptions.RemoteServices.GetOrDefault(clientConfig.RemoteServiceName)?.Version
?? _remoteServiceOptions.RemoteServices.Default?.Version;
return RemoteServiceOptions.RemoteServices.GetOrDefault(clientConfig.RemoteServiceName)?.Version
?? RemoteServiceOptions.RemoteServices.Default?.Version;
}
private async Task ThrowExceptionForResponseAsync(HttpResponseMessage response)
{
if (response.Headers.Contains(AbpHttpConsts.AbpErrorFormat))
{
var errorResponse = _jsonSerializer.Deserialize<RemoteServiceErrorResponse>(
var errorResponse = JsonSerializer.Deserialize<RemoteServiceErrorResponse>(
await response.Content.ReadAsStringAsync()
);
@ -220,5 +235,10 @@ namespace Volo.Abp.Http.Client.DynamicProxying
throw new AbpException($"Remote service returns error! HttpStatusCode: {response.StatusCode}, ReasonPhrase: {response.ReasonPhrase}");
}
protected virtual CancellationToken GetCancellationToken()
{
return CancellationTokenProvider.Token;
}
}
}

3
framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelRemoteServiceHttpClientAuthenticator.cs

@ -15,7 +15,6 @@ namespace Volo.Abp.IdentityModel
public class IdentityModelHttpClientAuthenticator : IIdentityModelHttpClientAuthenticator, ITransientDependency
{
public ILogger<IdentityModelHttpClientAuthenticator> Logger { get; set; }
protected IdentityClientOptions ClientOptions { get; }
public IdentityModelHttpClientAuthenticator(
@ -84,6 +83,8 @@ namespace Volo.Abp.IdentityModel
protected virtual async Task<TokenResponse> GetTokenResponse(DiscoveryResponse discoveryResponse, IdentityClientConfiguration configuration)
{
//TODO: Pass cancellation token
var tokenClient = new TokenClient(discoveryResponse.TokenEndpoint, configuration.ClientId, configuration.ClientSecret);
switch (configuration.GrantType)

2
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageProviderExtensions.cs

@ -7,7 +7,7 @@ namespace Volo.Abp.Localization
{
public static IReadOnlyList<LanguageInfo> GetLanguages(this ILanguageProvider languageProvider)
{
return AsyncHelper.RunSync(() => languageProvider.GetLanguagesAsync());
return AsyncHelper.RunSync(languageProvider.GetLanguagesAsync);
}
}
}

1
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo.Abp.MultiTenancy.Abstractions.csproj

@ -17,7 +17,6 @@
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />
</ItemGroup>
</Project>

19
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/AbpMultiTenancyAbstractionsModule.cs

@ -1,20 +1,13 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Data;
using Volo.Abp.Data;
using Volo.Abp.Modularity;
using Volo.Abp.Settings;
namespace Volo.Abp.MultiTenancy
{
[DependsOn(typeof(AbpDataModule))]
[DependsOn(typeof(AbpSettingsModule))]
public class AbpMultiTenancyAbstractionsModule : AbpModule //TODO: Rename to AbpMultiTenancyModule
[DependsOn(
typeof(AbpDataModule)
)]
public class AbpMultiTenancyAbstractionsModule : AbpModule //TODO: Rename to AbpMultiTenancyModule?
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<SettingOptions>(options =>
{
options.ValueProviders.Add<TenantSettingValueProvider>();
});
}
}
}

45
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/TenantSettingValueProvider.cs

@ -1,45 +0,0 @@
using System.Threading.Tasks;
using Volo.Abp.Settings;
namespace Volo.Abp.MultiTenancy
{
public class TenantSettingValueProvider : SettingValueProvider
{
public const string ProviderName = "Tenant";
public override string Name => ProviderName;
protected ICurrentTenant CurrentTenant { get; }
public TenantSettingValueProvider(ISettingStore settingStore, ICurrentTenant currentTenant)
: base(settingStore)
{
CurrentTenant = currentTenant;
}
public override async Task<string> GetOrNullAsync(SettingDefinition setting, string providerKey)
{
return await SettingStore.GetOrNullAsync(setting.Name, Name, NormalizeProviderKey(providerKey));
}
public override Task SetAsync(SettingDefinition setting, string value, string providerKey)
{
return SettingStore.SetAsync(setting.Name, value, Name, NormalizeProviderKey(providerKey));
}
public override Task ClearAsync(SettingDefinition setting, string providerKey)
{
return SettingStore.DeleteAsync(setting.Name, Name, NormalizeProviderKey(providerKey));
}
private string NormalizeProviderKey(string providerKey)
{
if (providerKey == null && CurrentTenant.Id.HasValue)
{
return CurrentTenant.Id.Value.ToString();
}
return providerKey;
}
}
}

1
framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj

@ -15,6 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Localization.Abstractions\Volo.Abp.Localization.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
</ItemGroup>

16
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/AbpSettingsModule.cs

@ -1,15 +1,27 @@
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security;
using Volo.Abp.Users;
namespace Volo.Abp.Settings
{
[DependsOn(
typeof(AbpLocalizationAbstractionsModule),
typeof(AbpSecurityModule)
typeof(AbpSecurityModule),
typeof(AbpMultiTenancyAbstractionsModule)
)]
public class AbpSettingsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<SettingOptions>(options =>
{
options.ValueProviders.Add<DefaultValueSettingValueProvider>();
options.ValueProviders.Add<GlobalSettingValueProvider>();
options.ValueProviders.Add<TenantSettingValueProvider>();
options.ValueProviders.Add<UserSettingValueProvider>();
});
}
}
}

14
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/DefaultValueSettingValueProvider.cs

@ -14,21 +14,9 @@ namespace Volo.Abp.Settings
}
public override Task<string> GetOrNullAsync(SettingDefinition setting, string providerKey)
public override Task<string> GetOrNullAsync(SettingDefinition setting)
{
return Task.FromResult(setting.DefaultValue);
}
public override Task SetAsync(SettingDefinition setting, string value, string providerKey)
{
setting.DefaultValue = value;
return Task.CompletedTask;
}
public override Task ClearAsync(SettingDefinition setting, string providerKey)
{
setting.DefaultValue = null;
return Task.CompletedTask;
}
}
}

12
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/GlobalSettingValueProvider.cs

@ -13,19 +13,9 @@ namespace Volo.Abp.Settings
{
}
public override Task<string> GetOrNullAsync(SettingDefinition setting, string providerKey)
public override Task<string> GetOrNullAsync(SettingDefinition setting)
{
return SettingStore.GetOrNullAsync(setting.Name, Name, null);
}
public override Task SetAsync(SettingDefinition setting, string value, string providerKey)
{
return SettingStore.SetAsync(setting.Name, value, Name, null);
}
public override Task ClearAsync(SettingDefinition setting, string providerKey)
{
return SettingStore.DeleteAsync(setting.Name, Name, null);
}
}
}

2
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingDefinitionManager.cs

@ -9,5 +9,7 @@ namespace Volo.Abp.Settings
SettingDefinition Get([NotNull] string name);
IReadOnlyList<SettingDefinition> GetAll();
SettingDefinition GetOrNull(string name);
}
}

13
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingProvider.cs

@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Settings
{
public interface ISettingProvider
{
Task<string> GetOrNullAsync([NotNull]string name);
Task<List<SettingValue>> GetAllAsync();
}
}

15
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingStore.cs

@ -1,17 +1,14 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Settings
{
public interface ISettingStore
{
Task<string> GetOrNullAsync([NotNull] string name, [CanBeNull] string providerName, [CanBeNull] string providerKey);
Task SetAsync([NotNull] string name, [NotNull] string value, [CanBeNull] string providerName, [CanBeNull] string providerKey);
Task<List<SettingValue>> GetListAsync([CanBeNull] string providerName, [CanBeNull] string providerKey);
Task DeleteAsync([NotNull] string name, [CanBeNull]string providerName, [CanBeNull]string providerKey);
Task<string> GetOrNullAsync(
[NotNull] string name,
[CanBeNull] string providerName,
[CanBeNull] string providerKey
);
}
}

8
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingValueProvider.cs

@ -7,12 +7,6 @@ namespace Volo.Abp.Settings
{
string Name { get; }
//TODO: There is a bug here, because we are checking the same providerKey in all providers in a fallback system!
Task<string> GetOrNullAsync([NotNull] SettingDefinition setting, [CanBeNull] string providerKey);
Task SetAsync([NotNull] SettingDefinition setting, [NotNull] string value, [CanBeNull] string providerKey);
Task ClearAsync([NotNull] SettingDefinition setting, [CanBeNull] string providerKey);
Task<string> GetOrNullAsync([NotNull] SettingDefinition setting);
}
}

31
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs

@ -36,6 +36,12 @@ namespace Volo.Abp.Settings
/// </summary>
public bool IsVisibleToClients { get; set; }
/// <summary>
/// A list of allowed providers to get/set value of this setting.
/// An empty list indicates that all providers are allowed.
/// </summary>
public List<string> Providers { get; }
/// <summary>
/// Is this setting inherited from parent scopes.
/// Default: True.
@ -72,6 +78,31 @@ namespace Volo.Abp.Settings
IsEncrypted = isEncrypted;
Properties = new Dictionary<string, object>();
Providers = new List<string>();
}
/// <summary>
/// Sets a property in the <see cref="Properties"/> dictionary.
/// This is a shortcut for nested calls on this object.
/// </summary>
public virtual SettingDefinition WithProperty(string key, object value)
{
Properties[key] = value;
return this;
}
/// <summary>
/// Sets a property in the <see cref="Properties"/> dictionary.
/// This is a shortcut for nested calls on this object.
/// </summary>
public virtual SettingDefinition WithProviders(params string[] providers)
{
if (!providers.IsNullOrEmpty())
{
Providers.AddRange(providers);
}
return this;
}
}
}

31
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerExtensions.cs

@ -1,31 +0,0 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Settings
{
public static class SettingManagerExtensions
{
public static async Task<bool> IsTrueAsync([NotNull] this ISettingManager settingManager, [NotNull] string name)
{
Check.NotNull(settingManager, nameof(settingManager));
Check.NotNull(name, nameof(name));
return string.Equals(
await settingManager.GetOrNullAsync(name),
"true",
StringComparison.OrdinalIgnoreCase
);
}
public static async Task<T> GetAsync<T>([NotNull] this ISettingManager settingManager, [NotNull] string name, T defaultValue = default)
where T : struct
{
Check.NotNull(settingManager, nameof(settingManager));
Check.NotNull(name, nameof(name));
var value = await settingManager.GetOrNullAsync(name);
return value?.To<T>() ?? defaultValue;
}
}
}

34
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerSyncExtensions.cs

@ -1,34 +0,0 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Threading;
namespace Volo.Abp.Settings
{
public static class SettingManagerSyncExtensions
{
public static string GetOrNull([NotNull] this ISettingManager settingManager, [NotNull] string name)
{
Check.NotNull(settingManager, nameof(settingManager));
return AsyncHelper.RunSync(() => settingManager.GetOrNullAsync(name));
}
public static List<SettingValue> GetAll([NotNull] this ISettingManager settingManager)
{
Check.NotNull(settingManager, nameof(settingManager));
return AsyncHelper.RunSync(settingManager.GetAllAsync);
}
public static T Get<T>([NotNull] this ISettingManager settingManager, [NotNull] string name, T defaultValue = default)
where T : struct
{
return AsyncHelper.RunSync(() => settingManager.GetAsync(name, defaultValue));
}
public static bool IsTrue([NotNull] this ISettingManager settingManager, [NotNull] string name)
{
return AsyncHelper.RunSync(() => settingManager.IsTrueAsync(name));
}
}
}

6
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingOptions.cs

@ -11,11 +11,7 @@ namespace Volo.Abp.Settings
public SettingOptions()
{
DefinitionProviders = new TypeList<ISettingDefinitionProvider>();
ValueProviders = new TypeList<ISettingValueProvider>
{
typeof(DefaultValueSettingValueProvider),
typeof(GlobalSettingValueProvider)
};
ValueProviders = new TypeList<ISettingValueProvider>();
}
}
}

101
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingProvider.cs

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Settings
{
public class SettingProvider : ISettingProvider, ITransientDependency
{
protected ISettingDefinitionManager SettingDefinitionManager { get; }
protected Lazy<List<ISettingValueProvider>> Providers { get; }
protected ISettingEncryptionService SettingEncryptionService { get; }
protected SettingOptions Options { get; }
public SettingProvider(
IOptions<SettingOptions> options,
IServiceProvider serviceProvider,
ISettingDefinitionManager settingDefinitionManager,
ISettingEncryptionService settingEncryptionService)
{
SettingDefinitionManager = settingDefinitionManager;
SettingEncryptionService = settingEncryptionService;
Options = options.Value;
Providers = new Lazy<List<ISettingValueProvider>>(
() => Options
.ValueProviders
.Select(c => serviceProvider.GetRequiredService(c) as ISettingValueProvider)
.ToList(),
true
);
}
public virtual async Task<string> GetOrNullAsync(string name)
{
var setting = SettingDefinitionManager.Get(name);
var providers = Enumerable
.Reverse(Providers.Value);
if (setting.Providers.Any())
{
providers = providers.Where(p => setting.Providers.Contains(p.Name));
}
//TODO: How to implement setting.IsInherited?
var value = await GetOrNullValueFromProvidersAsync(providers, setting);
if (setting.IsEncrypted)
{
value = SettingEncryptionService.Decrypt(setting, value);
}
return value;
}
public virtual async Task<List<SettingValue>> GetAllAsync()
{
var settingValues = new Dictionary<string, SettingValue>();
var settingDefinitions = SettingDefinitionManager.GetAll();
foreach (var provider in Providers.Value)
{
foreach (var setting in settingDefinitions)
{
var value = await provider.GetOrNullAsync(setting);
if (value != null)
{
if (setting.IsEncrypted)
{
value = SettingEncryptionService.Decrypt(setting, value);
}
settingValues[setting.Name] = new SettingValue(setting.Name, value);
}
}
}
return settingValues.Values.ToList();
}
protected virtual async Task<string> GetOrNullValueFromProvidersAsync(
IEnumerable<ISettingValueProvider> providers,
SettingDefinition setting)
{
foreach (var provider in providers)
{
var value = await provider.GetOrNullAsync(setting);
if (value != null)
{
return value;
}
}
return null;
}
}
}

56
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingProviderExtensions.cs

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Threading;
namespace Volo.Abp.Settings
{
public static class SettingProviderExtensions
{
public static async Task<bool> IsTrueAsync([NotNull] this ISettingProvider settingProvider, [NotNull] string name)
{
Check.NotNull(settingProvider, nameof(settingProvider));
Check.NotNull(name, nameof(name));
return string.Equals(
await settingProvider.GetOrNullAsync(name),
"true",
StringComparison.OrdinalIgnoreCase
);
}
public static async Task<T> GetAsync<T>([NotNull] this ISettingProvider settingProvider, [NotNull] string name, T defaultValue = default)
where T : struct
{
Check.NotNull(settingProvider, nameof(settingProvider));
Check.NotNull(name, nameof(name));
var value = await settingProvider.GetOrNullAsync(name);
return value?.To<T>() ?? defaultValue;
}
public static string GetOrNull([NotNull] this ISettingProvider settingProvider, [NotNull] string name)
{
Check.NotNull(settingProvider, nameof(settingProvider));
return AsyncHelper.RunSync(() => settingProvider.GetOrNullAsync(name));
}
public static List<SettingValue> GetAll([NotNull] this ISettingProvider settingProvider)
{
Check.NotNull(settingProvider, nameof(settingProvider));
return AsyncHelper.RunSync(settingProvider.GetAllAsync);
}
public static T Get<T>([NotNull] this ISettingProvider settingProvider, [NotNull] string name, T defaultValue = default)
where T : struct
{
return AsyncHelper.RunSync(() => settingProvider.GetAsync(name, defaultValue));
}
public static bool IsTrue([NotNull] this ISettingProvider settingProvider, [NotNull] string name)
{
return AsyncHelper.RunSync(() => settingProvider.IsTrueAsync(name));
}
}
}

5
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValue.cs

@ -1,5 +1,8 @@
namespace Volo.Abp.Settings
using System;
namespace Volo.Abp.Settings
{
[Serializable]
public class SettingValue : NameValue
{
/// <summary>

6
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProvider.cs

@ -14,10 +14,6 @@ namespace Volo.Abp.Settings
SettingStore = settingStore;
}
public abstract Task<string> GetOrNullAsync(SettingDefinition setting, string providerKey);
public abstract Task SetAsync(SettingDefinition setting, string value, string providerKey);
public abstract Task ClearAsync(SettingDefinition setting, string providerKey);
public abstract Task<string> GetOrNullAsync(SettingDefinition setting);
}
}

25
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/TenantSettingValueProvider.cs

@ -0,0 +1,25 @@
using System.Threading.Tasks;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Settings
{
public class TenantSettingValueProvider : SettingValueProvider
{
public const string ProviderName = "Tenant";
public override string Name => ProviderName;
protected ICurrentTenant CurrentTenant { get; }
public TenantSettingValueProvider(ISettingStore settingStore, ICurrentTenant currentTenant)
: base(settingStore)
{
CurrentTenant = currentTenant;
}
public override async Task<string> GetOrNullAsync(SettingDefinition setting)
{
return await SettingStore.GetOrNullAsync(setting.Name, Name, CurrentTenant.Id?.ToString());
}
}
}

30
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/UserSettingValueProvider.cs

@ -0,0 +1,30 @@
using System.Threading.Tasks;
using Volo.Abp.Users;
namespace Volo.Abp.Settings
{
public class UserSettingValueProvider : SettingValueProvider
{
public const string ProviderName = "User";
public override string Name => ProviderName;
protected ICurrentUser CurrentUser { get; }
public UserSettingValueProvider(ISettingStore settingStore, ICurrentUser currentUser)
: base(settingStore)
{
CurrentUser = currentUser;
}
public override async Task<string> GetOrNullAsync(SettingDefinition setting)
{
if (CurrentUser.Id == null)
{
return null;
}
return await SettingStore.GetOrNullAsync(setting.Name, Name, CurrentUser.Id.ToString());
}
}
}

1
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs

@ -82,6 +82,7 @@ namespace Volo.Abp.AspNetCore.Mvc
{
var app = context.GetApplicationBuilder();
app.UseCorrelationId();
app.UseMiddleware<FakeAuthenticationMiddleware>();
app.UseAuditing();
app.UseUnitOfWork();

53
framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingManager_Tests.cs

@ -1,53 +0,0 @@
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.Abp.Settings
{
public class SettingManager_Tests : AbpIntegratedTest<AbpSettingsTestModule>
{
private readonly ISettingManager _settingManager;
public SettingManager_Tests()
{
_settingManager = GetRequiredService<ISettingManager>();
}
[Fact]
public async Task Should_Get_Null_If_No_Value_Provided_And_No_Default_Value()
{
(await _settingManager.GetOrNullAsync(TestSettingNames.TestSettingWithoutDefaultValue))
.ShouldBeNull();
}
[Fact]
public async Task Should_Get_Default_Value_If_No_Value_Provided_And_There_Is_A_Default_Value()
{
(await _settingManager.GetOrNullAsync(TestSettingNames.TestSettingWithDefaultValue))
.ShouldBe("default-value");
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData("abc")]
[InlineData("This is a relatively long text... This is a relatively long text... This is a relatively long text... ")]
public async Task Should_Set_And_Get_Encrypted_Values(string plainValue)
{
(await _settingManager.GetOrNullAsync(TestSettingNames.TestSettingEncrypted))
.ShouldBeNull();
await _settingManager.SetAsync(
TestSettingNames.TestSettingEncrypted,
plainValue,
TestSettingValueProvider.ProviderName,
null
);
(await _settingManager.GetOrNullAsync(TestSettingNames.TestSettingEncrypted))
.ShouldBe(plainValue);
}
//TODO: Needs more tests with more advanced scenarios.
}
}

30
framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingProvider_Tests.cs

@ -0,0 +1,30 @@
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.Abp.Settings
{
public class SettingProvider_Tests : AbpIntegratedTest<AbpSettingsTestModule>
{
private readonly ISettingProvider _settingProvider;
public SettingProvider_Tests()
{
_settingProvider = GetRequiredService<ISettingProvider>();
}
[Fact]
public async Task Should_Get_Null_If_No_Value_Provided_And_No_Default_Value()
{
(await _settingProvider.GetOrNullAsync(TestSettingNames.TestSettingWithoutDefaultValue))
.ShouldBeNull();
}
[Fact]
public async Task Should_Get_Default_Value_If_No_Value_Provided_And_There_Is_A_Default_Value()
{
(await _settingProvider.GetOrNullAsync(TestSettingNames.TestSettingWithDefaultValue))
.ShouldBe("default-value");
}
}
}

14
framework/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/TestSettingValueProvider.cs

@ -17,21 +17,9 @@ namespace Volo.Abp.Settings
_values = new Dictionary<string, string>();
}
public Task<string> GetOrNullAsync(SettingDefinition setting, string providerKey)
public Task<string> GetOrNullAsync(SettingDefinition setting)
{
return Task.FromResult(_values.GetOrDefault(setting.Name));
}
public Task SetAsync(SettingDefinition setting, string value, string providerKey)
{
_values[setting.Name] = value;
return Task.CompletedTask;
}
public Task ClearAsync(SettingDefinition setting, string providerKey)
{
_values.Remove(setting.Name);
return Task.CompletedTask;
}
}
}

4
modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml

@ -2,7 +2,7 @@
@using Volo.Abp.Account.Web.Settings
@model Volo.Abp.Account.Web.Pages.Account.LoginModel
@inherits Volo.Abp.Account.Web.Pages.Account.AccountPage
@inject Volo.Abp.Settings.ISettingManager SettingManager
@inject Volo.Abp.Settings.ISettingProvider SettingProvider
@if (Model.EnableLocalLogin)
{
<form method="post">
@ -29,7 +29,7 @@
</form>
<div style="padding-top: 20px">
@if (string.Equals(await SettingManager.GetOrNullAsync(AccountSettingNames.IsSelfRegistrationEnabled), "true", StringComparison.OrdinalIgnoreCase))
@if (string.Equals(await SettingProvider.GetOrNullAsync(AccountSettingNames.IsSelfRegistrationEnabled), "true", StringComparison.OrdinalIgnoreCase))
{
<a href="@Url.Page("./Register", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})">@L["Register"]</a>
}

2
modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs

@ -48,7 +48,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
protected virtual async Task CheckSelfRegistrationAsync()
{
if (!await SettingManager.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled))
if (!await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled))
{
throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]);
}

2
modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/AuditLogConsts.cs

@ -2,6 +2,8 @@
{
public static class AuditLogConsts
{
public const int MaxApplicationNameLength = 96;
public const int MaxClientIpAddressLength = 64;
public const int MaxClientNameLength = 128;

4
modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Auditing;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
@ -12,6 +11,8 @@ namespace Volo.Abp.AuditLogging
[DisableAuditing]
public class AuditLog : AggregateRoot<Guid>, IMultiTenant
{
public virtual string ApplicationName { get; set; }
public virtual Guid? UserId { get; protected set; }
public virtual string UserName { get; protected set; }
@ -58,6 +59,7 @@ namespace Volo.Abp.AuditLogging
public AuditLog(IGuidGenerator guidGenerator, AuditLogInfo auditInfo)
{
Id = guidGenerator.Create();
ApplicationName = auditInfo.ApplicationName;
TenantId = auditInfo.TenantId;
UserId = auditInfo.UserId;
UserName = auditInfo.UserName.Truncate(AuditLogConsts.MaxUserNameLength);

1
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingtDbContextModelBuilderExtensions.cs

@ -24,6 +24,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
b.ConfigureExtraProperties();
b.Property(x => x.ApplicationName).HasMaxLength(AuditLogConsts.MaxApplicationNameLength).HasColumnName(nameof(AuditLog.ApplicationName));
b.Property(x => x.ClientIpAddress).HasMaxLength(AuditLogConsts.MaxClientIpAddressLength).HasColumnName(nameof(AuditLog.ClientIpAddress));
b.Property(x => x.ClientName).HasMaxLength(AuditLogConsts.MaxClientNameLength).HasColumnName(nameof(AuditLog.ClientName));
b.Property(x => x.ClientId).HasMaxLength(AuditLogConsts.MaxClientIdLength).HasColumnName(nameof(AuditLog.ClientId));

4
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityPermissionDefinitionProvider.cs

@ -22,7 +22,9 @@ namespace Volo.Abp.Identity
usersPermission.AddChild(IdentityPermissions.Users.Delete, L("Permission:Delete"));
usersPermission.AddChild(IdentityPermissions.Users.ManagePermissions, L("Permission:ChangePermissions"));
identityGroup.AddPermission(IdentityPermissions.UserLookup.Default, L("Permission:UserLookup"));
identityGroup
.AddPermission(IdentityPermissions.UserLookup.Default, L("Permission:UserLookup"))
.WithProviders(ClientPermissionValueProvider.ProviderName);
}
private static LocalizableString L(string name)

3
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityPermissions.cs

@ -41,7 +41,8 @@
Users.Create,
Users.Update,
Users.Delete,
Users.ManagePermissions
Users.ManagePermissions,
UserLookup.Default
};
}
}

4
modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs

@ -28,12 +28,12 @@ namespace Volo.Abp.Identity
{
var user = await _userManager.GetByIdAsync(CurrentUser.GetId());
if (await SettingManager.IsTrueAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled))
if (await SettingProvider.IsTrueAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled))
{
(await _userManager.SetUserNameAsync(user, input.UserName)).CheckErrors();
}
if (await SettingManager.IsTrueAsync(IdentitySettingNames.User.IsEmailUpdateEnabled))
if (await SettingProvider.IsTrueAsync(IdentitySettingNames.User.IsEmailUpdateEnabled))
{
(await _userManager.SetEmailAsync(user, input.Email)).CheckErrors();
}

2
modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj

@ -23,6 +23,8 @@
<ProjectReference Include="..\..\..\users\src\Volo.Abp.Users.Domain\Volo.Abp.Users.Domain.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" />
<ProjectReference Include="..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Domain\Volo.Abp.SettingManagement.Domain.csproj" />
</ItemGroup>
<ItemGroup>

33
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptionsFactory.cs

@ -10,15 +10,15 @@ namespace Volo.Abp.Identity
{
public class AbpIdentityOptionsFactory : AbpOptionsFactory<IdentityOptions>
{
private readonly ISettingManager _settingManager;
private readonly ISettingProvider _settingProvider;
public AbpIdentityOptionsFactory(
IEnumerable<IConfigureOptions<IdentityOptions>> setups,
IEnumerable<IPostConfigureOptions<IdentityOptions>> postConfigures,
ISettingManager settingManager)
ISettingProvider settingProvider)
: base(setups, postConfigures)
{
_settingManager = settingManager;
_settingProvider = settingProvider;
}
public override IdentityOptions Create(string name)
@ -32,19 +32,20 @@ namespace Volo.Abp.Identity
protected virtual void OverrideOptions(IdentityOptions options)
{
options.Password.RequiredLength = _settingManager.Get(IdentitySettingNames.Password.RequiredLength, options.Password.RequiredLength);
options.Password.RequiredUniqueChars = _settingManager.Get(IdentitySettingNames.Password.RequiredUniqueChars, options.Password.RequiredUniqueChars);
options.Password.RequireNonAlphanumeric = _settingManager.Get(IdentitySettingNames.Password.RequireNonAlphanumeric, options.Password.RequireNonAlphanumeric);
options.Password.RequireLowercase = _settingManager.Get(IdentitySettingNames.Password.RequireLowercase, options.Password.RequireLowercase);
options.Password.RequireUppercase = _settingManager.Get(IdentitySettingNames.Password.RequireUppercase, options.Password.RequireUppercase);
options.Password.RequireDigit = _settingManager.Get(IdentitySettingNames.Password.RequireDigit, options.Password.RequireDigit);
options.Lockout.AllowedForNewUsers = _settingManager.Get(IdentitySettingNames.Lockout.AllowedForNewUsers, options.Lockout.AllowedForNewUsers);
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds(_settingManager.Get(IdentitySettingNames.Lockout.LockoutDuration, options.Lockout.DefaultLockoutTimeSpan.TotalSeconds.To<int>()));
options.Lockout.MaxFailedAccessAttempts = _settingManager.Get(IdentitySettingNames.Lockout.MaxFailedAccessAttempts, options.Lockout.MaxFailedAccessAttempts);
options.SignIn.RequireConfirmedEmail = _settingManager.Get(IdentitySettingNames.SignIn.RequireConfirmedEmail, options.SignIn.RequireConfirmedEmail);
options.SignIn.RequireConfirmedPhoneNumber = _settingManager.Get(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, options.SignIn.RequireConfirmedPhoneNumber);
options.Password.RequiredLength = _settingProvider.Get(IdentitySettingNames.Password.RequiredLength, options.Password.RequiredLength);
options.Password.RequiredUniqueChars = _settingProvider.Get(IdentitySettingNames.Password.RequiredUniqueChars, options.Password.RequiredUniqueChars);
options.Password.RequireNonAlphanumeric = _settingProvider.Get(IdentitySettingNames.Password.RequireNonAlphanumeric, options.Password.RequireNonAlphanumeric);
options.Password.RequireLowercase = _settingProvider.Get(IdentitySettingNames.Password.RequireLowercase, options.Password.RequireLowercase);
options.Password.RequireUppercase = _settingProvider.Get(IdentitySettingNames.Password.RequireUppercase, options.Password.RequireUppercase);
options.Password.RequireDigit = _settingProvider.Get(IdentitySettingNames.Password.RequireDigit, options.Password.RequireDigit);
options.Lockout.AllowedForNewUsers = _settingProvider.Get(IdentitySettingNames.Lockout.AllowedForNewUsers, options.Lockout.AllowedForNewUsers);
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds(_settingProvider.Get(IdentitySettingNames.Lockout.LockoutDuration, options.Lockout.DefaultLockoutTimeSpan.TotalSeconds.To<int>()));
options.Lockout.MaxFailedAccessAttempts = _settingProvider.Get(IdentitySettingNames.Lockout.MaxFailedAccessAttempts, options.Lockout.MaxFailedAccessAttempts);
options.SignIn.RequireConfirmedEmail = _settingProvider.Get(IdentitySettingNames.SignIn.RequireConfirmedEmail, options.SignIn.RequireConfirmedEmail);
options.SignIn.RequireConfirmedPhoneNumber = _settingProvider.Get(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, options.SignIn.RequireConfirmedPhoneNumber);
}
}
}

10
modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityOptions_Tests.cs

@ -13,13 +13,13 @@ namespace Volo.Abp.Identity
{
public class IdentityOptions_Tests : AbpIdentityDomainTestBase
{
private ISettingManager _settingManager;
private ISettingProvider _settingProvider;
protected override void AfterAddApplication(IServiceCollection services)
{
_settingManager = Substitute.For<ISettingManager>();
_settingManager.GetOrNullAsync(Arg.Any<string>()).Returns((string) null);
services.Replace(ServiceDescriptor.Singleton(_settingManager));
_settingProvider = Substitute.For<ISettingProvider>();
_settingProvider.GetOrNullAsync(Arg.Any<string>()).Returns((string) null);
services.Replace(ServiceDescriptor.Singleton(_settingProvider));
}
[Fact]
@ -38,7 +38,7 @@ namespace Volo.Abp.Identity
options.Password.RequiredUniqueChars.ShouldBe(1); //Default value
}
_settingManager.GetOrNullAsync(IdentitySettingNames.Password.RequiredLength).Returns(Task.FromResult("42"));
_settingProvider.GetOrNullAsync(IdentitySettingNames.Password.RequiredLength).Returns(Task.FromResult("42"));
using (var scope2 = ServiceProvider.CreateScope())
{

2
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/AbpIdentityServerMongoDbModule.cs

@ -31,7 +31,7 @@ namespace Volo.Abp.IdentityServer.MongoDB
options.AddRepository<ApiResource, MongoApiResourceRepository>();
options.AddRepository<IdentityResource, MongoIdentityResourceRepository>();
options.AddRepository<Client, MongoClientRepository>();
options.AddRepository<PersistedGrant, MongoPersistedGrantRepository>();
options.AddRepository<PersistedGrant, MongoPersistentGrantRepository>();
});
}
}

4
modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistedGrantRepository.cs

@ -10,9 +10,9 @@ using Volo.Abp.MongoDB;
namespace Volo.Abp.IdentityServer.MongoDB
{
public class MongoPersistedGrantRepository : MongoDbRepository<IAbpIdentityServerMongoDbContext, PersistedGrant, Guid>, IPersistentGrantRepository
public class MongoPersistentGrantRepository : MongoDbRepository<IAbpIdentityServerMongoDbContext, PersistedGrant, Guid>, IPersistentGrantRepository
{
public MongoPersistedGrantRepository(IMongoDbContextProvider<IAbpIdentityServerMongoDbContext> dbContextProvider) : base(dbContextProvider)
public MongoPersistentGrantRepository(IMongoDbContextProvider<IAbpIdentityServerMongoDbContext> dbContextProvider) : base(dbContextProvider)
{
}

4
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo.Abp.PermissionManagement.Domain.Shared.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\common.props" />
@ -14,7 +14,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
</ItemGroup>
</Project>

16
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/AbpPermissionManagementDomainSharedModule.cs

@ -1,9 +1,21 @@
using Volo.Abp.Modularity;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement.Localization;
namespace Volo.Abp.PermissionManagement
{
[DependsOn(
typeof(AbpLocalizationModule)
)]
public class AbpPermissionManagementDomainSharedModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AbpPermissionManagementResource>("en");
});
}
}
}

10
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/AbpPermissionManagementResource.cs

@ -0,0 +1,10 @@
using Volo.Abp.Localization;
namespace Volo.Abp.PermissionManagement.Localization
{
[LocalizationResourceName("AbpPermissionManagement")]
public class AbpPermissionManagementResource
{
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save