Browse Source

Merge branch 'dev' into liangshiwei/feature-management

pull/5361/head
liangshiwei 6 years ago
parent
commit
291a5a6a19
  1. 2
      docs/en/CLI.md
  2. 23
      docs/en/Modules/Identity.md
  3. 2
      docs/zh-Hans/CLI.md
  4. 27
      docs/zh-Hans/Modules/Identity.md
  5. 49
      framework/Volo.Abp.sln
  6. 20
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AbpAspNetCoreComponentsWebAssemblyBasicTheme.cs
  7. 3
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/FodyWeavers.xml
  8. 30
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/FodyWeavers.xsd
  9. 7
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Pages/Authentication.razor
  10. 27
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/App.razor
  11. 65
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor
  12. 41
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor
  13. 18
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs
  14. 29
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor
  15. 7
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor
  16. 27
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor.cs
  17. 52
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenuItem.razor
  18. 8
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/RedirectToLogin.razor
  19. 10
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/_Imports.razor
  20. 16
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj
  21. 105
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.css
  22. 16
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.js
  23. 17
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/AbpAspNetCoreComponentsWebAssemblyThemingModule.cs
  24. 3
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xml
  25. 30
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xsd
  26. 16
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Routing/AbpBlazorRouterOptions.cs
  27. 10
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Routing/RouterAssemblyList.cs
  28. 17
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj
  29. 3
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/FodyWeavers.xml
  30. 30
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/FodyWeavers.xsd
  31. 51
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyHostBuilderExtensions.cs
  32. 27
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj
  33. 26
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs
  34. 42
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs
  35. 19
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpWebAssemblyApplicationCreationOptions.cs
  36. 20
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ApplicationConfigurationCache.cs
  37. 17
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/IUiMessageService.cs
  38. 42
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiMessageService.cs
  39. 50
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs
  40. 58
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs
  41. 69
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyRemoteTenantStore.cs
  42. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/FodyWeavers.xml
  43. 30
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/FodyWeavers.xsd
  44. 24
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo.Abp.AspNetCore.Mvc.Client.Common.csproj
  45. 33
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientCommonModule.cs
  46. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs
  47. 0
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs
  48. 0
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs
  49. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs
  50. 0
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs
  51. 0
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs
  52. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo.Abp.AspNetCore.Mvc.Client.csproj
  53. 26
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs
  54. 24
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs
  55. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs
  56. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo.Abp.AspNetCore.Mvc.Contracts.csproj
  57. 3
      framework/src/Volo.Abp.Autofac.WebAssembly/FodyWeavers.xml
  58. 30
      framework/src/Volo.Abp.Autofac.WebAssembly/FodyWeavers.xsd
  59. 23
      framework/src/Volo.Abp.Autofac.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyApplicationCreationOptionsAutofacExtensions.cs
  60. 16
      framework/src/Volo.Abp.Autofac.WebAssembly/Volo.Abp.Autofac.WebAssembly.csproj
  61. 14
      framework/src/Volo.Abp.Autofac.WebAssembly/Volo/Abp/Autofac/WebAssembly/AbpAutofacWebAssemblyModule.cs
  62. 19
      framework/src/Volo.Abp.Autofac/Volo/Abp/AbpAutofacAbpApplicationCreationOptionsExtensions.cs
  63. 3
      framework/src/Volo.Abp.BlazoriseUI/FodyWeavers.xml
  64. 30
      framework/src/Volo.Abp.BlazoriseUI/FodyWeavers.xsd
  65. 24
      framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj
  66. 23
      framework/src/Volo.Abp.BlazoriseUI/Volo/Abp/BlazoriseUI/AbpBlazoriseModule.cs
  67. 235
      framework/src/Volo.Abp.BlazoriseUI/Volo/Abp/BlazoriseUI/BlazoriseCrudPageBase.cs
  68. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  69. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs
  70. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs
  71. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs
  72. 30
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs
  73. 39
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/BlazorAppsettingsFilePortChangeForSeparatedIdentityServersStep.cs
  74. 2
      framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs
  75. 4
      framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModule.cs
  76. 2
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Services/ICrudAppService.cs
  77. 2
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs
  78. 3
      framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/FodyWeavers.xml
  79. 30
      framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/FodyWeavers.xsd
  80. 25
      framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj
  81. 13
      framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AbpHttpClientIdentityModelWebAssemblyModule.cs
  82. 50
      framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs
  83. 79
      framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs
  84. 19
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientBuilderOptions.cs
  85. 39
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientModule.cs
  86. 4
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs
  87. 7
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
  88. 30
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/CurrentPrincipalAccessorBase.cs
  89. 26
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ThreadCurrentPrincipalAccessor.cs
  90. 17
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs
  91. 4
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json
  92. 4
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json
  93. 13
      framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/DefaultBrandingProvider.cs
  94. 17
      framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/IBrandingProvider.cs
  95. 7
      modules/account/Volo.Abp.Account.sln
  96. 20
      modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs
  97. 37
      modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs
  98. 23
      modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorUserMenuContributor.cs
  99. 3
      modules/account/src/Volo.Abp.Account.Blazor/FodyWeavers.xml
  100. 30
      modules/account/src/Volo.Abp.Account.Blazor/FodyWeavers.xsd

2
docs/en/CLI.md

@ -86,6 +86,8 @@ abp new Acme.BookStore
* `--tiered`: Creates a tiered solution where Web and Http API layers are physically separated. If not specified, it creates a layered solution which is less complex and suitable for most scenarios.
* `angular`: Angular. There are some additional options for this template:
* `--separate-identity-server`: Separates the identity server application from the API host application. If not specified, you will have a single endpoint in the server side.
* `blazor`: Blazor. There are some additional options for this template:
* `--separate-identity-server`: Separates the identity server application from the API host application. If not specified, you will have a single endpoint in the server side.
* `none`: Without UI. There are some additional options for this template:
* `--separate-identity-server`: Separates the identity server application from the API host application. If not specified, you will have a single endpoint in the server side.
* `--mobile` or `-m`: Specifies the mobile application framework. If not specified, no mobile application will be created. Available options:

23
docs/en/Modules/Identity.md

