Browse Source

Merge pull request #10 from abpframework/master

merge
pull/847/head
Marcelo Mohr Maciel 8 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.AspNetCore.Mvc.Contracts\Volo.Abp.AspNetCore.Mvc.Contracts.csproj" />
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.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.Http.Client\Volo.Abp.Http.Client.csproj" />
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
</ItemGroup> </ItemGroup>
</Project> </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 Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Caching; using Volo.Abp.Caching;
using Volo.Abp.Http.Client; using Volo.Abp.Http.Client;
using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.Client namespace Volo.Abp.AspNetCore.Mvc.Client
@ -8,7 +9,8 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
[DependsOn( [DependsOn(
typeof(AbpHttpClientModule), typeof(AbpHttpClientModule),
typeof(AbpAspNetCoreMvcContractsModule), typeof(AbpAspNetCoreMvcContractsModule),
typeof(AbpCachingModule) typeof(AbpCachingModule),
typeof(AbpLocalizationModule)
)] )]
public class AbpAspNetCoreMvcClientModule : AbpModule public class AbpAspNetCoreMvcClientModule : AbpModule
{ {
@ -21,6 +23,11 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
RemoteServiceName, RemoteServiceName,
asDefaultServices: false 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;
using System.Globalization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Distributed;
@ -45,7 +46,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
async () => await Proxy.Service.GetAsync(), async () => await Proxy.Service.GetAsync(),
() => new DistributedCacheEntryOptions () => 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() 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 ApplicationAuthConfigurationDto Auth { get; set; }
public ApplicationSettingConfigurationDto Setting { get; set; }
public CurrentUserDto CurrentUser { 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); Process(context, output);
return Task.CompletedTask; 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 System.Text.Encodings.Web;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.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 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("breadcrumb-item");
output.Attributes.AddClass(AbpBreadcrumbItemActivePlaceholder); output.Attributes.AddClass(AbpBreadcrumbItemActivePlaceholder);
var list = GetValueFromContext<List<BreadcrumbItem>>(context, BreadcrumbItemsContent); var list = context.GetValue<List<BreadcrumbItem>>(BreadcrumbItemsContent);
output.Content.SetHtmlContent(GetInnerHtml(context, output)); output.Content.SetHtmlContent(GetInnerHtml(context, output));
list.Add(new BreadcrumbItem list.Add(new BreadcrumbItem
{ {
Html = RenderTagHelperOutput(output, _encoder), Html = output.Render(_encoder),
Active = TagHelper.Active 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 System.Text.Encodings.Web;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.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 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) 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)); 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.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse 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 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); tabHeaderItems.Add(html);

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

@ -1,10 +1,12 @@
using System; using System;
using System.Text; using System.Text;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; 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.Button;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
{ {
@ -22,22 +24,25 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
_serviceProvider = serviceProvider; _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.PreElement.SetHtmlContent(buttonsAsHtml);
output.TagName = "div"; output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag; output.TagMode = TagMode.StartTagAndEndTag;
output.Content.SetContent("");
output.Attributes.Clear(); 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 buttonBuilder = new StringBuilder("");
var mainButton = GetMainButton(context, output); var mainButton = GetMainButton(context, output, content);
buttonBuilder.AppendLine(mainButton); buttonBuilder.AppendLine(mainButton);
@ -51,10 +56,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
return buttonBuilder.ToString(); 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>(); var abpButtonTagHelper = _serviceProvider.GetRequiredService<AbpButtonTagHelper>();
abpButtonTagHelper.Icon = TagHelper.Icon; abpButtonTagHelper.Icon = TagHelper.Icon;
abpButtonTagHelper.Text = TagHelper.Text; abpButtonTagHelper.Text = TagHelper.Text;
abpButtonTagHelper.IconType = TagHelper.IconType; abpButtonTagHelper.IconType = TagHelper.IconType;
@ -62,15 +67,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown
abpButtonTagHelper.ButtonType = TagHelper.ButtonType; abpButtonTagHelper.ButtonType = TagHelper.ButtonType;
var attributes = GetAttributesForMainButton(context, output); 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)) if ((TagHelper.NavLink ?? false) || (TagHelper.Link ?? false))
{ {
var linkTag = ConvertButtonToLink(buttonTag); 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) 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; abpButtonTagHelper.ButtonType = TagHelper.ButtonType;
var attributes = GetAttributesForSplitButton(context, output); 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) 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) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {
output.TagName = "div"; output.TagName = "div";
output.Attributes.AddClass("dropdown");
output.Attributes.AddClass("btn-group"); output.Attributes.AddClass("btn-group");
SetDirection(context, output); 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 Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; 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.Button;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form 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 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(); await formTagOutput.GetChildContentAsync();
@ -146,7 +147,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{ {
var abpSelectTagHelper = GetSelectGroupTagHelper(context, output, model); 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) 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); GetSelectTagHelper(model);
} }
private AbpTagHelper GetSelectTagHelper(ModelExpression model) protected virtual AbpTagHelper GetSelectTagHelper(ModelExpression model)
{ {
var abpSelectTagHelper = _serviceProvider.GetRequiredService<AbpSelectTagHelper>(); var abpSelectTagHelper = _serviceProvider.GetRequiredService<AbpSelectTagHelper>();
abpSelectTagHelper.AspFor = model; abpSelectTagHelper.AspFor = model;
@ -165,9 +166,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return abpSelectTagHelper; 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>(); var abpRadioInputTagHelper = _serviceProvider.GetRequiredService<AbpRadioInputTagHelper>();
abpRadioInputTagHelper.AspFor = model; abpRadioInputTagHelper.AspFor = model;
abpRadioInputTagHelper.AspItems = null; abpRadioInputTagHelper.AspItems = null;
@ -184,7 +185,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
abpButtonTagHelper.Text = "Submit"; abpButtonTagHelper.Text = "Submit";
abpButtonTagHelper.ButtonType = AbpButtonType.Primary; 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) 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.ViewContext = TagHelper.ViewContext;
abpInputTagHelper.DisplayRequiredSymbol = TagHelper.RequiredSymbols ?? true; 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) 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) protected virtual bool AreSelectItemsProvided(ModelExplorer explorer)
{ {
return GetAttribute<SelectItems>(explorer) != null; return explorer.GetAttribute<SelectItems>() != null;
} }
protected virtual bool IsRadioGroup(ModelExplorer explorer) 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;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
@ -6,6 +7,7 @@ using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.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 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 innerHtml = GetFormInputGroupAsHtml(context, output, out var isCheckbox);
var order = GetInputOrder(TagHelper.AspFor.ModelExplorer); var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder();
AddGroupToFormGroupContents( AddGroupToFormGroupContents(
context, context,
@ -45,7 +47,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
output.TagMode = TagMode.StartTagAndEndTag; output.TagMode = TagMode.StartTagAndEndTag;
output.TagName = "div"; output.TagName = "div";
LeaveOnlyGroupAttributes(context, output); 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.Attributes.AddClass(isCheckbox ? "mb-2" : "");
output.Content.SetHtmlContent(output.Content.GetContent() + innerHtml); 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) protected virtual string GetFormInputGroupAsHtml(TagHelperContext context, TagHelperOutput output, out bool isCheckbox)
{ {
var inputTag = GetInputTagHelperOutput(context, output, out 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 label = GetLabelAsHtml(context, output, inputTag, isCheckbox);
var info = GetInfoAsHtml(context, output, inputTag, isCheckbox); var info = GetInfoAsHtml(context, output, inputTag, isCheckbox);
var validation = isCheckbox ? "" : GetValidationAsHtml(context, output, inputTag); 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" } }; 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) 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) 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 + Environment.NewLine + innerHtml + Environment.NewLine +
"</div>"; "</div>";
} }
protected virtual TagHelper GetInputTagHelper(TagHelperContext context, TagHelperOutput output) 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) if (textAreaAttribute != null)
{ {
@ -121,7 +124,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{ {
var tagHelper = GetInputTagHelper(context, output); 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); ConvertToTextAreaIfTextArea(inputTagHelperOutput);
AddDisabledAttribute(inputTagHelperOutput); AddDisabledAttribute(inputTagHelperOutput);
@ -141,7 +144,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
if (isCheckbox) if (isCheckbox)
{ {
className = "form-check-input"; className = "custom-control-input";
} }
inputTagHelperOutput.Attributes.AddClass(className + " " + GetSize(context, output)); 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) protected virtual void AddDisabledAttribute(TagHelperOutput inputTagHelperOutput)
{ {
if (inputTagHelperOutput.Attributes.ContainsName("disabled") == false && 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", ""); inputTagHelperOutput.Attributes.Add("disabled", "");
} }
@ -167,7 +170,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual void AddReadOnlyAttribute(TagHelperOutput inputTagHelperOutput) protected virtual void AddReadOnlyAttribute(TagHelperOutput inputTagHelperOutput)
{ {
if (inputTagHelperOutput.Attributes.ContainsName("readonly") == false && 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", ""); inputTagHelperOutput.Attributes.Add("readonly", "");
} }
@ -180,7 +183,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return; return;
} }
var attribute = GetAttribute<Placeholder>(TagHelper.AspFor.ModelExplorer); var attribute = TagHelper.AspFor.ModelExplorer.GetAttribute<Placeholder>();
if (attribute != null) if (attribute != null)
{ {
@ -192,7 +195,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual void AddInfoTextId(TagHelperOutput inputTagHelperOutput) protected virtual void AddInfoTextId(TagHelperOutput inputTagHelperOutput)
{ {
if (GetAttribute<InputInfoText>(TagHelper.AspFor.ModelExplorer) == null) if (TagHelper.AspFor.ModelExplorer.GetAttribute<InputInfoText>() == null)
{ {
return; return;
} }
@ -226,7 +229,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return GetLabelAsHtmlUsingTagHelper(context, output, isCheckbox) + GetRequiredSymbol(context, output, inputTag); 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) + ">" return "<label " + checkboxClass + GetIdAttributeAsString(inputTag) + ">"
+ TagHelper.Label + + TagHelper.Label +
@ -240,7 +243,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return ""; 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) 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 else
{ {
var infoAttribute = GetAttribute<InputInfoText>(TagHelper.AspFor.ModelExplorer); var infoAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<InputInfoText>();
if (infoAttribute != null) if (infoAttribute != null)
{ {
text = infoAttribute.Text; text = infoAttribute.Text;
@ -294,15 +297,15 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
if (isCheckbox) 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) protected virtual void ConvertToTextAreaIfTextArea(TagHelperOutput tagHelperOutput)
{ {
var textAreaAttribute = GetAttribute<TextArea>(TagHelper.AspFor.ModelExplorer); var textAreaAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<TextArea>();
if (textAreaAttribute == null) if (textAreaAttribute == null)
{ {
@ -354,7 +357,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
protected virtual string GetSize(TagHelperContext context, TagHelperOutput output) 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) 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"); 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.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form 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); var selectItems = GetSelectItems(context,output);
SetSelectedValue(context, output, selectItems); SetSelectedValue(context, output, selectItems);
var order = GetInputOrder(TagHelper.AspFor.ModelExplorer); var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder();
var html = GetHtml(context, output, selectItems); 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); return GetSelectItemsFromEnum(context, output, TagHelper.AspFor.ModelExplorer);
} }
var selectItemsAttribute = GetAttribute<SelectItems>(TagHelper.AspFor.ModelExplorer); var selectItemsAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<SelectItems>();
if (selectItemsAttribute != null) if (selectItemsAttribute != null)
{ {
return GetSelectItemsFromAttribute(selectItemsAttribute, TagHelper.AspFor.ModelExplorer); 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(); 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.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.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 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 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); 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) protected virtual string GetFormInputGroupAsHtml(TagHelperContext context, TagHelperOutput output)
{ {
var selectTag = GetSelectTag(context, output); var selectTag = GetSelectTag(context, output);
var selectAsHtml = RenderTagHelperOutput(selectTag, _encoder); var selectAsHtml = selectTag.Render(_encoder);
var label = GetLabelAsHtml(context, output, selectTag); var label = GetLabelAsHtml(context, output, selectTag);
var validation = GetValidationAsHtml(context, output, selectTag); var validation = GetValidationAsHtml(context, output, selectTag);
var infoText = GetInfoAsHtml(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 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("form-control");
selectTagHelperOutput.Attributes.AddClass(GetSize(context, output)); 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) 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")) 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); return GetSelectItemsFromEnum(context, output, TagHelper.AspFor.ModelExplorer);
} }
var selectItemsAttribute = GetAttribute<SelectItems>(TagHelper.AspFor.ModelExplorer); var selectItemsAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<SelectItems>();
if (selectItemsAttribute != null) if (selectItemsAttribute != null)
{ {
return GetSelectItemsFromAttribute(selectItemsAttribute, TagHelper.AspFor.ModelExplorer); return GetSelectItemsFromAttribute(selectItemsAttribute, TagHelper.AspFor.ModelExplorer);
@ -132,12 +133,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return ""; 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) protected virtual void AddInfoTextId(TagHelperOutput inputTagHelperOutput)
{ {
if (GetAttribute<InputInfoText>(TagHelper.AspFor.ModelExplorer) == null) if (TagHelper.AspFor.ModelExplorer.GetAttribute<InputInfoText>() == null)
{ {
return; return;
} }
@ -164,7 +165,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
} }
else else
{ {
var infoAttribute = GetAttribute<InputInfoText>(TagHelper.AspFor.ModelExplorer); var infoAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute<InputInfoText>();
if (infoAttribute != null) if (infoAttribute != null)
{ {
text = infoAttribute.Text; text = infoAttribute.Text;
@ -227,7 +228,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
ViewContext = TagHelper.ViewContext 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) 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" } }; 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) 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) if (attribute != null)
{ {
@ -255,11 +256,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
switch (TagHelper.Size) switch (TagHelper.Size)
{ {
case AbpFormControlSize.Small: case AbpFormControlSize.Small:
return "form-control-sm"; return "custom-select-sm";
case AbpFormControlSize.Medium: case AbpFormControlSize.Medium:
return "form-control-md"; return "custom-select-md";
case AbpFormControlSize.Large: case AbpFormControlSize.Large:
return "form-control-lg"; return "custom-select-lg";
} }
return ""; return "";
@ -277,6 +278,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
attrList.Add(tagHelperAttribute); attrList.Add(tagHelperAttribute);
} }
attrList.AddClass("custom-select");
return attrList; return attrList;
} }
@ -294,5 +297,27 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
output.Attributes.Add(newAttritube); 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.TagName = "div";
output.Attributes.AddClass("col"); output.Attributes.AddClass("col");
ProcessSizeClass(output, TagHelper.Size, ""); ProcessSizeClasses(context, output);
ProcessSizeClass(output, TagHelper.SizeSm, "-sm"); ProcessOffsetClasses(context, output);
ProcessSizeClass(output, TagHelper.SizeMd, "-md"); ProcessColumnOrder(context, output);
ProcessSizeClass(output, TagHelper.SizeLg, "-lg"); ProcessVerticalAlign(context, output);
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);
} }
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) if (size == ColumnSize.Undefined)
{ {
@ -47,7 +55,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid
output.Attributes.AddClass(classString); 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) if (size == ColumnSize.Undefined)
{ {
@ -68,7 +76,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid
output.Attributes.AddClass(classString); output.Attributes.AddClass(classString);
} }
protected virtual void ProcessVerticalAlign(TagHelperOutput output) protected virtual void ProcessVerticalAlign(TagHelperContext context, TagHelperOutput output)
{ {
if (TagHelper.VAlign == VerticalAlign.Default) 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()); 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) 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.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.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.Pagination 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 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]); tagHelperOutput.Content.SetHtmlContent(localizer[localizationKey]);
var renderedHtml = RenderTagHelperOutput(tagHelperOutput, _encoder); var renderedHtml = tagHelperOutput.Render(_encoder);
return renderedHtml; 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) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {
if (!TagHelper.Disabled??true) if (!TagHelper.Disabled ?? true)
{ {
SetDataToggle(context, output); SetDataToggle(context, output);
SetDataPlacement(context, output); SetDataPlacement(context, output);
@ -16,21 +16,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Popover
} }
else else
{ {
SetDisabled(context,output); SetDisabled(context, output);
} }
} }
protected virtual void SetDisabled(TagHelperContext context, TagHelperOutput output) protected virtual void SetDisabled(TagHelperContext context, TagHelperOutput output)
{ {
var triggerAsHtml = TagHelper.Dismissible ?? false ? "datatrigger=\"focus\" " : ""; 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 titleAttribute = output.Attributes.FirstOrDefault(at => at.Name == "title");
var titleAsHtml = titleAttribute == null? "":"title=\""+ titleAttribute.Value +"\" "; var titleAsHtml = titleAttribute == null ? "" : "title=\"" + titleAttribute.Value + "\" ";
var preElementHtml = "<span class=\"d-inline-block\" " + titleAsHtml + triggerAsHtml + dataPlacementAsHtml + "data-toggle=\"popover\" data-content=\"" + GetDataContent() + "\">";
var preElementHtml = "<span class=\"d-inline-block\" "+ titleAsHtml + triggerAsHtml + dataPlacementAsHtml + "data-toggle=\"popover\" data-content=\"" +GetDataContent()+"\">";
var postElementHtml = "</span>"; var postElementHtml = "</span>";
output.PreElement.SetHtmlContent(preElementHtml); 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.Attributes.AddClass("progress");
output.TagName = "div"; 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.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab 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(); await output.GetChildContentAsync();
var tabHeader = GetTabHeaderItem(context, output); 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)); 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.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab 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 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)); 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.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab 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 tabHeader = GetTabHeaderItem(context, output);
var tabContent = GetTabContentItem(innerContent.GetContent()); var tabContent = GetTabContentItem(innerContent.GetContent());
var tabHeaderItems = GetValueFromContext<List<TabItem>>(context, TabItems); var tabHeaderItems = context.GetValue<List<TabItem>>(TabItems);
var active = TagHelper.Active ?? false; 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) { var localize = function (key) {
return abp.localization.getResource('AbpUi')(key); return abp.localization.getResource('AbpUi')(key);
} };
var recordActions = function () { var recordActions = function () {
if (!$.fn.dataTableExt) { if (!$.fn.dataTableExt) {
@ -69,7 +69,7 @@
} else { } else {
return visibilityField; return visibilityField;
} }
} };
var _createDropdownItem = function (record, fieldItem) { var _createDropdownItem = function (record, fieldItem) {
var $li = $('<li/>'); var $li = $('<li/>');
@ -83,7 +83,7 @@
$a.append($("<i>").addClass("fa fa-" + fieldItem.icon + " mr-1")); $a.append($("<i>").addClass("fa fa-" + fieldItem.icon + " mr-1"));
} else if (fieldItem.iconClass) { } else if (fieldItem.iconClass) {
$a.append($("<i>").addClass(fieldItem.iconClass + " mr-1")); $a.append($("<i>").addClass(fieldItem.iconClass + " mr-1"));
} }
$a.append(fieldItem.text); $a.append(fieldItem.text);
} }
@ -109,7 +109,7 @@
$a.appendTo($li); $a.appendTo($li);
return $li; return $li;
} };
var _createButtonDropdown = function (record, field) { var _createButtonDropdown = function (record, field) {
var $container = $('<div/>') var $container = $('<div/>')
@ -200,11 +200,11 @@
} }
throw "DTE#1: Cannot create row action. Either set element or items fields!"; throw "DTE#1: Cannot create row action. Either set element or items fields!";
} };
var hideColumnWithoutRedraw = function (tableInstance, colIndex) { var hideColumnWithoutRedraw = function (tableInstance, colIndex) {
tableInstance.fnSetColumnVis(colIndex, false, false); tableInstance.fnSetColumnVis(colIndex, false, false);
} };
var hideEmptyColumn = function (cellContent, tableInstance, colIndex) { var hideEmptyColumn = function (cellContent, tableInstance, colIndex) {
if (cellContent == "") { 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; 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 ICurrentTenant CurrentTenant { get; set; }
public ISettingManager SettingManager { get; set; } public ISettingProvider SettingProvider { get; set; }
public IModelStateValidator ModelValidator { 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 Microsoft.Extensions.Options;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.Authorization; using Volo.Abp.Authorization;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Settings;
using Volo.Abp.Users; using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
@ -19,18 +21,24 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
private readonly IAbpAuthorizationPolicyProvider _abpAuthorizationPolicyProvider; private readonly IAbpAuthorizationPolicyProvider _abpAuthorizationPolicyProvider;
private readonly IAuthorizationService _authorizationService; private readonly IAuthorizationService _authorizationService;
private readonly ICurrentUser _currentUser; private readonly ICurrentUser _currentUser;
private readonly ISettingProvider _settingProvider;
private readonly ISettingDefinitionManager _settingDefinitionManager;
public AbpApplicationConfigurationAppService( public AbpApplicationConfigurationAppService(
IOptions<AbpLocalizationOptions> localizationOptions, IOptions<AbpLocalizationOptions> localizationOptions,
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider, IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider,
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
ICurrentUser currentUser) ICurrentUser currentUser,
ISettingProvider settingProvider,
SettingDefinitionManager settingDefinitionManager)
{ {
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider; _abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider;
_authorizationService = authorizationService; _authorizationService = authorizationService;
_currentUser = currentUser; _currentUser = currentUser;
_settingProvider = settingProvider;
_settingDefinitionManager = settingDefinitionManager;
_localizationOptions = localizationOptions.Value; _localizationOptions = localizationOptions.Value;
} }
@ -40,9 +48,10 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
return new ApplicationConfigurationDto return new ApplicationConfigurationDto
{ {
Auth = await GetAuthConfig(), Auth = await GetAuthConfigAsync(),
Localization = GetLocalizationConfig(), 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(); var authConfig = new ApplicationAuthConfigurationDto();
@ -97,5 +106,25 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
return localizationConfig; 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;
using Volo.Abp.AspNetCore.Auditing; using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling; using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.Tracing;
using Volo.Abp.AspNetCore.Uow; using Volo.Abp.AspNetCore.Uow;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization; using Volo.Abp.Localization;
@ -40,6 +41,12 @@ namespace Microsoft.AspNetCore.Builder
.UseMiddleware<AbpUnitOfWorkMiddleware>(); .UseMiddleware<AbpUnitOfWorkMiddleware>();
} }
public static IApplicationBuilder UseCorrelationId(this IApplicationBuilder app)
{
return app
.UseMiddleware<AbpCorrelationIdMiddleware>();
}
public static IApplicationBuilder UseAbpRequestLocalization(this IApplicationBuilder app) public static IApplicationBuilder UseAbpRequestLocalization(this IApplicationBuilder app)
{ {
IReadOnlyList<LanguageInfo> languages; IReadOnlyList<LanguageInfo> languages;
@ -48,10 +55,10 @@ namespace Microsoft.AspNetCore.Builder
using (var scope = app.ApplicationServices.CreateScope()) using (var scope = app.ApplicationServices.CreateScope())
{ {
var languageProvider = scope.ServiceProvider.GetRequiredService<ILanguageProvider>(); var languageProvider = scope.ServiceProvider.GetRequiredService<ILanguageProvider>();
var settingManager = scope.ServiceProvider.GetRequiredService<ISettingManager>(); languages = languageProvider.GetLanguages();
languages = AsyncHelper.RunSync(() => languageProvider.GetLanguagesAsync()); var settingProvider = scope.ServiceProvider.GetRequiredService<ISettingProvider>();
defaultLanguage = settingManager.GetOrNull(LocalizationSettingNames.DefaultLanguage); defaultLanguage = settingProvider.GetOrNull(LocalizationSettingNames.DefaultLanguage);
} }
if (!languages.Any()) 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> /// </summary>
public bool IsEnabled { get; set; } 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> /// <summary>
/// Default: true. /// Default: true.
/// </summary> /// </summary>

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

@ -10,6 +10,8 @@ namespace Volo.Abp.Auditing
//TODO: Make serializable! //TODO: Make serializable!
public class AuditLogInfo : IMultiTenant, IHasExtraProperties public class AuditLogInfo : IMultiTenant, IHasExtraProperties
{ {
public string ApplicationName { get; set; }
public Guid? UserId { get; set; } public Guid? UserId { get; set; }
public string UserName { 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.DependencyInjection;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Timing; using Volo.Abp.Timing;
using Volo.Abp.Tracing;
using Volo.Abp.Users; using Volo.Abp.Users;
namespace Volo.Abp.Auditing namespace Volo.Abp.Auditing
@ -89,6 +90,7 @@ namespace Volo.Abp.Auditing
{ {
var auditInfo = new AuditLogInfo var auditInfo = new AuditLogInfo
{ {
ApplicationName = Options.ApplicationName,
TenantId = CurrentTenant.Id, TenantId = CurrentTenant.Id,
UserId = CurrentUser.Id, UserId = CurrentUser.Id,
UserName = CurrentUser.UserName, 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> /// </summary>
public PermissionDefinition Parent { get; private set; } 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 List<string> Providers { get; }
public ILocalizableString DisplayName 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); Logger.LogException(ex, LogLevel.Warning);
return null; return null;
} }
throw; 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; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
try try
{ {
return Cache.SetAsync( await Cache.SetAsync(
NormalizeKey(key), NormalizeKey(key),
ObjectSerializer.Serialize(value), ObjectSerializer.Serialize(value),
options ?? DefaultCacheOptions, options ?? DefaultCacheOptions,
@ -212,8 +213,9 @@ namespace Volo.Abp.Caching
if ((bool)hideErrors) if ((bool)hideErrors)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return Task.CompletedTask; return;
} }
throw; 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; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
try try
{ {
return Cache.RefreshAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token)); await Cache.RefreshAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token));
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool)hideErrors) if ((bool)hideErrors)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return Task.CompletedTask; return;
} }
throw; 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; hideErrors = hideErrors ?? _distributedCacheOption.HideErrors;
try try
{ {
return Cache.RemoveAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token)); await Cache.RemoveAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token));
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool)hideErrors) if ((bool)hideErrors)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return Task.CompletedTask; return;
} }
throw; 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 public interface ICorrelationIdProvider
{ {
[NotNull]
string Get(); 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.Http.Abstractions\Volo.Abp.Http.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" /> <ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.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" /> <ProjectReference Include="..\Volo.Abp.Validation\Volo.Abp.Validation.csproj" />
</ItemGroup> </ItemGroup>

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

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.Authorization; using Volo.Abp.Authorization;
using Volo.Abp.Domain; using Volo.Abp.Domain;
@ -8,17 +7,21 @@ using Volo.Abp.Http.Modeling;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.ObjectMapping; using Volo.Abp.ObjectMapping;
using Volo.Abp.Security; using Volo.Abp.Security;
using Volo.Abp.Settings;
using Volo.Abp.Uow; using Volo.Abp.Uow;
using Volo.Abp.Validation; using Volo.Abp.Validation;
namespace Volo.Abp.Application namespace Volo.Abp.Application
{ {
[DependsOn(typeof(AbpDddDomainModule))] [DependsOn(
[DependsOn(typeof(AbpSecurityModule))] typeof(AbpDddDomainModule),
[DependsOn(typeof(AbpObjectMappingModule))] typeof(AbpSecurityModule),
[DependsOn(typeof(AbpValidationModule))] typeof(AbpObjectMappingModule),
[DependsOn(typeof(AbpAuthorizationModule))] typeof(AbpValidationModule),
[DependsOn(typeof(AbpHttpAbstractionsModule))] typeof(AbpAuthorizationModule),
typeof(AbpHttpAbstractionsModule),
typeof(AbpSettingsModule)
)]
public class AbpDddApplicationModule : AbpModule public class AbpDddApplicationModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) 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 ICurrentUser CurrentUser { get; set; }
public ISettingManager SettingManager { get; set; } public ISettingProvider SettingProvider { get; set; }
public IClock Clock { 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.Linq;
using System.Reflection;
namespace Volo.Abp.Domain.Values 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/ //Inspired from https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/implement-value-objects
/// <summary> public abstract class ValueObject
/// 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>
{ {
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 false;
} }
return ReferenceEquals(left, null) || left.Equals(right);
}
var publicProperties = GetType().GetTypeInfo().GetProperties(); protected static bool NotEqualOperator(ValueObject left, ValueObject right)
if (!publicProperties.Any()) {
{ return !(EqualOperator(left, right));
return true;
}
return publicProperties.All(property => Equals(property.GetValue(this, null), property.GetValue(other, null)));
} }
protected abstract IEnumerable<object> GetAtomicValues();
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj == null) if (obj == null || obj.GetType() != GetType())
{ {
return false; return false;
} }
var item = obj as ValueObject<TValueObject>; ValueObject other = (ValueObject)obj;
return (object)item != null && Equals((TValueObject)item); IEnumerator<object> thisValues = GetAtomicValues().GetEnumerator();
} IEnumerator<object> otherValues = other.GetAtomicValues().GetEnumerator();
while (thisValues.MoveNext() && otherValues.MoveNext())
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())
{ {
return initialHasCode; if (ReferenceEquals(thisValues.Current, null) ^
} ReferenceEquals(otherValues.Current, null))
var hashCode = initialHasCode;
var changeMultiplier = false;
foreach (var property in publicProperties)
{
var value = property.GetValue(this, null);
if (value == null)
{ {
//support {"a",null,null,"a"} != {null,"a","a",null} return false;
hashCode = hashCode ^ (index * 13);
continue;
} }
hashCode = hashCode * (changeMultiplier ? 59 : 114) + value.GetHashCode(); if (thisValues.Current != null &&
changeMultiplier = !changeMultiplier; !thisValues.Current.Equals(otherValues.Current))
} {
return false;
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;
} }
return !thisValues.MoveNext() && !otherValues.MoveNext();
return x.Equals(y);
} }
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;
using Volo.Abp.Emailing.Templates.Virtual; using Volo.Abp.Emailing.Templates.Virtual;
using Volo.Abp.Localization; 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 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> /// <summary>
/// Creates a new <see cref="EmailSenderConfiguration"/>. /// Creates a new <see cref="EmailSenderConfiguration"/>.
/// </summary> /// </summary>
protected EmailSenderConfiguration(ISettingManager settingManager) protected EmailSenderConfiguration(ISettingProvider settingProvider)
{ {
SettingManager = settingManager; SettingProvider = settingProvider;
} }
/// <summary> /// <summary>
@ -30,7 +30,7 @@ namespace Volo.Abp.Emailing
/// <returns>Value of the setting</returns> /// <returns>Value of the setting</returns>
protected string GetNotEmptySettingValue(string name) protected string GetNotEmptySettingValue(string name)
{ {
var value = SettingManager.GetOrNull(name); var value = SettingProvider.GetOrNull(name);
if (value.IsNullOrEmpty()) 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 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) public SmtpEmailSenderConfiguration(ISettingProvider settingProvider)
: base(settingManager) : base(settingProvider)
{ {
} }

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

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

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

@ -1,17 +1,20 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Castle; using Volo.Abp.Castle;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.Threading;
namespace Volo.Abp.Http.Client namespace Volo.Abp.Http.Client
{ {
[DependsOn(typeof(AbpHttpModule))] [DependsOn(
[DependsOn(typeof(AbpCastleCoreModule))] typeof(AbpHttpModule),
typeof(AbpCastleCoreModule),
typeof(AbpThreadingModule)
)]
public class AbpHttpClientModule : AbpModule public class AbpHttpClientModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
var configuration = context.Services.GetConfiguration(); var configuration = context.Services.GetConfiguration();
Configure<RemoteServiceOptions>(configuration); 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.Linq;
using System.Net.Http; using System.Net.Http;
using System.Reflection; using System.Reflection;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
@ -15,21 +16,25 @@ using Volo.Abp.Http.ProxyScripting.Generators;
using Volo.Abp.Json; using Volo.Abp.Json;
using Volo.Abp.Reflection; using Volo.Abp.Reflection;
using Volo.Abp.Threading; using Volo.Abp.Threading;
using Volo.Abp.Tracing;
namespace Volo.Abp.Http.Client.DynamicProxying namespace Volo.Abp.Http.Client.DynamicProxying
{ {
//TODO: Somehow capture cancellationtoken and pass to other methods...?
public class DynamicHttpProxyInterceptor<TService> : AbpInterceptor, ITransientDependency 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; } public ILogger<DynamicHttpProxyInterceptor<TService>> Logger { get; set; }
@ -46,14 +51,20 @@ namespace Volo.Abp.Http.Client.DynamicProxying
IOptionsSnapshot<RemoteServiceOptions> remoteServiceOptions, IOptionsSnapshot<RemoteServiceOptions> remoteServiceOptions,
IApiDescriptionFinder apiDescriptionFinder, IApiDescriptionFinder apiDescriptionFinder,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IRemoteServiceHttpClientAuthenticator clientAuthenticator) IRemoteServiceHttpClientAuthenticator clientAuthenticator,
ICancellationTokenProvider cancellationTokenProvider,
ICorrelationIdProvider correlationIdProvider,
IOptions<CorrelationIdOptions> correlationIdOptions)
{ {
_httpClientFactory = httpClientFactory; CancellationTokenProvider = cancellationTokenProvider;
_apiDescriptionFinder = apiDescriptionFinder; CorrelationIdProvider = correlationIdProvider;
_jsonSerializer = jsonSerializer; CorrelationIdOptions = correlationIdOptions.Value;
_clientAuthenticator = clientAuthenticator; HttpClientFactory = httpClientFactory;
_clientOptions = clientOptions.Value; ApiDescriptionFinder = apiDescriptionFinder;
_remoteServiceOptions = remoteServiceOptions.Value; JsonSerializer = jsonSerializer;
ClientAuthenticator = clientAuthenticator;
ClientOptions = clientOptions.Value;
RemoteServiceOptions = remoteServiceOptions.Value;
Logger = NullLogger<DynamicHttpProxyInterceptor<TService>>.Instance; Logger = NullLogger<DynamicHttpProxyInterceptor<TService>>.Instance;
} }
@ -62,11 +73,11 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{ {
if (invocation.Method.ReturnType == typeof(void)) if (invocation.Method.ReturnType == typeof(void))
{ {
AsyncHelper.RunSync(() => MakeRequest(invocation)); AsyncHelper.RunSync(() => MakeRequestAsync(invocation));
} }
else else
{ {
var responseAsString = AsyncHelper.RunSync(() => MakeRequest(invocation)); var responseAsString = AsyncHelper.RunSync(() => MakeRequestAsync(invocation));
//TODO: Think on that //TODO: Think on that
if (TypeHelper.IsPrimitiveExtended(invocation.Method.ReturnType, true)) if (TypeHelper.IsPrimitiveExtended(invocation.Method.ReturnType, true))
@ -75,7 +86,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
} }
else else
{ {
invocation.ReturnValue = _jsonSerializer.Deserialize( invocation.ReturnValue = JsonSerializer.Deserialize(
invocation.Method.ReturnType, invocation.Method.ReturnType,
responseAsString responseAsString
); );
@ -87,7 +98,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{ {
if (invocation.Method.ReturnType.GenericTypeArguments.IsNullOrEmpty()) if (invocation.Method.ReturnType.GenericTypeArguments.IsNullOrEmpty())
{ {
return MakeRequest(invocation); return MakeRequestAsync(invocation);
} }
invocation.ReturnValue = GenericInterceptAsyncMethod invocation.ReturnValue = GenericInterceptAsyncMethod
@ -99,7 +110,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
private async Task<T> MakeRequestAndGetResultAsync<T>(IAbpMethodInvocation invocation) private async Task<T> MakeRequestAndGetResultAsync<T>(IAbpMethodInvocation invocation)
{ {
var responseAsString = await MakeRequest(invocation); var responseAsString = await MakeRequestAsync(invocation);
//TODO: Think on that //TODO: Think on that
if (TypeHelper.IsPrimitiveExtended(typeof(T), true)) if (TypeHelper.IsPrimitiveExtended(typeof(T), true))
@ -107,28 +118,28 @@ namespace Volo.Abp.Http.Client.DynamicProxying
return (T)Convert.ChangeType(responseAsString, typeof(T)); 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 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 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 apiVersion = GetApiVersionInfo(action);
var url = remoteServiceConfig.BaseUrl + UrlBuilder.GenerateUrlWithParameters(action, invocation.ArgumentsDictionary, apiVersion); var url = remoteServiceConfig.BaseUrl + UrlBuilder.GenerateUrlWithParameters(action, invocation.ArgumentsDictionary, apiVersion);
var requestMessage = new HttpRequestMessage(action.GetHttpMethod(), url) 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); AddHeaders(invocation, action, requestMessage, apiVersion);
await _clientAuthenticator.Authenticate( await ClientAuthenticator.Authenticate(
new RemoteServiceHttpClientAuthenticateContext( new RemoteServiceHttpClientAuthenticateContext(
client, client,
requestMessage, 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) if (!response.IsSuccessStatusCode)
{ {
@ -176,8 +187,9 @@ namespace Volo.Abp.Http.Client.DynamicProxying
return action.SupportedVersions.Last(); //TODO: Ensure to get the latest version! 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()) if (!apiVersion.Version.IsNullOrEmpty())
{ {
//TODO: What about other media types? //TODO: What about other media types?
@ -186,8 +198,8 @@ namespace Volo.Abp.Http.Client.DynamicProxying
requestMessage.Headers.Add("api-version", apiVersion.Version); requestMessage.Headers.Add("api-version", apiVersion.Version);
} }
//Header parameters
var headers = action.Parameters.Where(p => p.BindingSourceId == ParameterBindingSources.Header).ToArray(); var headers = action.Parameters.Where(p => p.BindingSourceId == ParameterBindingSources.Header).ToArray();
foreach (var headerParameter in headers) foreach (var headerParameter in headers)
{ {
var value = HttpActionParameterHelper.FindParameterValue(invocation.ArgumentsDictionary, headerParameter); var value = HttpActionParameterHelper.FindParameterValue(invocation.ArgumentsDictionary, headerParameter);
@ -196,22 +208,25 @@ namespace Volo.Abp.Http.Client.DynamicProxying
requestMessage.Headers.Add(headerParameter.Name, value.ToString()); requestMessage.Headers.Add(headerParameter.Name, value.ToString());
} }
} }
//CorrelationId
requestMessage.Headers.Add(CorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get());
} }
private string GetConfiguredApiVersion() 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}."); ?? throw new AbpException($"Could not get DynamicHttpClientProxyConfig for {typeof(TService).FullName}.");
return _remoteServiceOptions.RemoteServices.GetOrDefault(clientConfig.RemoteServiceName)?.Version return RemoteServiceOptions.RemoteServices.GetOrDefault(clientConfig.RemoteServiceName)?.Version
?? _remoteServiceOptions.RemoteServices.Default?.Version; ?? RemoteServiceOptions.RemoteServices.Default?.Version;
} }
private async Task ThrowExceptionForResponseAsync(HttpResponseMessage response) private async Task ThrowExceptionForResponseAsync(HttpResponseMessage response)
{ {
if (response.Headers.Contains(AbpHttpConsts.AbpErrorFormat)) if (response.Headers.Contains(AbpHttpConsts.AbpErrorFormat))
{ {
var errorResponse = _jsonSerializer.Deserialize<RemoteServiceErrorResponse>( var errorResponse = JsonSerializer.Deserialize<RemoteServiceErrorResponse>(
await response.Content.ReadAsStringAsync() 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}"); 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 class IdentityModelHttpClientAuthenticator : IIdentityModelHttpClientAuthenticator, ITransientDependency
{ {
public ILogger<IdentityModelHttpClientAuthenticator> Logger { get; set; } public ILogger<IdentityModelHttpClientAuthenticator> Logger { get; set; }
protected IdentityClientOptions ClientOptions { get; } protected IdentityClientOptions ClientOptions { get; }
public IdentityModelHttpClientAuthenticator( public IdentityModelHttpClientAuthenticator(
@ -84,6 +83,8 @@ namespace Volo.Abp.IdentityModel
protected virtual async Task<TokenResponse> GetTokenResponse(DiscoveryResponse discoveryResponse, IdentityClientConfiguration configuration) protected virtual async Task<TokenResponse> GetTokenResponse(DiscoveryResponse discoveryResponse, IdentityClientConfiguration configuration)
{ {
//TODO: Pass cancellation token
var tokenClient = new TokenClient(discoveryResponse.TokenEndpoint, configuration.ClientId, configuration.ClientSecret); var tokenClient = new TokenClient(discoveryResponse.TokenEndpoint, configuration.ClientId, configuration.ClientSecret);
switch (configuration.GrantType) 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) 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.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" /> <ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" /> <ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />
</ItemGroup> </ItemGroup>
</Project> </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.Modularity;
using Volo.Abp.Settings;
namespace Volo.Abp.MultiTenancy namespace Volo.Abp.MultiTenancy
{ {
[DependsOn(typeof(AbpDataModule))] [DependsOn(
[DependsOn(typeof(AbpSettingsModule))] typeof(AbpDataModule)
public class AbpMultiTenancyAbstractionsModule : AbpModule //TODO: Rename to AbpMultiTenancyModule )]
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> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.Localization.Abstractions\Volo.Abp.Localization.Abstractions.csproj" /> <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" /> <ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
</ItemGroup> </ItemGroup>

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

@ -1,15 +1,27 @@
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security; using Volo.Abp.Security;
using Volo.Abp.Users;
namespace Volo.Abp.Settings namespace Volo.Abp.Settings
{ {
[DependsOn( [DependsOn(
typeof(AbpLocalizationAbstractionsModule), typeof(AbpLocalizationAbstractionsModule),
typeof(AbpSecurityModule) typeof(AbpSecurityModule),
typeof(AbpMultiTenancyAbstractionsModule)
)] )]
public class AbpSettingsModule : AbpModule 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); 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); 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); SettingDefinition Get([NotNull] string name);
IReadOnlyList<SettingDefinition> GetAll(); 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; using JetBrains.Annotations;
namespace Volo.Abp.Settings namespace Volo.Abp.Settings
{ {
public interface ISettingStore public interface ISettingStore
{ {
Task<string> GetOrNullAsync([NotNull] string name, [CanBeNull] string providerName, [CanBeNull] string providerKey); Task<string> GetOrNullAsync(
[NotNull] string name,
Task SetAsync([NotNull] string name, [NotNull] string value, [CanBeNull] string providerName, [CanBeNull] string providerKey); [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);
} }
} }

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

@ -7,12 +7,6 @@ namespace Volo.Abp.Settings
{ {
string Name { get; } 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);
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);
} }
} }

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

@ -36,6 +36,12 @@ namespace Volo.Abp.Settings
/// </summary> /// </summary>
public bool IsVisibleToClients { get; set; } 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> /// <summary>
/// Is this setting inherited from parent scopes. /// Is this setting inherited from parent scopes.
/// Default: True. /// Default: True.
@ -72,6 +78,31 @@ namespace Volo.Abp.Settings
IsEncrypted = isEncrypted; IsEncrypted = isEncrypted;
Properties = new Dictionary<string, object>(); 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() public SettingOptions()
{ {
DefinitionProviders = new TypeList<ISettingDefinitionProvider>(); DefinitionProviders = new TypeList<ISettingDefinitionProvider>();
ValueProviders = new TypeList<ISettingValueProvider> ValueProviders = new TypeList<ISettingValueProvider>();
{
typeof(DefaultValueSettingValueProvider),
typeof(GlobalSettingValueProvider)
};
} }
} }
} }

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 public class SettingValue : NameValue
{ {
/// <summary> /// <summary>

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

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

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(); var app = context.GetApplicationBuilder();
app.UseCorrelationId();
app.UseMiddleware<FakeAuthenticationMiddleware>(); app.UseMiddleware<FakeAuthenticationMiddleware>();
app.UseAuditing(); app.UseAuditing();
app.UseUnitOfWork(); 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>(); _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)); 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 @using Volo.Abp.Account.Web.Settings
@model Volo.Abp.Account.Web.Pages.Account.LoginModel @model Volo.Abp.Account.Web.Pages.Account.LoginModel
@inherits Volo.Abp.Account.Web.Pages.Account.AccountPage @inherits Volo.Abp.Account.Web.Pages.Account.AccountPage
@inject Volo.Abp.Settings.ISettingManager SettingManager @inject Volo.Abp.Settings.ISettingProvider SettingProvider
@if (Model.EnableLocalLogin) @if (Model.EnableLocalLogin)
{ {
<form method="post"> <form method="post">
@ -29,7 +29,7 @@
</form> </form>
<div style="padding-top: 20px"> <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> <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() protected virtual async Task CheckSelfRegistrationAsync()
{ {
if (!await SettingManager.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled)) if (!await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled))
{ {
throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]); 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 static class AuditLogConsts
{ {
public const int MaxApplicationNameLength = 96;
public const int MaxClientIpAddressLength = 64; public const int MaxClientIpAddressLength = 64;
public const int MaxClientNameLength = 128; 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.Collections.Generic;
using System.Linq; using System.Linq;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
@ -12,6 +11,8 @@ namespace Volo.Abp.AuditLogging
[DisableAuditing] [DisableAuditing]
public class AuditLog : AggregateRoot<Guid>, IMultiTenant public class AuditLog : AggregateRoot<Guid>, IMultiTenant
{ {
public virtual string ApplicationName { get; set; }
public virtual Guid? UserId { get; protected set; } public virtual Guid? UserId { get; protected set; }
public virtual string UserName { get; protected set; } public virtual string UserName { get; protected set; }
@ -58,6 +59,7 @@ namespace Volo.Abp.AuditLogging
public AuditLog(IGuidGenerator guidGenerator, AuditLogInfo auditInfo) public AuditLog(IGuidGenerator guidGenerator, AuditLogInfo auditInfo)
{ {
Id = guidGenerator.Create(); Id = guidGenerator.Create();
ApplicationName = auditInfo.ApplicationName;
TenantId = auditInfo.TenantId; TenantId = auditInfo.TenantId;
UserId = auditInfo.UserId; UserId = auditInfo.UserId;
UserName = auditInfo.UserName.Truncate(AuditLogConsts.MaxUserNameLength); 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.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.ClientIpAddress).HasMaxLength(AuditLogConsts.MaxClientIpAddressLength).HasColumnName(nameof(AuditLog.ClientIpAddress));
b.Property(x => x.ClientName).HasMaxLength(AuditLogConsts.MaxClientNameLength).HasColumnName(nameof(AuditLog.ClientName)); b.Property(x => x.ClientName).HasMaxLength(AuditLogConsts.MaxClientNameLength).HasColumnName(nameof(AuditLog.ClientName));
b.Property(x => x.ClientId).HasMaxLength(AuditLogConsts.MaxClientIdLength).HasColumnName(nameof(AuditLog.ClientId)); 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.Delete, L("Permission:Delete"));
usersPermission.AddChild(IdentityPermissions.Users.ManagePermissions, L("Permission:ChangePermissions")); 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) 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.Create,
Users.Update, Users.Update,
Users.Delete, 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()); 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(); (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(); (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="..\..\..\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="..\..\..\..\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>
<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> public class AbpIdentityOptionsFactory : AbpOptionsFactory<IdentityOptions>
{ {
private readonly ISettingManager _settingManager; private readonly ISettingProvider _settingProvider;
public AbpIdentityOptionsFactory( public AbpIdentityOptionsFactory(
IEnumerable<IConfigureOptions<IdentityOptions>> setups, IEnumerable<IConfigureOptions<IdentityOptions>> setups,
IEnumerable<IPostConfigureOptions<IdentityOptions>> postConfigures, IEnumerable<IPostConfigureOptions<IdentityOptions>> postConfigures,
ISettingManager settingManager) ISettingProvider settingProvider)
: base(setups, postConfigures) : base(setups, postConfigures)
{ {
_settingManager = settingManager; _settingProvider = settingProvider;
} }
public override IdentityOptions Create(string name) public override IdentityOptions Create(string name)
@ -32,19 +32,20 @@ namespace Volo.Abp.Identity
protected virtual void OverrideOptions(IdentityOptions options) 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.RequiredLength = _settingProvider.Get(IdentitySettingNames.Password.RequiredLength, options.Password.RequiredLength);
options.Password.RequireNonAlphanumeric = _settingManager.Get(IdentitySettingNames.Password.RequireNonAlphanumeric, options.Password.RequireNonAlphanumeric); options.Password.RequiredUniqueChars = _settingProvider.Get(IdentitySettingNames.Password.RequiredUniqueChars, options.Password.RequiredUniqueChars);
options.Password.RequireLowercase = _settingManager.Get(IdentitySettingNames.Password.RequireLowercase, options.Password.RequireLowercase); options.Password.RequireNonAlphanumeric = _settingProvider.Get(IdentitySettingNames.Password.RequireNonAlphanumeric, options.Password.RequireNonAlphanumeric);
options.Password.RequireUppercase = _settingManager.Get(IdentitySettingNames.Password.RequireUppercase, options.Password.RequireUppercase); options.Password.RequireLowercase = _settingProvider.Get(IdentitySettingNames.Password.RequireLowercase, options.Password.RequireLowercase);
options.Password.RequireDigit = _settingManager.Get(IdentitySettingNames.Password.RequireDigit, options.Password.RequireDigit); 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 = _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.AllowedForNewUsers = _settingProvider.Get(IdentitySettingNames.Lockout.AllowedForNewUsers, options.Lockout.AllowedForNewUsers);
options.Lockout.MaxFailedAccessAttempts = _settingManager.Get(IdentitySettingNames.Lockout.MaxFailedAccessAttempts, options.Lockout.MaxFailedAccessAttempts); 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 = _settingManager.Get(IdentitySettingNames.SignIn.RequireConfirmedEmail, options.SignIn.RequireConfirmedEmail);
options.SignIn.RequireConfirmedPhoneNumber = _settingManager.Get(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, options.SignIn.RequireConfirmedPhoneNumber); 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 public class IdentityOptions_Tests : AbpIdentityDomainTestBase
{ {
private ISettingManager _settingManager; private ISettingProvider _settingProvider;
protected override void AfterAddApplication(IServiceCollection services) protected override void AfterAddApplication(IServiceCollection services)
{ {
_settingManager = Substitute.For<ISettingManager>(); _settingProvider = Substitute.For<ISettingProvider>();
_settingManager.GetOrNullAsync(Arg.Any<string>()).Returns((string) null); _settingProvider.GetOrNullAsync(Arg.Any<string>()).Returns((string) null);
services.Replace(ServiceDescriptor.Singleton(_settingManager)); services.Replace(ServiceDescriptor.Singleton(_settingProvider));
} }
[Fact] [Fact]
@ -38,7 +38,7 @@ namespace Volo.Abp.Identity
options.Password.RequiredUniqueChars.ShouldBe(1); //Default value 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()) 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<ApiResource, MongoApiResourceRepository>();
options.AddRepository<IdentityResource, MongoIdentityResourceRepository>(); options.AddRepository<IdentityResource, MongoIdentityResourceRepository>();
options.AddRepository<Client, MongoClientRepository>(); 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 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" /> <Import Project="..\..\..\..\common.props" />
@ -14,7 +14,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Core\Volo.Abp.Core.csproj" /> <ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
</ItemGroup> </ItemGroup>
</Project> </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 namespace Volo.Abp.PermissionManagement
{ {
[DependsOn(
typeof(AbpLocalizationModule)
)]
public class AbpPermissionManagementDomainSharedModule : AbpModule 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