Browse Source

Merge remote-tracking branch 'abpframework/dev' into Translate

pull/2313/head
liangshiwei 7 years ago
parent
commit
a41c573a08
  1. 4
      .github/labeler.yml
  2. 17
      .github/workflows/labeler.yml
  3. 24
      .github/workflows/main.yml
  4. 1
      .gitignore
  5. 6
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json
  6. 8
      docs/cs/Getting-Started-Angular-Template.md
  7. 6
      docs/cs/Getting-Started-AspNetCore-MVC-Template.md
  8. 8
      docs/en/AspNetCore/Bundling-Minification.md
  9. 2
      docs/en/Background-Jobs.md
  10. 4
      docs/en/Best-Practices/Module-Architecture.md
  11. 11
      docs/en/Data-Access.md
  12. 3
      docs/en/Entities.md
  13. 8
      docs/en/Getting-Started-Angular-Template.md
  14. 6
      docs/en/Getting-Started-AspNetCore-MVC-Template.md
  15. 4
      docs/en/Multi-Tenancy.md
  16. 42
      docs/en/Tutorials/Angular/Part-II.md
  17. 1
      docs/en/docs-nav.json
  18. 8
      docs/pt-BR/Getting-Started-Angular-Template.md
  19. 6
      docs/pt-BR/Getting-Started-AspNetCore-MVC-Template.md
  20. 2
      docs/zh-Hans/Background-Jobs.md
  21. 2
      docs/zh-Hans/Best-Practices/Application-Services.md
  22. 2
      docs/zh-Hans/Best-Practices/Entity-Framework-Core-Integration.md
  23. 16
      docs/zh-Hans/Best-Practices/Module-Architecture.md
  24. 6
      docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md
  25. 6
      docs/zh-Hans/Index.md
  26. 4
      docs/zh-Hans/Multi-Tenancy.md
  27. 16
      framework/Volo.Abp.sln
  28. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj
  29. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/AbpAspNetCoreMvcUiBundlingModule.cs
  30. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundlerBase.cs
  31. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Scripts/ScriptBundler.cs
  32. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Styles/StyleBundler.cs
  33. 28
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/LanguageSwitch/Default.cshtml
  34. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/UserMenu/Default.cshtml
  35. 14
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml
  36. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml
  37. 3
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs
  38. 12
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs
  39. 49
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinder.cs
  40. 47
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinderProvider.cs
  41. 7
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ProxyScripting/AbpServiceProxyScriptController.cs
  42. 4
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ProxyScripting/ServiceProxyGenerationModel.cs
  43. 24
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs
  44. 10
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeServicesAttribute.cs
  45. 3
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposedServiceExplorer.cs
  46. 55
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  47. 17
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter.cs
  48. 62
      framework/src/Volo.Abp.Http.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicHttpClientProxyExtensions.cs
  49. 1
      framework/src/Volo.Abp.Http/Volo.Abp.Http.csproj
  50. 2
      framework/src/Volo.Abp.Http/Volo/Abp/Http/AbpHttpModule.cs
  51. 9
      framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/ProxyScriptManager.cs
  52. 5
      framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/ProxyScriptingModel.cs
  53. 2
      framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj
  54. 24
      framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj
  55. 8
      framework/src/Volo.Abp.Minify/Volo/Abp/Minify/AbpMinifyModule.cs
  56. 7
      framework/src/Volo.Abp.Minify/Volo/Abp/Minify/Html/IHtmlMinifier.cs
  57. 2
      framework/src/Volo.Abp.Minify/Volo/Abp/Minify/IMinifier.cs
  58. 4
      framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyCssMinifier.cs
  59. 2
      framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyException.cs
  60. 13
      framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyHtmlMinifier.cs
  61. 6
      framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyJavascriptMinifier.cs
  62. 2
      framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyMinifierBase.cs
  63. 2
      framework/src/Volo.Abp.Minify/Volo/Abp/Minify/Scripts/IJavascriptMinifier.cs
  64. 2
      framework/src/Volo.Abp.Minify/Volo/Abp/Minify/Styles/ICssMinifier.cs
  65. 61
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController.cs
  66. 100
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController_Tests.cs
  67. 13
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ProxyScripting/AbpServiceProxiesController_Tests.cs
  68. 26
      framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo/Abp/AspNetCore/Mvc/UI/Minification/NUglify/JavascriptMinifier_Tests.cs
  69. 9
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs
  70. 11
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
  71. 9
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter_Tests.cs
  72. 24
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/PersonRepository.cs
  73. 20
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs
  74. 16
      framework/test/Volo.Abp.Minify.Tests/Volo.Abp.Minify.Tests.csproj
  75. 11
      framework/test/Volo.Abp.Minify.Tests/Volo/Abp/Minify/AbpMinifyTestModule.cs
  76. 28
      framework/test/Volo.Abp.Minify.Tests/Volo/Abp/Minify/NUglify/CssMinifier_Tests.cs
  77. 27
      framework/test/Volo.Abp.Minify.Tests/Volo/Abp/Minify/NUglify/HtmlMinifier_Tests.cs
  78. 28
      framework/test/Volo.Abp.Minify.Tests/Volo/Abp/Minify/NUglify/JavascriptMinifier_Tests.cs
  79. 10
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/City.cs
  80. 30
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/District.cs
  81. 13
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/IPersonRepository.cs
  82. 6
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs
  83. 17
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PersonView.cs
  84. 7
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestDataBuilder.cs
  85. 73
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/AbpDateTimeValueConverter_Tests.cs
  86. 17
      modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs
  87. 7
      modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/LogoutController.cs
  88. 12
      modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs
  89. 4
      modules/account/src/Volo.Abp.Account.Web/Settings/AccountSettingDefinitionProvider.cs
  90. 2
      modules/account/src/Volo.Abp.Account.Web/Settings/AccountSettingNames.cs
  91. 2
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs
  92. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs
  93. 9
      modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/AbpIdentityHttpApiModule.cs
  94. 8
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json
  95. 3
      modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.js
  96. 3
      npm/ng-packs/.prettierrc
  97. 1
      npm/ng-packs/.vscode/settings.json
  98. 1
      npm/ng-packs/apps/dev-app/src/app/app.component.ts
  99. 2
      npm/ng-packs/apps/dev-app/src/index.html
  100. 4
      npm/ng-packs/dist/account-config/README.md

4
.github/labeler.yml

@ -0,0 +1,4 @@
ui-angular:
- npm/ng-packs/**/*
- templates/app/angular/**/*
- templates/module/angular/**/*

17
.github/workflows/labeler.yml

@ -0,0 +1,17 @@
name: "Pull Request Labeler"
on:
pull_request:
paths:
- npm/ng-packs/**/*
- templates/app/angular/**/*
- templates/module/angular/**/*
branches:
- master
- dev
jobs:
labeler:
runs-on: ubuntu-18.04
steps:
- uses: actions/labeler@v2
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

24
.github/workflows/main.yml

@ -1,24 +0,0 @@
name: 'Main'
on:
pull_request:
paths:
- 'framework/**'
- 'modules/**'
branches:
- dev
jobs:
build-test:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-dotnet@master
with:
dotnet-version: '3.0.100'
- name: Build All
run: .\build-all.ps1
shell: pwsh
- name: Test All
run: .\test-all.ps1
shell: pwsh

1
.gitignore

@ -289,4 +289,5 @@ samples/MicroserviceDemo/gateways/BackendAdminAppGateway.Host/Logs/logs.txt
samples/MicroserviceDemo/applications/PublicWebSite.Host/Logs/logs.txt samples/MicroserviceDemo/applications/PublicWebSite.Host/Logs/logs.txt
samples/MicroserviceDemo/gateways/PublicWebSiteGateway.Host/Logs/logs.txt samples/MicroserviceDemo/gateways/PublicWebSiteGateway.Host/Logs/logs.txt
samples/MicroserviceDemo/microservices/BloggingService.Host/Logs/logs.txt samples/MicroserviceDemo/microservices/BloggingService.Host/Logs/logs.txt
samples/MicroserviceDemo/applications/ConsoleClientDemo/Logs/logs.txt
modules/docs/app/Volo.DocsTestApp/Logs/logs.txt modules/docs/app/Volo.DocsTestApp/Logs/logs.txt

6
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json

@ -18,10 +18,10 @@
"AbpShortDescription": "ABP é uma arquitetura completa e uma forte infraestrutura para criar aplicativos da web modernos! Segue as melhores práticas e convenções para fornecer uma sólida experiência de desenvolvimento.", "AbpShortDescription": "ABP é uma arquitetura completa e uma forte infraestrutura para criar aplicativos da web modernos! Segue as melhores práticas e convenções para fornecer uma sólida experiência de desenvolvimento.",
"SourceCodeUpper": "CÓDIGO FONTE", "SourceCodeUpper": "CÓDIGO FONTE",
"LatestReleaseLogs": "Últimos registros de lançamento", "LatestReleaseLogs": "Últimos registros de lançamento",
"Infrastructure": "Infra-estrutura", "Infrastructure": "Infraestrutura",
"Architecture": "Arquitetura", "Architecture": "Arquitetura",
"Modular": "Modular", "Modular": "Modular",
"DontRepeatYourself": "Não se repita", "DontRepeatYourself": "Não repita a si mesmo",
"DeveloperFocused": "Desenvolvedor focado", "DeveloperFocused": "Desenvolvedor focado",
"FullStackApplicationInfrastructure": "Infraestrutura de aplicativos full stack.", "FullStackApplicationInfrastructure": "Infraestrutura de aplicativos full stack.",
"DomainDrivenDesign": "Design Orientado a Domínio", "DomainDrivenDesign": "Design Orientado a Domínio",
@ -30,7 +30,7 @@
"AuthorizationExplanation": "Autorização avançada com usuário, função e sistema de permissão refinado. Criada na biblioteca Microsoft Identity.", "AuthorizationExplanation": "Autorização avançada com usuário, função e sistema de permissão refinado. Criada na biblioteca Microsoft Identity.",
"MultiTenancy": "Múltiplos inquilinos", "MultiTenancy": "Múltiplos inquilinos",
"MultiTenancyExplanation": "Aplicativos SaaS facilitados! Multilocação integrada do banco de dados à interface do usuário.", "MultiTenancyExplanation": "Aplicativos SaaS facilitados! Multilocação integrada do banco de dados à interface do usuário.",
"CrossCuttingConcerns": "Preocupações transversais", "CrossCuttingConcerns": "Características transversais",
"CrossCuttingConcernsExplanation": "Infraestrutura completa para autorização, validação, tratamento de exceções, armazenamento em cache, log de auditoria, gerenciamento de transações e assim por diante.", "CrossCuttingConcernsExplanation": "Infraestrutura completa para autorização, validação, tratamento de exceções, armazenamento em cache, log de auditoria, gerenciamento de transações e assim por diante.",
"BuiltInBundlingMinification": "Pacote & Minificação Integrados", "BuiltInBundlingMinification": "Pacote & Minificação Integrados",
"BuiltInBundlingMinificationExplanation": "Pare de usar ferramentas externas para empacotamento e minificação. O ABP oferece uma maneira mais simples, dinâmica, poderosa, modular e integrada!", "BuiltInBundlingMinificationExplanation": "Pare de usar ferramentas externas para empacotamento e minificação. O ABP oferece uma maneira mais simples, dinâmica, poderosa, modular e integrada!",

8
docs/cs/Getting-Started-Angular-Template.md