@ -4,3 +4,26 @@ Identity module is used to manage [organization units](Organization-Units.md), r
See [the source code](https://github.com/abpframework/abp/tree/dev/modules/identity). Documentation will come soon...
## Identity Security Log
The security log can record some important operations or changes about your account. You can save the security log if needed.
You can inject and use `IdentitySecurityLogManager` or `ISecurityLogManager` to write security logs. It will create a log object by default and fill in some common values, such as `CreationTime`, `ClientIpAddress`, `BrowserInfo`, `current user/tenant`, etc. Of course, you can override them.
```cs
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = "IdentityServer";
Action = "ChangePassword";
});
```
Configure `AbpSecurityLogOptions` to provide the application name for the log or disable this feature. **Enabled** by default.
```cs
Configure<AbpSecurityLogOptions>(options =>
{
options.ApplicationName = "AbpSecurityTest";
});
```

2
docs/zh-Hans/CLI.md

@ -85,6 +85,8 @@ abp new Acme.BookStore
* `--tiered`: 创建分层解决方案,Web和Http Api层在物理上是分开的.如果未指定会创建一个分层的解决方案,此解决方案没有那么复杂,适合大多数场景.
* `angular`: Angular. 这个模板还有一些额外的选项:
* `--separate-identity-server`: 将Identity Server应用程序与API host应用程序分开. 如果未指定,则服务器端将只有一个端点.
* `blazor`: Blazor. 这个模板还有一些额外的选项:
* `--separate-identity-server`: 将Identity Server应用程序与API host应用程序分开. 如果未指定,则服务器端将只有一个端点.
* `none`: 无UI. 这个模板还有一些额外的选项:
* `--separate-identity-server`: 将Identity Server应用程序与API host应用程序分开. 如果未指定,则服务器端将只有一个端点.
* `--mobile` 或者 `-m`: 指定移动应用程序框架. 如果未指定,则不会创建任何移动应用程序,其他选项:

27
docs/zh-Hans/Modules/Identity.md

@ -1,5 +1,28 @@
# 身份管理模块
身份模块基于Microsoft Identity 库用于管理[组织单元](Organization-Units.md), 角色, 用户和他们的权限.
身份模块基于Microsoft Identity库用于管理[组织单元](Organization-Units.md), 角色, 用户和他们的权限.
参阅 [源码](https://github.com/abpframework/abp/tree/dev/modules/identity). 文档很快会被完善.
参阅 [源码](https://github.com/abpframework/abp/tree/dev/modules/identity). 文档很快会被完善.
## Identity安全日志
安全日志可以记录账户的一些重要的操作或者改动, 你可以在在一些功能中保存安全日志.
你可以注入和使用 `IdentitySecurityLogManager` 或 `ISecurityLogManager` 来保存安全日志. 默认它会创建一个安全日志对象并填充常用的值. 如 `CreationTime`, `ClientIpAddress`, `BrowserInfo`, `current user/tenant`等等. 当然你可以自定义这些值.
```cs
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = "IdentityServer";
Action = "ChangePassword";
});
```
通过配置 `AbpSecurityLogOptions` 来提供应用程序的名称或者禁用安全日志功能. 默认是**启用**状态.
```cs
Configure<AbpSecurityLogOptions>(options =>
{
options.ApplicationName = "AbpSecurityTest";
});
```

49
framework/Volo.Abp.sln

@ -331,6 +331,20 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.GlobalFeatures", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.GlobalFeatures.Tests", "test\Volo.Abp.GlobalFeatures.Tests\Volo.Abp.GlobalFeatures.Tests.csproj", "{231F1581-AA21-44C3-BF27-51EB3AD5355C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Http.Client.IdentityModel.WebAssembly", "src\Volo.Abp.Http.Client.IdentityModel.WebAssembly\Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj", "{3D35A1E0-A9A1-404F-9B55-5F1A7EB6D5B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Mvc.Client.Common", "src\Volo.Abp.AspNetCore.Mvc.Client.Common\Volo.Abp.AspNetCore.Mvc.Client.Common.csproj", "{8A22D962-016E-474A-8BB7-F831F0ABF3AC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Components.WebAssembly", "src\Volo.Abp.AspNetCore.Components.WebAssembly\Volo.Abp.AspNetCore.Components.WebAssembly.csproj", "{E1A62D10-F2FB-4040-BD60-11A3934058DF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlazoriseUI", "src\Volo.Abp.BlazoriseUI\Volo.Abp.BlazoriseUI.csproj", "{4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme", "src\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj", "{ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Components.WebAssembly.Theming", "src\Volo.Abp.AspNetCore.Components.WebAssembly.Theming\Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj", "{29CA7471-4E3E-4E75-8B33-001DDF682F01}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Autofac.WebAssembly", "src\Volo.Abp.Autofac.WebAssembly\Volo.Abp.Autofac.WebAssembly.csproj", "{37F89B0B-1C6B-426F-A5EE-676D1956D9E9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -985,6 +999,34 @@ Global
{231F1581-AA21-44C3-BF27-51EB3AD5355C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{231F1581-AA21-44C3-BF27-51EB3AD5355C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{231F1581-AA21-44C3-BF27-51EB3AD5355C}.Release|Any CPU.Build.0 = Release|Any CPU
{3D35A1E0-A9A1-404F-9B55-5F1A7EB6D5B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D35A1E0-A9A1-404F-9B55-5F1A7EB6D5B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D35A1E0-A9A1-404F-9B55-5F1A7EB6D5B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D35A1E0-A9A1-404F-9B55-5F1A7EB6D5B8}.Release|Any CPU.Build.0 = Release|Any CPU
{8A22D962-016E-474A-8BB7-F831F0ABF3AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A22D962-016E-474A-8BB7-F831F0ABF3AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A22D962-016E-474A-8BB7-F831F0ABF3AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A22D962-016E-474A-8BB7-F831F0ABF3AC}.Release|Any CPU.Build.0 = Release|Any CPU
{E1A62D10-F2FB-4040-BD60-11A3934058DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1A62D10-F2FB-4040-BD60-11A3934058DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1A62D10-F2FB-4040-BD60-11A3934058DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1A62D10-F2FB-4040-BD60-11A3934058DF}.Release|Any CPU.Build.0 = Release|Any CPU
{4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5}.Release|Any CPU.Build.0 = Release|Any CPU
{ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Release|Any CPU.Build.0 = Release|Any CPU
{29CA7471-4E3E-4E75-8B33-001DDF682F01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29CA7471-4E3E-4E75-8B33-001DDF682F01}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29CA7471-4E3E-4E75-8B33-001DDF682F01}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29CA7471-4E3E-4E75-8B33-001DDF682F01}.Release|Any CPU.Build.0 = Release|Any CPU
{37F89B0B-1C6B-426F-A5EE-676D1956D9E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{37F89B0B-1C6B-426F-A5EE-676D1956D9E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{37F89B0B-1C6B-426F-A5EE-676D1956D9E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{37F89B0B-1C6B-426F-A5EE-676D1956D9E9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1152,6 +1194,13 @@ Global
{C1D891B0-AE83-42CB-987D-425A2787DE78} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{04F44063-C952-403A-815F-EFB778BDA125} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{231F1581-AA21-44C3-BF27-51EB3AD5355C} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{3D35A1E0-A9A1-404F-9B55-5F1A7EB6D5B8} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{8A22D962-016E-474A-8BB7-F831F0ABF3AC} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{E1A62D10-F2FB-4040-BD60-11A3934058DF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{ABC27C10-C0FF-44CB-B4FF-A09C0B79F695} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{29CA7471-4E3E-4E75-8B33-001DDF682F01} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{37F89B0B-1C6B-426F-A5EE-676D1956D9E9} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

20
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AbpAspNetCoreComponentsWebAssemblyBasicTheme.cs

@ -0,0 +1,20 @@
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming;
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme
{
[DependsOn(
typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule)
)]
public class AbpAspNetCoreComponentsWebAssemblyBasicThemeModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpRouterOptions>(options =>
{
options.AdditionalAssemblies.Add(typeof(AbpAspNetCoreComponentsWebAssemblyBasicThemeModule).Assembly);
});
}
}
}

3
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

7
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Pages/Authentication.razor

@ -0,0 +1,7 @@
@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action" />
@code{
[Parameter] public string Action { get; set; }
}

27
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/App.razor

@ -0,0 +1,27 @@
@using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing
@using Microsoft.Extensions.Options
@inject IOptions<AbpRouterOptions> RouterOptions
<CascadingAuthenticationState>
<Router AppAssembly="RouterOptions.Value.AppAssembly"
AdditionalAssemblies="RouterOptions.Value.AdditionalAssemblies">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
@if (!context.User.Identity.IsAuthenticated)
{
<RedirectToLogin />
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>

65
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor

@ -0,0 +1,65 @@
@using Volo.Abp.Localization
@using System.Globalization
@using System.Collections.Immutable
@inject ILanguageProvider LanguageProvider
@inject IJSRuntime JsRuntime
@if (_otherLanguages != null && _otherLanguages.Any())
{
<Dropdown>
<DropdownToggle Color="Color.None">
@_currentLanguage.DisplayName
</DropdownToggle>
<DropdownMenu>
@foreach (var language in _otherLanguages)
{
<DropdownItem Clicked="() => ChangeLanguageAsync(language)">@language.DisplayName</DropdownItem>
}
</DropdownMenu>
</Dropdown>
}
@code {
private IReadOnlyList<LanguageInfo> _otherLanguages;
private LanguageInfo _currentLanguage;
protected override async Task OnInitializedAsync()
{
var selectedLanguageName = await JsRuntime.InvokeAsync<string>(
"localStorage.getItem",
"Abp.SelectedLanguage"
);
_otherLanguages = await LanguageProvider.GetLanguagesAsync();
if (!_otherLanguages.Any())
{
return;
}
if (!selectedLanguageName.IsNullOrWhiteSpace())
{
_currentLanguage = _otherLanguages.FirstOrDefault(l => l.UiCultureName == selectedLanguageName);
}
if (_currentLanguage == null)
{
_currentLanguage = _otherLanguages.FirstOrDefault(l => l.UiCultureName == CultureInfo.CurrentUICulture.Name);
}
if (_currentLanguage == null)
{
_currentLanguage = _otherLanguages.FirstOrDefault();
}
_otherLanguages = _otherLanguages.Where(l => l != _currentLanguage).ToImmutableList();
}
private async Task ChangeLanguageAsync(LanguageInfo language)
{
await JsRuntime.InvokeVoidAsync(
"localStorage.setItem",
"Abp.SelectedLanguage", language.UiCultureName
);
await JsRuntime.InvokeVoidAsync("location.reload");
}
}

41
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor

@ -0,0 +1,41 @@
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Volo.Abp.Users
@inject ICurrentUser CurrentUser
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager
<AuthorizeView>
<Authorized>
<Dropdown>
<DropdownToggle Color="Color.None">
@CurrentUser.UserName
</DropdownToggle>
<DropdownMenu>
@if (Menu != null)
{
@foreach (var menuItem in Menu.Items)
{
<DropdownItem Clicked="@(() => NavigateTo(menuItem.Url))">@menuItem.DisplayName</DropdownItem>
}
}
<Divider />
<DropdownItem Clicked="BeginSignOut">Logout</DropdownItem>
</DropdownMenu>
</Dropdown>
</Authorized>
<NotAuthorized>
<a class="nav-link" href="authentication/login">Log in</a>
</NotAuthorized>
</AuthorizeView>
@code{
private void NavigateTo(string uri)
{
Navigation.NavigateTo(uri);
}
private async Task BeginSignOut()
{
await SignOutManager.SetSignOutState();
NavigateTo("authentication/logout");
}
}

18
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs

@ -0,0 +1,18 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic
{
public partial class LoginDisplay
{
[Inject] protected IMenuManager MenuManager { get; set; }
protected ApplicationMenu Menu { get; set; }
protected override async Task OnInitializedAsync()
{
Menu = await MenuManager.GetAsync(StandardMenus.User);
}
}
}

29
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor

@ -0,0 +1,29 @@
@inherits LayoutComponentBase
@using Volo.Abp.Ui.Branding
@inject IBrandingProvider BrandingProvider
<nav class="navbar navbar-expand-md navbar-dark bg-dark shadow-sm flex-column flex-md-row mb-4" id="main-navbar" style="min-height: 4rem;">
<div class="container">
<a class="navbar-brand" href="/">@BrandingProvider.AppName</a>
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#main-navbar-collapse" aria-controls="main-navbar-collapse"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="main-navbar-collapse">
<ul class="navbar-nav mx-auto">
<NavMenu/>
</ul>
<ul class="navbar-nav">
<li class="nav-item">
<LanguageSwitch/>
</li>
<li class="nav-item">
<LoginDisplay/>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
@Body
</div>

7
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor

@ -0,0 +1,7 @@
@if (Menu != null)
{
foreach (var menuItem in Menu.Items)
{
<NavMenuItem MenuItem="@menuItem" />
}
}

27
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor.cs

@ -0,0 +1,27 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic
{
public partial class NavMenu
{
[Inject] protected IMenuManager MenuManager { get; set; }
protected ApplicationMenu Menu { get; set; }
private bool collapseNavMenu = true;
private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
protected override async Task OnInitializedAsync()
{
Menu = await MenuManager.GetAsync(StandardMenus.Main);
}
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
}
}

52
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenuItem.razor

@ -0,0 +1,52 @@
@using Volo.Abp.UI.Navigation
@{
var elementId = MenuItem.ElementId ?? "MenuItem_" + MenuItem.Name.Replace(".", "_");
var cssClass = string.IsNullOrEmpty(MenuItem.CssClass) ? string.Empty : MenuItem.CssClass;
var url = string.IsNullOrEmpty(MenuItem.Url) ? "#" : MenuItem.Url;
}
@if (MenuItem.IsLeaf)
{
if (MenuItem.Url != null)
{
<li class="nav-item @cssClass" disabled="@MenuItem.IsDisabled">
<NavLink class="nav-link" href="@url" id="@elementId">
@if (MenuItem.Icon != null)
{
if (MenuItem.Icon.StartsWith("fa"))
{
<i class="@MenuItem.Icon"></i>
}
}
@MenuItem.DisplayName
</NavLink>
</li>
}
}
else
{
<li class="nav-item">
<div class="dropdown">
<a class="nav-link dropdown-toggle" href="#" id="@elementId" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@if (MenuItem.Icon != null)
{
if (MenuItem.Icon.StartsWith("fa"))
{
<i class="@MenuItem.Icon"></i>
}
}
@MenuItem.DisplayName
</a>
<div class="dropdown-menu border-0 shadow-sm" aria-labelledby="@elementId">
@foreach (var childMenuItem in MenuItem.Items)
{
<NavMenuItem MenuItem="@childMenuItem" />
}
</div>
</div>
</li>
}
@code {
[Parameter]
public ApplicationMenuItem MenuItem { get; set; }
}

8
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/RedirectToLogin.razor

@ -0,0 +1,8 @@
@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@code {
protected override void OnInitialized()
{
Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
}
}

10
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/_Imports.razor

@ -0,0 +1,10 @@
@using System.Net.Http
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using Volo.Abp.AspNetCore.Components.WebAssembly
@using Blazorise
@using Blazorise.DataGrid

16
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
<PackageId>Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme</PackageId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.WebAssembly.Theming\Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj" />
</ItemGroup>
</Project>

105
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.css

@ -0,0 +1,105 @@
#main-navbar-tools a.dropdown-toggle {
text-decoration: none;
color: #fff;
}
.navbar .dropdown-submenu {
position: relative;
}
.navbar .dropdown-menu {
margin: 0;
padding: 0;
}
.navbar .dropdown-menu a {
font-size: .9em;
padding: 10px 15px;
display: block;
min-width: 210px;
text-align: left;
border-radius: 0.25rem;
min-height: 44px;
}
.navbar .dropdown-submenu a::after {
transform: rotate(-90deg);
position: absolute;
right: 16px;
top: 18px;
}
.navbar .dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
}
.card-header .btn {
padding: 2px 6px;
}
.card-header h5 {
margin: 0;
}
.container > .card {
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;
}
@media screen and (min-width: 768px) {
.navbar .dropdown:hover > .dropdown-menu {
display: block;
}
.navbar .dropdown-submenu:hover > .dropdown-menu {
display: block;
}
}
.input-validation-error {
border-color: #dc3545;
}
.field-validation-error {
font-size: 0.8em;
}
.dataTables_scrollBody {
min-height: 248px;
}
div.dataTables_wrapper div.dataTables_info {
padding-top: 11px;
white-space: nowrap;
}
div.dataTables_wrapper div.dataTables_length label {
padding-top: 10px;
margin-bottom: 0;
}
.rtl .dropdown-menu-right {
right: auto;
left: 0;
}
.rtl .dropdown-menu-right a {
text-align: right;
}
.rtl .navbar .dropdown-menu a {
text-align: right;
}
.rtl .navbar .dropdown-submenu .dropdown-menu {
top: 0;
left: auto;
right: 100%;
}
/* TEMP */
.navbar-dark .navbar-nav .nav-link {
color: #000 !important;
}
.navbar-nav > .nav-item > .nav-link,
.navbar-nav > .nav-item > .dropdown > .nav-link {
color: #fff !important;
}
.navbar-nav>.nav-item>div>button{
color:#fff;
}

16
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.js

@ -0,0 +1,16 @@
$(function () {
$('.dropdown-menu a.dropdown-toggle').on('click', function (e) {
if (!$(this).next().hasClass('show')) {
$(this).parents('.dropdown-menu').first().find('.show').removeClass("show");
}
var $subMenu = $(this).next(".dropdown-menu");
$subMenu.toggleClass('show');
$(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function (e) {
$('.dropdown-submenu .show').removeClass("show");
});
return false;
});
});

17
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/AbpAspNetCoreComponentsWebAssemblyThemingModule.cs

@ -0,0 +1,17 @@
using Volo.Abp.BlazoriseUI;
using Volo.Abp.Http.Client.IdentityModel.WebAssembly;
using Volo.Abp.Modularity;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming
{
[DependsOn(
typeof(AbpBlazoriseUIModule),
typeof(AbpHttpClientIdentityModelWebAssemblyModule),
typeof(AbpUiNavigationModule)
)]
public class AbpAspNetCoreComponentsWebAssemblyThemingModule : AbpModule
{
}
}

3
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

16
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Routing/AbpBlazorRouterOptions.cs

@ -0,0 +1,16 @@
using System.Reflection;
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing
{
public class AbpRouterOptions
{
public Assembly AppAssembly { get; set; }
public RouterAssemblyList AdditionalAssemblies { get; }
public AbpRouterOptions()
{
AdditionalAssemblies = new RouterAssemblyList();
}
}
}

10
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Routing/RouterAssemblyList.cs

@ -0,0 +1,10 @@
using System.Collections.Generic;
using System.Reflection;
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing
{
public class RouterAssemblyList : List<Assembly>
{
}
}

17
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.BlazoriseUI\Volo.Abp.BlazoriseUI.csproj" />
<ProjectReference Include="..\Volo.Abp.Http.Client.IdentityModel.WebAssembly\Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj" />
<ProjectReference Include="..\Volo.Abp.UI.Navigation\Volo.Abp.UI.Navigation.csproj" />
</ItemGroup>
</Project>

3
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

51
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyHostBuilderExtensions.cs

@ -0,0 +1,51 @@
using System;
using System.Reflection;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.AspNetCore.Components.WebAssembly;
using Volo.Abp.AspNetCore.Mvc.Client;
using Volo.Abp.Modularity;
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
{
public static class AbpWebAssemblyHostBuilderExtensions
{
public static IAbpApplicationWithExternalServiceProvider AddApplication<TStartupModule>(
[NotNull] this WebAssemblyHostBuilder builder,
Action<AbpWebAssemblyApplicationCreationOptions> options)
where TStartupModule : IAbpModule
{
Check.NotNull(builder, nameof(builder));
builder.Services.AddSingleton<IConfiguration>(builder.Configuration);
builder.Services.AddSingleton(builder);
var application = builder.Services.AddApplication<TStartupModule>(opts =>
{
options?.Invoke(new AbpWebAssemblyApplicationCreationOptions(builder, opts));
});
return application;
}
public static async Task InitializeAsync(
[NotNull] this IAbpApplicationWithExternalServiceProvider application,
[NotNull] IServiceProvider serviceProvider)
{
Check.NotNull(application, nameof(application));
Check.NotNull(serviceProvider, nameof(serviceProvider));
application.Initialize(serviceProvider);
using (var scope = serviceProvider.CreateScope())
{
await scope.ServiceProvider
.GetRequiredService<ICachedApplicationConfigurationClient>()
.InitializeAsync();
}
}
}
}

27
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Components.WebAssembly</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Components.WebAssembly</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Client.Common\Volo.Abp.AspNetCore.Mvc.Client.Common.csproj" />
<ProjectReference Include="..\Volo.Abp.UI\Volo.Abp.UI.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="3.1.6" />
</ItemGroup>
</Project>

26
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs

@ -0,0 +1,26 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.Client;
using Volo.Abp.Http.Client;
using Volo.Abp.Modularity;
using Volo.Abp.UI;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
[DependsOn(
typeof(AbpAspNetCoreMvcClientCommonModule),
typeof(AbpUiModule)
)]
public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpHttpClientBuilderOptions>(options =>
{
options.ProxyClientBuildActions.Add((_, builder) =>
{
builder.AddHttpMessageHandler<AbpBlazorClientHttpMessageHandler>();
});
});
}
}
}

42
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs

@ -0,0 +1,42 @@
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.JSInterop;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDependency
{
private readonly IJSRuntime _jsRuntime;
public AbpBlazorClientHttpMessageHandler(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
await SetLanguageAsync(request, cancellationToken);
return await base.SendAsync(request, cancellationToken);
}
private async Task SetLanguageAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var selectedLanguage = await _jsRuntime.InvokeAsync<string>(
"localStorage.getItem",
cancellationToken,
"Abp.SelectedLanguage"
);
if (!selectedLanguage.IsNullOrWhiteSpace())
{
request.Headers.AcceptLanguage.Clear();
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(selectedLanguage));
}
}
}
}

