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/gateways/PublicWebSiteGateway.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

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.",
"SourceCodeUpper": "CÓDIGO FONTE",
"LatestReleaseLogs": "Últimos registros de lançamento",
"Infrastructure": "Infra-estrutura",
"Infrastructure": "Infraestrutura",
"Architecture": "Arquitetura",
"Modular": "Modular",
"DontRepeatYourself": "Não se repita",
"DontRepeatYourself": "Não repita a si mesmo",
"DeveloperFocused": "Desenvolvedor focado",
"FullStackApplicationInfrastructure": "Infraestrutura de aplicativos full stack.",
"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.",
"MultiTenancy": "Múltiplos inquilinos",
"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.",
"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!",

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

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

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;
* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/)
* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/)
* [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
* [.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í

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

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

2
docs/en/Background-Jobs.md

@ -40,7 +40,7 @@ using Volo.Abp.Emailing;
namespace MyProject
{
public class EmailSendingJob : BackgroundJob<EmailSendingArgs>
public class EmailSendingJob : BackgroundJob<EmailSendingArgs>, ITransientDependency
{
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:
* **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 depends on the **Domain.Share** package.
* Domain package depends on the **Domain.Shared** package.
#### Application Layer
@ -85,5 +85,5 @@ Next section describes the packages in more details.
#### 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.

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.
> 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

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

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

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

@ -26,8 +26,10 @@ abp new Acme.BookStore
The created solution requires;
* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/)
* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/)
* [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
* [.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

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
"__tenant" parameter name can be changed using AspNetCoreMultiTenancyOptions. Example:
"__tenant" parameter name can be changed using AbpAspNetCoreMultiTenancyOptions. Example:
````C#
services.Configure<AspNetCoreMultiTenancyOptions>(options =>
services.Configure<AbpAspNetCoreMultiTenancyOptions>(options =>
{
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.
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
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.
#### 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)
#### Saving the Book

1
docs/en/docs-nav.json

@ -257,6 +257,7 @@
},
{
"text": "Data Access",
"path": "Data-Access.md"
"items": [
{
"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;
- [Visual Studio 2017 (v15.9.0 +)](https://visualstudio.microsoft.com/tr/downloads/)
- [.NET Core 2.2 ou superior](https://www.microsoft.com/net/download/dotnet-core/)
- [Node v10.16 +](https://nodejs.org/)
- [Yarn v1.17 +](https://yarnpkg.com/)
* [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
* [.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

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

@ -26,8 +26,10 @@ abp new Acme.BookStore
A solução criada requer;
- [Visual Studio 2017 (v15.9.0 +)](https://visualstudio.microsoft.com/tr/downloads/)
- [.NET Core 2.2 ou superior](https://www.microsoft.com/net/download/dotnet-core/)
* [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
* [.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

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

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

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

@ -45,7 +45,7 @@ public class IssueLabelDto
##### 详细DTO
**Do** 如果实体持有对其他聚合根的引用,那么应该为其定义**详细**DTO.
**推荐** 如果实体持有对其他聚合根的引用,那么应该为其定义**详细**DTO.
* 直接包含实体中所有的 **原始属性**.
- 例外-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
- **Do** 重写 `DbContext` 的 `OnModelCreating` 方法显式 **配置所有实体**. 例如:
- **推荐** 重写 `DbContext` 的 `OnModelCreating` 方法显式 **配置所有实体**. 例如:
````C#
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** 包(项目) 命名为*CompanyName.ModuleName.Domain*, 包含实体, 仓储接口,领域服务接口及其实现和其他领域对象.
* Domain package 依赖于 **Domain.Share** package.
* Domain 包依赖于 **Domain.Shared** 包.
#### 应用服务层
* **推荐** 将应用服务层划分为两个项目:
* **Application.Contracts** 包(项目) 命名为*CompanyName.ModuleName.Application.Contracts,包含应用服务接口和相关的数据传输对象(DTO).
* Application contract package 依赖于 **Domain.Shared** package.
* Application contract 包依赖于 **Domain.Shared** 包.
* **Application** 包(项目)命名为*CompanyName.ModuleName.Application*,包含应用服务实现.
* Application package 依赖于 **Domain** 和 **Application.Contracts** packages.
* Application 包依赖于 **Domain** 包和 **Application.Contracts** 包.
#### 基础设施层
* **推荐** 为每个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/数据库集成包中的其他层.
* **推荐** 为每个主要的库创建一个独立的集成包, 在不影响其他包的情况下可以被另一个库替换.
#### HTTP 层
* **推荐** 创建命名为*CompanyName.ModuleName.HttpApi*的**HTTP API**包, 为模块开发REST风格的HTTP API.
* HTTP API package 只依赖于 **Application.Contracts** package. 不要依赖 Application package.
* HTTP API 包只依赖于 **Application.Contracts** 包. 不要依赖 Application 包.
* **推荐** 为每个应用服务创建一个Controller (通常通过实现其接口). 这些控制器使用应用服务接口来委托操作. 它根据需要配置路由, HTTP方法和其他与Web相关的东西.
* **推荐** 创建一个为HTTP API包提供客户端服务的**HTTP API Client**包, 它的命名为*companyname.modulename.httpapi*. 这些客户端服务将应用服务接口实现远程端点的客户端.
* HTTP API Client package 仅依赖于 **Application.Contracts** package.
* **推荐** 创建一个为HTTP API包提供客户端服务的**HTTP API Client**包, 它的命名为*Companyname.ModuleName.HttpApi.Client*. 这些客户端服务将应用服务接口实现远程端点的客户端.
* HTTP API Client 包仅依赖于 **Application.Contracts** 包.
* **推荐** 使用ABP框架提供的动态代理HTTP C#客户端的功能.
#### Web 层
* **推荐** 创建命名为*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/)
* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/)
* [Visual Studio 2019 (v16.3+)](https://visualstudio.microsoft.com/vs/)
* [.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开发新项目的最简单方法是使用启动模板:

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#underscores_in_headers
可以使用AspNetCoreMultiTenancyOptions修改默认的参数名"__tenant".例如:
可以使用AbpAspNetCoreMultiTenancyOptions修改默认的参数名"__tenant".例如:
````C#
services.Configure<AspNetCoreMultiTenancyOptions>(options =>
services.Configure<AbpAspNetCoreMultiTenancyOptions>(options =>
{
options.TenantKey = "MyTenantKey";
});

16
framework/Volo.Abp.sln

@ -250,7 +250,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MailKit.Tests", "t
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}"
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
Global
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}.Release|Any CPU.ActiveCfg = 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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -878,6 +890,8 @@ Global
{70DD6E17-B98B-4B00-8F38-C489E291BB53} = {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}
{928DC30D-C078-4BB4-A9F8-FE7252C67DC6} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{E69182B3-350A-43F5-A935-5EBBEBECEF97} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
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>
<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>
</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.Minify;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
{
[DependsOn(typeof(AbpAspNetCoreMvcUiBootstrapModule))]
[DependsOn(typeof(AbpAspNetCoreMvcUiBootstrapModule), typeof(AbpMinifyModule))]
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.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.AspNetCore.Mvc.UI.Minification;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Minify;
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 Volo.Abp.AspNetCore.Mvc.UI.Minification.Scripts;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.Minify.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.IO;
using Microsoft.AspNetCore.Hosting;
using Volo.Abp.AspNetCore.Mvc.UI.Minification.Styles;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.Minify.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
<div class="dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@Model.CurrentLanguage.DisplayName
</a>
@if (Model.OtherLanguages.Any())
{
<div class="dropdown">
<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">
@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>
}
</div>
</div>
<div class="dropdown-menu dropdown-menu-right border-0 shadow-sm" aria-labelledby="dropdownMenuLink">
@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>
}
</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
<div class="dropdown">
<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>
@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">
<abp-row>
<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-body px-5">
<div class="row">
<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">
@if (CurrentTenant.Id == null)
{
@ -72,15 +75,12 @@
</h6>
</div>
<div class="col-auto">
@if (MultiTenancyOptions.Value.IsEnabled &&
(TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true))
{
<a id="AbpTenantSwitchLink" href="javascript:;" class="btn btn-sm mt-3 btn-outline-primary">@MultiTenancyStringLocalizer["Switch"]</a>
}
<a id="AbpTenantSwitchLink" href="javascript:;" class="btn btn-sm mt-3 btn-outline-primary">@MultiTenancyStringLocalizer["Switch"]</a>
</div>
</div>
</div>
</div>
</div>
}
@(await Component.InvokeAsync<PageAlertsViewComponent>())
@RenderBody()
</abp-column>

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

@ -57,7 +57,9 @@
<div class="@containerClass">
@(await Component.InvokeAsync<PageAlertsViewComponent>())
<div id="AbpContentToolbar">
@RenderSection("content_toolbar", false)
<div class="text-right mb-2">
@RenderSection("content_toolbar", false)
</div>
</div>
@RenderBody()
</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.ExceptionHandling;
using Volo.Abp.AspNetCore.Mvc.Features;
using Volo.Abp.AspNetCore.Mvc.ModelBinding;
using Volo.Abp.AspNetCore.Mvc.Uow;
using Volo.Abp.AspNetCore.Mvc.Validation;
@ -35,7 +36,7 @@ namespace Volo.Abp.AspNetCore.Mvc
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)

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 Microsoft.AspNetCore.Mvc;
using Volo.Abp.Auditing;
using Volo.Abp.Http;
using Volo.Abp.Json;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
@ -24,11 +25,14 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
}
[HttpGet]
[Produces("text/javascript", "text/plain")]
public async Task<string> Get()
[Produces(MimeTypes.Application.Javascript, MimeTypes.Text.Plain)]
public async Task<ActionResult> Get()
{
return CreateAbpExtendScript(
await _configurationAppService.GetAsync()
return Content(
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 Volo.Abp.Auditing;
using Volo.Abp.Http;
using Volo.Abp.Http.ProxyScripting;
namespace Volo.Abp.AspNetCore.Mvc.ProxyScripting
@ -17,11 +18,11 @@ namespace Volo.Abp.AspNetCore.Mvc.ProxyScripting
}
[HttpGet]
[Produces("text/javascript", "text/plain")]
public string GetAll(ServiceProxyGenerationModel model)
[Produces(MimeTypes.Application.Javascript, MimeTypes.Text.Plain)]
public ActionResult GetAll(ServiceProxyGenerationModel model)
{
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 Minify { get; set; }
public string Modules { get; set; }
public string Controllers { get; set; }
@ -32,7 +34,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ProxyScripting
public ProxyScriptingModel CreateOptions()
{
var options = new ProxyScriptingModel(Type, UseCache);
var options = new ProxyScriptingModel(Type, UseCache, Minify);
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 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);
if (updateNuget || both)
{
await UpdateNugetPackages(commandLineArgs);
await UpdateNugetPackages(commandLineArgs, directory);
}
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 =
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)
{
@ -131,6 +137,12 @@ namespace Volo.Abp.Cli.Commands
public static class Options
{
public static class SolutionPath
{
public const string Short = "sp";
public const string Long = "solution-path";
}
public static class IncludePreviews
{
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 bool? IncludeDefaults { get; set; }
public bool IncludeDefaults { get; set; }
public bool? IncludeSelf { get; set; }
public bool IncludeSelf { get; set; }
public ExposeServicesAttribute(params Type[] serviceTypes)
{
@ -22,19 +22,19 @@ namespace Volo.Abp.DependencyInjection
{
var serviceList = ServiceTypes.ToList();
if (IncludeDefaults == true)
if (IncludeDefaults)
{
foreach (var type in GetDefaultServices(targetType))
{
serviceList.AddIfNotContains(type);
}
if (IncludeSelf != false)
if (IncludeSelf)
{
serviceList.AddIfNotContains(targetType);
}
}
else if (IncludeSelf == true)
else if (IncludeSelf)
{
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 =
new ExposeServicesAttribute
{
IncludeDefaults = true
IncludeDefaults = true,
IncludeSelf = true
};
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.ComponentModel.DataAnnotations.Schema;
using System.Linq;
@ -18,10 +18,12 @@ using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EntityFrameworkCore.EntityHistory;
using Volo.Abp.EntityFrameworkCore.ValueConverters;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Reflection;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
namespace Volo.Abp.EntityFrameworkCore
{
@ -48,6 +50,8 @@ namespace Volo.Abp.EntityFrameworkCore
public IAuditingManager AuditingManager { get; set; }
public IClock Clock { get; set; }
public ILogger<AbpDbContext<TDbContext>> Logger { get; set; }
private static readonly MethodInfo ConfigureBasePropertiesMethodInfo
@ -57,6 +61,13 @@ namespace Volo.Abp.EntityFrameworkCore
BindingFlags.Instance | BindingFlags.NonPublic
);
private static readonly MethodInfo ConfigureValueConverterMethodInfo
= typeof(AbpDbContext<TDbContext>)
.GetMethod(
nameof(ConfigureValueConverter),
BindingFlags.Instance | BindingFlags.NonPublic
);
protected AbpDbContext(DbContextOptions<TDbContext> options)
: base(options)
{
@ -75,6 +86,10 @@ namespace Volo.Abp.EntityFrameworkCore
ConfigureBasePropertiesMethodInfo
.MakeGenericMethod(entityType.ClrType)
.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)
where TEntity : class
{
if (mutableEntityType.IsOwned())
{
return;
}
ConfigureConcurrencyStampProperty<TEntity>(modelBuilder, mutableEntityType);
ConfigureExtraProperties<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
{
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));
AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName, configureHttpClientBuilder);
//TODO: Make a configuration option and add remoteServiceName inside it!
//TODO: Add option to change type filter
@ -53,9 +55,8 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddHttpClientProxy(
serviceType,
remoteServiceConfigurationName,
asDefaultServices,
configureHttpClientBuilder
);
asDefaultServices
);
}
return services;
@ -82,14 +83,46 @@ namespace Microsoft.Extensions.DependencyInjection
bool asDefaultService = true,
Action<IHttpClientBuilder> configureHttpClientBuilder = null)
{
AddHttpClientFactoryAndPolicy(services, remoteServiceConfigurationName, configureHttpClientBuilder);
return services.AddHttpClientProxy(
typeof(T),
remoteServiceConfigurationName,
asDefaultService,
configureHttpClientBuilder
asDefaultService
);
}
/// <summary>
/// Use IHttpClientFactory and polly
/// </summary>
/// <param name="services">Service collection</param>
/// <param name="remoteServiceConfigurationName">
/// The name of the remote service configuration to be used by the HTTP Client proxies.
/// See <see cref="AbpRemoteServiceOptions"/>.
/// </param>
/// <param name="configureHttpClientBuilder">
/// A delegate that is used to configure an <see cref="T:Microsoft.Extensions.DependencyInjection.IHttpClientBuilder" />.
/// </param>
public static IServiceCollection AddHttpClientFactoryAndPolicy(
[NotNull] this IServiceCollection services,
[NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName,
Action<IHttpClientBuilder> configureHttpClientBuilder = null)
{
var httpClientBuilder = services.AddHttpClient(remoteServiceConfigurationName);
if (configureHttpClientBuilder == null)
{
httpClientBuilder.AddTransientHttpErrorPolicy(builder =>
// retry 3 times
builder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i))));
}
else
{
configureHttpClientBuilder.Invoke(httpClientBuilder);
}
return services;
}
/// <summary>
/// Registers HTTP Client Proxy for given service <paramref name="type"/>.
/// </summary>
@ -102,15 +135,11 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="asDefaultService">
/// True, to register the HTTP client proxy as the default implementation for the service <paramref name="type"/>.
/// </param>
/// <param name="configureHttpClientBuilder">
/// A delegate that is used to configure an <see cref="T:Microsoft.Extensions.DependencyInjection.IHttpClientBuilder" />.
/// </param>
public static IServiceCollection AddHttpClientProxy(
[NotNull] this IServiceCollection services,
[NotNull] Type type,
[NotNull] string remoteServiceConfigurationName = RemoteServiceConfigurationDictionary.DefaultName,
bool asDefaultService = true,
Action<IHttpClientBuilder> configureHttpClientBuilder = null)
bool asDefaultService = true)
{
Check.NotNull(services, nameof(services));
Check.NotNull(type, nameof(type));
@ -120,19 +149,6 @@ namespace Microsoft.Extensions.DependencyInjection
{
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);
services.AddTransient(interceptorType);

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

@ -16,6 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Http.Abstractions\Volo.Abp.Http.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
<ProjectReference Include="..\Volo.Abp.Minify\Volo.Abp.Minify.csproj" />
</ItemGroup>
</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.Generators.JQuery;
using Volo.Abp.Json;
using Volo.Abp.Minify;
using Volo.Abp.Modularity;
namespace Volo.Abp.Http
{
[DependsOn(typeof(AbpHttpAbstractionsModule))]
[DependsOn(typeof(AbpJsonModule))]
[DependsOn(typeof(AbpMinifyModule))]
public class AbpHttpModule : AbpModule
{
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.Generators;
using Volo.Abp.Json;
using Volo.Abp.Minify.Scripts;
namespace Volo.Abp.Http.ProxyScripting
{
@ -17,18 +18,21 @@ namespace Volo.Abp.Http.ProxyScripting
private readonly IJsonSerializer _jsonSerializer;
private readonly IProxyScriptManagerCache _cache;
private readonly AbpApiProxyScriptingOptions _options;
private readonly IJavascriptMinifier _javascriptMinifier;
public ProxyScriptManager(
IApiDescriptionModelProvider modelProvider,
IServiceProvider serviceProvider,
IJsonSerializer jsonSerializer,
IProxyScriptManagerCache cache,
IOptions<AbpApiProxyScriptingOptions> options)
IOptions<AbpApiProxyScriptingOptions> options,
IJavascriptMinifier javascriptMinifier)
{
_modelProvider = modelProvider;
_serviceProvider = serviceProvider;
_jsonSerializer = jsonSerializer;
_cache = cache;
_javascriptMinifier = javascriptMinifier;
_options = options.Value;
}
@ -63,7 +67,8 @@ namespace Volo.Abp.Http.ProxyScripting
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 Minify { get; set; }
public string[] Modules { get; set; }
public string[] Controllers { get; set; }
@ -16,10 +18,11 @@ namespace Volo.Abp.Http.ProxyScripting
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;
UseCache = useCache;
Minify = minify;
Properties = new Dictionary<string, string>();
}

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

@ -14,7 +14,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MailKit" Version="2.3.2" />
<PackageReference Include="MailKit" Version="2.4.1" />
</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
{

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 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
{

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 NUglify;
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification.NUglify
namespace Volo.Abp.Minify.NUglify
{
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.JavaScript;
using Volo.Abp.AspNetCore.Mvc.UI.Minification.Scripts;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Minify.Scripts;
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification.NUglify
namespace Volo.Abp.Minify.NUglify
{
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 Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.UI.Minification.NUglify
namespace Volo.Abp.Minify.NUglify
{
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
{

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
{

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]
public async Task GetAll()
{
var script = await GetResponseAsStringAsync("/Abp/ServiceProxyScript/");
var script = await GetResponseAsStringAsync("/Abp/ServiceProxyScript?minify=true");
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.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
@ -10,6 +11,7 @@ using Volo.Abp.Modularity;
using Volo.Abp.TestApp;
using Volo.Abp.TestApp.Domain;
using Volo.Abp.TestApp.EntityFrameworkCore;
using Volo.Abp.Timing;
namespace Volo.Abp.EntityFrameworkCore
{
@ -41,6 +43,8 @@ namespace Volo.Abp.EntityFrameworkCore
abpDbContextConfigurationContext.DbContextOptions.UseSqlite(sqliteConnection);
});
});
Configure<AbpClockOptions>(options => options.Kind = DateTimeKind.Utc);
}
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))
{
context.GetService<IRelationalDatabaseCreator>().CreateTables();
context.Database.ExecuteSqlRaw(
@"CREATE VIEW View_PersonView AS
SELECT Name, CreationTime, Birthday, LastActive FROM People");
}
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)
{
modelBuilder.Owned<District>();
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Phone>(b =>
{
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<PersonView> PersonView { get; set; }
public DbSet<ThirdDbContextDummyEntity> DummyEntities { get; set; }
public DbSet<EntityWithIntPk> EntityWithIntPks { get; set; }
@ -23,12 +25,30 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Owned<District>();
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Phone>(b =>
{
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.Collections.Generic;
using System.Linq;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.TestApp.Domain
@ -7,6 +9,8 @@ namespace Volo.Abp.TestApp.Domain
{
public string Name { get; set; }
public ICollection<District> Districts { get; set; }
private City()
{
@ -16,6 +20,12 @@ namespace Volo.Abp.TestApp.Domain
: base(id)
{
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 Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Timing;
namespace Volo.Abp.TestApp.Domain
{
@ -15,6 +16,11 @@ namespace Volo.Abp.TestApp.Domain
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; }
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()
{
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(), "Madrid"));
_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(), "Washington"));
_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.Models;
using IdentityServer4.Services;
@ -12,8 +12,10 @@ using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using Volo.Abp.Account.Web.Settings;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
namespace Volo.Abp.Account.Web.Pages.Account
@ -40,7 +42,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
IdentityServerEvents = identityServerEvents;
}
public override async Task OnGetAsync()
public override async Task<IActionResult> OnGetAsync()
{
LoginInput = new LoginInputModel();
@ -63,7 +65,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
{
LoginInput.UserNameOrEmailAddress = context.LoginHint;
ExternalProviders = new[] { new ExternalProviderModel { AuthenticationScheme = context.IdP } };
return;
return Page();
}
var schemes = await _schemeProvider.GetAllSchemesAsync();
@ -77,7 +79,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
})
.ToList();
EnableLocalLogin = true; //TODO: We can get default from a setting?
EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);
if (context?.ClientId != null)
{
var client = await ClientStore.FindEnabledClientByIdAsync(context.ClientId);
@ -96,15 +98,16 @@ namespace Volo.Abp.Account.Web.Pages.Account
if (IsExternalLoginOnly)
{
//return await ExternalLogin(vm.ExternalLoginScheme, returnUrl);
throw new NotImplementedException();
return await base.OnPostExternalLogin(providers.First().AuthenticationScheme);
}
return Page();
}
[UnitOfWork] //TODO: Will be removed when we implement action filter
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")
{

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

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

@ -9,6 +9,10 @@ namespace Volo.Abp.Account.Web.Settings
context.Add(
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 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,
LocalDirectory = localDirectory,
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 = "/"
};
}

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; }
/// <summary>
/// Gets or sets the Surame for the user.
/// Gets or sets the Surname for the user.
/// </summary>
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.Modularity;
using Localization.Resources.AbpUi;
using Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.Identity
{
[DependsOn(typeof(AbpIdentityApplicationContractsModule), typeof(AbpAspNetCoreMvcModule))]
public class AbpIdentityHttpApiModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpIdentityHttpApiModule).Assembly);
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
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({
order: [[1, "asc"]],
processing: true,
paging: true,
serverSide: true,
ajax: abp.libs.datatables.createAjax(_tenantAppService.getList),
columnDefs: [
{

3
npm/ng-packs/.prettierrc

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

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

@ -6,6 +6,7 @@
"typescript.tsdk": "../node_modules/typescript/lib",
"workbench.colorCustomizations": {
"activityBar.background": "#258ecd",
"activityBar.activeBorder": "#f0aed7",
"activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799",
"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',
null,
'head',
'afterbegin',
)
.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" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body class="abp-application-layout bg-light">
<body class="bg-light">
<app-root></app-root>
</body>
</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