@ -26,10 +26,10 @@ abp new Acme.BookStore -u angular
Vytvořené řešení vyžaduje; Vytvořené řešení vyžaduje;
* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/) * [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/) * [.NET Core 3.0+](https://www.microsoft.com/net/download/dotnet-core/)
* [Node v10.16+](https://nodejs.org) * [Node v12+](https://nodejs.org)
* [Yarn v1.17+](https://yarnpkg.com/) * [Yarn v1.19+](https://yarnpkg.com/)
### Struktura řešení ### Struktura řešení

6
docs/cs/Getting-Started-AspNetCore-MVC-Template.md

@ -26,8 +26,10 @@ Příkaz `new` vytvoří **vrstvenou MVC aplikaci** s **Entity Framework Core**
Vytvořené řešení vyžaduje; Vytvořené řešení vyžaduje;
* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/) * [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/) * [.NET Core 3.0+](https://www.microsoft.com/net/download/dotnet-core/)
* [Node v12+](https://nodejs.org)
* [Yarn v1.19+](https://yarnpkg.com/)
### Struktura řešení ### Struktura řešení

8
docs/en/AspNetCore/Bundling-Minification.md

@ -114,7 +114,7 @@ public class MyWebModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
Configure<BundlingOptions>(options => Configure<AbpBundlingOptions>(options =>
{ {
options options
.ScriptBundles .ScriptBundles
@ -151,7 +151,7 @@ public class MyWebExtensionModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
Configure<BundlingOptions>(options => Configure<AbpBundlingOptions>(options =>
{ {
options options
.ScriptBundles .ScriptBundles
@ -189,7 +189,7 @@ public class MyExtensionGlobalStyleContributor : BundleContributor
Then you can use this contributor as like below: Then you can use this contributor as like below:
````C# ````C#
services.Configure<BundlingOptions>(options => services.Configure<AbpBundlingOptions>(options =>
{ {
options options
.ScriptBundles .ScriptBundles
@ -317,7 +317,7 @@ In some specific cases, it may be needed to create a **new** bundle **inherited*
Example: Example:
````c# ````c#
services.Configure<BundlingOptions>(options => services.Configure<AbpBundlingOptions>(options =>
{ {
options options
.StyleBundles .StyleBundles

2
docs/en/Background-Jobs.md

@ -40,7 +40,7 @@ using Volo.Abp.Emailing;
namespace MyProject namespace MyProject
{ {
public class EmailSendingJob : BackgroundJob<EmailSendingArgs> public class EmailSendingJob : BackgroundJob<EmailSendingArgs>, ITransientDependency
{ {
private readonly IEmailSender _emailSender; private readonly IEmailSender _emailSender;

4
docs/en/Best-Practices/Module-Architecture.md

@ -57,7 +57,7 @@ Next section describes the packages in more details.
* **Do** divide the domain layer into two projects: * **Do** divide the domain layer into two projects:
* **Domain.Shared** package, named as *CompanyName.ModuleName.Domain.Shared*, that contains constants, enums and other types those can be safely shared with the all layers of the module. This package can also be shared to 3rd-party clients. It can not contain entities, repositories, domain services or any other business objects. * **Domain.Shared** package, named as *CompanyName.ModuleName.Domain.Shared*, that contains constants, enums and other types those can be safely shared with the all layers of the module. This package can also be shared to 3rd-party clients. It can not contain entities, repositories, domain services or any other business objects.
* **Domain** package, named as *CompanyName.ModuleName.Domain*, that contains entities, repository interfaces, domain service interfaces and their implementations and other domain objects. * **Domain** package, named as *CompanyName.ModuleName.Domain*, that contains entities, repository interfaces, domain service interfaces and their implementations and other domain objects.
* Domain package depends on the **Domain.Share** package. * Domain package depends on the **Domain.Shared** package.
#### Application Layer #### Application Layer
@ -85,5 +85,5 @@ Next section describes the packages in more details.
#### Web Layer #### Web Layer
* Do create a **Web** package, named as *CompanyName.ModuleName.Web*, that contains pages, views, scripts, styles, images and other UI components. * **Do** create a **Web** package, named as *CompanyName.ModuleName.Web*, that contains pages, views, scripts, styles, images and other UI components.
* Web package only depends on the **HttpApi** package. * Web package only depends on the **HttpApi** package.

11
docs/en/Data-Access.md

@ -0,0 +1,11 @@
# Data Access
ABP framework was designed as database agnostic, it can work any type of data source by the help of the [repository](Repositories.md) and [unit of work](Unit-Of-Work.md) abstractions.
However, currently the following providers are implements:
* [Entity Framework Core](Entity-Framework-Core.md) (works with [various DBMS and providers](https://docs.microsoft.com/en-us/ef/core/providers/?tabs=dotnet-core-cli).)
* [MongoDB](MongoDB.md)
* [Dapper](Dapper.md)
More providers might be added in the next releases.

3
docs/en/Entities.md

@ -59,7 +59,8 @@ Entities with composite keys should implement the `GetKeys()` method as shown ab
Notice that you also need to define keys of the entity in your **object-relational mapping** (ORM) configuration. Notice that you also need to define keys of the entity in your **object-relational mapping** (ORM) configuration.
> Composite primary keys has a restriction with repositories. Since it has not known Id property, you can not use `IRepository<TEntity, TKey>` for these entities. However, you can always use `IRepository<TEntity>`. See [repositories documentation](Repositories.md) for more. > Also note that Entities with Composite Primary Keys cannot utilize the `IRepository<TEntity, TKey>` interface since it requires a single unique Id property. However, you can always use `IRepository<TEntity>`. See [repositories documentation](Repositories.md) for more.
### AggregateRoot Class ### AggregateRoot Class

8
docs/en/Getting-Started-Angular-Template.md

@ -26,10 +26,10 @@ abp new Acme.BookStore -u angular
The created solution requires; The created solution requires;
* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/) * [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/) * [.NET Core 3.0+](https://www.microsoft.com/net/download/dotnet-core/)
* [Node v10.16+](https://nodejs.org) * [Node v12+](https://nodejs.org)
* [Yarn v1.17+](https://yarnpkg.com/) * [Yarn v1.19+](https://yarnpkg.com/)
### The Solution Structure ### The Solution Structure

6
docs/en/Getting-Started-AspNetCore-MVC-Template.md

@ -26,8 +26,10 @@ abp new Acme.BookStore
The created solution requires; The created solution requires;
* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/) * [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/) * [.NET Core 3.0+](https://www.microsoft.com/net/download/dotnet-core/)
* [Node v12+](https://nodejs.org)
* [Yarn v1.19+](https://yarnpkg.com/)
### The Solution Structure ### The Solution Structure

4
docs/en/Multi-Tenancy.md

@ -312,10 +312,10 @@ http://nginx.org/en/docs/http/ngx_http_core_module.html#ignore_invalid_headers
http://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers http://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers
"__tenant" parameter name can be changed using AspNetCoreMultiTenancyOptions. Example: "__tenant" parameter name can be changed using AbpAspNetCoreMultiTenancyOptions. Example:
````C# ````C#
services.Configure<AspNetCoreMultiTenancyOptions>(options => services.Configure<AbpAspNetCoreMultiTenancyOptions>(options =>
{ {
options.TenantKey = "MyTenantKey"; options.TenantKey = "MyTenantKey";
}); });

42
docs/en/Tutorials/Angular/Part-II.md

@ -218,26 +218,6 @@ Open `book-list.component.html` and add the form in the body template of the mod
> We've used [NgBootstrap datepicker](https://ng-bootstrap.github.io/#/components/datepicker/overview) in this component. > We've used [NgBootstrap datepicker](https://ng-bootstrap.github.io/#/components/datepicker/overview) in this component.
Open the `book-list.component.ts` and then create an array, named `bookTypeArr`:
```js
//...
booksType = Books.BookType;
bookTypeArr = Object.keys(Books.BookType).filter(
bookType => typeof this.booksType[bookType] === 'number'
);
```
> It use the `booksType` field,please put the `bookTypeArr` defined below that line
The `bookTypeArr` contains the fields of the `BookType` enum. Resulting array is shown below:
```js
['Adventure', 'Biography', 'Dystopia', 'Fantastic' ...]
```
This array was used in the previous form template (in the `ngFor` loop).
#### Datepicker Requirements #### Datepicker Requirements
You need to import `NgbDatepickerModule` to the `books.module.ts`: You need to import `NgbDatepickerModule` to the `books.module.ts`:
@ -269,6 +249,28 @@ export class BookListComponent implements OnInit {
> The `NgbDateAdapter` converts Datepicker value to `Date` type. See the [datepicker adapters](https://ng-bootstrap.github.io/#/components/datepicker/overview) for more details. > The `NgbDateAdapter` converts Datepicker value to `Date` type. See the [datepicker adapters](https://ng-bootstrap.github.io/#/components/datepicker/overview) for more details.
#### Create the Book Type Array
Open the `book-list.component.ts` and then create an array, named `bookTypeArr`:
```js
//...
booksType = Books.BookType;
bookTypeArr = Object.keys(Books.BookType).filter(
bookType => typeof this.booksType[bookType] === 'number'
);
```
The `bookTypeArr` contains the fields of the `BookType` enum. Resulting array is shown below:
```js
['Adventure', 'Biography', 'Dystopia', 'Fantastic' ...]
```
This array was used in the previous form template (in the `ngFor` loop).
![new-book-form](images/bookstore-new-book-form.png) ![new-book-form](images/bookstore-new-book-form.png)
#### Saving the Book #### Saving the Book

1
docs/en/docs-nav.json

@ -257,6 +257,7 @@
}, },
{ {
"text": "Data Access", "text": "Data Access",
"path": "Data-Access.md"
"items": [ "items": [
{ {
"text": "Entity Framework Core Integration", "text": "Entity Framework Core Integration",

8
docs/pt-BR/Getting-Started-Angular-Template.md

@ -26,10 +26,10 @@ abp new Acme.BookStore -u angular
A solução criada requer; A solução criada requer;
- [Visual Studio 2017 (v15.9.0 +)](https://visualstudio.microsoft.com/tr/downloads/) * [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
- [.NET Core 2.2 ou superior](https://www.microsoft.com/net/download/dotnet-core/) * [.NET Core 3.0+](https://www.microsoft.com/net/download/dotnet-core/)
- [Node v10.16 +](https://nodejs.org/) * [Node v12+](https://nodejs.org)
- [Yarn v1.17 +](https://yarnpkg.com/) * [Yarn v1.19+](https://yarnpkg.com/)
### A Estrutura da Solução ### A Estrutura da Solução

6
docs/pt-BR/Getting-Started-AspNetCore-MVC-Template.md

@ -26,8 +26,10 @@ abp new Acme.BookStore
A solução criada requer; A solução criada requer;
- [Visual Studio 2017 (v15.9.0 +)](https://visualstudio.microsoft.com/tr/downloads/) * [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
- [.NET Core 2.2 ou superior](https://www.microsoft.com/net/download/dotnet-core/) * [.NET Core 3.0+](https://www.microsoft.com/net/download/dotnet-core/)
* [Node v12+](https://nodejs.org)
* [Yarn v1.19+](https://yarnpkg.com/)
### A Estrutura da Solução ### A Estrutura da Solução

2
docs/zh-Hans/Background-Jobs.md

@ -42,7 +42,7 @@ using Volo.Abp.Emailing;
namespace MyProject namespace MyProject
{ {
public class EmailSendingJob : BackgroundJob<EmailSendingArgs> public class EmailSendingJob : BackgroundJob<EmailSendingArgs>, ITransientDependency
{ {
private readonly IEmailSender _emailSender; private readonly IEmailSender _emailSender;

2
docs/zh-Hans/Best-Practices/Application-Services.md

@ -45,7 +45,7 @@ public class IssueLabelDto
##### 详细DTO ##### 详细DTO
**Do** 如果实体持有对其他聚合根的引用,那么应该为其定义**详细**DTO. **推荐** 如果实体持有对其他聚合根的引用,那么应该为其定义**详细**DTO.
* 直接包含实体中所有的 **原始属性**. * 直接包含实体中所有的 **原始属性**.
- 例外-1: 出于**安全**原因,可以**排除**某些属性(像 `User.Password`). - 例外-1: 出于**安全**原因,可以**排除**某些属性(像 `User.Password`).

2
docs/zh-Hans/Best-Practices/Entity-Framework-Core-Integration.md

@ -58,7 +58,7 @@ public static string Schema { get; set; } = AbpIdentityConsts.DefaultDbSchema;
### Model Mapping ### Model Mapping
- **Do** 重写 `DbContext` 的 `OnModelCreating` 方法显式 **配置所有实体**. 例如: - **推荐** 重写 `DbContext` 的 `OnModelCreating` 方法显式 **配置所有实体**. 例如:
````C# ````C#
protected override void OnModelCreating(ModelBuilder builder) protected override void OnModelCreating(ModelBuilder builder)

16
docs/zh-Hans/Best-Practices/Module-Architecture.md

@ -57,33 +57,33 @@
* **推荐** 将领域层划分为两个项目: * **推荐** 将领域层划分为两个项目:
* **Domain.Shared** 包(项目) 命名为*CompanyName.ModuleName.Domain.Shared*,包含常量,枚举和其他类型, 它不能包含实体,存储库,域服务或任何其他业务对象. 可以安全地与模块中的所有层使用. 此包也可以与第三方客户端使用. * **Domain.Shared** 包(项目) 命名为*CompanyName.ModuleName.Domain.Shared*,包含常量,枚举和其他类型, 它不能包含实体,存储库,域服务或任何其他业务对象. 可以安全地与模块中的所有层使用. 此包也可以与第三方客户端使用.
* **Domain** 包(项目) 命名为*CompanyName.ModuleName.Domain*, 包含实体, 仓储接口,领域服务接口及其实现和其他领域对象. * **Domain** 包(项目) 命名为*CompanyName.ModuleName.Domain*, 包含实体, 仓储接口,领域服务接口及其实现和其他领域对象.
* Domain package 依赖于 **Domain.Share** package. * Domain 包依赖于 **Domain.Shared** 包.
#### 应用服务层 #### 应用服务层
* **推荐** 将应用服务层划分为两个项目: * **推荐** 将应用服务层划分为两个项目:
* **Application.Contracts** 包(项目) 命名为*CompanyName.ModuleName.Application.Contracts,包含应用服务接口和相关的数据传输对象(DTO). * **Application.Contracts** 包(项目) 命名为*CompanyName.ModuleName.Application.Contracts,包含应用服务接口和相关的数据传输对象(DTO).
* Application contract package 依赖于 **Domain.Shared** package. * Application contract 包依赖于 **Domain.Shared** 包.
* **Application** 包(项目)命名为*CompanyName.ModuleName.Application*,包含应用服务实现. * **Application** 包(项目)命名为*CompanyName.ModuleName.Application*,包含应用服务实现.
* Application package 依赖于 **Domain** 和 **Application.Contracts** packages. * Application 包依赖于 **Domain** 包和 **Application.Contracts** 包.
#### 基础设施层 #### 基础设施层
* **推荐** 为每个orm/数据库集成创建一个独立的集成包, 比如Entity Framework Core 和 MongoDB. * **推荐** 为每个orm/数据库集成创建一个独立的集成包, 比如Entity Framework Core 和 MongoDB.
* **推荐** 例如, 创建一个抽象Entity Framework Core集成的*CompanyName.ModuleName.EntityFrameworkCore* package. ORM 集成 package 依赖于 **Domain** package. * **推荐** 例如, 创建一个抽象Entity Framework Core集成的*CompanyName.ModuleName.EntityFrameworkCore* 包. ORM 集成包依赖于 **Domain** 包.
* **不推荐** 依赖于orm/数据库集成包中的其他层. * **不推荐** 依赖于orm/数据库集成包中的其他层.
* **推荐** 为每个主要的库创建一个独立的集成包, 在不影响其他包的情况下可以被另一个库替换. * **推荐** 为每个主要的库创建一个独立的集成包, 在不影响其他包的情况下可以被另一个库替换.
#### HTTP 层 #### HTTP 层
* **推荐** 创建命名为*CompanyName.ModuleName.HttpApi*的**HTTP API**包, 为模块开发REST风格的HTTP API. * **推荐** 创建命名为*CompanyName.ModuleName.HttpApi*的**HTTP API**包, 为模块开发REST风格的HTTP API.
* HTTP API package 只依赖于 **Application.Contracts** package. 不要依赖 Application package. * HTTP API 包只依赖于 **Application.Contracts** 包. 不要依赖 Application 包.
* **推荐** 为每个应用服务创建一个Controller (通常通过实现其接口). 这些控制器使用应用服务接口来委托操作. 它根据需要配置路由, HTTP方法和其他与Web相关的东西. * **推荐** 为每个应用服务创建一个Controller (通常通过实现其接口). 这些控制器使用应用服务接口来委托操作. 它根据需要配置路由, HTTP方法和其他与Web相关的东西.
* **推荐** 创建一个为HTTP API包提供客户端服务的**HTTP API Client**包, 它的命名为*companyname.modulename.httpapi*. 这些客户端服务将应用服务接口实现远程端点的客户端. * **推荐** 创建一个为HTTP API包提供客户端服务的**HTTP API Client**包, 它的命名为*Companyname.ModuleName.HttpApi.Client*. 这些客户端服务将应用服务接口实现远程端点的客户端.
* HTTP API Client package 仅依赖于 **Application.Contracts** package. * HTTP API Client 包仅依赖于 **Application.Contracts** 包.
* **推荐** 使用ABP框架提供的动态代理HTTP C#客户端的功能. * **推荐** 使用ABP框架提供的动态代理HTTP C#客户端的功能.
#### Web 层 #### Web 层
* **推荐** 创建命名为*CompanyName.ModuleName.Web*的 **Web**包. 包含页面,视图,脚本,样式,图像和其他UI组件. * **推荐** 创建命名为*CompanyName.ModuleName.Web*的 **Web**包. 包含页面,视图,脚本,样式,图像和其他UI组件.
* Web package 仅依赖于 **HttpApi** package. * Web 包仅依赖于 **HttpApi** 包.

6
docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md

@ -24,8 +24,10 @@ abp new Acme.BookStore
创建项目的要求: 创建项目的要求:
* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/) * [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/) * [.NET Core 3.0+](https://www.microsoft.com/net/download/dotnet-core/)
* [Node v12+](https://nodejs.org)
* [Yarn v1.19+](https://yarnpkg.com/)
### 解决方案结构 ### 解决方案结构

6
docs/zh-Hans/Index.md

@ -6,12 +6,6 @@ ABP是一个**开源应用程序框架**,专注于基于ASP.NET Core的Web应用
浏览左侧导航菜单以深入了解文档. 浏览左侧导航菜单以深入了解文档.
## 项目状态
ABP是开源[ASP.NET Boilerplate](https://aspnetboilerplate.com/)框架的**下一代框架**, 它目前处于早期预览阶段,尚未准备好在生产中使用. 文档仍在进行中,远未完成.
对于短期和生产级应用程序, 建议使用[ASP.NET Boilerplate](https://aspnetboilerplate.com/)框架,该框架具有丰富的功能集,成熟,积极维护和最新.
## 入门 ## 入门
使用ABP开发新项目的最简单方法是使用启动模板: 使用ABP开发新项目的最简单方法是使用启动模板:

4
docs/zh-Hans/Multi-Tenancy.md

@ -312,10 +312,10 @@ Volo.Abp.AspNetCore.MultiTenancy 添加了下面这些租户解析器,从当前W
http://nginx.org/en/docs/http/ngx_http_core_module.html#ignore_invalid_headers http://nginx.org/en/docs/http/ngx_http_core_module.html#ignore_invalid_headers
http://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers http://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers
可以使用AspNetCoreMultiTenancyOptions修改默认的参数名"__tenant".例如: 可以使用AbpAspNetCoreMultiTenancyOptions修改默认的参数名"__tenant".例如:
````C# ````C#
services.Configure<AspNetCoreMultiTenancyOptions>(options => services.Configure<AbpAspNetCoreMultiTenancyOptions>(options =>
{ {
options.TenantKey = "MyTenantKey"; options.TenantKey = "MyTenantKey";
}); });

16
framework/Volo.Abp.sln

@ -250,7 +250,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MailKit.Tests", "t
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.ObjectMapping.Tests", "test\Volo.Abp.ObjectMapping.Tests\Volo.Abp.ObjectMapping.Tests.csproj", "{667F5544-C1EB-447C-96FD-9B757F04DE2B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.ObjectMapping.Tests", "test\Volo.Abp.ObjectMapping.Tests\Volo.Abp.ObjectMapping.Tests.csproj", "{667F5544-C1EB-447C-96FD-9B757F04DE2B}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Ddd.Application.Contracts", "src\Volo.Abp.Ddd.Application.Contracts\Volo.Abp.Ddd.Application.Contracts.csproj", "{73559227-EBF0-475F-835B-1FF0CD9132AA}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Ddd.Application.Contracts", "src\Volo.Abp.Ddd.Application.Contracts\Volo.Abp.Ddd.Application.Contracts.csproj", "{73559227-EBF0-475F-835B-1FF0CD9132AA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Minify", "src\Volo.Abp.Minify\Volo.Abp.Minify.csproj", "{928DC30D-C078-4BB4-A9F8-FE7252C67DC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Minify.Tests", "test\Volo.Abp.Minify.Tests\Volo.Abp.Minify.Tests.csproj", "{E69182B3-350A-43F5-A935-5EBBEBECEF97}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -750,6 +754,14 @@ Global
{73559227-EBF0-475F-835B-1FF0CD9132AA}.Debug|Any CPU.Build.0 = Debug|Any CPU {73559227-EBF0-475F-835B-1FF0CD9132AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73559227-EBF0-475F-835B-1FF0CD9132AA}.Release|Any CPU.ActiveCfg = Release|Any CPU {73559227-EBF0-475F-835B-1FF0CD9132AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73559227-EBF0-475F-835B-1FF0CD9132AA}.Release|Any CPU.Build.0 = Release|Any CPU {73559227-EBF0-475F-835B-1FF0CD9132AA}.Release|Any CPU.Build.0 = Release|Any CPU
{928DC30D-C078-4BB4-A9F8-FE7252C67DC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{928DC30D-C078-4BB4-A9F8-FE7252C67DC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{928DC30D-C078-4BB4-A9F8-FE7252C67DC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{928DC30D-C078-4BB4-A9F8-FE7252C67DC6}.Release|Any CPU.Build.0 = Release|Any CPU
{E69182B3-350A-43F5-A935-5EBBEBECEF97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E69182B3-350A-43F5-A935-5EBBEBECEF97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E69182B3-350A-43F5-A935-5EBBEBECEF97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E69182B3-350A-43F5-A935-5EBBEBECEF97}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -878,6 +890,8 @@ Global
{70DD6E17-B98B-4B00-8F38-C489E291BB53} = {447C8A77-E5F0-4538-8687-7383196D04EA} {70DD6E17-B98B-4B00-8F38-C489E291BB53} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{667F5544-C1EB-447C-96FD-9B757F04DE2B} = {447C8A77-E5F0-4538-8687-7383196D04EA} {667F5544-C1EB-447C-96FD-9B757F04DE2B} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{73559227-EBF0-475F-835B-1FF0CD9132AA} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {73559227-EBF0-475F-835B-1FF0CD9132AA} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{928DC30D-C078-4BB4-A9F8-FE7252C67DC6} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{E69182B3-350A-43F5-A935-5EBBEBECEF97} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

1
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj

@ -13,6 +13,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" /> <ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" />
<ProjectReference Include="..\Volo.Abp.Minify\Volo.Abp.Minify.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/AbpAspNetCoreMvcUiBundlingModule.cs

@ -1,9 +1,10 @@
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.Minify;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
{ {
[DependsOn(typeof(AbpAspNetCoreMvcUiBootstrapModule))] [DependsOn(typeof(AbpAspNetCoreMvcUiBootstrapModule), typeof(AbpMinifyModule))]
public class AbpAspNetCoreMvcUiBundlingModule : AbpModule public class AbpAspNetCoreMvcUiBundlingModule : AbpModule
{ {

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundlerBase.cs

@ -3,9 +3,9 @@ using System.Text;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.AspNetCore.Mvc.UI.Minification;
using Volo.Abp.AspNetCore.VirtualFileSystem; using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Minify;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
{ {

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Scripts/ScriptBundler.cs

@ -1,6 +1,6 @@
using System; using System;
using Volo.Abp.AspNetCore.Mvc.UI.Minification.Scripts;
using Volo.Abp.AspNetCore.VirtualFileSystem; using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.Minify.Scripts;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.Scripts namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.Scripts
{ {

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Styles/StyleBundler.cs

@ -1,8 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Volo.Abp.AspNetCore.Mvc.UI.Minification.Styles;
using Volo.Abp.AspNetCore.VirtualFileSystem; using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.Minify.Styles;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.Styles namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.Styles
{ {

28
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/LanguageSwitch/Default.cshtml

@ -1,14 +1,18 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.Toolbar.LanguageSwitch @using System.Linq
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.Toolbar.LanguageSwitch
@model LanguageSwitchViewComponentModel @model LanguageSwitchViewComponentModel
<div class="dropdown"> @if (Model.OtherLanguages.Any())
<a class="nav-link dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> {
@Model.CurrentLanguage.DisplayName <div class="dropdown">
</a> <a class="nav-link dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@Model.CurrentLanguage.DisplayName
</a>
<div class="dropdown-menu dropdown-menu-right border-0 shadow-sm" aria-labelledby="dropdownMenuLink"> <div class="dropdown-menu dropdown-menu-right border-0 shadow-sm" aria-labelledby="dropdownMenuLink">
@foreach (var language in Model.OtherLanguages) @foreach (var language in Model.OtherLanguages)
{ {
<a class="dropdown-item" href="/Abp/Languages/Switch?culture=@(language.CultureName)&uiCulture=@(language.UiCultureName)&returnUrl=@Context.Request.Path">@language.DisplayName</a> <a class="dropdown-item" href="/Abp/Languages/Switch?culture=@(language.CultureName)&uiCulture=@(language.UiCultureName)&returnUrl=@Context.Request.Path">@language.DisplayName</a>
} }
</div> </div>
</div> </div>
}

9
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/UserMenu/Default.cshtml

@ -9,7 +9,14 @@
@model ApplicationMenu @model ApplicationMenu
<div class="dropdown"> <div class="dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <a class="nav-link dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@CurrentUser.UserName @if (CurrentUser.TenantId != null)
{
<small><i>@CurrentTenant.Name</i>\</small>@CurrentUser.UserName
}
else
{
@CurrentUser.UserName
}
</a> </a>
@if (Model.Items.Any()) @if (Model.Items.Any())

14
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml

@ -53,11 +53,14 @@
<div class="@containerClass"> <div class="@containerClass">
<abp-row> <abp-row>
<abp-column size-md="_5" class="mx-auto"> <abp-column size-md="_5" class="mx-auto">
@if (MultiTenancyOptions.Value.IsEnabled &&
(TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true))
{
<div class="card shadow-sm rounded mb-3"> <div class="card shadow-sm rounded mb-3">
<div class="card-body px-5"> <div class="card-body px-5">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<span style="font-size: .8em;" class="text-uppercase text-muted">@MultiTenancyStringLocalizer["Tenant"]</span><br /> <span style="font-size: .8em;" class="text-uppercase text-muted">@MultiTenancyStringLocalizer["Tenant"]</span><br/>
<h6 class="m-0 d-inline-block"> <h6 class="m-0 d-inline-block">
@if (CurrentTenant.Id == null) @if (CurrentTenant.Id == null)
{ {
@ -72,15 +75,12 @@
</h6> </h6>
</div> </div>
<div class="col-auto"> <div class="col-auto">
@if (MultiTenancyOptions.Value.IsEnabled && <a id="AbpTenantSwitchLink" href="javascript:;" class="btn btn-sm mt-3 btn-outline-primary">@MultiTenancyStringLocalizer["Switch"]</a>
(TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true))
{
<a id="AbpTenantSwitchLink" href="javascript:;" class="btn btn-sm mt-3 btn-outline-primary">@MultiTenancyStringLocalizer["Switch"]</a>
}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
}
@(await Component.InvokeAsync<PageAlertsViewComponent>()) @(await Component.InvokeAsync<PageAlertsViewComponent>())
@RenderBody() @RenderBody()
</abp-column> </abp-column>

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml

@ -57,7 +57,9 @@
<div class="@containerClass"> <div class="@containerClass">
@(await Component.InvokeAsync<PageAlertsViewComponent>()) @(await Component.InvokeAsync<PageAlertsViewComponent>())
<div id="AbpContentToolbar"> <div id="AbpContentToolbar">
@RenderSection("content_toolbar", false) <div class="text-right mb-2">
@RenderSection("content_toolbar", false)
</div>
</div> </div>
@RenderBody() @RenderBody()
</div> </div>

3
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs

@ -4,6 +4,7 @@ using Volo.Abp.AspNetCore.Mvc.Auditing;
using Volo.Abp.AspNetCore.Mvc.Conventions; using Volo.Abp.AspNetCore.Mvc.Conventions;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling; using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.Mvc.Features; using Volo.Abp.AspNetCore.Mvc.Features;
using Volo.Abp.AspNetCore.Mvc.ModelBinding;
using Volo.Abp.AspNetCore.Mvc.Uow; using Volo.Abp.AspNetCore.Mvc.Uow;
using Volo.Abp.AspNetCore.Mvc.Validation; using Volo.Abp.AspNetCore.Mvc.Validation;
@ -35,7 +36,7 @@ namespace Volo.Abp.AspNetCore.Mvc
private static void AddModelBinders(MvcOptions options) private static void AddModelBinders(MvcOptions options)
{ {
//options.ModelBinderProviders.Add(new AbpDateTimeModelBinderProvider()); options.ModelBinderProviders.Insert(0, new AbpDateTimeModelBinderProvider());
} }
private static void AddMetadataProviders(MvcOptions options, IServiceCollection services) private static void AddMetadataProviders(MvcOptions options, IServiceCollection services)

12
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationScriptController.cs

@ -3,6 +3,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.Http;
using Volo.Abp.Json; using Volo.Abp.Json;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
@ -24,11 +25,14 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
} }
[HttpGet] [HttpGet]
[Produces("text/javascript", "text/plain")] [Produces(MimeTypes.Application.Javascript, MimeTypes.Text.Plain)]
public async Task<string> Get() public async Task<ActionResult> Get()
{ {
return CreateAbpExtendScript( return Content(
await _configurationAppService.GetAsync() CreateAbpExtendScript(
await _configurationAppService.GetAsync()
),
MimeTypes.Application.Javascript
); );
} }

49
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinder.cs

@ -0,0 +1,49 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.Timing;
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding
{
public class AbpDateTimeModelBinder : IModelBinder
{
private readonly Type _type;
private readonly SimpleTypeModelBinder _simpleTypeModelBinder;
private readonly IClock _clock;
public AbpDateTimeModelBinder(ModelBinderProviderContext context)
{
_type = context.Metadata.ModelType;
_clock = context.Services.GetRequiredService<IClock>();
_simpleTypeModelBinder = new SimpleTypeModelBinder(context.Metadata.ModelType,
context.Services.GetRequiredService<ILoggerFactory>());
}
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
await _simpleTypeModelBinder.BindModelAsync(bindingContext);
if (!bindingContext.Result.IsModelSet)
{
return;
}
if (_type == typeof(DateTime))
{
var dateTime = (DateTime) bindingContext.Result.Model;
bindingContext.Result = ModelBindingResult.Success(_clock.Normalize(dateTime));
}
else
{
var dateTime = (DateTime?) bindingContext.Result.Model;
if (dateTime != null)
{
bindingContext.Result = ModelBindingResult.Success(_clock.Normalize(dateTime.Value));
}
}
}
}
}

47
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinderProvider.cs

@ -0,0 +1,47 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Volo.Abp.Timing;
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding
{
public class AbpDateTimeModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.Metadata.ModelType != typeof(DateTime) &&
context.Metadata.ModelType != typeof(DateTime?))
{
return null;
}
if (context.Metadata.ContainerType == null)
{
if (context.Metadata is DefaultModelMetadata defaultModelMetadata &&
defaultModelMetadata.Attributes.Attributes.All(x => x.GetType() != typeof(DisableDateTimeNormalizationAttribute)))
{
return new AbpDateTimeModelBinder(context);
}
}
else
{
var dateNormalizationDisabledForClass =
context.Metadata.ContainerType.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true);
var dateNormalizationDisabledForProperty = context.Metadata.ContainerType
.GetProperty(context.Metadata.PropertyName)
?.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true);
if (!dateNormalizationDisabledForClass &&
dateNormalizationDisabledForProperty != null &&
!dateNormalizationDisabledForProperty.Value)
{
return new AbpDateTimeModelBinder(context);
}
}
return null;
}
}
}

7
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ProxyScripting/AbpServiceProxyScriptController.cs

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.Http;
using Volo.Abp.Http.ProxyScripting; using Volo.Abp.Http.ProxyScripting;
namespace Volo.Abp.AspNetCore.Mvc.ProxyScripting namespace Volo.Abp.AspNetCore.Mvc.ProxyScripting
@ -17,11 +18,11 @@ namespace Volo.Abp.AspNetCore.Mvc.ProxyScripting
} }
[HttpGet] [HttpGet]
[Produces("text/javascript", "text/plain")] [Produces(MimeTypes.Application.Javascript, MimeTypes.Text.Plain)]
public string GetAll(ServiceProxyGenerationModel model) public ActionResult GetAll(ServiceProxyGenerationModel model)
{ {
model.Normalize(); model.Normalize();
return _proxyScriptManager.GetScript(model.CreateOptions()); return Content(_proxyScriptManager.GetScript(model.CreateOptions()), MimeTypes.Application.Javascript);
} }
} }
} }

4
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ProxyScripting/ServiceProxyGenerationModel.cs

@ -11,6 +11,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ProxyScripting
public bool UseCache { get; set; } public bool UseCache { get; set; }
public bool Minify { get; set; }
public string Modules { get; set; } public string Modules { get; set; }
public string Controllers { get; set; } public string Controllers { get; set; }
@ -32,7 +34,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ProxyScripting
public ProxyScriptingModel CreateOptions() public ProxyScriptingModel CreateOptions()
{ {
var options = new ProxyScriptingModel(Type, UseCache); var options = new ProxyScriptingModel(Type, UseCache, Minify);
if (!Modules.IsNullOrEmpty()) if (!Modules.IsNullOrEmpty())
{ {

24
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs

@ -44,31 +44,37 @@ namespace Volo.Abp.Cli.Commands
var updateNpm = commandLineArgs.Options.ContainsKey(Options.Packages.Npm); var updateNpm = commandLineArgs.Options.ContainsKey(Options.Packages.Npm);
var updateNuget = commandLineArgs.Options.ContainsKey(Options.Packages.NuGet); var updateNuget = commandLineArgs.Options.ContainsKey(Options.Packages.NuGet);
var directory = commandLineArgs.Options.GetOrNull(Options.SolutionPath.Short, Options.SolutionPath.Long);
if (directory == null)
{
directory = Directory.GetCurrentDirectory();
}
var both = (updateNuget && updateNpm) || (!updateNuget && !updateNpm); var both = (updateNuget && updateNpm) || (!updateNuget && !updateNpm);
if (updateNuget || both) if (updateNuget || both)
{ {
await UpdateNugetPackages(commandLineArgs); await UpdateNugetPackages(commandLineArgs, directory);
} }
if (updateNpm || both) if (updateNpm || both)
{ {
UpdateNpmPackages(); UpdateNpmPackages(directory);
} }
} }
private void UpdateNpmPackages() private void UpdateNpmPackages(string directory)
{ {
_npmPackagesUpdater.Update(Directory.GetCurrentDirectory()); _npmPackagesUpdater.Update(directory);
} }
private async Task UpdateNugetPackages(CommandLineArgs commandLineArgs) private async Task UpdateNugetPackages(CommandLineArgs commandLineArgs, string directory)
{ {
var includePreviews = var includePreviews =
commandLineArgs.Options.GetOrNull(Options.IncludePreviews.Short, Options.IncludePreviews.Long) != null; commandLineArgs.Options.GetOrNull(Options.IncludePreviews.Short, Options.IncludePreviews.Long) != null;
var solution = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln").FirstOrDefault(); var solution = Directory.GetFiles(directory, "*.sln").FirstOrDefault();
if (solution != null) if (solution != null)
{ {
@ -131,6 +137,12 @@ namespace Volo.Abp.Cli.Commands
public static class Options public static class Options
{ {
public static class SolutionPath
{
public const string Short = "sp";
public const string Long = "solution-path";
}
public static class IncludePreviews public static class IncludePreviews
{ {
public const string Short = "p"; public const string Short = "p";

10
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposeServicesAttribute.cs

@ -9,9 +9,9 @@ namespace Volo.Abp.DependencyInjection
{ {
public Type[] ServiceTypes { get; } public Type[] ServiceTypes { get; }
public bool? IncludeDefaults { get; set; } public bool IncludeDefaults { get; set; }
public bool? IncludeSelf { get; set; } public bool IncludeSelf { get; set; }
public ExposeServicesAttribute(params Type[] serviceTypes) public ExposeServicesAttribute(params Type[] serviceTypes)
{ {
@ -22,19 +22,19 @@ namespace Volo.Abp.DependencyInjection
{ {
var serviceList = ServiceTypes.ToList(); var serviceList = ServiceTypes.ToList();
if (IncludeDefaults == true) if (IncludeDefaults)
{ {
foreach (var type in GetDefaultServices(targetType)) foreach (var type in GetDefaultServices(targetType))
{ {
serviceList.AddIfNotContains(type); serviceList.AddIfNotContains(type);
} }
if (IncludeSelf != false) if (IncludeSelf)
{ {
serviceList.AddIfNotContains(targetType); serviceList.AddIfNotContains(targetType);
} }
} }
else if (IncludeSelf == true) else if (IncludeSelf)
{ {
serviceList.AddIfNotContains(targetType); serviceList.AddIfNotContains(targetType);
} }

3
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ExposedServiceExplorer.cs

@ -10,7 +10,8 @@ namespace Volo.Abp.DependencyInjection
private static readonly ExposeServicesAttribute DefaultExposeServicesAttribute = private static readonly ExposeServicesAttribute DefaultExposeServicesAttribute =
new ExposeServicesAttribute new ExposeServicesAttribute
{ {
IncludeDefaults = true IncludeDefaults = true,
IncludeSelf = true
}; };
public static List<Type> GetExposedServices(Type type) public static List<Type> GetExposedServices(Type type)

55
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Linq; using System.Linq;
@ -18,10 +18,12 @@ using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Events; using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EntityFrameworkCore.EntityHistory; using Volo.Abp.EntityFrameworkCore.EntityHistory;
using Volo.Abp.EntityFrameworkCore.ValueConverters;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Reflection; using Volo.Abp.Reflection;
using Volo.Abp.Threading; using Volo.Abp.Threading;
using Volo.Abp.Timing;
namespace Volo.Abp.EntityFrameworkCore namespace Volo.Abp.EntityFrameworkCore
{ {
@ -48,6 +50,8 @@ namespace Volo.Abp.EntityFrameworkCore
public IAuditingManager AuditingManager { get; set; } public IAuditingManager AuditingManager { get; set; }
public IClock Clock { get; set; }
public ILogger<AbpDbContext<TDbContext>> Logger { get; set; } public ILogger<AbpDbContext<TDbContext>> Logger { get; set; }
private static readonly MethodInfo ConfigureBasePropertiesMethodInfo private static readonly MethodInfo ConfigureBasePropertiesMethodInfo
@ -57,6 +61,13 @@ namespace Volo.Abp.EntityFrameworkCore
BindingFlags.Instance | BindingFlags.NonPublic BindingFlags.Instance | BindingFlags.NonPublic
); );
private static readonly MethodInfo ConfigureValueConverterMethodInfo
= typeof(AbpDbContext<TDbContext>)
.GetMethod(
nameof(ConfigureValueConverter),
BindingFlags.Instance | BindingFlags.NonPublic
);
protected AbpDbContext(DbContextOptions<TDbContext> options) protected AbpDbContext(DbContextOptions<TDbContext> options)
: base(options) : base(options)
{ {
@ -75,6 +86,10 @@ namespace Volo.Abp.EntityFrameworkCore
ConfigureBasePropertiesMethodInfo ConfigureBasePropertiesMethodInfo
.MakeGenericMethod(entityType.ClrType) .MakeGenericMethod(entityType.ClrType)
.Invoke(this, new object[] { modelBuilder, entityType }); .Invoke(this, new object[] { modelBuilder, entityType });
ConfigureValueConverterMethodInfo
.MakeGenericMethod(entityType.ClrType)
.Invoke(this, new object[] { modelBuilder, entityType });
} }
} }
@ -332,6 +347,11 @@ namespace Volo.Abp.EntityFrameworkCore
protected virtual void ConfigureBaseProperties<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) protected virtual void ConfigureBaseProperties<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)
where TEntity : class where TEntity : class
{ {
if (mutableEntityType.IsOwned())
{
return;
}
ConfigureConcurrencyStampProperty<TEntity>(modelBuilder, mutableEntityType); ConfigureConcurrencyStampProperty<TEntity>(modelBuilder, mutableEntityType);
ConfigureExtraProperties<TEntity>(modelBuilder, mutableEntityType); ConfigureExtraProperties<TEntity>(modelBuilder, mutableEntityType);
ConfigureAuditProperties<TEntity>(modelBuilder, mutableEntityType); ConfigureAuditProperties<TEntity>(modelBuilder, mutableEntityType);
@ -488,6 +508,39 @@ namespace Volo.Abp.EntityFrameworkCore
} }
} }
protected virtual void ConfigureValueConverter<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)
where TEntity : class
{
if (mutableEntityType.BaseType == null &&
!typeof(TEntity).IsDefined(typeof(DisableDateTimeNormalizationAttribute), true) &&
!typeof(TEntity).IsDefined(typeof(OwnedAttribute), true) &&
!mutableEntityType.IsOwned())
{
if (Clock == null || !Clock.SupportsMultipleTimezone)
{
return;
}
var dateTimeValueConverter = new AbpDateTimeValueConverter(Clock);
var dateTimePropertyInfos = typeof(TEntity).GetProperties()
.Where(property =>
(property.PropertyType == typeof(DateTime) ||
property.PropertyType == typeof(DateTime?)) &&
property.CanWrite &&
!property.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true)
).ToList();
dateTimePropertyInfos.ForEach(property =>
{
modelBuilder
.Entity<TEntity>()
.Property(property.Name)
.HasConversion(dateTimeValueConverter);
});
}
}
protected virtual bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType) where TEntity : class protected virtual bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType) where TEntity : class
{ {
if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity))) if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity)))

17
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter.cs

@ -0,0 +1,17 @@
using System;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.Abp.Timing;
namespace Volo.Abp.EntityFrameworkCore.ValueConverters
{
public class AbpDateTimeValueConverter : ValueConverter<DateTime?, DateTime?>
{
public AbpDateTimeValueConverter(IClock clock, [CanBeNull] ConverterMappingHints mappingHints = null)
: base(
x => x.HasValue ? clock.Normalize(x.Value) : x,
x => x.HasValue ? clock.Normalize(x.Value) : x, mappingHints)
{
}
}
}

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

@ -41,6 +41,8 @@ namespace Microsoft.Extensions.DependencyInjection
{ {
Check.NotNull(services, nameof(assembly)); Check.NotNull(services, nameof(assembly));
AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName, configureHttpClientBuilder);
//TODO: Make a configuration option and add remoteServiceName inside it! //TODO: Make a configuration option and add remoteServiceName inside it!
//TODO: Add option to change type filter //TODO: Add option to change type filter
@ -53,9 +55,8 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddHttpClientProxy( services.AddHttpClientProxy(
serviceType, serviceType,
remoteServiceConfigurationName, remoteServiceConfigurationName,
asDefaultServices, asDefaultServices
configureHttpClientBuilder );
);
} }
return services; return services;
@ -82,14 +83,46 @@ namespace Microsoft.Extensions.DependencyInjection
bool asDefaultService = true, bool asDefaultService = true,
Action<IHttpClientBuilder> configureHttpClientBuilder = null) Action<IHttpClientBuilder> configureHttpClientBuilder = null)
{ {
AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName, configureHttpClientBuilder);
return services.AddHttpClientProxy( return services.AddHttpClientProxy(
typeof(T), typeof(T),
remoteServiceConfigurationName, remoteServiceConfigurationName,
asDefaultService, asDefaultService
configureHttpClientBuilder
); );
} }
/// <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> /// <summary>
/// Registers HTTP Client Proxy for given service <paramref name="type"/>. /// Registers HTTP Client Proxy for given service <paramref name="type"/>.
/// </summary> /// </summary>
@ -102,15 +135,11 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="asDefaultService"> /// <param name="asDefaultService">
/// True, to register the HTTP client proxy as the default implementation for the service <paramref name="type"/>. /// True, to register the HTTP client proxy as the default implementation for the service <paramref name="type"/>.
/// </param> /// </param>
/// <param name="configureHttpClientBuilder">
/// A delegate that is used to configure an <see cref="T:Microsoft.Extensions.DependencyInjection.IHttpClientBuilder" />.
/// </param>
public static IServiceCollection AddHttpClientProxy( public static IServiceCollection AddHttpClientProxy(
[NotNull] this IServiceCollection services, [NotNull] this IServiceCollection services,
[NotNull] Type type, [NotNull] Type type,
[NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName, [NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName,
bool asDefaultService = true, bool asDefaultService = true)
Action<IHttpClientBuilder> configureHttpClientBuilder = null)
{ {
Check.NotNull(services, nameof(services)); Check.NotNull(services, nameof(services));
Check.NotNull(type, nameof(type)); Check.NotNull(type, nameof(type));
@ -120,19 +149,6 @@ namespace Microsoft.Extensions.DependencyInjection
{ {
options.HttpClientProxies[type] = new DynamicHttpClientProxyConfig(type, remoteServiceConfigurationName); options.HttpClientProxies[type] = new DynamicHttpClientProxyConfig(type, remoteServiceConfigurationName);
}); });
//use IHttpClientFactory and polly
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);
}
var interceptorType = typeof(DynamicHttpProxyInterceptor<>).MakeGenericType(type); var interceptorType = typeof(DynamicHttpProxyInterceptor<>).MakeGenericType(type);
services.AddTransient(interceptorType); services.AddTransient(interceptorType);

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

@ -16,6 +16,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.Http.Abstractions\Volo.Abp.Http.Abstractions.csproj" /> <ProjectReference Include="..\Volo.Abp.Http.Abstractions\Volo.Abp.Http.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" /> <ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
<ProjectReference Include="..\Volo.Abp.Minify\Volo.Abp.Minify.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

2
framework/src/Volo.Abp.Http/Volo/Abp/Http/AbpHttpModule.cs

@ -1,12 +1,14 @@
using Volo.Abp.Http.ProxyScripting.Configuration; using Volo.Abp.Http.ProxyScripting.Configuration;
using Volo.Abp.Http.ProxyScripting.Generators.JQuery; using Volo.Abp.Http.ProxyScripting.Generators.JQuery;
using Volo.Abp.Json; using Volo.Abp.Json;
using Volo.Abp.Minify;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.Abp.Http namespace Volo.Abp.Http
{ {
[DependsOn(typeof(AbpHttpAbstractionsModule))] [DependsOn(typeof(AbpHttpAbstractionsModule))]
[DependsOn(typeof(AbpJsonModule))] [DependsOn(typeof(AbpJsonModule))]
[DependsOn(typeof(AbpMinifyModule))]
public class AbpHttpModule : AbpModule public class AbpHttpModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)

9
framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/ProxyScriptManager.cs

@ -7,6 +7,7 @@ using Volo.Abp.Http.Modeling;
using Volo.Abp.Http.ProxyScripting.Configuration; using Volo.Abp.Http.ProxyScripting.Configuration;
using Volo.Abp.Http.ProxyScripting.Generators; using Volo.Abp.Http.ProxyScripting.Generators;
using Volo.Abp.Json; using Volo.Abp.Json;
using Volo.Abp.Minify.Scripts;
namespace Volo.Abp.Http.ProxyScripting namespace Volo.Abp.Http.ProxyScripting
{ {
@ -17,18 +18,21 @@ namespace Volo.Abp.Http.ProxyScripting
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
private readonly IProxyScriptManagerCache _cache; private readonly IProxyScriptManagerCache _cache;
private readonly AbpApiProxyScriptingOptions _options; private readonly AbpApiProxyScriptingOptions _options;
private readonly IJavascriptMinifier _javascriptMinifier;
public ProxyScriptManager( public ProxyScriptManager(
IApiDescriptionModelProvider modelProvider, IApiDescriptionModelProvider modelProvider,
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IProxyScriptManagerCache cache, IProxyScriptManagerCache cache,
IOptions<AbpApiProxyScriptingOptions> options) IOptions<AbpApiProxyScriptingOptions> options,
IJavascriptMinifier javascriptMinifier)
{ {
_modelProvider = modelProvider; _modelProvider = modelProvider;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_jsonSerializer = jsonSerializer; _jsonSerializer = jsonSerializer;
_cache = cache; _cache = cache;
_javascriptMinifier = javascriptMinifier;
_options = options.Value; _options = options.Value;
} }
@ -63,7 +67,8 @@ namespace Volo.Abp.Http.ProxyScripting
using (var scope = _serviceProvider.CreateScope()) using (var scope = _serviceProvider.CreateScope())
{ {
return scope.ServiceProvider.GetRequiredService(generatorType).As<IProxyScriptGenerator>().CreateScript(apiModel); var script = scope.ServiceProvider.GetRequiredService(generatorType).As<IProxyScriptGenerator>().CreateScript(apiModel);
return scriptingModel.Minify ? _javascriptMinifier.Minify(script) : script;
} }
} }

5
framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/ProxyScriptingModel.cs

@ -8,6 +8,8 @@ namespace Volo.Abp.Http.ProxyScripting
public bool UseCache { get; set; } public bool UseCache { get; set; }
public bool Minify { get; set; }
public string[] Modules { get; set; } public string[] Modules { get; set; }
public string[] Controllers { get; set; } public string[] Controllers { get; set; }
@ -16,10 +18,11 @@ namespace Volo.Abp.Http.ProxyScripting
public IDictionary<string, string> Properties { get; set; } public IDictionary<string, string> Properties { get; set; }
public ProxyScriptingModel(string generatorType, bool useCache = true) public ProxyScriptingModel(string generatorType, bool useCache = true, bool minify = false)
{ {
GeneratorType = generatorType; GeneratorType = generatorType;
UseCache = useCache; UseCache = useCache;
Minify = minify;
Properties = new Dictionary<string, string>(); Properties = new Dictionary<string, string>();
} }

2
framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj

@ -14,7 +14,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MailKit" Version="2.3.2" /> <PackageReference Include="MailKit" Version="2.4.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

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

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Minify</AssemblyName>
<PackageId>Volo.Abp.Minify</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.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NUglify" Version="1.5.13" />
</ItemGroup>
</Project>

8
framework/src/Volo.Abp.Minify/Volo/Abp/Minify/AbpMinifyModule.cs

@ -0,0 +1,8 @@
using Volo.Abp.Modularity;
namespace Volo.Abp.Minify
{
public class AbpMinifyModule : AbpModule
{
}
}

7
framework/src/Volo.Abp.Minify/Volo/Abp/Minify/Html/IHtmlMinifier.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.Minify.Html
{
public interface IHtmlMinifier : IMinifier
{
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Minification/IMinifier.cs → framework/src/Volo.Abp.Minify/Volo/Abp/Minify/IMinifier.cs

@ -1,4 +1,4 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification namespace Volo.Abp.Minify
{ {
public interface IMinifier public interface IMinifier
{ {

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Minification/NUglify/NUglifyCssMinifier.cs → framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyCssMinifier.cs

@ -1,7 +1,7 @@
using NUglify; using NUglify;
using Volo.Abp.AspNetCore.Mvc.UI.Minification.Styles; using Volo.Abp.Minify.Styles;
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification.NUglify namespace Volo.Abp.Minify.NUglify
{ {
public class NUglifyCssMinifier : NUglifyMinifierBase, ICssMinifier public class NUglifyCssMinifier : NUglifyMinifierBase, ICssMinifier
{ {

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Minification/NUglify/NUglifyException.cs → framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyException.cs

@ -2,7 +2,7 @@ using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using NUglify; using NUglify;
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification.NUglify namespace Volo.Abp.Minify.NUglify
{ {
public class NUglifyException : AbpException public class NUglifyException : AbpException
{ {

13
framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyHtmlMinifier.cs

@ -0,0 +1,13 @@
using NUglify;
using Volo.Abp.Minify.Html;
namespace Volo.Abp.Minify.NUglify
{
public class NUglifyHtmlMinifier : NUglifyMinifierBase, IHtmlMinifier
{
protected override UglifyResult UglifySource(string source, string fileName)
{
return Uglify.Html(source, sourceFileName: fileName);
}
}
}

6
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Minification/NUglify/NUglifyJavascriptMinifier.cs → framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyJavascriptMinifier.cs

@ -1,9 +1,7 @@
using NUglify; using NUglify;
using NUglify.JavaScript; using Volo.Abp.Minify.Scripts;
using Volo.Abp.AspNetCore.Mvc.UI.Minification.Scripts;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification.NUglify namespace Volo.Abp.Minify.NUglify
{ {
public class NUglifyJavascriptMinifier : NUglifyMinifierBase, IJavascriptMinifier public class NUglifyJavascriptMinifier : NUglifyMinifierBase, IJavascriptMinifier
{ {

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Minification/NUglify/NUglifyMinifierBase.cs → framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyMinifierBase.cs

@ -4,7 +4,7 @@ using System.Linq;
using NUglify; using NUglify;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification.NUglify namespace Volo.Abp.Minify.NUglify
{ {
public abstract class NUglifyMinifierBase : IMinifier, ITransientDependency public abstract class NUglifyMinifierBase : IMinifier, ITransientDependency
{ {

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Minification/Scripts/IJavascriptMinifier.cs → framework/src/Volo.Abp.Minify/Volo/Abp/Minify/Scripts/IJavascriptMinifier.cs

@ -1,4 +1,4 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification.Scripts namespace Volo.Abp.Minify.Scripts
{ {
public interface IJavascriptMinifier : IMinifier public interface IJavascriptMinifier : IMinifier
{ {

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Minification/Styles/ICssMinifier.cs → framework/src/Volo.Abp.Minify/Volo/Abp/Minify/Styles/ICssMinifier.cs

@ -1,4 +1,4 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification.Styles namespace Volo.Abp.Minify.Styles
{ {
public interface ICssMinifier : IMinifier public interface ICssMinifier : IMinifier
{ {

61
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController.cs

@ -0,0 +1,61 @@
using System;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Timing;
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding
{
[Route("api/model-Binding-test")]
public class ModelBindingController : AbpController
{
[HttpGet("DateTimeKind")]
public string DateTimeKind(DateTime input)
{
return input.Kind.ToString().ToLower();
}
[HttpGet("NullableDateTimeKind")]
public string NullableDateTimeKind(DateTime? input)
{
return input.Value.Kind.ToString().ToLower();
}
[HttpGet("DisableDateTimeNormalizationDateTimeKind")]
public string DisableDateTimeNormalizationDateTimeKind([DisableDateTimeNormalization]DateTime input)
{
return input.Kind.ToString().ToLower();
}
[HttpGet("DisableDateTimeNormalizationNullableDateTimeKind")]
public string DisableDateTimeNormalizationNullableDateTimeKind([DisableDateTimeNormalization]DateTime? input)
{
return input.Value.Kind.ToString().ToLower();
}
[HttpGet("ComplexTypeDateTimeKind")]
public string ComplexTypeDateTimeKind(GetDateTimeKindModel input)
{
return input.Time1.Kind.ToString().ToLower() + "_" +
input.Time2.Kind.ToString().ToLower() + "_" +
input.Time3.Value.Kind.ToString().ToLower() + "_" +
input.InnerModel.Time4.Kind.ToString().ToLower();
}
}
public class GetDateTimeKindModel
{
[DisableDateTimeNormalization]
public DateTime Time1 { get; set; }
public DateTime Time2 { get; set; }
public DateTime? Time3 { get; set; }
public GetDateTimeKindInnerModel InnerModel { get; set; }
[DisableDateTimeNormalization]
public class GetDateTimeKindInnerModel
{
public DateTime Time4 { get; set; }
}
}
}

100
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ModelBinding/ModelBindingController_Tests.cs

@ -0,0 +1,100 @@
using System;
using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Shouldly;
using Volo.Abp.Timing;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding
{
public abstract class ModelBindingController_Tests : AspNetCoreMvcTestBase
{
protected DateTimeKind DateTimeKind { get; set; }
protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
services.Configure<AbpClockOptions>(x => x.Kind = DateTimeKind);
}
[Fact]
public async Task DateTimeKind_Test()
{
var response = await Client.GetAsync("/api/model-Binding-test/DateTimeKind?input=2010-01-01T00:00:00Z");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
resultAsString.ShouldBe(DateTimeKind.ToString().ToLower());
}
[Fact]
public async Task NullableDateTimeKind_Test()
{
var response =
await Client.GetAsync("/api/model-Binding-test/NullableDateTimeKind?input=2010-01-01T00:00:00Z");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
resultAsString.ShouldBe(DateTimeKind.ToString().ToLower());
}
[Fact]
public async Task DisableDateTimeNormalizationDateTimeKind_Test()
{
var response =
await Client.GetAsync(
"/api/model-Binding-test/DisableDateTimeNormalizationDateTimeKind?input=2010-01-01T00:00:00Z");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
//Time parameter(2010-01-01T00:00:00Z) with time zone information, so the default Kind is Local.
resultAsString.ShouldBe(DateTimeKind.Local.ToString().ToLower());
}
[Fact]
public async Task DisableDateTimeNormalizationNullableDateTimeKind_Test()
{
var response =
await Client.GetAsync(
"/api/model-Binding-test/DisableDateTimeNormalizationNullableDateTimeKind?input=2010-01-01T00:00:00Z");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
//Time parameter(2010-01-01T00:00:00Z) with time zone information, so the default Kind is Local.
resultAsString.ShouldBe(DateTimeKind.Local.ToString().ToLower());
}
[Fact]
public async Task ComplexTypeDateTimeKind_Test()
{
var response = await Client.GetAsync("/api/model-Binding-test/ComplexTypeDateTimeKind?" +
"Time1=2010-01-01T00:00:00Z&" +
"Time2=2010-01-01T00:00:00Z&" +
"Time3=2010-01-01T00:00:00Z&" +
"InnerModel.Time4=2010-01-01T00:00:00Z");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
var resultAsString = await response.Content.ReadAsStringAsync();
//Time parameter(2010-01-01T00:00:00Z) with time zone information, so the default Kind is Local.
resultAsString.ShouldBe(
$"local_{DateTimeKind.ToString().ToLower()}_{DateTimeKind.ToString().ToLower()}_local");
}
}
public class ModelBindingController_Utc_Tests : ModelBindingController_Tests
{
public ModelBindingController_Utc_Tests()
{
DateTimeKind = DateTimeKind.Utc;
}
}
public class ModelBindingController_Local_Tests : ModelBindingController_Tests
{
public ModelBindingController_Local_Tests()
{
DateTimeKind = DateTimeKind.Local;
}
}
}

13
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ProxyScripting/AbpServiceProxiesController_Tests.cs

@ -9,8 +9,19 @@ namespace Volo.Abp.AspNetCore.Mvc.ProxyScripting
[Fact] [Fact]
public async Task GetAll() public async Task GetAll()
{ {
var script = await GetResponseAsStringAsync("/Abp/ServiceProxyScript/"); var script = await GetResponseAsStringAsync("/Abp/ServiceProxyScript?minify=true");
script.Length.ShouldBeGreaterThan(0); script.Length.ShouldBeGreaterThan(0);
} }
[Fact]
public async Task GetAllWithMinify()
{
var script = await GetResponseAsStringAsync("/Abp/ServiceProxyScript");
var minifyScript = await GetResponseAsStringAsync("/Abp/ServiceProxyScript?minify=true");
script.Length.ShouldBeGreaterThan(0);
minifyScript.Length.ShouldBeGreaterThan(0);
minifyScript.Length.ShouldBeLessThan(script.Length);
}
} }
} }

26
framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo/Abp/AspNetCore/Mvc/UI/Minification/NUglify/JavascriptMinifier_Tests.cs

@ -1,26 +0,0 @@
using Shouldly;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification.NUglify
{
public class NUglifyJavascriptMinifier_Tests : AbpAspNetCoreMvcUiTestBase
{
private readonly NUglifyJavascriptMinifier _nUglifyJavascriptMinifier;
public NUglifyJavascriptMinifier_Tests()
{
_nUglifyJavascriptMinifier = GetRequiredService<NUglifyJavascriptMinifier>();
}
[Fact]
public void Should_Minify_Simple_Code()
{
const string source = "var x = 5; var y = 6;";
var minified = _nUglifyJavascriptMinifier.Minify(source);
minified.Length.ShouldBeGreaterThan(0);
minified.Length.ShouldBeLessThan(source.Length);
}
}
}

9
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs

@ -1,4 +1,5 @@
using Microsoft.Data.Sqlite; using System;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage;
@ -10,6 +11,7 @@ using Volo.Abp.Modularity;
using Volo.Abp.TestApp; using Volo.Abp.TestApp;
using Volo.Abp.TestApp.Domain; using Volo.Abp.TestApp.Domain;
using Volo.Abp.TestApp.EntityFrameworkCore; using Volo.Abp.TestApp.EntityFrameworkCore;
using Volo.Abp.Timing;
namespace Volo.Abp.EntityFrameworkCore namespace Volo.Abp.EntityFrameworkCore
{ {
@ -41,6 +43,8 @@ namespace Volo.Abp.EntityFrameworkCore
abpDbContextConfigurationContext.DbContextOptions.UseSqlite(sqliteConnection); abpDbContextConfigurationContext.DbContextOptions.UseSqlite(sqliteConnection);
}); });
}); });
Configure<AbpClockOptions>(options => options.Kind = DateTimeKind.Utc);
} }
public override void OnPreApplicationInitialization(ApplicationInitializationContext context) public override void OnPreApplicationInitialization(ApplicationInitializationContext context)
@ -56,6 +60,9 @@ namespace Volo.Abp.EntityFrameworkCore
using (var context = new TestMigrationsDbContext(new DbContextOptionsBuilder<TestMigrationsDbContext>().UseSqlite(connection).Options)) using (var context = new TestMigrationsDbContext(new DbContextOptionsBuilder<TestMigrationsDbContext>().UseSqlite(connection).Options))
{ {
context.GetService<IRelationalDatabaseCreator>().CreateTables(); context.GetService<IRelationalDatabaseCreator>().CreateTables();
context.Database.ExecuteSqlRaw(
@"CREATE VIEW View_PersonView AS
SELECT Name, CreationTime, Birthday, LastActive FROM People");
} }
return connection; return connection;

11
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs

@ -25,12 +25,23 @@ namespace Volo.Abp.EntityFrameworkCore
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
modelBuilder.Owned<District>();
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Phone>(b => modelBuilder.Entity<Phone>(b =>
{ {
b.HasKey(p => new { p.PersonId, p.Number }); b.HasKey(p => new { p.PersonId, p.Number });
}); });
modelBuilder.Entity<City>(b =>
{
b.OwnsMany(c => c.Districts, d =>
{
d.WithOwner().HasForeignKey(x => x.CityId);
d.HasKey(x => new { x.CityId, x.Name });
});
});
} }
} }
} }

9
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter_Tests.cs

@ -0,0 +1,9 @@
using Volo.Abp.TestApp.Testing;
namespace Volo.Abp.EntityFrameworkCore.ValueConverters
{
public class AbpDateTimeValueConverter_Tests : AbpDateTimeValueConverter_Tests<AbpEntityFrameworkCoreTestModule>
{
}
}

24
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/PersonRepository.cs

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.TestApp.Domain;
namespace Volo.Abp.TestApp.EntityFrameworkCore
{
public class PersonRepository : EfCoreRepository<TestAppDbContext, Person, Guid>, IPersonRepository
{
public PersonRepository(IDbContextProvider<TestAppDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task<PersonView> GetViewAsync(string name)
{
return await DbContext.PersonView.Where(x => x.Name == name).FirstOrDefaultAsync();
}
}
}

20
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs

@ -11,6 +11,8 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore
public DbSet<City> Cities { get; set; } public DbSet<City> Cities { get; set; }
public DbSet<PersonView> PersonView { get; set; }
public DbSet<ThirdDbContextDummyEntity> DummyEntities { get; set; } public DbSet<ThirdDbContextDummyEntity> DummyEntities { get; set; }
public DbSet<EntityWithIntPk> EntityWithIntPks { get; set; } public DbSet<EntityWithIntPk> EntityWithIntPks { get; set; }
@ -23,12 +25,30 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
modelBuilder.Owned<District>();
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Phone>(b => modelBuilder.Entity<Phone>(b =>
{ {
b.HasKey(p => new {p.PersonId, p.Number}); b.HasKey(p => new {p.PersonId, p.Number});
}); });
modelBuilder
.Entity<PersonView>(p =>
{
p.HasNoKey();
p.ToView("View_PersonView");
});
modelBuilder.Entity<City>(b =>
{
b.OwnsMany(c => c.Districts, d =>
{
d.WithOwner().HasForeignKey(x => x.CityId);
d.HasKey(x => new {x.CityId, x.Name});
});
});
} }
} }
} }

16
framework/test/Volo.Abp.Minify.Tests/Volo.Abp.Minify.Tests.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Minify\Volo.Abp.Minify.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
</ItemGroup>
</Project>

11
framework/test/Volo.Abp.Minify.Tests/Volo/Abp/Minify/AbpMinifyTestModule.cs

@ -0,0 +1,11 @@
using Volo.Abp.Modularity;
namespace Volo.Abp.Minify
{
[DependsOn(
typeof(AbpMinifyModule),
typeof(AbpTestBaseModule))]
public class AbpMinifyTestModule : AbpModule
{
}
}

28
framework/test/Volo.Abp.Minify.Tests/Volo/Abp/Minify/NUglify/CssMinifier_Tests.cs

@ -0,0 +1,28 @@
using Shouldly;
using Volo.Abp.Minify.Styles;
using Xunit;
namespace Volo.Abp.Minify.NUglify
{
public class CssMinifier_Tests : AbpIntegratedTest<AbpMinifyModule>
{
private readonly ICssMinifier _cssMinifier;
public CssMinifier_Tests()
{
_cssMinifier = GetRequiredService<ICssMinifier>();
}
[Fact]
public void Should_Minify_Simple_Code()
{
const string source = "div { color: #FFF; }";
var minified = _cssMinifier.Minify(source);
minified.Length.ShouldBeGreaterThan(0);
minified.Length.ShouldBeLessThan(source.Length);
}
}
}

27
framework/test/Volo.Abp.Minify.Tests/Volo/Abp/Minify/NUglify/HtmlMinifier_Tests.cs

@ -0,0 +1,27 @@
using Shouldly;
using Volo.Abp.Minify.Html;
using Xunit;
namespace Volo.Abp.Minify.NUglify
{
public class HtmlMinifier_Tests : AbpIntegratedTest<AbpMinifyModule>
{
private readonly IHtmlMinifier _htmlMinifier;
public HtmlMinifier_Tests()
{
_htmlMinifier = GetRequiredService<IHtmlMinifier>();
}
[Fact]
public void Should_Minify_Simple_Code()
{
const string source = "<div> <p>This is <em> a text </em></p> </div>";
var minified = _htmlMinifier.Minify(source);
minified.Length.ShouldBeGreaterThan(0);
minified.Length.ShouldBeLessThan(source.Length);
}
}
}

28
framework/test/Volo.Abp.Minify.Tests/Volo/Abp/Minify/NUglify/JavascriptMinifier_Tests.cs

@ -0,0 +1,28 @@
using Shouldly;
using Volo.Abp.Minify.Scripts;
using Xunit;
namespace Volo.Abp.Minify.NUglify
{
public class JavascriptMinifier_Tests : AbpIntegratedTest<AbpMinifyModule>
{
private readonly IJavascriptMinifier _javascriptMinifier;
public JavascriptMinifier_Tests()
{
_javascriptMinifier = GetRequiredService<IJavascriptMinifier>();
}
[Fact]
public void Should_Minify_Simple_Code()
{
const string source = "var x = 5; var y = 6;";
var minified = _javascriptMinifier.Minify(source);
minified.Length.ShouldBeGreaterThan(0);
minified.Length.ShouldBeLessThan(source.Length);
}
}
}

10
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/City.cs

@ -1,4 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
namespace Volo.Abp.TestApp.Domain namespace Volo.Abp.TestApp.Domain
@ -7,6 +9,8 @@ namespace Volo.Abp.TestApp.Domain
{ {
public string Name { get; set; } public string Name { get; set; }
public ICollection<District> Districts { get; set; }
private City() private City()
{ {
@ -16,6 +20,12 @@ namespace Volo.Abp.TestApp.Domain
: base(id) : base(id)
{ {
Name = name; Name = name;
Districts = new List<District>();
}
public int GetPopulation()
{
return Districts.Select(d => d.Population).Sum();
} }
} }
} }

30
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/District.cs

@ -0,0 +1,30 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
namespace Volo.Abp.TestApp.Domain
{
public class District : CreationAuditedEntity
{
public Guid CityId { get; private set; }
public string Name { get; private set; }
public int Population { get; set; }
private District()
{
}
public District(Guid cityId, string name, int population = 0)
{
CityId = cityId;
Name = name;
}
public override object[] GetKeys()
{
return new Object[] {CityId, Name};
}
}
}

13
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/IPersonRepository.cs

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.TestApp.Domain
{
public interface IPersonRepository : IBasicRepository<Person, Guid>
{
Task<PersonView> GetViewAsync(string name);
}
}

6
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs

@ -2,6 +2,7 @@ using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Timing;
namespace Volo.Abp.TestApp.Domain namespace Volo.Abp.TestApp.Domain
{ {
@ -15,6 +16,11 @@ namespace Volo.Abp.TestApp.Domain
public virtual int Age { get; set; } public virtual int Age { get; set; }
public virtual DateTime? Birthday { get; set; }
[DisableDateTimeNormalization]
public virtual DateTime? LastActive { get; set; }
public virtual Collection<Phone> Phones { get; set; } public virtual Collection<Phone> Phones { get; set; }
private Person() private Person()

17
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/PersonView.cs

@ -0,0 +1,17 @@
using System;
using Volo.Abp.Timing;
namespace Volo.Abp.TestApp.Domain
{
public class PersonView
{
public string Name { get; set; }
public DateTime CreationTime { get; set; }
public DateTime? Birthday { get; set; }
[DisableDateTimeNormalization]
public DateTime? LastActive { get; set; }
}
}

7
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestDataBuilder.cs

@ -38,10 +38,15 @@ namespace Volo.Abp.TestApp
private void AddCities() private void AddCities()
{ {
var istanbul = new City(IstanbulCityId, "Istanbul");
istanbul.Districts.Add(new District(istanbul.Id, "Bakirkoy", 1283999));
istanbul.Districts.Add(new District(istanbul.Id, "Mecidiyeköy", 2222321));
istanbul.Districts.Add(new District(istanbul.Id, "Uskudar", 726172));
_cityRepository.Insert(new City(Guid.NewGuid(), "Tokyo")); _cityRepository.Insert(new City(Guid.NewGuid(), "Tokyo"));
_cityRepository.Insert(new City(Guid.NewGuid(), "Madrid")); _cityRepository.Insert(new City(Guid.NewGuid(), "Madrid"));
_cityRepository.Insert(new City(LondonCityId, "London") {ExtraProperties = { { "Population", 10_470_000 } } }); _cityRepository.Insert(new City(LondonCityId, "London") {ExtraProperties = { { "Population", 10_470_000 } } });
_cityRepository.Insert(new City(IstanbulCityId, "Istanbul")); _cityRepository.Insert(istanbul);
_cityRepository.Insert(new City(Guid.NewGuid(), "Paris")); _cityRepository.Insert(new City(Guid.NewGuid(), "Paris"));
_cityRepository.Insert(new City(Guid.NewGuid(), "Washington")); _cityRepository.Insert(new City(Guid.NewGuid(), "Washington"));
_cityRepository.Insert(new City(Guid.NewGuid(), "Sao Paulo")); _cityRepository.Insert(new City(Guid.NewGuid(), "Sao Paulo"));

73
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/AbpDateTimeValueConverter_Tests.cs

@ -0,0 +1,73 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Modularity;
using Volo.Abp.TestApp.Domain;
using Volo.Abp.Timing;
using Xunit;
namespace Volo.Abp.TestApp.Testing
{
public abstract class AbpDateTimeValueConverter_Tests<TStartupModule> : TestAppTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
private readonly IPersonRepository _personRepository;
protected AbpDateTimeValueConverter_Tests()
{
_personRepository = GetRequiredService<IPersonRepository>();
}
[Fact]
public async Task DateTime_Kind_Should_Be_Normalized_To_UTC_Test()
{
var personId = Guid.Parse("4125582e-d100-4c27-aa84-e4de85830dca");
await _personRepository.InsertAsync(new Person(personId, "bob lee", 18)
{
Birthday = DateTime.Parse("2020-01-01 00:00:00"),
LastActive = DateTime.Parse("2020-01-01 00:00:00"),
}, true);
var person = await _personRepository.GetAsync(personId);
person.ShouldNotBeNull();
person.CreationTime.Kind.ShouldBe(DateTimeKind.Utc);
person.Birthday.ShouldNotBeNull();
person.Birthday.Value.Kind.ShouldBe(DateTimeKind.Utc);
person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00");
//LastActive DisableDateTimeNormalization
person.LastActive.ShouldNotBeNull();
person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified);
person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00");
}
[Fact]
public async Task DateTime_Kind_Should_Be_Normalized_To_UTC_View_Test()
{
var personName = "bob lee";
await _personRepository.InsertAsync(new Person(Guid.NewGuid(), personName, 18)
{
Birthday = DateTime.Parse("2020-01-01 00:00:00"),
LastActive = DateTime.Parse("2020-01-01 00:00:00"),
}, true);
var person = await _personRepository.GetViewAsync(personName);
person.ShouldNotBeNull();
person.CreationTime.Kind.ShouldBe(DateTimeKind.Utc);
person.Birthday.ShouldNotBeNull();
person.Birthday.Value.Kind.ShouldBe(DateTimeKind.Utc);
person.Birthday.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00");
//LastActive DisableDateTimeNormalization
person.LastActive.ShouldNotBeNull();
person.LastActive.Value.Kind.ShouldBe(DateTimeKind.Unspecified);
person.LastActive.Value.ToString("yyy-MM-dd HH:mm:ss").ShouldBe("2020-01-01 00:00:00");
}
}
}

17
modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs

@ -1,4 +1,4 @@
using IdentityModel; using IdentityModel;
using IdentityServer4.Events; using IdentityServer4.Events;
using IdentityServer4.Models; using IdentityServer4.Models;
using IdentityServer4.Services; using IdentityServer4.Services;
@ -12,8 +12,10 @@ using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Account.Web.Settings;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Settings;
using Volo.Abp.Uow; using Volo.Abp.Uow;
namespace Volo.Abp.Account.Web.Pages.Account namespace Volo.Abp.Account.Web.Pages.Account
@ -40,7 +42,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
IdentityServerEvents = identityServerEvents; IdentityServerEvents = identityServerEvents;
} }
public override async Task OnGetAsync() public override async Task<IActionResult> OnGetAsync()
{ {
LoginInput = new LoginInputModel(); LoginInput = new LoginInputModel();
@ -63,7 +65,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
{ {
LoginInput.UserNameOrEmailAddress = context.LoginHint; LoginInput.UserNameOrEmailAddress = context.LoginHint;
ExternalProviders = new[] { new ExternalProviderModel { AuthenticationScheme = context.IdP } }; ExternalProviders = new[] { new ExternalProviderModel { AuthenticationScheme = context.IdP } };
return; return Page();
} }
var schemes = await _schemeProvider.GetAllSchemesAsync(); var schemes = await _schemeProvider.GetAllSchemesAsync();
@ -77,7 +79,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
}) })
.ToList(); .ToList();
EnableLocalLogin = true; //TODO: We can get default from a setting? EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);
if (context?.ClientId != null) if (context?.ClientId != null)
{ {
var client = await ClientStore.FindEnabledClientByIdAsync(context.ClientId); var client = await ClientStore.FindEnabledClientByIdAsync(context.ClientId);
@ -96,15 +98,16 @@ namespace Volo.Abp.Account.Web.Pages.Account
if (IsExternalLoginOnly) if (IsExternalLoginOnly)
{ {
//return await ExternalLogin(vm.ExternalLoginScheme, returnUrl); return await base.OnPostExternalLogin(providers.First().AuthenticationScheme);
throw new NotImplementedException();
} }
return Page();
} }
[UnitOfWork] //TODO: Will be removed when we implement action filter [UnitOfWork] //TODO: Will be removed when we implement action filter
public override async Task<IActionResult> OnPostAsync(string action) public override async Task<IActionResult> OnPostAsync(string action)
{ {
EnableLocalLogin = true; //TODO: We can get default from a setting? EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);
if (action == "Cancel") if (action == "Cancel")
{ {

7
modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/LogoutController.cs

@ -17,10 +17,15 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
} }
//todo@alper: this method can be moved to AccountController like "account/logout" //todo@alper: this method can be moved to AccountController like "account/logout"
public async Task<IActionResult> Index() public async Task<IActionResult> Index(string returnUrl = null)
{ {
await _signInManager.SignOutAsync(); await _signInManager.SignOutAsync();
if (returnUrl != null)
{
return LocalRedirect(returnUrl);
}
return RedirectToPage("/Account/Login"); return RedirectToPage("/Account/Login");
} }
} }

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

@ -10,8 +10,10 @@ using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Account.Web.Settings;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.Security.Claims; using Volo.Abp.Security.Claims;
using Volo.Abp.Settings;
using Volo.Abp.Uow; using Volo.Abp.Uow;
using Volo.Abp.Validation; using Volo.Abp.Validation;
using IdentityUser = Volo.Abp.Identity.IdentityUser; using IdentityUser = Volo.Abp.Identity.IdentityUser;
@ -56,7 +58,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
_accountOptions = accountOptions.Value; _accountOptions = accountOptions.Value;
} }
public virtual async Task OnGetAsync() public virtual async Task<IActionResult> OnGetAsync()
{ {
LoginInput = new LoginInputModel(); LoginInput = new LoginInputModel();
@ -71,8 +73,8 @@ namespace Volo.Abp.Account.Web.Pages.Account
}) })
.ToList(); .ToList();
EnableLocalLogin = true; //TODO: We can get default from a setting? EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);
ExternalProviders = providers.ToArray(); ExternalProviders = providers.ToArray();
if (IsExternalLoginOnly) if (IsExternalLoginOnly)
@ -80,12 +82,14 @@ namespace Volo.Abp.Account.Web.Pages.Account
//return await ExternalLogin(vm.ExternalLoginScheme, returnUrl); //return await ExternalLogin(vm.ExternalLoginScheme, returnUrl);
throw new NotImplementedException(); throw new NotImplementedException();
} }
return Page();
} }
[UnitOfWork] //TODO: Will be removed when we implement action filter [UnitOfWork] //TODO: Will be removed when we implement action filter
public virtual async Task<IActionResult> OnPostAsync(string action) public virtual async Task<IActionResult> OnPostAsync(string action)
{ {
EnableLocalLogin = true; //TODO: We can get default from a setting? EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);
ValidateModel(); ValidateModel();

4
modules/account/src/Volo.Abp.Account.Web/Settings/AccountSettingDefinitionProvider.cs

@ -9,6 +9,10 @@ namespace Volo.Abp.Account.Web.Settings
context.Add( context.Add(
new SettingDefinition(AccountSettingNames.IsSelfRegistrationEnabled, "true") new SettingDefinition(AccountSettingNames.IsSelfRegistrationEnabled, "true")
); );
context.Add(
new SettingDefinition(AccountSettingNames.EnableLocalLogin, "true")
);
} }
} }
} }

2
modules/account/src/Volo.Abp.Account.Web/Settings/AccountSettingNames.cs

@ -3,5 +3,7 @@
public class AccountSettingNames public class AccountSettingNames
{ {
public const string IsSelfRegistrationEnabled = "Abp.Account.IsSelfRegistrationEnabled"; public const string IsSelfRegistrationEnabled = "Abp.Account.IsSelfRegistrationEnabled";
public const string EnableLocalLogin = "Abp.Account.EnableLocalLogin";
} }
} }

2
modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs

@ -37,7 +37,7 @@ namespace Volo.Docs.FileSystem.Documents
Format = project.Format, Format = project.Format,
LocalDirectory = localDirectory, LocalDirectory = localDirectory,
Title = documentName, Title = documentName,
RawRootUrl = $"/document-resources?projectId={project.Id.ToString()}&version={version}&name=", RawRootUrl = $"/document-resources?projectId={project.Id.ToString()}&version={version}&languageCode={languageCode}&name=",
RootUrl = "/" RootUrl = "/"
}; };
} }

2
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs

@ -34,7 +34,7 @@ namespace Volo.Abp.Identity
public virtual string Name { get; set; } public virtual string Name { get; set; }
/// <summary> /// <summary>
/// Gets or sets the Surame for the user. /// Gets or sets the Surname for the user.
/// </summary> /// </summary>
public virtual string Surname { get; set; } public virtual string Surname { get; set; }

9
modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/AbpIdentityHttpApiModule.cs

@ -3,12 +3,21 @@ using Volo.Abp.Identity.Localization;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Localization.Resources.AbpUi; using Localization.Resources.AbpUi;
using Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.Identity namespace Volo.Abp.Identity
{ {
[DependsOn(typeof(AbpIdentityApplicationContractsModule), typeof(AbpAspNetCoreMvcModule))] [DependsOn(typeof(AbpIdentityApplicationContractsModule), typeof(AbpAspNetCoreMvcModule))]
public class AbpIdentityHttpApiModule : AbpModule public class AbpIdentityHttpApiModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpIdentityHttpApiModule).Assembly);
});
}
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>

8
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json

@ -0,0 +1,8 @@
{
"culture": "tr",
"texts": {
"Volo.IdentityServer:DuplicateIdentityResourceName": "Identity Resource adı zaten mevcut: {Name}",
"Volo.IdentityServer:DuplicateApiResourceName": "Api Resource adı zaten mevcut: {Name}",
"Volo.IdentityServer:DuplicateClientId": "ClientId already zaten mevcut: {ClientId}"
}
}

3
modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.js

@ -17,6 +17,9 @@
var _dataTable = _$wrapper.find('table').DataTable(abp.libs.datatables.normalizeConfiguration({ var _dataTable = _$wrapper.find('table').DataTable(abp.libs.datatables.normalizeConfiguration({
order: [[1, "asc"]], order: [[1, "asc"]],
processing: true,
paging: true,
serverSide: true,
ajax: abp.libs.datatables.createAjax(_tenantAppService.getList), ajax: abp.libs.datatables.createAjax(_tenantAppService.getList),
columnDefs: [ columnDefs: [
{ {

3
npm/ng-packs/.prettierrc

@ -1,6 +1,5 @@
{ {
"printWidth": 120, "printWidth": 100,
"singleQuote": true, "singleQuote": true,
"trailingComma": "all" "trailingComma": "all"
} }

1
npm/ng-packs/.vscode/settings.json

@ -6,6 +6,7 @@
"typescript.tsdk": "../node_modules/typescript/lib", "typescript.tsdk": "../node_modules/typescript/lib",
"workbench.colorCustomizations": { "workbench.colorCustomizations": {
"activityBar.background": "#258ecd", "activityBar.background": "#258ecd",
"activityBar.activeBorder": "#f0aed7",
"activityBar.foreground": "#e7e7e7", "activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799", "activityBar.inactiveForeground": "#e7e7e799",
"activityBarBadge.background": "#f0aed7", "activityBarBadge.background": "#f0aed7",

1
npm/ng-packs/apps/dev-app/src/app/app.component.ts

@ -24,6 +24,7 @@ export class AppComponent implements OnInit {
'style', 'style',
null, null,
'head', 'head',
'afterbegin',
) )
.subscribe(); .subscribe();
} }

2
npm/ng-packs/apps/dev-app/src/index.html

@ -7,7 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" /> <link rel="icon" type="image/x-icon" href="favicon.ico" />
</head> </head>
<body class="abp-application-layout bg-light"> <body class="bg-light">
<app-root></app-root> <app-root></app-root>
</body> </body>
</html> </html>

4
npm/ng-packs/dist/account-config/README.md

@ -1 +1,3 @@
# @abp/ng.account.config # @abp/ng.account.config
[docs.abp.io](https://docs.abp.io)

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

Loading…
Cancel
Save