19
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpWebAssemblyApplicationCreationOptions.cs

@ -0,0 +1,19 @@
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public class AbpWebAssemblyApplicationCreationOptions
{
public WebAssemblyHostBuilder HostBuilder { get; }
public AbpApplicationCreationOptions ApplicationCreationOptions { get; }
public AbpWebAssemblyApplicationCreationOptions(
WebAssemblyHostBuilder hostBuilder,
AbpApplicationCreationOptions applicationCreationOptions)
{
HostBuilder = hostBuilder;
ApplicationCreationOptions = applicationCreationOptions;
}
}
}

20
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ApplicationConfigurationCache.cs

@ -0,0 +1,20 @@
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public class ApplicationConfigurationCache : ISingletonDependency
{
protected ApplicationConfigurationDto Configuration { get; set; }
public virtual ApplicationConfigurationDto Get()
{
return Configuration;
}
internal void Set(ApplicationConfigurationDto configuration)
{
Configuration = configuration;
}
}
}

17
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/IUiMessageService.cs

@ -0,0 +1,17 @@
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public interface IUiMessageService
{
Task InfoAsync(string message, string title = null);
Task SuccessAsync(string message, string title = null);
Task WarnAsync(string message, string title = null);
Task ErrorAsync(string message, string title = null);
Task<bool> ConfirmAsync(string message, string title = null);
}
}

42
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiMessageService.cs

@ -0,0 +1,42 @@
using System.Threading.Tasks;
using Microsoft.JSInterop;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
//TODO: Implement with sweetalert in a new package
public class UiMessageService : IUiMessageService, ITransientDependency
{
protected IJSRuntime JsRuntime { get; }
public UiMessageService(IJSRuntime jsRuntime)
{
JsRuntime = jsRuntime;
}
public async Task InfoAsync(string message, string title = null)
{
await JsRuntime.InvokeVoidAsync("alert", message);
}
public async Task SuccessAsync(string message, string title = null)
{
await JsRuntime.InvokeVoidAsync("alert", message);
}
public async Task WarnAsync(string message, string title = null)
{
await JsRuntime.InvokeVoidAsync("alert", message);
}
public async Task ErrorAsync(string message, string title = null)
{
await JsRuntime.InvokeVoidAsync("alert", message);
}
public async Task<bool> ConfirmAsync(string message, string title = null)
{
return await JsRuntime.InvokeAsync<bool>("confirm", message);
}
}
}

50
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs

@ -0,0 +1,50 @@
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.AspNetCore.Mvc.Client;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.DynamicProxying;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency
{
protected IHttpClientProxy<IAbpApplicationConfigurationAppService> Proxy { get; }
protected ApplicationConfigurationCache Cache { get; }
public WebAssemblyCachedApplicationConfigurationClient(
IHttpClientProxy<IAbpApplicationConfigurationAppService> proxy,
ApplicationConfigurationCache cache)
{
Proxy = proxy;
Cache = cache;
}
public virtual async Task InitializeAsync()
{
Cache.Set(await Proxy.Service.GetAsync());
}
public virtual Task<ApplicationConfigurationDto> GetAsync()
{
return Task.FromResult(GetConfigurationByChecking());
}
public virtual ApplicationConfigurationDto Get()
{
return GetConfigurationByChecking();
}
private ApplicationConfigurationDto GetConfigurationByChecking()
{
var configuration = Cache.Get();
if (configuration == null)
{
throw new AbpException(
$"{nameof(WebAssemblyCachedApplicationConfigurationClient)} should be initialized before using it.");
}
return configuration;
}
}
}

58
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Security.Claims;
using Volo.Abp.AspNetCore.Mvc.Client;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public class WebAssemblyCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ITransientDependency
{
protected ICachedApplicationConfigurationClient ConfigurationClient { get; }
public WebAssemblyCurrentPrincipalAccessor(
ICachedApplicationConfigurationClient configurationClient)
{
ConfigurationClient = configurationClient;
}
protected override ClaimsPrincipal GetClaimsPrincipal()
{
var configuration = ConfigurationClient.Get();
var claims = new List<Claim>();
if (!configuration.CurrentUser.UserName.IsNullOrWhiteSpace())
{
claims.Add(new Claim(AbpClaimTypes.UserName,configuration.CurrentUser.UserName));
}
if (!configuration.CurrentUser.Email.IsNullOrWhiteSpace())
{
claims.Add(new Claim(AbpClaimTypes.Email,configuration.CurrentUser.Email));
}
if (configuration.CurrentUser.Id != null)
{
claims.Add(new Claim(AbpClaimTypes.UserId,configuration.CurrentUser.Id.ToString()));
}
if (configuration.CurrentUser.TenantId != null)
{
claims.Add(new Claim(AbpClaimTypes.TenantId,configuration.CurrentUser.TenantId.ToString()));
}
else if (configuration.CurrentTenant.Id != null)
{
claims.Add(new Claim(AbpClaimTypes.TenantId,configuration.CurrentTenant.Id.ToString()));
}
foreach (var role in configuration.CurrentUser.Roles)
{
claims.Add(new Claim(AbpClaimTypes.Role, role));
}
return new ClaimsPrincipal(new ClaimsIdentity(claims));
}
}
}

69
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyRemoteTenantStore.cs

@ -0,0 +1,69 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.MultiTenancy;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.DynamicProxying;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
namespace Volo.Abp.AspNetCore.Components.WebAssembly
{
public class WebAssemblyRemoteTenantStore : ITenantStore, ITransientDependency
{
protected IHttpClientProxy<IAbpTenantAppService> Proxy { get; }
public WebAssemblyRemoteTenantStore(
IHttpClientProxy<IAbpTenantAppService> proxy)
{
Proxy = proxy;
}
public async Task<TenantConfiguration> FindAsync(string name)
{
//TODO: Cache
return CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name));
}
public async Task<TenantConfiguration> FindAsync(Guid id)
{
//TODO: Cache
return CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id));
}
public TenantConfiguration Find(string name)
{
//TODO: Cache
return AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name)));
}
public TenantConfiguration Find(Guid id)
{
//TODO: Cache
return AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id)));
}
protected virtual TenantConfiguration CreateTenantConfiguration(FindTenantResultDto tenantResultDto)
{
if (!tenantResultDto.Success || tenantResultDto.TenantId == null)
{
return null;
}
return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name);
}
protected virtual string CreateCacheKey(string tenantName)
{
return $"RemoteTenantStore_Name_{tenantName}";
}
protected virtual string CreateCacheKey(Guid tenantId)
{
return $"RemoteTenantStore_Id_{tenantId:N}";
}
}
}

3
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

24
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo.Abp.AspNetCore.Mvc.Client.Common.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.Client.Common</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.Client.Common</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Contracts\Volo.Abp.AspNetCore.Mvc.Contracts.csproj" />
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.csproj" />
<ProjectReference Include="..\Volo.Abp.Http.Client\Volo.Abp.Http.Client.csproj" />
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
</ItemGroup>
</Project>

33
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientCommonModule.cs

@ -0,0 +1,33 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Caching;
using Volo.Abp.Http.Client;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
[DependsOn(
typeof(AbpHttpClientModule),
typeof(AbpAspNetCoreMvcContractsModule),
typeof(AbpCachingModule),
typeof(AbpLocalizationModule)
)]
public class AbpAspNetCoreMvcClientCommonModule : AbpModule
{
public const string RemoteServiceName = "AbpMvcClient";
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddHttpClientProxies(
typeof(AbpAspNetCoreMvcContractsModule).Assembly,
RemoteServiceName,
asDefaultServices: false
);
Configure<AbpLocalizationOptions>(options =>
{
options.GlobalContributors.Add<RemoteLocalizationContributor>();
});
}
}
}

6
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs → framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs

@ -5,6 +5,10 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
{
public interface ICachedApplicationConfigurationClient
{
Task InitializeAsync();
Task<ApplicationConfigurationDto> GetAsync();
ApplicationConfigurationDto Get();
}
}
}

0
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs → framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs

0
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs → framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs

5
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs → framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs

@ -4,7 +4,6 @@ using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Localization;
using Volo.Abp.Threading;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
@ -55,7 +54,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
private Dictionary<string, string> GetResourceOrNull()
{
var applicationConfigurationDto = AsyncHelper.RunSync(() => _applicationConfigurationClient.GetAsync());
var applicationConfigurationDto = _applicationConfigurationClient.Get();
var resource = applicationConfigurationDto
.Localization.Values
@ -69,4 +68,4 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
return resource;
}
}
}
}

0
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs → framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs

0
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs → framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs

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

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

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

@ -1,33 +1,11 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Caching;
using Volo.Abp.Http.Client;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
[DependsOn(
typeof(AbpHttpClientModule),
typeof(AbpAspNetCoreMvcContractsModule),
typeof(AbpCachingModule),
typeof(AbpLocalizationModule)
typeof(AbpAspNetCoreMvcClientCommonModule)
)]
public class AbpAspNetCoreMvcClientModule : AbpModule
{
public const string RemoteServiceName = "AbpMvcClient";
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddHttpClientProxies(
typeof(AbpAspNetCoreMvcContractsModule).Assembly,
RemoteServiceName,
asDefaultServices: false
);
Configure<AbpLocalizationOptions>(options =>
{
options.GlobalContributors.Add<RemoteLocalizationContributor>();
});
}
}
}

24
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs → framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs

@ -12,14 +12,14 @@ using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
public class CachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency
public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency
{
protected IHttpContextAccessor HttpContextAccessor { get; }
protected IHttpClientProxy<IAbpApplicationConfigurationAppService> Proxy { get; }
protected ICurrentUser CurrentUser { get; }
protected IDistributedCache<ApplicationConfigurationDto> Cache { get; }
public CachedApplicationConfigurationClient(
public MvcCachedApplicationConfigurationClient(
IDistributedCache<ApplicationConfigurationDto> cache,
IHttpClientProxy<IAbpApplicationConfigurationAppService> proxy,
ICurrentUser currentUser,
@ -31,6 +31,11 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
Cache = cache;
}
public async Task InitializeAsync()
{
await GetAsync();
}
public async Task<ApplicationConfigurationDto> GetAsync()
{
var cacheKey = CreateCacheKey();
@ -58,9 +63,22 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
return configuration;
}
public ApplicationConfigurationDto Get()
{
var cacheKey = CreateCacheKey();
var httpContext = HttpContextAccessor?.HttpContext;
if (httpContext != null && httpContext.Items[cacheKey] is ApplicationConfigurationDto configuration)
{
return configuration;
}
return AsyncHelper.RunSync(GetAsync);
}
protected virtual string CreateCacheKey()
{
return $"ApplicationConfiguration_{CurrentUser.Id?.ToString("N") ?? "Anonymous"}_{CultureInfo.CurrentUICulture.Name}";
}
}
}
}

6
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs → framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs

@ -11,13 +11,13 @@ using Volo.Abp.Threading;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
public class RemoteTenantStore : ITenantStore, ITransientDependency
public class MvcRemoteTenantStore : ITenantStore, ITransientDependency
{
protected IHttpClientProxy<IAbpTenantAppService> Proxy { get; }
protected IHttpContextAccessor HttpContextAccessor { get; }
protected IDistributedCache<TenantConfiguration> Cache { get; }
public RemoteTenantStore(
public MvcRemoteTenantStore(
IHttpClientProxy<IAbpTenantAppService> proxy,
IHttpContextAccessor httpContextAccessor,
IDistributedCache<TenantConfiguration> cache)
@ -120,7 +120,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
{
return tenantConfiguration;
}
tenantConfiguration = Cache.GetOrAdd(
cacheKey,
() => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id))),

2
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo.Abp.AspNetCore.Mvc.Contracts.csproj

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.Contracts</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.Contracts</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

3
framework/src/Volo.Abp.Autofac.WebAssembly/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.Autofac.WebAssembly/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

23
framework/src/Volo.Abp.Autofac.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyApplicationCreationOptionsAutofacExtensions.cs

@ -0,0 +1,23 @@
using System;
using Autofac;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.AspNetCore.Components.WebAssembly;
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
{
public static class AbpWebAssemblyApplicationCreationOptionsAutofacExtensions
{
public static void UseAutofac(
[NotNull] this AbpWebAssemblyApplicationCreationOptions options,
[CanBeNull] Action<ContainerBuilder> configure = null)
{
options.HostBuilder.Services.AddAutofacServiceProviderFactory();
options.HostBuilder.ConfigureContainer(
options.HostBuilder.Services.GetSingletonInstance<IServiceProviderFactory<ContainerBuilder>>(),
configure
);
}
}
}

16
framework/src/Volo.Abp.Autofac.WebAssembly/Volo.Abp.Autofac.WebAssembly.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.WebAssembly\Volo.Abp.AspNetCore.Components.WebAssembly.csproj" />
<ProjectReference Include="..\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
</ItemGroup>
</Project>

14
framework/src/Volo.Abp.Autofac.WebAssembly/Volo/Abp/Autofac/WebAssembly/AbpAutofacWebAssemblyModule.cs

@ -0,0 +1,14 @@
using Volo.Abp.AspNetCore.Components.WebAssembly;
using Volo.Abp.Modularity;
namespace Volo.Abp.Autofac.WebAssembly
{
[DependsOn(
typeof(AbpAutofacModule),
typeof(AbpAspNetCoreComponentsWebAssemblyModule)
)]
public class AbpAutofacWebAssemblyModule : AbpModule
{
}
}

19
framework/src/Volo.Abp.Autofac/Volo/Abp/AbpAutofacAbpApplicationCreationOptionsExtensions.cs

@ -8,9 +8,22 @@ namespace Volo.Abp
{
public static void UseAutofac(this AbpApplicationCreationOptions options)
{
var builder = new ContainerBuilder();
options.Services.AddObjectAccessor(builder);
options.Services.AddSingleton((IServiceProviderFactory<ContainerBuilder>) new AbpAutofacServiceProviderFactory(builder));
options.Services.AddAutofacServiceProviderFactory();
}
public static AbpAutofacServiceProviderFactory AddAutofacServiceProviderFactory(this IServiceCollection services)
{
return services.AddAutofacServiceProviderFactory(new ContainerBuilder());
}
public static AbpAutofacServiceProviderFactory AddAutofacServiceProviderFactory(this IServiceCollection services, ContainerBuilder containerBuilder)
{
var factory = new AbpAutofacServiceProviderFactory(containerBuilder);
services.AddObjectAccessor(containerBuilder);
services.AddSingleton((IServiceProviderFactory<ContainerBuilder>) factory);
return factory;
}
}
}

3
framework/src/Volo.Abp.BlazoriseUI/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.BlazoriseUI/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

24
framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.WebAssembly\Volo.Abp.AspNetCore.Components.WebAssembly.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Blazorise" Version="0.9.1.2" />
<PackageReference Include="Blazorise.DataGrid" Version="0.9.1.2" />
</ItemGroup>
</Project>

23
framework/src/Volo.Abp.BlazoriseUI/Volo/Abp/BlazoriseUI/AbpBlazoriseModule.cs

@ -0,0 +1,23 @@
using Blazorise;
using Volo.Abp.AspNetCore.Components.WebAssembly;
using Volo.Abp.Modularity;
namespace Volo.Abp.BlazoriseUI
{
[DependsOn(
typeof(AbpAspNetCoreComponentsWebAssemblyModule)
)]
public class AbpBlazoriseUIModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
ConfigureBlazorise(context);
}
private void ConfigureBlazorise(ServiceConfigurationContext context)
{
context.Services
.AddBlazorise();
}
}
}

235
framework/src/Volo.Abp.BlazoriseUI/Volo/Abp/BlazoriseUI/BlazoriseCrudPageBase.cs

@ -0,0 +1,235 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Blazorise;
using Blazorise.DataGrid;
using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.AspNetCore.Components.WebAssembly;
using Volo.Abp.ObjectMapping;
namespace Volo.Abp.BlazoriseUI
{
public abstract class BlazoriseCrudPageBase<TAppService, TEntityDto, TKey>
: BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, PagedAndSortedResultRequestDto>
where TAppService : ICrudAppService<TEntityDto, TKey>
where TEntityDto : IEntityDto<TKey>, new()
{
}
public abstract class BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput>
: BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput, TEntityDto>
where TAppService : ICrudAppService<TEntityDto, TKey, TGetListInput>
where TEntityDto : IEntityDto<TKey>, new()
where TGetListInput : new()
{
}
public abstract class BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput, TCreateInput>
: BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput, TCreateInput, TCreateInput>
where TAppService : ICrudAppService<TEntityDto, TKey, TGetListInput, TCreateInput>
where TEntityDto : IEntityDto<TKey>
where TCreateInput : new()
where TGetListInput : new()
{
}
public abstract class BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
: BlazoriseCrudPageBase<TAppService, TEntityDto, TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
where TAppService : ICrudAppService<TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
where TEntityDto : IEntityDto<TKey>
where TCreateInput : new()
where TUpdateInput : new()
where TGetListInput : new()
{
}
public abstract class BlazoriseCrudPageBase<TAppService, TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
: OwningComponentBase
where TAppService : ICrudAppService<TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
where TGetOutputDto : IEntityDto<TKey>
where TGetListOutputDto : IEntityDto<TKey>
where TCreateInput : new()
where TUpdateInput : new()
where TGetListInput : new()
{
[Inject] protected TAppService AppService { get; set; }
[Inject] protected IUiMessageService UiMessageService { get; set; }
[Inject] protected IStringLocalizer<AbpUiResource> UiLocalizer { get; set; }
protected virtual int PageSize { get; } = LimitedResultRequestDto.DefaultMaxResultCount;
protected int CurrentPage;
protected string CurrentSorting;
protected int? TotalCount;
protected IReadOnlyList<TGetListOutputDto> Entities = Array.Empty<TGetListOutputDto>();
protected TCreateInput NewEntity;
protected TKey EditingEntityId;
protected TUpdateInput EditingEntity;
protected Modal CreateModal;
protected Modal EditModal;
protected Type ObjectMapperContext { get; set; }
protected IObjectMapper ObjectMapper
{
get
{
if (_objectMapper != null)
{
return _objectMapper;
}
if (ObjectMapperContext == null)
{
return LazyGetRequiredService(ref _objectMapper);
}
return LazyGetRequiredService(
typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext),
ref _objectMapper
);
}
}
private IObjectMapper _objectMapper;
protected TService LazyGetRequiredService<TService>(ref TService reference)
=> LazyGetRequiredService(typeof(TService), ref reference);
protected TRef LazyGetRequiredService<TRef>(Type serviceType, ref TRef reference)
{
if (reference == null)
{
reference = (TRef) ScopedServices.GetRequiredService(serviceType);
}
return reference;
}
protected BlazoriseCrudPageBase()
{
NewEntity = new TCreateInput();
EditingEntity = new TUpdateInput();
}
protected override async Task OnInitializedAsync()
{
await GetEntitiesAsync();
}
protected virtual async Task GetEntitiesAsync()
{
var input = await CreateGetListInputAsync();
var result = await AppService.GetListAsync(input);
Entities = result.Items;
TotalCount = (int?) result.TotalCount;
}
protected virtual Task<TGetListInput> CreateGetListInputAsync()
{
var input = new TGetListInput();
if (input is ISortedResultRequest sortedResultRequestInput)
{
sortedResultRequestInput.Sorting = CurrentSorting;
}
if (input is IPagedResultRequest pagedResultRequestInput)
{
pagedResultRequestInput.SkipCount = CurrentPage * PageSize;
}
if (input is ILimitedResultRequest limitedResultRequestInput)
{
limitedResultRequestInput.MaxResultCount = PageSize;
}
return Task.FromResult(input);
}
protected virtual async Task OnDataGridReadAsync(DataGridReadDataEventArgs<TGetListOutputDto> e)
{
CurrentSorting = e.Columns
.Where(c => c.Direction != SortDirection.None)
.Select(c => c.Field + (c.Direction == SortDirection.Descending ? " DESC" : ""))
.JoinAsString(",");
CurrentPage = e.Page - 1;
await GetEntitiesAsync();
StateHasChanged();
}
protected virtual Task OpenCreateModalAsync()
{
NewEntity = new TCreateInput();
CreateModal.Show();
return Task.CompletedTask;
}
protected virtual Task CloseCreateModalAsync()
{
CreateModal.Hide();
return Task.CompletedTask;
}
protected virtual async Task OpenEditModalAsync(TKey id)
{
var entityDto = await AppService.GetAsync(id);
EditingEntityId = id;
EditingEntity = MapToEditingEntity(entityDto);
EditModal.Show();
}
protected virtual TUpdateInput MapToEditingEntity(TGetOutputDto entityDto)
{
return ObjectMapper.Map<TGetOutputDto, TUpdateInput>(entityDto);
}
protected virtual Task CloseEditModalAsync()
{
EditModal.Hide();
return Task.CompletedTask;
}
protected virtual async Task CreateEntityAsync()
{
await AppService.CreateAsync(NewEntity);
await GetEntitiesAsync();
CreateModal.Hide();
}
protected virtual async Task UpdateEntityAsync()
{
await AppService.UpdateAsync(EditingEntityId, EditingEntity);
await GetEntitiesAsync();
EditModal.Hide();
}
protected virtual async Task DeleteEntityAsync(TGetListOutputDto entity)
{
if (!await UiMessageService.ConfirmAsync(GetDeleteConfirmationMessage(entity)))
{
return;
}
await AppService.DeleteAsync(entity.Id);
await GetEntitiesAsync();
}
protected virtual string GetDeleteConfirmationMessage(TGetListOutputDto entity)
{
return UiLocalizer["ItemWillBeDeletedMessage"];
}
}
}

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -286,6 +286,8 @@ namespace Volo.Abp.Cli.Commands
return UiFramework.Mvc;
case "angular":
return UiFramework.Angular;
case "blazor":
return UiFramework.Blazor;
default:
return UiFramework.NotSpecified;
}

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs

@ -19,13 +19,14 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
pipeline.Steps.Add(new TemplateCodeDeleteStep());
pipeline.Steps.Add(new SolutionRenameStep());
if (context.Template.Name == AppProTemplate.TemplateName ||
if (context.Template.Name == AppProTemplate.TemplateName ||
context.Template.Name == ModuleProTemplate.TemplateName)
{
pipeline.Steps.Add(new LicenseCodeReplaceStep());
}
if (context.BuildArgs.UiFramework == UiFramework.Mvc && context.BuildArgs.MobileApp == MobileApp.None)
if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor)
&& context.BuildArgs.MobileApp == MobileApp.None)
{
pipeline.Steps.Add(new RemoveRootFolderStep());
}

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs

@ -5,6 +5,7 @@
NotSpecified = 0,
None = 1,
Mvc = 2,
Angular = 3
Angular = 3,
Blazor = 4
}
}
}

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs

@ -9,9 +9,10 @@
case UiFramework.None: return "none";
case UiFramework.Mvc: return "mvc";
case UiFramework.Angular: return "angular";
case UiFramework.Blazor: return "blazor";
case UiFramework.NotSpecified: return "NotSpecified";
default: return "NotSpecified";
}
}
}
}
}

30
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs

@ -65,12 +65,22 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
ConfigureWithAngularUi(context, steps);
break;
case UiFramework.Blazor:
ConfigureWithBlazorUi(context, steps);
break;
case UiFramework.Mvc:
case UiFramework.NotSpecified:
ConfigureWithMvcUi(context, steps);
break;
}
if (context.BuildArgs.UiFramework != UiFramework.Blazor)
{
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor"));
}
if (context.BuildArgs.UiFramework != UiFramework.Angular)
{
steps.Add(new RemoveFolderStep("/angular"));
@ -101,6 +111,26 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
}
}
private static void ConfigureWithBlazorUi(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Host"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Tests", projectFolderPath: "/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests"));
if (context.BuildArgs.ExtraProperties.ContainsKey("separate-identity-server"))
{
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds"));
steps.Add(new BlazorAppsettingsFilePortChangeForSeparatedIdentityServersStep());
}
else
{
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.HttpApi.Host"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.IdentityServer"));
steps.Add(new AppTemplateProjectRenameStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds", "MyCompanyName.MyProjectName.HttpApi.Host"));
steps.Add(new AppTemplateChangeConsoleTestClientPortSettingsStep("44305"));
}
}
private static void ConfigureWithMvcUi(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
if (context.BuildArgs.ExtraProperties.ContainsKey("tiered"))

39
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/BlazorAppsettingsFilePortChangeForSeparatedIdentityServersStep.cs

@ -0,0 +1,39 @@
using System;
using System.Linq;
using Volo.Abp.Cli.ProjectBuilding.Building;
namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
{
public class BlazorAppsettingsFilePortChangeForSeparatedIdentityServersStep : ProjectBuildPipelineStep
{
public override void Execute(ProjectBuildContext context)
{
var appsettingsFile = context.Files.FirstOrDefault(x =>
!x.IsDirectory &&
x.Name.EndsWith("aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/appsettings.json",
StringComparison.InvariantCultureIgnoreCase)
);
appsettingsFile.NormalizeLineEndings();
var lines = appsettingsFile.GetLines();
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i];
if (line.Contains("Authority") && line.Contains("localhost"))
{
line = line.Replace("44305", "44301");
}
else if (line.Contains("BaseUrl") && line.Contains("localhost"))
{
line = line.Replace("44305", "44300");
}
lines[i] = line;
}
appsettingsFile.SetLines(lines);
}
}
}

2
framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs

@ -7,4 +7,4 @@ namespace Volo.Abp
{
void Initialize([NotNull] IServiceProvider serviceProvider);
}
}
}

4
framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModule.cs

@ -1,6 +1,4 @@
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Modularity
namespace Volo.Abp.Modularity
{
public interface IAbpModule
{

2
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Services/ICrudAppService.cs

@ -9,7 +9,7 @@ namespace Volo.Abp.Application.Services
}
public interface ICrudAppService<TEntityDto, in TKey, in TGetListInput>
: ICrudAppService<TEntityDto, TKey, TGetListInput, TEntityDto, TEntityDto>
: ICrudAppService<TEntityDto, TKey, TGetListInput, TEntityDto>
{
}

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

@ -21,7 +21,7 @@ namespace Volo.Abp.Application.Services
}
public abstract class CrudAppService<TEntity, TEntityDto, TKey, TGetListInput>
: CrudAppService<TEntity, TEntityDto, TKey, TGetListInput, TEntityDto, TEntityDto>
: CrudAppService<TEntity, TEntityDto, TKey, TGetListInput, TEntityDto>
where TEntity : class, IEntity<TKey>
where TEntityDto : IEntityDto<TKey>
{

3
framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

25
framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<AssemblyName>Volo.Abp.Http.Client.IdentityModel.WebAssembly</AssemblyName>
<PackageId>Volo.Abp.Http.Client.IdentityModel.WebAssembly</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="3.2.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Http.Client.IdentityModel\Volo.Abp.Http.Client.IdentityModel.csproj" />
</ItemGroup>
</Project>

13
framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AbpHttpClientIdentityModelWebAssemblyModule.cs

@ -0,0 +1,13 @@
using System;
using Volo.Abp.Modularity;
namespace Volo.Abp.Http.Client.IdentityModel.WebAssembly
{
[DependsOn(
typeof(AbpHttpClientIdentityModelModule)
)]
public class AbpHttpClientIdentityModelWebAssemblyModule : AbpModule
{
}
}

50
framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs

@ -0,0 +1,50 @@
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.Authentication;
using Volo.Abp.IdentityModel;
namespace Volo.Abp.Http.Client.IdentityModel.WebAssembly
{
[Dependency(ReplaceServices = true)]
public class AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator : IdentityModelRemoteServiceHttpClientAuthenticator
{
protected IAccessTokenProvider AccessTokenProvider { get; }
public AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator(
IIdentityModelAuthenticationService identityModelAuthenticationService,
IAccessTokenProvider accessTokenProvider)
: base(identityModelAuthenticationService)
{
AccessTokenProvider = accessTokenProvider;
}
public override async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context)
{
if (context.RemoteService.GetUseCurrentAccessToken() != false)
{
var accessToken = await GetAccessTokenFromAccessTokenProviderOrNullAsync();
if (accessToken != null)
{
context.Request.SetBearerToken(accessToken);
return;
}
}
await base.Authenticate(context);
}
protected virtual async Task<string> GetAccessTokenFromAccessTokenProviderOrNullAsync()
{
var result = await AccessTokenProvider.RequestAccessToken();
if (result.Status != AccessTokenResultStatus.Success)
{
return null;
}
result.TryGetToken(out var token);
return token.Value;
}
}
}

79
framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs

@ -3,7 +3,6 @@ using System.Linq;
using System.Reflection;
using Castle.DynamicProxy;
using JetBrains.Annotations;
using Polly;
using Volo.Abp;
using Volo.Abp.Castle.DynamicProxy;
using Volo.Abp.Http.Client;
@ -30,23 +29,15 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="asDefaultServices">
/// True, to register the HTTP client proxy as the default implementation for the services.
/// </param>
/// <param name="configureHttpClientBuilder">
/// A delegate that is used to configure an <see cref="T:Microsoft.Extensions.DependencyInjection.IHttpClientBuilder" />.
/// </param>
public static IServiceCollection AddHttpClientProxies(
[NotNull] this IServiceCollection services,
[NotNull] Assembly assembly,
[NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName,
bool asDefaultServices = true,
Action<IHttpClientBuilder> configureHttpClientBuilder = null)
bool asDefaultServices = true)
{
Check.NotNull(services, nameof(assembly));
AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName, configureHttpClientBuilder);
//TODO: Make a configuration option and add remoteServiceName inside it!
var serviceTypes = assembly.GetTypes().Where(IsSuitableForDynamicClientProxying);
var serviceTypes = assembly.GetTypes().Where(IsSuitableForDynamicClientProxying).ToArray();
foreach (var serviceType in serviceTypes)
{
@ -72,17 +63,11 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="asDefaultService">
/// True, to register the HTTP client proxy as the default implementation for the service <typeparamref name="T"/>.
/// </param>
/// <param name="configureHttpClientBuilder">
/// A delegate that is used to configure an <see cref="T:Microsoft.Extensions.DependencyInjection.IHttpClientBuilder" />.
/// </param>
public static IServiceCollection AddHttpClientProxy<T>(
[NotNull] this IServiceCollection services,
[NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName,
bool asDefaultService = true,
Action<IHttpClientBuilder> configureHttpClientBuilder = null)
bool asDefaultService = true)
{
AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName, configureHttpClientBuilder);
return services.AddHttpClientProxy(
typeof(T),
remoteServiceConfigurationName,
@ -90,37 +75,6 @@ namespace Microsoft.Extensions.DependencyInjection
);
}
/// <summary>
/// Use IHttpClientFactory and polly
/// </summary>
/// <param name="services">Service collection</param>
/// <param name="remoteServiceConfigurationName">
/// The name of the remote service configuration to be used by the HTTP Client proxies.
/// See <see cref="AbpRemoteServiceOptions"/>.
/// </param>
/// <param name="configureHttpClientBuilder">
/// A delegate that is used to configure an <see cref="T:Microsoft.Extensions.DependencyInjection.IHttpClientBuilder" />.
/// </param>
public static IServiceCollection AddHttpClientFactoryAndPolicy(
[NotNull] this IServiceCollection services,
[NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName,
Action<IHttpClientBuilder> configureHttpClientBuilder = null)
{
var httpClientBuilder = services.AddHttpClient(remoteServiceConfigurationName);
if (configureHttpClientBuilder == null)
{
httpClientBuilder.AddTransientHttpErrorPolicy(builder =>
// retry 3 times
builder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i))));
}
else
{
configureHttpClientBuilder.Invoke(httpClientBuilder);
}
return services;
}
/// <summary>
/// Registers HTTP Client Proxy for given service <paramref name="type"/>.
/// </summary>
@ -143,6 +97,8 @@ namespace Microsoft.Extensions.DependencyInjection
Check.NotNull(type, nameof(type));
Check.NotNullOrWhiteSpace(remoteServiceConfigurationName, nameof(remoteServiceConfigurationName));
AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName);
services.Configure<AbpHttpClientOptions>(options =>
{
options.HttpClientProxies[type] = new DynamicHttpClientProxyConfig(type, remoteServiceConfigurationName);
@ -189,13 +145,36 @@ namespace Microsoft.Extensions.DependencyInjection
return services;
}
private static IServiceCollection AddHttpClientFactoryAndPolicy(
[NotNull] this IServiceCollection services,
[NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName)
{
var preOptions = services.ExecutePreConfiguredActions<AbpHttpClientBuilderOptions>();
if (preOptions.ConfiguredProxyClients.Contains(remoteServiceConfigurationName))
{
return services;
}
var clientBuilder = services.AddHttpClient(remoteServiceConfigurationName);
foreach (var clientBuildAction in preOptions.ProxyClientBuildActions)
{
clientBuildAction(remoteServiceConfigurationName, clientBuilder);
}
preOptions.ConfiguredProxyClients.Add(remoteServiceConfigurationName);
return services;
}
/// <summary>
/// Checks wether the type is suitable to use with the dynamic proxying.
/// Currently the type is checked statically against some fixed conditions.
/// </summary>
/// <param name="type">Type to check</param>
/// <returns>True, if the type is suitable for dynamic proxying. Otherwise false.</returns>
static bool IsSuitableForDynamicClientProxying(Type type)
private static bool IsSuitableForDynamicClientProxying(Type type)
{
//TODO: Add option to change type filter

19
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientBuilderOptions.cs

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.Http.Client
{
public class AbpHttpClientBuilderOptions
{
public List<Action<string, IHttpClientBuilder>> ProxyClientBuildActions { get; }
internal HashSet<string> ConfiguredProxyClients { get; }
public AbpHttpClientBuilderOptions()
{
ProxyClientBuildActions = new List<Action<string, IHttpClientBuilder>>();
ConfiguredProxyClients = new HashSet<string>();
}
}
}

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

@ -1,11 +1,11 @@
using System.Linq;
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http;
using Volo.Abp.Castle;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Threading;
using Volo.Abp.Validation;
using Polly;
namespace Volo.Abp.Http.Client
{
@ -18,29 +18,26 @@ namespace Volo.Abp.Http.Client
)]
public class AbpHttpClientModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpRemoteServiceOptions>(configuration);
}
public override void PostConfigureServices(ServiceConfigurationContext context)
public override void PreConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpHttpClientOptions>(options =>
PreConfigure<AbpHttpClientBuilderOptions>(options =>
{
if (options.HttpClientActions.Any())
options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) =>
{
var httpClientNames = options.HttpClientProxies.Select(x => x.Value.RemoteServiceName);
foreach (var httpClientName in httpClientNames)
{
foreach (var httpClientAction in options.HttpClientActions)
{
context.Services.Configure<HttpClientFactoryOptions>(httpClientName,
x => x.HttpClientActions.Add(httpClientAction.Invoke(httpClientName)));
}
}
}
clientBuilder.AddTransientHttpErrorPolicy(policyBuilder =>
policyBuilder.WaitAndRetryAsync(
3,
i => TimeSpan.FromSeconds(Math.Pow(2, i))
)
);
});
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AbpRemoteServiceOptions>(configuration);
}
}
}

4
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/AbpHttpClientOptions.cs

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using Volo.Abp.Http.Client.DynamicProxying;
namespace Volo.Abp.Http.Client
@ -9,12 +8,9 @@ namespace Volo.Abp.Http.Client
{
public Dictionary<Type, DynamicHttpClientProxyConfig> HttpClientProxies { get; set; }
public List<Func<string, Action<HttpClient>>> HttpClientActions { get; }
public AbpHttpClientOptions()
{
HttpClientProxies = new Dictionary<Type, DynamicHttpClientProxyConfig>();
HttpClientActions = new List<Func<string, Action<HttpClient>>>();
}
}
}

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

@ -25,7 +25,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
public class DynamicHttpProxyInterceptor<TService> : AbpInterceptor, ITransientDependency
{
// ReSharper disable once StaticMemberInGenericType
protected static MethodInfo GenericInterceptAsyncMethod { get; }
protected static MethodInfo MakeRequestAndGetResultAsyncMethod { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected ICorrelationIdProvider CorrelationIdProvider { get; }
@ -42,7 +42,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
static DynamicHttpProxyInterceptor()
{
GenericInterceptAsyncMethod = typeof(DynamicHttpProxyInterceptor<TService>)
MakeRequestAndGetResultAsyncMethod = typeof(DynamicHttpProxyInterceptor<TService>)
.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
.First(m => m.Name == nameof(MakeRequestAndGetResultAsync) && m.IsGenericMethodDefinition);
}
@ -81,7 +81,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
}
else
{
var result = (Task)GenericInterceptAsyncMethod
var result = (Task)MakeRequestAndGetResultAsyncMethod
.MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
.Invoke(this, new object[] { invocation });
@ -90,7 +90,6 @@ namespace Volo.Abp.Http.Client.DynamicProxying
invocation.Method.ReturnType.GetGenericArguments()[0]
);
}
}
private async Task<object> GetResultAsync(Task task, Type resultType)

30
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/CurrentPrincipalAccessorBase.cs

@ -0,0 +1,30 @@
using System;
using System.Security.Claims;
using System.Threading;
namespace Volo.Abp.Security.Claims
{
public abstract class CurrentPrincipalAccessorBase : ICurrentPrincipalAccessor
{
public ClaimsPrincipal Principal => _currentPrincipal.Value ?? GetClaimsPrincipal();
private readonly AsyncLocal<ClaimsPrincipal> _currentPrincipal = new AsyncLocal<ClaimsPrincipal>();
protected abstract ClaimsPrincipal GetClaimsPrincipal();
public virtual IDisposable Change(ClaimsPrincipal principal)
{
return SetCurrent(principal);
}
private IDisposable SetCurrent(ClaimsPrincipal principal)
{
var parent = Principal;
_currentPrincipal.Value = principal;
return new DisposeAction(() =>
{
_currentPrincipal.Value = parent;
});
}
}
}

26
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ThreadCurrentPrincipalAccessor.cs

@ -1,34 +1,14 @@
using System;
using System.Security.Claims;
using System.Security.Claims;
using System.Threading;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Security.Claims
{
public class ThreadCurrentPrincipalAccessor : ICurrentPrincipalAccessor, ISingletonDependency
public class ThreadCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ISingletonDependency
{
public ClaimsPrincipal Principal => _currentPrincipal.Value ?? GetClaimsPrincipal();
private readonly AsyncLocal<ClaimsPrincipal> _currentPrincipal = new AsyncLocal<ClaimsPrincipal>();
protected virtual ClaimsPrincipal GetClaimsPrincipal()
protected override ClaimsPrincipal GetClaimsPrincipal()
{
return Thread.CurrentPrincipal as ClaimsPrincipal;
}
public virtual IDisposable Change(ClaimsPrincipal principal)
{
return SetCurrent(principal);
}
private IDisposable SetCurrent(ClaimsPrincipal principal)
{
var parent = Principal;
_currentPrincipal.Value = principal;
return new DisposeAction(() =>
{
_currentPrincipal.Value = parent;
});
}
}
}

17
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs

@ -87,13 +87,16 @@ namespace Volo.Abp.UI.Navigation.Urls
tenantNamePlaceHolder = TenantNamePlaceHolder + '.';
}
if (CurrentTenant.Id.HasValue)
if (url.Contains(tenantNamePlaceHolder))
{
url = url.Replace(tenantNamePlaceHolder, await GetCurrentTenantNameAsync());
}
else
{
url = url.Replace(tenantNamePlaceHolder, "");
if (CurrentTenant.Id.HasValue)
{
url = url.Replace(tenantNamePlaceHolder, await GetCurrentTenantNameAsync());
}
else
{
url = url.Replace(tenantNamePlaceHolder, "");
}
}
return url;
@ -110,4 +113,4 @@ namespace Volo.Abp.UI.Navigation.Urls
return CurrentTenant.Name;
}
}
}
}

4
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json

@ -62,6 +62,8 @@
"500Message": "Internal Server Error",
"GoHomePage": "Go to the homepage",
"GoBack": "Go back",
"Search": "Search"
"Search": "Search",
"ItemWillBeDeletedMessageWithFormat": "{0} will be deleted!",
"ItemWillBeDeletedMessage": "This item will be deleted!"
}
}

4
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json

@ -62,6 +62,8 @@
"500Message": "Sunucu tarafında hata",
"GoHomePage": "Ana sayfaya git",
"GoBack": "Geri dön",
"Search": "Arama"
"Search": "Arama",
"ItemWillBeDeletedMessageWithFormat": "{0} silinecektir!",
"ItemWillBeDeletedMessage": "Bu nesne silinecektir!"
}
}

13
framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/DefaultBrandingProvider.cs

@ -0,0 +1,13 @@
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Ui.Branding
{
public class DefaultBrandingProvider : IBrandingProvider, ITransientDependency
{
public virtual string AppName => "MyApplication";
public virtual string LogoUrl => null;
public virtual string LogoReverseUrl => null;
}
}

17
framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/IBrandingProvider.cs

@ -0,0 +1,17 @@
namespace Volo.Abp.Ui.Branding
{
public interface IBrandingProvider
{
string AppName { get; }
/// <summary>
/// Logo on white background
/// </summary>
string LogoUrl { get; }
/// <summary>
/// Logo on dark background
/// </summary>
string LogoReverseUrl { get; }
}
}

7
modules/account/Volo.Abp.Account.sln

@ -21,6 +21,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{12FAE513-7
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Account.Application.Tests", "test\Volo.Abp.Account.Application.Tests\Volo.Abp.Account.Application.Tests.csproj", "{356EAC51-5D55-4852-A8A5-2F90EAC8DAE3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Account.Blazor", "src\Volo.Abp.Account.Blazor\Volo.Abp.Account.Blazor.csproj", "{EE8858B3-A638-481B-8EB9-74F5E7D43D80}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -55,6 +57,10 @@ Global
{356EAC51-5D55-4852-A8A5-2F90EAC8DAE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{356EAC51-5D55-4852-A8A5-2F90EAC8DAE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{356EAC51-5D55-4852-A8A5-2F90EAC8DAE3}.Release|Any CPU.Build.0 = Release|Any CPU
{EE8858B3-A638-481B-8EB9-74F5E7D43D80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE8858B3-A638-481B-8EB9-74F5E7D43D80}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE8858B3-A638-481B-8EB9-74F5E7D43D80}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE8858B3-A638-481B-8EB9-74F5E7D43D80}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -67,6 +73,7 @@ Global
{EBF0C2B3-14CB-4DFC-9753-ECBF959CBA2E} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
{7BCA5955-B3F6-41E8-9D5D-D115195C6098} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
{356EAC51-5D55-4852-A8A5-2F90EAC8DAE3} = {12FAE513-7575-4235-89DF-277BA1A3B098}
{EE8858B3-A638-481B-8EB9-74F5E7D43D80} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2B054393-D2B2-4EA8-8A15-D60CBCF3E7A9}

20
modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs

@ -0,0 +1,20 @@
using AutoMapper;
using Volo.Abp.Account.Blazor.Pages.Account;
using Volo.Abp.AutoMapper;
using Volo.Abp.Identity;
namespace Volo.Abp.Account.Blazor
{
public class AbpAccountBlazorAutoMapperProfile : Profile
{
public AbpAccountBlazorAutoMapperProfile()
{
CreateMap<ProfileDto, PersonalInfoModel>()
.Ignore(x => x.PhoneNumberConfirmed)
.Ignore(x => x.EmailConfirmed);
CreateMap<PersonalInfoModel, UpdateProfileDto>()
.Ignore(x => x.ExtraProperties);
}
}
}

37
modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs

@ -0,0 +1,37 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming;
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.Account.Blazor
{
[DependsOn(
typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule),
typeof(AbpAutoMapperModule),
typeof(AbpAccountHttpApiClientModule)
)]
public class AbpAccountBlazorModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<AbpAccountBlazorModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpAccountBlazorAutoMapperProfile>(validate: true);
});
Configure<AbpNavigationOptions>(options =>
{
options.MenuContributors.Add(new AbpAccountBlazorUserMenuContributor());
});
Configure<AbpRouterOptions>(options =>
{
options.AdditionalAssemblies.Add(typeof(AbpAccountBlazorModule).Assembly);
});
}
}
}

23
modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorUserMenuContributor.cs

@ -0,0 +1,23 @@
using System.Threading.Tasks;
using Volo.Abp.Account.Localization;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.Account.Blazor
{
public class AbpAccountBlazorUserMenuContributor : IMenuContributor
{
public Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name != StandardMenus.User)
{
return Task.CompletedTask;
}
var accountResource = context.GetLocalizer<AccountResource>();
context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountResource["ManageYourProfile"], url: "account/manage-profile", icon: "fa fa-cog"));
return Task.CompletedTask;
}
}
}

3
modules/account/src/Volo.Abp.Account.Blazor/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
modules/account/src/Volo.Abp.Account.Blazor/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

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

Loading…
Cancel
Save