Browse Source

Merge branch 'dev' into Proxy-Contracts

pull/14429/head
maliming 3 years ago
parent
commit
e47529c99c
No known key found for this signature in database GPG Key ID: 96224957E51C89E
  1. 29
      .github/workflows/spellcheck.yml
  2. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json
  3. 151
      cSpell.json
  4. 2
      docs/en/Blob-Storing-Aws.md
  5. 2
      docs/en/Blog-Posts/2022-01-11 v5_1_Release_Stable/POST.md
  6. 2
      docs/en/Community-Articles/2020-04-19-Customize-the-SignIn-Manager/POST.md
  7. 4
      docs/en/Community-Articles/2020-04-27-Use-Azure-Active-Directory-Authentication-for-MVC-Razor-Page-Applications/POST.md
  8. 2
      docs/en/Community-Articles/2020-05-29-Real-Time-Messaging-In-A-Distributed-Architecture-Using-Abp-Framework-SingalR-RabbitMQ/POST.md
  9. 6
      docs/en/Community-Articles/2020-07-21-File-Upload-Download-With-BLOB-Storage-System-in-ASPNET-Core-ABP-Framework/POST.md
  10. 2
      docs/en/Community-Articles/2020-09-16-How-to-Setup-Azure-Active-Directory-and-Integrate-Abp-Angular-Application/POST.md
  11. 4
      docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/POST.md
  12. 4
      docs/en/Community-Articles/2022-02-22-Integrating-MAUI-Client-via-using-OpenID-Connect/README.md
  13. 265
      docs/en/Community-Articles/2022-10-27-Dotnet7-Upgrade/Upgrade-Your-Existing-Projects-to-Dotnet7.md
  14. BIN
      docs/en/Community-Articles/2022-10-27-Dotnet7-Upgrade/as-single-query.jpg
  15. BIN
      docs/en/Community-Articles/2022-10-27-Dotnet7-Upgrade/cover-image.jpg
  16. 6
      docs/en/Contribution/How-to-Contribute-abp.io-as-a-frontend-developer.md
  17. 2
      docs/en/Dependency-Injection.md
  18. 2
      docs/en/Distributed-Event-Bus-Rebus-Integration.md
  19. 4
      docs/en/Entity-Framework-Core-Oracle.md
  20. 24
      docs/en/JSON.md
  21. 2
      docs/en/Migration-Guides/Abp-4_0-Blazor.md
  22. 2
      docs/en/Migration-Guides/Abp-5_2.md
  23. 36
      docs/en/Migration-Guides/Abp-7_0.md
  24. 4
      docs/en/Migration-Guides/IdentityServer_To_OpenIddict.md
  25. 122
      docs/en/Migration-Guides/OpenIddict-Step-by-Step.md
  26. 2
      docs/en/Module-Entity-Extensions.md
  27. 2
      docs/en/Modules/Cms-Kit/Dynamic-Widget.md
  28. 2
      docs/en/Modules/Cms-Kit/Index.md
  29. 2
      docs/en/Redis-Cache.md
  30. 2
      docs/en/SignalR-Integration.md
  31. 2
      docs/en/Specifications.md
  32. 12
      docs/en/Startup-Templates/Index.md
  33. 186
      docs/en/Themes/LeptonXLite/Angular.md
  34. 4
      docs/en/UI/Angular/Chart-Component.md
  35. 10
      docs/en/UI/Angular/DateTime-Format-Pipe.md
  36. 2
      docs/en/UI/Angular/Dynamic-Form-Extensions.md
  37. 2
      docs/en/UI/Angular/Loading-Strategy.md
  38. 6
      docs/en/UI/AspNetCore/Client-Side-Package-Management.md
  39. 5
      docs/en/UI/AspNetCore/JavaScript-API/DOM.md
  40. BIN
      docs/en/images/angular-footer.png
  41. 28
      framework/Volo.Abp.sln
  42. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/FodyWeavers.xml
  43. 30
      framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/FodyWeavers.xsd
  44. 29
      framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson.csproj
  45. 21
      framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs
  46. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js
  47. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
  48. 6
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
  49. 11
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProviderOptions.cs
  50. 45
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonInputFormatter.cs
  51. 72
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOptionsSetup.cs
  52. 42
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOutputFormatter.cs
  53. 33
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs
  54. 48
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs
  55. 21
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcNewtonsoftJsonOptionsSetup.cs
  56. 21
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MediaTypeHeaderValues.cs
  57. 35
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs
  58. 2
      framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs
  59. 18
      framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpNoopHostLifetime.cs
  60. 19
      framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/WebHostBuilderExtensions.cs
  61. 42
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs
  62. 77
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonAuditSerializer.cs
  63. 43
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs
  64. 1
      framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
  65. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs
  66. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs
  67. 143
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs
  68. 18
      framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Configuration/AbpApiProxyScriptingConfiguration.cs
  69. 3
      framework/src/Volo.Abp.Json.Abstractions/FodyWeavers.xml
  70. 30
      framework/src/Volo.Abp.Json.Abstractions/FodyWeavers.xsd
  71. 20
      framework/src/Volo.Abp.Json.Abstractions/Volo.Abp.Json.Abstractions.csproj
  72. 8
      framework/src/Volo.Abp.Json.Abstractions/Volo/Abp/Json/AbpJsonAbstractionsModule.cs
  73. 21
      framework/src/Volo.Abp.Json.Abstractions/Volo/Abp/Json/AbpJsonOptions.cs
  74. 0
      framework/src/Volo.Abp.Json.Abstractions/Volo/Abp/Json/IJsonSerializer.cs
  75. 3
      framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml
  76. 30
      framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd
  77. 23
      framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj
  78. 38
      framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpCamelCasePropertyNamesContractResolver.cs
  79. 116
      framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs
  80. 33
      framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDefaultContractResolver.cs
  81. 18
      framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs
  82. 96
      framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs
  83. 5
      framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs
  84. 3
      framework/src/Volo.Abp.Json.SystemTextJson/FodyWeavers.xml
  85. 30
      framework/src/Volo.Abp.Json.SystemTextJson/FodyWeavers.xsd
  86. 23
      framework/src/Volo.Abp.Json.SystemTextJson/Volo.Abp.Json.SystemTextJson.csproj
  87. 16
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpDefaultJsonTypeInfoResolver.cs
  88. 37
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs
  89. 17
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializer.cs
  90. 20
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerModifiersOptions.cs
  91. 4
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptions.cs
  92. 28
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs
  93. 24
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs
  94. 0
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToBooleanConverter.cs
  95. 0
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs
  96. 0
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumFactory.cs
  97. 0
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs
  98. 39
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpDateTimeConverterModifier.cs
  99. 29
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIgnorePropertiesModifiers.cs
  100. 32
      framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIncludeExtraPropertiesModifiers.cs

29
.github/workflows/spellcheck.yml

@ -0,0 +1,29 @@
name: Documentation Checks
on:
push:
branches:
- dev
paths:
# This ensures the check will only be run when something changes in the docs content
- "docs/en/**/*"
pull_request:
branches:
- dev
paths:
- "docs/en/**/*"
jobs:
spellcheck:
name: "Docs: Spellcheck (En)"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
name: Check out the code
- uses: actions/setup-node@v1
name: Setup node
with:
node-version: "16"
- run: npm install -g cspell
name: Install cSpell
- run: cspell --config ./cSpell.json "docs/en/**/*.md" --no-progress # Update for path to the markdown files
name: Run cSpell

5
abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json

@ -11,6 +11,7 @@
"CommercialSupportWebSite": "Commercial support web site",
"CommunityWebSite": "ABP community web site",
"ManageAccount": "My Account | ABP.IO",
"ManageYourProfile": "Manage your profile"
"ManageYourProfile": "Manage your profile",
"ReturnToApplication": "Return to application"
}
}
}

151
cSpell.json

@ -0,0 +1,151 @@
{
"version": "0.2",
"language": "en",
"words": [
"ABP's",
"abpframework",
"Antiforgery",
"appsettings",
"aspnet",
"aspnetcore",
"Autofac",
"automagically",
"Blazor",
"CQRS",
"crossfade",
"Dapr",
"Datagrid's",
"Datatable",
"datepicker",
"dismissable",
"dockerized",
"entrypoints",
"findability",
"hoverable",
"Iddict",
"IntelliCode",
"Keysize",
"Linq",
"Microservices",
"middlewares",
"Minifier",
"multitenancy",
"multitenant",
"Navs",
"Newtonsoft",
"Npgsql",
"oidc",
"overridable",
"Parameterless",
"Passwordless",
"PKCE",
"preconfigured",
"proxying",
"redirections",
"scrollbars",
"signin",
"Templating",
"textboxes",
"toolset",
"unsubscription",
"Xunit"
],
"ignoreWords": [
"Aliyun",
"Allibone",
"Blazorise",
"Boutwell",
"Cmskit",
"connectionstrings",
"Devart",
"Formik",
"Halil",
"Hanselman",
"hikalkan",
"Ibrahim",
"İbrahim",
"Kalkan",
"Kirti",
"Kommunity",
"Kulkarni",
"Luxon",
"malihu",
"Malik",
"Masis",
"Minio",
"NGXS",
"NSWAG",
"Scriban",
"Serilog",
"Shoudly",
"Shouldly",
"Sweetalert",
"Syncfusion",
"Telerik",
"Timeago",
"Toastr",
"Volo",
"Volosoft",
"Xeevis"
],
"patterns": [
{
"name": "Markdown links",
"pattern": "\\((.*)\\)",
"description": ""
},
{
"name": "Markdown code blocks",
"pattern": "/^(\\s*`{3,}).*[\\s\\S]*?^\\1/gmx",
"description": "Taken from the cSpell example at https://cspell.org/configuration/patterns/#verbose-regular-expressions"
},
{
"name": "Inline code blocks",
"pattern": "\\`([^\\`\\r\\n]+?)\\`",
"description": "https://stackoverflow.com/questions/41274241/how-to-capture-inline-markdown-code-but-not-a-markdown-code-fence-with-regex"
},
{
"name": "Link contents",
"pattern": "\\<a(.*)\\>",
"description": ""
},
{
"name": "Snippet references",
"pattern": "-- snippet:(.*)",
"description": ""
},
{
"name": "Snippet references 2",
"pattern": "\\<\\[sample:(.*)",
"description": "another kind of snippet reference"
},
{
"name": "Multi-line code blocks",
"pattern": "/^\\s*```[\\s\\S]*?^\\s*```/gm"
},
{
"name": "HTML Tags",
"pattern": "<[^>]*>",
"description": "Reference: https://stackoverflow.com/questions/11229831/regular-expression-to-remove-html-tags-from-a-string"
},
{
"name": "Markdown Image",
"pattern": "!\\[(.*)\\]\\((.*)\\)"
}
],
"ignoreRegExpList": [
"Markdown links",
"Markdown code blocks",
"Inline code blocks",
"Link contents",
"Snippet references",
"Snippet references 2",
"Multi-line code blocks",
"HTML Tags",
"Markdown Image"
],
"ignorePaths": [
"**/*Release/Post.md",
"**/*Preview/POST.md"
]
}

2
docs/en/Blob-Storing-Aws.md

@ -59,7 +59,7 @@ Configure<AbpBlobStoringOptions>(options =>
* **ProfilesLocation** (string): The path to the aws credentials file to look at.
* **Region** (string): The system name of the service.
* **Policy** (string): An IAM policy in JSON format that you want to use as an inline session policy.
* **DurationSeconds** (int): Validity period(s) of a temporary access certificate,minimum is 900 and the maximum is 3600. **note**: Using subaccounts operated OSS,if the value is 0.
* **DurationSeconds** (int): Validity period(s) of a temporary access certificate,minimum is 900 and the maximum is 3600. **note**: Using sub-accounts operated OSS,if the value is 0.
* **ContainerName** (string): You can specify the container name in Aws. If this is not specified, it uses the name of the BLOB container defined with the `BlobContainerName` attribute (see the [BLOB storing document](Blob-Storing.md)). Please note that Aws has some **rules for naming containers**. A container name must be a valid DNS name, conforming to the [following naming rules](https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html):
* Bucket names must be between **3** and **63** characters long.
* Bucket names can consist only of **lowercase** letters, numbers, dots (.), and hyphens (-).

2
docs/en/Blog-Posts/2022-01-11 v5_1_Release_Stable/POST.md

@ -107,7 +107,7 @@ Here are some other notable changes that come with this release:
* Developers should control `EnableLegacyTimestampBehavior` when using PostgreSQL. [#11371](https://github.com/abpframework/abp/pull/11371) [#65](https://github.com/abpframework/eShopOnAbp/pull/65)
All issues & PRs in [5.1 milesone](https://github.com/abpframework/abp/milestone/60?closed=1).
All issues & PRs in [5.1 milestone](https://github.com/abpframework/abp/milestone/60?closed=1).
### About ABP Commercial

2
docs/en/Community-Articles/2020-04-19-Customize-the-SignIn-Manager/POST.md

@ -8,7 +8,7 @@ This document explains how to customize the SignIn Manager for your own applicat
## Create a CustomSignInManager
Create a new class inheriting the [SignInMager](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs) of Microsoft Identity package.
Create a new class inheriting the [SignInManager](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs) of Microsoft Identity package.
````csharp
public class CustomSignInManager : Microsoft.AspNetCore.Identity.SignInManager<Volo.Abp.Identity.IdentityUser>

4
docs/en/Community-Articles/2020-04-27-Use-Azure-Active-Directory-Authentication-for-MVC-Razor-Page-Applications/POST.md

@ -12,7 +12,7 @@ Two different **alternative approaches** for AzureAD integration will be demonst
> There is **no difference** in functionality between these approaches. AddAzureAD is an abstracted way of OpenIdConnection ([source](https://github.com/dotnet/aspnetcore/blob/c56aa320c32ee5429d60647782c91d53ac765865/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADAuthenticationBuilderExtensions.cs#L122)) with predefined cookie settings.
>
> However there are key differences in integration to ABP applications because of default configurated signin schemes which will be explained below.
> However there are key differences in integration to ABP applications because of default configured signin schemes which will be explained below.
## 1. AddOpenIdConnect
@ -211,7 +211,7 @@ You can find the source code of the completed example [here](https://github.com/
to your openid configuration.
* Help! I keep getting ***AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application*** error!
* Help! I keep getting `AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application` error!
* If you set your **CallbackPath** in appsettings as:

2
docs/en/Community-Articles/2020-05-29-Real-Time-Messaging-In-A-Distributed-Architecture-Using-Abp-Framework-SingalR-RabbitMQ/POST.md

@ -1,4 +1,4 @@
# Real Time Messaging In A Distributed Architecture Using Abp Framework, SingalR & RabbitMQ
# Real Time Messaging In A Distributed Architecture Using Abp Framework, SignalR & RabbitMQ
In this article, we will build a basic real time messaging application in a distributed architecture. We will use [Abp Framework](https://abp.io) for infrastructure and tiered startup template, [SignalR](https://dotnet.microsoft.com/apps/aspnet/signalr) for real time server-client communication and [RabbitMQ](https://www.rabbitmq.com/) as the distributed event bus.

6
docs/en/Community-Articles/2020-07-21-File-Upload-Download-With-BLOB-Storage-System-in-ASPNET-Core-ABP-Framework/POST.md

@ -46,11 +46,11 @@ Open a command prompt (terminal) in the folder containing your solution (.sln) f
`abp add-module Volo.Abp.BlobStoring.Database`
This action will add the module depencies and also module migration. After this action, run `FileActionsDemo.DbMigrator` to update the database.
This action will add the module dependencies and also module migration. After this action, run `FileActionsDemo.DbMigrator` to update the database.
### Setting up Blob Storaging
### Setting up Blob Storage
BLOB Strorage system works with `Containers`. Before the using blob storage, we need to create our blob container.
BLOB Storage system works with `Containers`. Before the using blob storage, we need to create our blob container.
Create a class that name `MyFileContainer` at the `FileActionsDemo.Domain` project.

2
docs/en/Community-Articles/2020-09-16-How-to-Setup-Azure-Active-Directory-and-Integrate-Abp-Angular-Application/POST.md

@ -107,7 +107,7 @@ Next time you hit login, you should be seeing login screen enabled Azure AD like
* But I don't want my users to see default login screen. I want my users to login **only** from AzureAD.
* You can **mimic** this behaviour by customizing the login page and instantly trigger Azure AD provider click. For more info, you can check [this article](https://community.abp.io/articles/how-to-customize-the-login-page-for-mvc-razor-page-applications-9a40f3cd).
* You can **mimic** this behavior by customizing the login page and instantly trigger Azure AD provider click. For more info, you can check [this article](https://community.abp.io/articles/how-to-customize-the-login-page-for-mvc-razor-page-applications-9a40f3cd).
# May 2021 Update

4
docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/POST.md

@ -85,7 +85,7 @@ Add [Microsoft.SignalR](https://www.npmjs.com/package/@microsoft/signalr) JavaSc
You can install the latest version (3.1.13 will be old)
```
"@microsoft/signalr": "^3.1.13"
````
```
![Add SignalR package](signalr-package.jpg)
@ -93,7 +93,7 @@ You can install the latest version (3.1.13 will be old)
We added SignalR to the `package.json` but it comes into your `node_modules` folder. We need to copy the related files to `wwwroot/libs` folder. To do this copy the content of the following file to your `abp.resourcemappings.js` file. It's in your root directory of Web folder. After you do this, go to your web directory and run `abp install-libs` command. By doing this, it'll copy the related files into your `wwwroot/libs` folder.
[abp.resourcemappings.js](https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-abp-resourcemapping-js)
[`abp.resourcemappings.js`](https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-abp-resourcemapping-js)
![Resource mappings](resource-mappings.jpg)

4
docs/en/Community-Articles/2022-02-22-Integrating-MAUI-Client-via-using-OpenID-Connect/README.md

@ -595,7 +595,7 @@ In this step we have to store access token & refresh token for future requests.
## Recap
The purpose of this arcitle is connecting to ABP backend with access token and it's working properly.
The purpose of this article is connecting to ABP backend with access token and it's working properly.
I'm planning to integrate HttpApi.Client library of backend project instead of making requests manually as a second part of this article. I'll get inspired by [hikalkan/maui-abp-playing](https://github.com/hikalkan/maui-abp-playing) repo to achive that.
I'm planning to integrate HttpApi.Client library of backend project instead of making requests manually as a second part of this article. I'll get inspired by [hikalkan/maui-abp-playing](https://github.com/hikalkan/maui-abp-playing) repo to achieve that.

265
docs/en/Community-Articles/2022-10-27-Dotnet7-Upgrade/Upgrade-Your-Existing-Projects-to-Dotnet7.md

@ -0,0 +1,265 @@
# Upgrade Your Existing Projects to .NET7
A new .NET version has come. As open-source contributors, we are tracking the latest libraries and adopting them to our existing projects. In this sense, we completed our .NET 7 upgrade in our repositories for ABP Framework and ABP Commercial. In this article, I'll share the experiences we faced while upgrading to the new .NET version 👉 .NET 7.
When I wrote this article, the latest .NET version was `7.0.0-rc.2`. So some of the version statements I wrote below must be changed due to the stable version release.
**To see the latest and greatest stuff, let's see how to upgrade our existing projects to .NET 7!**
## Install .NET7 SDK
If you are on your development computer, then you need to install the .NET7 SDK `7.x.x`. For the production servers, you need to install the .NET 7 runtimes. Download link for the .NET7 SDK and runtimes is:
* https://dotnet.microsoft.com/en-us/download/dotnet/7.0
## Update Your *.csproj Files
First, you need to update all your `*.csproj` files to support .NET7. Find and replace all your `<TargetFramework>*</TargetFramework>` in the `*.csproj` files to support .NET 7:
```xml
<TargetFramework>net7.0</TargetFramework>
```
We already did this in ABP Framework, see this commit as an example [github.com/abpframework/abp/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.csproj](https://github.com/abpframework/abp/blob/dev/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj#L4).
### Microsoft Package Updates
You must be using Microsoft packages as well; then you need to update them to the latest .NET 7 version.
At the time, I wrote this article, the latest version was `7.0.0-rc.2.22476.2`, so I'll update them to this version including minor version changes.
Here's the list of all package reference updates I did:
```xml
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Components" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0-rc.2.*">
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0-rc.2.*">
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Composite" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0-rc.2.*" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0-rc.2.*" />
<PackageReference Include="System.Text.Encodings.Web" Version="7.0.0-rc.2.*" />
<PackageReference Include="System.Text.Json" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.0-rc.2.*" />
<PackageReference Include="System.Collections.Immutable" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.0-rc.2.*" />
```
---
## Entity Framework Core Updates
If you use EF Core as your data access library, you should update your `dotnet-ef` CLI tool. Here's the terminal command to update it:
```bash
dotnet tool update dotnet-ef --global --prerelease
```
We already did the the EF Core package reference update in the *Microsoft Package Updates* section.
### Breaking Change: OrderBy
This release makes a breaking change in an EF Core query running behavior. We faced this issue in some of our queries that were missing `OrderBy` statement. It throws an exception and does not run the query. Here's the explanation of a EF Core team member for this issue: [github.com/dotnet/efcore/issues/21202#issuecomment-913206415](https://github.com/dotnet/efcore/issues/21202#issuecomment-913206415).
The following exception is being thrown:
> InvalidOperationException: The query uses 'Skip' without specifying ordering and uses split query mode. This generates incorrect results. Either provide ordering or run query in single query mode using AsSingleQuery(). See https://go.microsoft.com/fwlink/?linkid=2196526 for more information
If you don't want to add `OrderBy` statement to solve the issue, you can also use `AsSingleQuery()`.
![AsSingleQuery](https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2022-10-27-Dotnet7-Upgrade/./as-single-query.jpg)
### EF Core - SQL Client Connection String Update
With this version, the behavior of the SQL connection has been changed. There is a keyword in the SQL connection string called `TrustServerCertificate`. This keyword indicates whether the channel will be encrypted while bypassing walking the certificate chain to validate trust.
> When `TrustServerCertificate` is set to `True`, the transport layer will use SSL to encrypt the channel and bypass walking the certificate chain to validate trust. If `TrustServerCertificate` is set to `true` and encryption is turned on, the encryption level specified on the server will be used even if `Encrypt` is set to `false`. The connection will fail otherwise.
After the .NET7 update, it just started to throw the following exception:
> A connection was successfully established with the server, but then an error occurred during the login process.
We fixed this problem by adding the `TrustServerCertificate=true` to your connection string. Here's an example connection string that supports,
````sql
Server=localhost; Database=MyProjectName; Trusted_Connection=True; TrustServerCertificate=True
````
See our commit for this fix:
* [github.com/abpframework/abp/commit/96f17e67918eb87edd2baf876d4a7598281fe608](https://github.com/abpframework/abp/commit/96f17e67918eb87edd2baf876d4a7598281fe608)
Related docs:
* [learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/breaking-changes#encrypt-true](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/breaking-changes#encrypt-true)
* [stackoverflow.com/questions/34430550/a-connection-was-successfully-established-with-the-server-but-then-an-error-occ](https://stackoverflow.com/questions/34430550/a-connection-was-successfully-established-with-the-server-but-then-an-error-occ)
---
## Blazor Update
Ensure that you have updated your Blazor project's csproj to support .NET7:
```xml
<TargetFramework>net7.0</TargetFramework>
```
### Install Blazor Workloads
#### .NET Web Assembly build tools
If you have a Blazor-WASM project, install the workloads by running the following in a command shell:
```bash
dotnet workload install wasm-tools
```
**OR** you can update your workloads by running the following command in your Blazor project directory:
```bash
dotnet workload restore
```
---
## .NET MAUI Update
Ensure that you have updated your Blazor project's csproj to support .NET7:
```xml
<TargetFrameworks>net7.0-android;net7.0-ios;net7.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
```
### Install MAUI Workloads
If you have .NET MAUI project, then you also need to update your `TargetFramework` as below:
If you have a .NET MAUI project, after installing the .NET 7 SDK, install the latest workloads with the following command:
```bash
dotnet workload install maui
```
**OR** run the following command in your existing .NET MAUI project directory
```bash
dotnet workload restore
```
Further information, check out https://github.com/dotnet/maui/wiki/.NET-7-and-.NET-MAUI
---
#### Dotnet Maui Check Tool
Alternatively, there's a 3rd party tool for .NET MAUI to install the required workloads. This tool installs the missing SDK packs. You can reach the tool's repository at [github.com/Redth/dotnet-maui-check](https://github.com/Redth/dotnet-maui-check).
Installation:
```bash
dotnet tool install -g Redth.Net.Maui.Check
```
Run:
```bash
maui-check
```
---
## Docker Image Update
If you are using Docker to automate the deployment of applications, you also need to update your images. We were using `aspnet:6.0.0-bullseye-slim` base and after the .NET 7 update, we started using `aspnet:7.0-bullseye-slim` in our Docker files.
```
FROM mcr.microsoft.com/dotnet/aspnet:7.0-bullseye-slim AS base
```
For this update, you can check out the following commit as an example:
* [github.com/abpframework/abp/commit/2d07b9bd00152bef4658c48ff9b2cbee5788d308](https://github.com/abpframework/abp/commit/2d07b9bd00152bef4658c48ff9b2cbee5788d308)
## ABP Framework .NET 7 Update
In [ABP Framework repository](https://github.com/abpframework/abp), we pdated all our dependencies from .NET 6 to .NET 7.
Not all the changes are here, but you can check out the following PR of the .NET 7 update:
* [github.com/abpframework/abp/pull/13626/files](https://github.com/abpframework/abp/pull/13626/files)
...
Happy coding with .NET 7 🤗
...

BIN
docs/en/Community-Articles/2022-10-27-Dotnet7-Upgrade/as-single-query.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
docs/en/Community-Articles/2022-10-27-Dotnet7-Upgrade/cover-image.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

6
docs/en/Contribution/How-to-Contribute-abp.io-as-a-frontend-developer.md

@ -11,7 +11,7 @@
- Abp CLI https://docs.abp.io/en/abp/latest/cli
- A code editor
Note: This arcticle prepare Windows OS. You may change the path type of your OS. an Example
Note: This article prepare Windows OS. You may change the path type of your OS. an Example
Windows: `templates\app\aspnet-core\src\MyCompanyName.MyProjectName.DbMigrator\appsettings.json`
@ -22,11 +22,15 @@ Unix: `templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/apps
You need to install SQL Server and Redis. You can install these programs without docker, but my example uses docker containers. Your computer should have Docker Engine. Then open the terminal en execute the commands one by one.
For the Sql Server
```cmd
docker run -v sqlvolume:/var/opt/mssql -e 'ACCEPT_EULA=Y' -e "SA_PASSWORD=yourpassword" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-CU3-ubuntu-18.04
```
For the Redis
```cmd
docker run -p 6379:6379 -d redis
```
Then we are ready to download and execute the code.

2
docs/en/Dependency-Injection.md

@ -6,7 +6,7 @@ ABP's Dependency Injection system is developed based on Microsoft's [dependency
## Modularity
Since ABP is a modular framework, every module defines it's own services and registers via dependency injection in it's own seperate [module class](Module-Development-Basics.md). Example:
Since ABP is a modular framework, every module defines it's own services and registers via dependency injection in it's own separate [module class](Module-Development-Basics.md). Example:
````C#
public class BlogModule : AbpModule

2
docs/en/Distributed-Event-Bus-Rebus-Integration.md

@ -18,7 +18,7 @@ You can configure using the standard [configuration system](Configuration.md), l
### The Options Classes
`AbpRebusEventBusOptions` classe can be used to configure the event bus options for the Rebus.
`AbpRebusEventBusOptions` class can be used to configure the event bus options for the Rebus.
You can configure this options inside the `PreConfigureServices` of your [module](Module-Development-Basics.md).

4
docs/en/Entity-Framework-Core-Oracle.md

@ -6,7 +6,7 @@ This document explains how to switch to the **Oracle** database provider for **[
ABP Framework provides integrations for two different Oracle packages. See one of the following documents based on your provider decision:
* **[Volo.Abp.EntityFrameworkCore.Oracle](Entity-Framework-Core-Oracle-Official.md)** package uses the official & free oracle driver.
* **[Volo.Abp.EntityFrameworkCore.Oracle.Devart](Entity-Framework-Core-Oracle-Devart.md)** package uses the commercial (paid) driver of [Devart](https://www.devart.com/) company.
* **[`Volo.Abp.EntityFrameworkCore.Oracle`](Entity-Framework-Core-Oracle-Official.md)** package uses the official & free oracle driver.
* **[`Volo.Abp.EntityFrameworkCore.Oracle.Devart`](Entity-Framework-Core-Oracle-Devart.md)** package uses the commercial (paid) driver of [Devart](https://www.devart.com/) company.
> You can choose one of the package you want. If you don't know the differences of the packages, please search for it. ABP Framework only provides integrations it doesn't provide support for such 3rd-party libraries.

24
docs/en/JSON.md

@ -4,7 +4,7 @@ The ABP Framework provides an abstraction to work with JSON. Having such an abst
* You can write library independent code. Therefore, you can change the underlying library with the minimum effort and code change.
* You can use the predefined converters defined in the ABP without worrying about the underlying library's internal details.
> The JSON serialization system is implemented with the [Volo.Abp.Json](https://www.nuget.org/packages/Volo.Abp.Json) NuGet package. Most of the time, you don't need to manually [install it](https://abp.io/package-detail/Volo.Abp.Json) since it comes pre-installed with the [application startup template](Startup-Templates/Application.md).
> The JSON serialization system is implemented with the [Volo.Abp.Json](https://www.nuget.org/packages/Volo.Abp.Json) NuGet package([Volo.Abp.Json.SystemTextJson](https://www.nuget.org/packages/Volo.Abp.Json.SystemTextJson) is the default implementation). Most of the time, you don't need to manually [install it](https://abp.io/package-detail/Volo.Abp.Json) since it comes pre-installed with the [application startup template](Startup-Templates/Application.md).
## IJsonSerializer
@ -45,16 +45,24 @@ public class ProductManager
`AbpJsonOptions` type provides options for the JSON operations in the ABP Framework.
Properties:
* **DefaultDateTimeFormat(`string`)**: Default `DateTime` format.
* **UseHybridSerializer(`bool`)**: True by default. Boolean field indicating whether the ABP Framework uses the hybrid approach or not. If the field is true, it will try to use `System.Json.Text` to handle JSON if it can otherwise use the `Newtonsoft.Json.`
* **Providers(`ITypeList<IJsonSerializerProvider>`)**: List of JSON serializer providers implementing the `IJsonSerializerProvider` interface. You can create and add custom serializers to the list, and the ABP Framework uses them automatically. When the `Serialize` or `Deserialize` method is called on the `IJsonSerializer` interface, the ABP Framework calls the `CanHandle` methods of the given providers in reverse order and uses the first provider that returns `true` to do the JSON operation.
* **InputDateTimeFormats(`List<string>`)**: Formats of input JSON date, Empty string means default format. You can provide multiple formats to parse the date.
* **OutputDateTimeFormat(`string`)**: Format of output json date, Null or empty string means default format.
## System Text Json
### AbpSystemTextJsonSerializerOptions
`AbpSystemTextJsonSerializerOptions` provides options for `System.Text.Json` usage.
- **JsonSerializerOptions(`System.Text.Json.JsonSerializerOptions`)**: Global options for System.Text.Json library operations. See [here](https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions) for reference.
Properties:
### AbpSystemTextJsonSerializerModifiersOptions
- **JsonSerializerOptions(`System.Text.Json.JsonSerializerOptions`)**: Global options for System.Text.Json library operations. See [here](https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions) for reference.
- **UnsupportedTypes(`ITypeList`)**: List of the unsupported types. You can add types of the unsupported types to the list and, the hybrid JSON serializer automatically uses the `Newtonsoft.Json` library instead of `System.Text.Json`.
- **Modifiers(`List<Action<JsonTypeInfo>>`)**: Configure `Modifiers` of `DefaultJsonTypeInfoResolver`. See [here](https://devblogs.microsoft.com/dotnet/announcing-dotnet-7-preview-6/#json-contract-customization) for reference.
## Newtonsoft
Add [Volo.Abp.Json.Newtonsoft](https://www.nuget.org/packages/Volo.Abp.Json.Newtonsoft) packge and depends on `AbpJsonNewtonsoftModule` to replace the `System Text Json`.
#### AbpNewtonsoftJsonSerializerOptions
- **JsonSerializerSettings(`Newtonsoft.Json.JsonSerializerSettings`)**: Global options for Newtonsoft library operations. See [here](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonSerializerSettings.htm) for reference.

2
docs/en/Migration-Guides/Abp-4_0-Blazor.md

@ -9,7 +9,7 @@ These changes are required to manually applied in your own solution. It would be
* Add `<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>` to the `PropertyGroup` section of your project (`.csproj`) file.
* Update the `Blazorise.*` packages to the latest version (to the latest RC for the ABP 4.0 preview).
### wwwroot/index.html
### `wwwroot/index.html`
There are some changes made in the index.html file;

2
docs/en/Migration-Guides/Abp-5_2.md

@ -15,7 +15,7 @@ We've upgraded to Blazorise 1.0 stable version. So there is some breaking change
Also You can review that pull request [#11649 - Blazorise 1.0 Migration](https://github.com/abpframework/abp/pull/11649)
- `NumericEdit` is now made around the native `input type="number"` so a lot of its formating features are moved to the new `NumericPicker` component. Replace NumericEdit with NumericPicker.
- `NumericEdit` is now made around the native `input type="number"` so a lot of its formatting features are moved to the new `NumericPicker` component. Replace NumericEdit with NumericPicker.
- Rename `DecimalsSeparator` to `DecimalSeparator` on the `DataGridColumn` and `NumericPicker`.
- Rename `MaxMessageSize` to `MaxChunkSize`.
- Remove `Fullscreen` parameter on `<ModalContent>` and replace it with `Size="ModalSize.Fullscreen"` parameter.

36
docs/en/Migration-Guides/Abp-7_0.md

@ -0,0 +1,36 @@
# ABP Version 7.0 Migration Guide
This document is a guide for upgrading ABP v6.0 solutions to ABP v7.0. There is a change in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
## Hybrid JSON was removed.
Since [System.Text.Json](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/overview) library supports more custom features in NET 7, ABP no longer need the hybrid Json feature.
### Previous Behavior
There is a `Volo.Abp.Json` package which contains the `AbpJsonModule` module.
`Serialization/deserialization` features of [System.Text.Json](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/overview) and [Nettonsoft](https://www.newtonsoft.com/json/help/html/SerializingJSON.htm) are implemented in this module.
We use [System.Text.Json](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/overview) first, More custom cases can be handled with [Nettonsoft](https://www.newtonsoft.com/json/help/html/SerializingJSON.htm) by configuring `UnsupportedTypes` of `AbpSystemTextJsonSerializerOptions`.
### New Behavior
We created `Volo.Abp.Json.SystemTextJson` and `Volo.Abp.Json.Newtonsoft` as separate packages, which means you can only use one of them in your project. The default is to use `SystemTextJson`. If you want `Newtonsoft`, please also use `Volo.Abp.AspNetCore.Mvc.NewtonsoftJson` in your web project.
* Volo.Abp.Json.Abstractions
* Volo.Abp.Json.Newtonsoft
* Volo.Abp.Json.SystemTextJson
* Volo.Abp.Json (Depends on `Volo.Abp.Json.SystemTextJson` by default to prevent breaking)
* Volo.Abp.AspNetCore.Mvc.NewtonsoftJson
The `AbpJsonOptions` now has only two properties, which are
* `InputDateTimeFormats(List<string>)`: Formats of input JSON date, Empty string means default format. You can provide multiple formats to parse the date.
* `OutputDateTimeFormat(string)`: Format of output json date, Null or empty string means default format.
Please remove all `UnsupportedTypes` add custom `Modifiers` to control serialization/deserialization behavior.
Check the docs to see the more info: https://github.com/abpframework/abp/blob/dev/docs/en/JSON.md#configuration
Check the docs to see how to customize a JSON contract: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/custom-contracts

4
docs/en/Migration-Guides/IdentityServer_To_OpenIddict.md

@ -72,7 +72,7 @@ private void ConfigureAuthentication(ServiceConfigurationContext context)
## Source code of samples and module
* [Open source tiered & separate auth server application migrate Identity Server to OpenIddct](https://github.com/abpframework/abp-samples/tree/master/Ids2OpenId)
* [Commercial tiered & separate auth server application migrate Identity Server to OpenIddct](https://abp.io/Account/Login?returnUrl=/api/download/samples/Ids2OpenId)
* [Open source tiered & separate auth server application migrate Identity Server to OpenIddict](https://github.com/abpframework/abp-samples/tree/master/Ids2OpenId)
* [Commercial tiered & separate auth server application migrate Identity Server to OpenIddict](https://abp.io/Account/Login?returnUrl=/api/download/samples/Ids2OpenId)
* [OpenIddict module document](https://docs.abp.io/en/abp/6.0/Modules/OpenIddict)
* [OpenIddict module source code](https://github.com/abpframework/abp/tree/rel-6.0/modules/openiddict)

122
docs/en/Migration-Guides/OpenIddict-Step-by-Step.md

@ -19,62 +19,68 @@ Use the `abp update` command to update your existing application. See [Upgrading
### Domain.Shared Layer
- In **MyApplication.Domain.Shared.csproj** replace **project reference**:
```csharp
<PackageReference Include="Volo.Abp.IdentityServer.Domain.Shared" Version="6.0.*" />
```
```csharp
<PackageReference Include="Volo.Abp.IdentityServer.Domain.Shared" Version="6.0.*" />
```
with
```csharp
<PackageReference Include="Volo.Abp.OpenIddict.Domain.Shared" Version="6.0.*" />
```
```csharp
<PackageReference Include="Volo.Abp.OpenIddict.Domain.Shared" Version="6.0.*" />
```
- In **MyApplicationDomainSharedModule.cs** replace usings and **module dependencies:**
```csharp
using Volo.Abp.IdentityServer;
...
typeof(AbpIdentityServerDomainSharedModule)
```
```csharp
using Volo.Abp.IdentityServer;
...
typeof(AbpIdentityServerDomainSharedModule)
```
with
```csharp
using Volo.Abp.OpenIddict;
...
typeof(AbpOpenIddictDomainSharedModule)
```csharp
using Volo.Abp.OpenIddict;
...
typeof(AbpOpenIddictDomainSharedModule)
```
### Domain Layer
- In **MyApplication.Domain.csproj** replace **project references**:
```csharp
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="6.0.*" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.IdentityServer" Version="6.0.*" />
```
```csharp
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="6.0.*" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.IdentityServer" Version="6.0.*" />
```
with
```csharp
<PackageReference Include="Volo.Abp.OpenIddict.Domain" Version="6.0.*" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.OpenIddict" Version="6.0.*" />
```
```csharp
<PackageReference Include="Volo.Abp.OpenIddict.Domain" Version="6.0.*" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.OpenIddict" Version="6.0.*" />
```
- In **MyApplicationDomainModule.cs** replace usings and **module dependencies**:
```csharp
using Volo.Abp.IdentityServer;
using Volo.Abp.PermissionManagement.IdentityServer;
...
typeof(AbpIdentityServerDomainModule),
typeof(AbpPermissionManagementDomainIdentityServerModule),
```
```csharp
using Volo.Abp.IdentityServer;
using Volo.Abp.PermissionManagement.IdentityServer;
...
typeof(AbpIdentityServerDomainModule),
typeof(AbpPermissionManagementDomainIdentityServerModule),
```
with
```csharp
using Volo.Abp.OpenIddict;
using Volo.Abp.PermissionManagement.OpenIddict;
...
typeof(AbpOpenIddictDomainModule),
typeof(AbpPermissionManagementDomainOpenIddictModule),
```
```csharp
using Volo.Abp.OpenIddict;
using Volo.Abp.PermissionManagement.OpenIddict;
...
typeof(AbpOpenIddictDomainModule),
typeof(AbpPermissionManagementDomainOpenIddictModule),
```
#### OpenIddictDataSeedContributor
@ -101,19 +107,19 @@ If you are using MongoDB, skip this step and check the *MongoDB* layer section.
- In **MyApplicationEntityFrameworkCoreModule.cs** replace usings and **module dependencies**:
```csharp
using Volo.Abp.IdentityServer.EntityFrameworkCore;
...
typeof(AbpIdentityServerEntityFrameworkCoreModule),
```
```csharp
using Volo.Abp.IdentityServer.EntityFrameworkCore;
...
typeof(AbpIdentityServerEntityFrameworkCoreModule),
```
with
```csharp
using Volo.Abp.OpenIddict.EntityFrameworkCore;
...
typeof(AbpOpenIddictEntityFrameworkCoreModule),
```
```csharp
using Volo.Abp.OpenIddict.EntityFrameworkCore;
...
typeof(AbpOpenIddictEntityFrameworkCoreModule),
```
- In **MyApplicationDbContext.cs** replace usings and **fluent api configurations**:
@ -165,19 +171,19 @@ If you are using EntityFrameworkCore, skip this step and check the *EntityFramew
- In **MyApplicationMongoDbModule.cs** replace usings and **module dependencies**:
```csharp
using Volo.Abp.IdentityServer.MongoDB;
...
typeof(AbpIdentityServerMongoDbModule),
```
```csharp
using Volo.Abp.IdentityServer.MongoDB;
...
typeof(AbpIdentityServerMongoDbModule),
```
with
```csharp
using Volo.Abp.OpenIddict.MongoDB;
...
typeof(AbpOpenIddictMongoDbModule),
```
```csharp
using Volo.Abp.OpenIddict.MongoDB;
...
typeof(AbpOpenIddictMongoDbModule),
```
### DbMigrator Project
@ -251,7 +257,7 @@ for creating the host builder.
## Source code of samples and module
* [Open source tiered & separate auth server application migrate Identity Server to OpenIddct](https://github.com/abpframework/abp-samples/tree/master/Ids2OpenId)
* [Open source tiered & separate auth server application migrate Identity Server to OpenIddict](https://github.com/abpframework/abp-samples/tree/master/Ids2OpenId)
* [OpenIddict module document](https://docs.abp.io/en/abp/6.0/Modules/OpenIddict)
* [OpenIddict module source code](https://github.com/abpframework/abp/tree/rel-6.0/modules/openiddict)

2
docs/en/Module-Entity-Extensions.md

@ -6,7 +6,7 @@ Module entity extension system is a **high level** extension system that allows
## Quick Example
Open the *YourProjectNameModuleExtensionConfigurator* class inside the `Domain.Shared` project of your solution and change the `ConfigureExtraProperties`method as shown below to add a `SocialSecurityNumber` property to the `IdentityUser` entity of the [Identity Module](Modules/Identity.md).
Open the `YourProjectNameModuleExtensionConfigurator` class inside the `Domain.Shared` project of your solution and change the `ConfigureExtraProperties`method as shown below to add a `SocialSecurityNumber` property to the `IdentityUser` entity of the [Identity Module](Modules/Identity.md).
````csharp
public static void ConfigureExtraProperties()

2
docs/en/Modules/Cms-Kit/Dynamic-Widget.md

@ -3,7 +3,7 @@
CMS kit provides a dynamic [widget](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Widgets) used to render the components previously developed by the software in the content of the pages and blog posts. Its means, that in static content you can use dynamic content. We will mention how you can do it. You have two choices to define the widget in the system: Writing and UI.
### Adding the widget
Firstly we will show how to use the widget system via writing manually in the page and blogpost contents.
Firstly we will show how to use the widget system via writing manually in the page and blog post contents.
Let's define the view component

2
docs/en/Modules/Cms-Kit/Index.md

@ -22,7 +22,7 @@ All features are individually usable. If you disable a feature, it completely di
## Pre Requirements
- This module depends on [BlobStoring](../../Blob-Storing.md) module for keeping media content.
> Make sure `BlobStoring` module is installed and at leats one provider is configured properly. For more information, check the [documentation](../../Blob-Storing.md).
> Make sure `BlobStoring` module is installed and at least one provider is configured properly. For more information, check the [documentation](../../Blob-Storing.md).
- CMS Kit uses [distributed cache](../../Caching.md) for responding faster.
> Using a distributed cache, such as [Redis](../../Redis-Cache.md), is highly recommended for data consistency in distributed/clustered deployments.

2
docs/en/Redis-Cache.md

@ -4,7 +4,7 @@ ABP Framework [Caching System](Caching.md) extends the [ASP.NET Core distributed
However, ABP provides an **integration package** for Redis Cache: [Volo.Abp.Caching.StackExchangeRedis](https://www.nuget.org/packages/Volo.Abp.Caching.StackExchangeRedis). There are two reasons for using this package, instead of the standard [Microsoft.Extensions.Caching.StackExchangeRedis](https://www.nuget.org/packages/Microsoft.Extensions.Caching.StackExchangeRedis/) package.
1. It implements `SetManyAsync` and `GetManyAsync` methods. These are not standard methods of the Microsoft Caching library, but added by the ABP Framework [Caching](Caching.md) system. They **significiantly increases the performance** when you need to set/get multiple cache items with a single method call.
1. It implements `SetManyAsync` and `GetManyAsync` methods. These are not standard methods of the Microsoft Caching library, but added by the ABP Framework [Caching](Caching.md) system. They **significantly increases the performance** when you need to set/get multiple cache items with a single method call.
2. It **simplifies** the Redis cache **configuration** (will be explained below).
> Volo.Abp.Caching.StackExchangeRedis is already uses the Microsoft.Extensions.Caching.StackExchangeRedis package, but extends and improves it.

2
docs/en/SignalR-Integration.md

@ -235,4 +235,4 @@ Refer to the Microsoft's documentation to [host and scale](https://docs.microsof
## See Also
- [Microsoft SignalR documentation](https://docs.microsoft.com/en-us/aspnet/core/signalr/introduction)
- [Real-Time Messaging In A Distributed Architecture Using ABP, SingalR & RabbitMQ](https://volosoft.com/blog/RealTime-Messaging-Distributed-Architecture-Abp-SingalR-RabbitMQ)
- [Real-Time Messaging In A Distributed Architecture Using ABP, SignalR & RabbitMQ](https://volosoft.com/blog/RealTime-Messaging-Distributed-Architecture-Abp-SingalR-RabbitMQ)

2
docs/en/Specifications.md

@ -246,7 +246,7 @@ So, what's the point of a specification? Why and when should we consider to use
Some benefits of using specifications:
- **Reusabe**: Imagine that you need the Premium Customer filter in many places in your code base. If you go with expressions and do not create a specification, what happens if you later change the "Premium Customer" definition? Say you want to change the minimum balance from $100,000 to $250,000 and add another condition to be a customer older than 3 years. If you'd used a specification, you just change a single class. If you repeated (copy/pasted) the same expression everywhere, you need to change all of them.
- **Reusable**: Imagine that you need the Premium Customer filter in many places in your code base. If you go with expressions and do not create a specification, what happens if you later change the "Premium Customer" definition? Say you want to change the minimum balance from $100,000 to $250,000 and add another condition to be a customer older than 3 years. If you'd used a specification, you just change a single class. If you repeated (copy/pasted) the same expression everywhere, you need to change all of them.
- **Composable**: You can combine multiple specifications to create new specifications. This is another type of reusability.
- **Named**: `PremiumCustomerSpecification` better explains the intent rather than a complex expression. So, if you have an expression that is meaningful in your business, consider using specifications.
- **Testable**: A specification is a separately (and easily) testable object.

12
docs/en/Startup-Templates/Index.md

@ -2,9 +2,9 @@
While you can start with an empty project and add needed packages manually, startup templates make easy and comfortable to start a new solution with the ABP framework. Click the name from the list below to see the documentation of the related startup template:
* [**app**](Application.md): Application template.
* [**app-nolayers**](Application-Single-Layer.md): Application (single layer) template.
* [**module**](Module.md): Module/service template.
* [**console**](Console.md): Console template.
* [**WPF**](WPF.md): WPF template.
* [**MAUI**](MAUI.md): MAUI template.
* [**`app`**](Application.md): Application template.
* [**`app-nolayers`**](Application-Single-Layer.md): Application (single layer) template.
* [**`module`**](Module.md): Module/service template.
* [**`console`**](Console.md): Console template.
* [**`WPF`**](WPF.md): WPF template.
* [**`MAUI`**](MAUI.md): MAUI template.

186
docs/en/Themes/LeptonXLite/Angular.md

@ -1,7 +1,8 @@
# LeptonX Lite Angular UI
LeptonX Lite has implementation for the ABP Framework Angular Client. It's a simplified variation of the [LeptonX Theme](https://x.leptontheme.com/).
> If you are looking for a professional, enterprise ready theme, you can check the [LeptonX Theme](https://x.leptontheme.com/), which is a part of [ABP Commercial](https://commercial.abp.io/).
> If you are looking for a professional, enterprise ready theme, you can check the [LeptonX Theme](https://x.leptontheme.com/), which is a part of [ABP Commercial](https://commercial.abp.io/).
> See the [Theming document](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Theming) to learn about themes.
@ -11,28 +12,27 @@ This theme is **already installed** when you create a new solution using the sta
To add `LeptonX-lite` into your project,
* Install `@abp/ng.theme.lepton-x`
- Install `@abp/ng.theme.lepton-x`
`yarn add @abp/ng.theme.lepton-x@preview`
* Install `bootstrap-icons`
- Install `bootstrap-icons`
`yarn add bootstrap-icons`
- Then, we need to edit the styles array in `angular.json` to replace the existing style with the new one.
* Then, we need to edit the styles array in `angular.json` to replace the existing style with the new one.
Add the following style
Add the following style
```json
"node_modules/bootstrap-icons/font/bootstrap-icons.css",
```
* Finally, remove `ThemeBasicModule` from `app.module.ts`, and import the related modules in `app.module.ts`
- Finally, remove `ThemeBasicModule` from `app.module.ts`, and import the related modules in `app.module.ts`
```js
import { ThemeLeptonXModule } from '@abp/ng.theme.lepton-x';
import { SideMenuLayoutModule } from '@abp/ng.theme.lepton-x/layouts';
import { ThemeLeptonXModule } from "@abp/ng.theme.lepton-x";
import { SideMenuLayoutModule } from "@abp/ng.theme.lepton-x/layouts";
@NgModule({
imports: [
@ -51,7 +51,7 @@ export class AppModule {}
Note: If you employ [Resource Owner Password Flow](https://docs.abp.io/en/abp/latest/UI/Angular/Authorization#resource-owner-password-flow) for authorization, you should import the following module as well:
```js
import { AccountLayoutModule } from '@abp/ng.theme.lepton-x/account';
import { AccountLayoutModule } from "@abp/ng.theme.lepton-x/account";
@NgModule({
// ...
@ -69,15 +69,15 @@ To change the logos and brand color of `LeptonX`, simply add the following CSS t
```css
:root {
--lpx-logo: url('/assets/images/logo.png');
--lpx-logo-icon: url('/assets/images/logo-icon.png');
--lpx-logo: url("/assets/images/logo.png");
--lpx-logo-icon: url("/assets/images/logo-icon.png");
--lpx-brand: #edae53;
}
```
- `--lpx-logo` is used to place the logo in the menu.
- `--lpx-logo-icon` is a square icon used when the menu is collapsed.
- `--lpx-brand` is a color used throughout the application, especially on active elements.
- `--lpx-logo-icon` is a square icon used when the menu is collapsed.
- `--lpx-brand` is a color used throughout the application, especially on active elements.
### Server Side
@ -85,22 +85,18 @@ In order to migrate to LeptonX on your server side projects (Host and/or AuthSer
## Customization
### Layouts
The Angular version of LeptonX Lite provides **layout components** for your **user interface** on [ABP Framework Theming](https://docs.abp.io/en/abp/latest/UI/Angular/Theming). You can use layouts to **organize your user interface**. You can replace the **layout components** and some parts of the **layout components** with the [ABP replaceable component system](https://docs.abp.io/en/abp/latest/UI/Angular/Component-Replacement).
The Angular version of LeptonX Lite provides **layout components** for your **user interface** on [ABP Framework Theming](https://docs.abp.io/en/abp/latest/UI/Angular/Theming). You can use the layouts to **organize your user interface**. You can replace the **layout components** and some parts of the **layout components** with the [ABP replaceable component system](https://docs.abp.io/en/abp/latest/UI/Angular/Component-Replacement).
The main responsibility of a theme is to **provide** the layouts. There are **three pre-defined layouts that must be implemented by all the themes:**
* **ApplicationLayoutComponent:** The **default** layout which is used by the **main** application pages.
* **AccountLayoutComponent:** Mostly used by the **account module** for **login**, **register**, **forgot password**... pages.
* **EmptyLayoutComponent:** The **Minimal** layout that **has no layout components** at all.
- **ApplicationLayoutComponent:** The **default** layout which is used by the **main** application pages.
- **AccountLayoutComponent:** Mostly used by the **account module** for **login**, **register**, **forgot password**... pages.
- **EmptyLayoutComponent:** The **Minimal** layout that **has no layout components** at all.
The **Layout components** and all the replacable components are predefined in `eThemeLeptonXComponents` as enum.
The **Layout components** and all the replacable components are predefined in `eThemeLeptonXComponents` as enum.
### How to replace a component
```js
@ -122,8 +118,8 @@ export class AppComponent {
}
}
```
See the [Component Replacement](https://docs.abp.io/en/abp/latest/UI/Angular/Component-Replacement) documentation for more information on how to replace components.
See the [Component Replacement](https://docs.abp.io/en/abp/latest/UI/Angular/Component-Replacement) documentation for more information on how to replace components.
### Brand Component
@ -131,16 +127,14 @@ The **brand component** is a simple component that can be used to display your b
```js
///...
this.replaceableComponents.add({
component: YourNewLogoComponent,
key: eThemeLeptonXComponents.Logo,
});
this.replaceableComponents.add({
component: YourNewLogoComponent,
key: eThemeLeptonXComponents.Logo,
});
///...
```
![Brand component](../../images/leptonxlite-brand-component.png)
![Brand component](../../images/leptonxlite-brand-component.png)
## Breadcrumb Component
@ -148,14 +142,14 @@ On websites that have a lot of pages, **breadcrumb navigation** can greatly **en
```js
///...
this.replaceableComponents.add({
component: YourNewSidebarComponent,
key: eThemeLeptonXComponents.Breadcrumb,
});
this.replaceableComponents.add({
component: YourNewSidebarComponent,
key: eThemeLeptonXComponents.Breadcrumb,
});
///...
```
![Breadcrumb component](../../images/leptonxlite-breadcrumb-component.png)
![Breadcrumb component](../../images/leptonxlite-breadcrumb-component.png)
## Sidebar Menu Component
@ -163,54 +157,61 @@ Sidebar menus have been used as a **directory for Related Pages** to a **Service
```js
///...
this.replaceableComponents.add({
component: YourNewSidebarComponent,
key: eThemeLeptonXComponents.Sidebar,
});
this.replaceableComponents.add({
component: YourNewSidebarComponent,
key: eThemeLeptonXComponents.Sidebar,
});
///...
```
![Sidebar menu component](../../images/leptonxlite-sidebar-menu-component.png)
![Sidebar menu component](../../images/leptonxlite-sidebar-menu-component.png)
## Page Alerts Component
Provides contextual **feedback messages** for typical user actions with a handful of **available** and **flexible** **alert messages**. Alerts are available for any length of text, as well as an **optional dismiss button**.
![Page alerts component](../../images/leptonxlite-page-alerts-component.png)
![Page alerts component](../../images/leptonxlite-page-alerts-component.png)
```js
///...
this.replaceableComponents.add({
component: YourNewPageAlertContainerComponent,
key: eThemeLeptonXComponents.PageAlertContainer,
});
this.replaceableComponents.add({
component: YourNewPageAlertContainerComponent,
key: eThemeLeptonXComponents.PageAlertContainer,
});
///...
```
## Toolbar Component
![Breadcrumb component](../../images/leptonxlite-toolbar-component.png)
Toolbar items are used to add **extra functionality to the toolbar**. The toolbar is a **horizontal bar** that **contains** a group of **toolbar items**.
```js
///...
this.replaceableComponents.add({
component: YourNewNavItemsComponent,
key: eThemeLeptonXComponents.NavItems,
});
this.replaceableComponents.add({
component: YourNewNavItemsComponent,
key: eThemeLeptonXComponents.NavItems,
});
///...
```
## Toolbar Items
There are two parts to the toolbar. The first is Language-Switch. The second is the User-Profile element. You can swap out each of these parts individually.
## Language Switch Component
Think about a **multi-lingual** website and the first thing that could **hit your mind** is **the language switch component**. A **navigation bar** is a **great place** to **embed a language switch**. By embedding the language switch in the navigation bar of your website, you would **make it simpler** for users to **find it** and **easily** switch the **language** <u>**without trying to locate it across the website.**</u>
Think about a **multi-lingual** website and the first thing that could **hit your mind** is **the language switch component**. A **navigation bar** is a **great place** to **embed a language switch**. By embedding the language switch in the navigation bar of your website, you would **make it simpler** for users to **find it** and **easily** switch the **language** <u>**without trying to locate it across the website.**</u>
![Language switch component](../../images/leptonxlite-language-switch-component.png)
![Language switch component](../../images/leptonxlite-language-switch-component.png)
```js
///...
this.replaceableComponents.add({
component: YourNewLanguagesComponent,
key: eThemeLeptonXComponents.Languages,
});
this.replaceableComponents.add({
component: YourNewLanguagesComponent,
key: eThemeLeptonXComponents.Languages,
});
///...
```
@ -219,33 +220,84 @@ Think about a **multi-lingual** website and the first thing that could **hit you
The **User Menu** is the **menu** that **drops down** when you **click your name** or **profile picture** in the **upper right corner** of your page (**in the toolbar**). It drops down options such as **Settings**, **Logout**, etc.
![User menu component](../../images/leptonxlite-user-menu-component.png)
```js
///...
this.replaceableComponents.add({
component: YourNewCurrentUserComponent,
key: eThemeLeptonXComponents.CurrentUser,
});
this.replaceableComponents.add({
component: YourNewCurrentUserComponent,
key: eThemeLeptonXComponents.CurrentUser,
});
///...
```
Note: The language selection component in the Volo app is not replaceable. It is part of the settings menu.
## Mobile Navbar Component
The **mobile navbar component** is used to display the **navbar menu on mobile devices**. The mobile navbar component is a **dropdown menu** that contains language selection and user menu.
![Mobile user menu component](../../images/leptonxlite-mobile-user-menu-component.png)
![Mobile user menu component](../../images/leptonxlite-mobile-user-menu-component.png)
```js
///...
this.replaceableComponents.add({
component: YourNewMobileNavbarComponent,
key: eThemeLeptonXComponents.MobileNavbar,
});
this.replaceableComponents.add({
component: YourNewMobileNavbarComponent,
key: eThemeLeptonXComponents.MobileNavbar,
});
///...
```
## Mobile Navbar Items.
There are two parts of the mobile navbar. The mobile navbar has Language-Switch and User-Profile. You can swap out each of these parts individually.
There are two parts of the mobile navbar. The mobile navbar has Language-Switch and User-Profile. You can swap out each of these parts individually.
The Mobile language-Selection component key is `eThemeLeptonXComponents.MobileLanguageSelection`.
The Mobile User-Profile component key is `eThemeLeptonXComponents.MobileUserProfile`.
## Footer Component
![Angular Footer Component](../../images/angular-footer.png)
The Footer is the section of content at the very bottom of the site. This section of the content can be modified.
Inject **FooterLinksService** and use the **setFooterInfo** method of **FooterLinksService**
to assign path or link and description.
**descUrl** and **footerLinks** are nullable. Constant **footerLinks** are on the right side of footer.
```js
///...
const footerLinks = [
{
link: "/components/bootstrap/badge",
text: "Manage Your Profile",
},
{
link: "/components/bootstrap/border",
text: "My Security Logs",
},
];
const footerInfo: FooterNav = {
desc: "Home",
descUrl: "/components/home",
footerLinks: footerLinks,
};
this.footerLinksService.setFooterInfo(footerInfo);
///...
```
If you want to change the footer component, the key is `eThemeLeptonXComponents.Footer`
```js
///...
this.replaceableComponents.add({
component: YourNewFooterComponent,
key: eThemeLeptonXComponents.Footer,
});
///...
```

4
docs/en/UI/Angular/Chart-Component.md

@ -231,8 +231,8 @@ See the [`chart.js` samples](https://www.chartjs.org/docs/latest/samples) for mo
| `[type]` | Type of the chart. | `string` | null |
| `[data]` | Chart data to display | `any` | null |
| `[options]` | Chart options to customize | `any` | null |
| `[plugins]` | Chart plugins to customize behaviour | `any` | null |
| `[width]` | Witdh of the chart | `string` | null |
| `[plugins]` | Chart plugins to customize behavior | `any` | null |
| `[width]` | Width of the chart | `string` | null |
| `[height]` | Height of the chart | `string` | null |
| `[responsive]` | Whether the chart is responsive | `boolean` | true |
| `(dataSelect)` | A callback that executes when an element on the chart is clicked | `EventEmitter<any>` | - |

10
docs/en/UI/Angular/DateTime-Format-Pipe.md

@ -1,3 +1,4 @@
{%{
# DateTime Format Pipes
You can format date by Date pipe of angular.
@ -5,7 +6,7 @@ You can format date by Date pipe of angular.
Example
```html
<span> {{today | date 'dd/mm/yy'}}</span>
<span>{{today | date 'dd/mm/yy'}}</span>
```
ShortDate, ShortTime and ShortDateTime format data like angular's data pipe but easier. Also the pipes get format from config service by culture.
@ -13,17 +14,18 @@ ShortDate, ShortTime and ShortDateTime format data like angular's data pipe but
# ShortDate Pipe
```html
<span> {{today | shortDatePipe }}</span>
<span>{{today | shortDatePipe }}</span>
```
# ShortTime Pipe
```html
<span> {{today | shortTimePipe }}</span>
<span>{{today | shortTimePipe }}</span>
```
# ShortDateTime Pipe
```html
<span> {{today | shortDateTimePipe }}</span>
<span>{{today | shortDateTimePipe }}</span>
```
}%}

2
docs/en/UI/Angular/Dynamic-Form-Extensions.md

@ -7,7 +7,7 @@ Form prop extension system allows you to add a new field to the create and/or ed
<img alt="Form Prop Extension Example: 'Date of Birth' Field" src="./images/form-prop-extensions---birthday-field.gif" width="800px" style="max-width:100%">
You can validate the field, perform visibility checks, and do more. You will also have access to the current entity when creating a contibutor for an edit form.
You can validate the field, perform visibility checks, and do more. You will also have access to the current entity when creating a contributor for an edit form.
## How to Set Up

2
docs/en/UI/Angular/Loading-Strategy.md

@ -102,7 +102,7 @@ Sets given paremeters and `crossorigin="anonymous"` as attributes of created `<s
LOADING_STRATEGY.PrependAnonymousStyleToHead(href: string, integrity?: string)
```
Sets given paremeters and `crossorigin="anonymous"` as attributes of created `<style>` element and places it at the **beginning** of `<head>` tag in the document.
Sets given parameters and `crossorigin="anonymous"` as attributes of created `<style>` element and places it at the **beginning** of `<head>` tag in the document.
## See Also

6
docs/en/UI/AspNetCore/Client-Side-Package-Management.md

@ -18,7 +18,7 @@ To solve the versioning problem, we created a **standard set of packages** those
The benefit of a **standard package** is:
* It depends on a **standard version** of a package. Depending on this package is **safe** because all modules depend on the same version.
* It contains the mappings copy library resources (js, css, img... files) from the **node_modules** folder to **wwwroot/libs** folder. See the *Mapping The Library Resources* section for more.
* It contains the mappings copy library resources (js, css, img... files) from the `node_modules` folder to `wwwroot/libs` folder. See the *Mapping The Library Resources* section for more.
Depending on a standard package is easy. Just add it to your **package.json** file like you normally do. Example:
@ -57,7 +57,7 @@ See current standard packages for examples.
### Mapping The Library Resources
Using NPM packages and NPM/Yarn tool is the de facto standard for client side libraries. NPM/Yarn tool creates a **node_modules** folder in the root folder of your web project.
Using NPM packages and NPM/Yarn tool is the de facto standard for client side libraries. NPM/Yarn tool creates a **node_modules** folder in the root folder of your web project.
Next challenge is copying needed resources (js, css, img... files) from the `node_modules` into a folder inside the **wwwroot** folder to make it accessible to the clients/browsers.
@ -108,7 +108,7 @@ Once you properly configure the `abp.resourcemapping.js` file, you can run the f
abp install-libs
````
When you run this command, all packages will copy their own resources into the **wwwroot/libs** folder. Running `abp install-libs` is only necessary if you make a change in your dependencies in the **package.json** file.
When you run this command, all packages will copy their own resources into the `wwwroot/libs` folder. Running `abp install-libs` is only necessary if you make a change in your dependencies in the **package.json** file.
#### See Also

5
docs/en/UI/AspNetCore/JavaScript-API/DOM.md

@ -61,7 +61,7 @@ Script initializer (`abp.dom.initializers.initializeScript`) can execute a JavaS
Assume that you've a container to load the element inside:
````html
<div id="LazyComponent"></div>
<div id="LazyComponent"></div>
````
And this is the component that will be loaded via AJAX from the server and inserted into the container:
@ -113,5 +113,4 @@ The following Bootstrap components and libraries are automatically initialized w
* Tooltip
* Popover
* Timeage
* Timeago

BIN
docs/en/images/angular-footer.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

28
framework/Volo.Abp.sln

@ -409,6 +409,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.RemoteServices", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Mvc.PlugIn", "test\Volo.Abp.AspNetCore.Mvc.PlugIn\Volo.Abp.AspNetCore.Mvc.PlugIn.csproj", "{C6D6D878-208A-4FD2-822E-365545D8681B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Json.Newtonsoft", "src\Volo.Abp.Json.Newtonsoft\Volo.Abp.Json.Newtonsoft.csproj", "{9DD41C8F-0886-483C-B98B-C55EAA7F226D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Json.SystemTextJson", "src\Volo.Abp.Json.SystemTextJson\Volo.Abp.Json.SystemTextJson.csproj", "{0AD06E14-CBFE-4551-8D18-9E921D8F2A87}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Json.Abstractions", "src\Volo.Abp.Json.Abstractions\Volo.Abp.Json.Abstractions.csproj", "{08531C5D-0436-4721-986D-96446CF54316}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Mvc.NewtonsoftJson", "src\Volo.Abp.AspNetCore.Mvc.NewtonsoftJson\Volo.Abp.AspNetCore.Mvc.NewtonsoftJson.csproj", "{0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Dapr", "src\Volo.Abp.Dapr\Volo.Abp.Dapr.csproj", "{192A829F-D608-4E41-8DE0-058E943E453F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Dapr", "src\Volo.Abp.EventBus.Dapr\Volo.Abp.EventBus.Dapr.csproj", "{DCC41E99-EBC7-4F19-BA0D-A6F770D8E431}"
@ -1231,6 +1239,22 @@ Global
{C6D6D878-208A-4FD2-822E-365545D8681B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6D6D878-208A-4FD2-822E-365545D8681B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6D6D878-208A-4FD2-822E-365545D8681B}.Release|Any CPU.Build.0 = Release|Any CPU
{9DD41C8F-0886-483C-B98B-C55EAA7F226D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9DD41C8F-0886-483C-B98B-C55EAA7F226D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9DD41C8F-0886-483C-B98B-C55EAA7F226D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9DD41C8F-0886-483C-B98B-C55EAA7F226D}.Release|Any CPU.Build.0 = Release|Any CPU
{0AD06E14-CBFE-4551-8D18-9E921D8F2A87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0AD06E14-CBFE-4551-8D18-9E921D8F2A87}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0AD06E14-CBFE-4551-8D18-9E921D8F2A87}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0AD06E14-CBFE-4551-8D18-9E921D8F2A87}.Release|Any CPU.Build.0 = Release|Any CPU
{08531C5D-0436-4721-986D-96446CF54316}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{08531C5D-0436-4721-986D-96446CF54316}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08531C5D-0436-4721-986D-96446CF54316}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08531C5D-0436-4721-986D-96446CF54316}.Release|Any CPU.Build.0 = Release|Any CPU
{0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2}.Release|Any CPU.Build.0 = Release|Any CPU
{192A829F-D608-4E41-8DE0-058E943E453F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{192A829F-D608-4E41-8DE0-058E943E453F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{192A829F-D608-4E41-8DE0-058E943E453F}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -1461,6 +1485,10 @@ Global
{3683340D-92F5-4B14-B77B-34A163333309} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{EDFFDA74-090D-439C-A58D-06CCF86D4423} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{C6D6D878-208A-4FD2-822E-365545D8681B} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{9DD41C8F-0886-483C-B98B-C55EAA7F226D} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{0AD06E14-CBFE-4551-8D18-9E921D8F2A87} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{08531C5D-0436-4721-986D-96446CF54316} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{0CFC9D4F-F12F-4B44-ABCF-AB4A0E9E85B2} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{192A829F-D608-4E41-8DE0-058E943E453F} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{DCC41E99-EBC7-4F19-BA0D-A6F770D8E431} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{18B796D2-D45D-41AE-9A42-75C9B14B20DF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}

3
framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/FodyWeavers.xml

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

30
framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/FodyWeavers.xsd

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

29
framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson.csproj

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.NewtonsoftJson</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.NewtonsoftJson</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<IsPackable>true</IsPackable>
<OutputType>Library</OutputType>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc\Volo.Abp.AspNetCore.Mvc.csproj" />
<ProjectReference Include="..\Volo.Abp.Json.Newtonsoft\Volo.Abp.Json.Newtonsoft.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(MicrosoftAspNetCorePackageVersion)" />
</ItemGroup>
</Project>

21
framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs

@ -0,0 +1,21 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Json.Newtonsoft;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.NewtonsoftJson;
[DependsOn(typeof(AbpJsonNewtonsoftModule), typeof(AbpAspNetCoreMvcModule))]
public class AbpAspNetCoreMvcNewtonsoftModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMvcCore().AddNewtonsoftJson();
context.Services.AddOptions<MvcNewtonsoftJsonOptions>()
.Configure<AbpCamelCasePropertyNamesContractResolver>((options, contractResolver) =>
{
options.SerializerSettings.ContractResolver = contractResolver;
});
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js

@ -86,7 +86,7 @@
parentSelector = ".modal.fade";
}
var name = $(this).attr("name");
var selectedTextInputName = name.substring(0, name.length - 1) + "_Text]";
var selectedTextInputName = name + "_Text";
var selectedTextInput = $('<input>', {
type: 'hidden',
id: selectedTextInputName,

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

@ -29,7 +29,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
</ItemGroup>

6
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs

@ -38,6 +38,7 @@ using Volo.Abp.GlobalFeatures;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Http.ProxyScripting.Generators.JQuery;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.UI;
@ -52,7 +53,8 @@ namespace Volo.Abp.AspNetCore.Mvc;
typeof(AbpAspNetCoreMvcContractsModule),
typeof(AbpUiNavigationModule),
typeof(AbpGlobalFeaturesModule),
typeof(AbpDddApplicationModule)
typeof(AbpDddApplicationModule),
typeof(AbpJsonSystemTextJsonModule)
)]
public class AbpAspNetCoreMvcModule : AbpModule
{
@ -145,7 +147,7 @@ public class AbpAspNetCoreMvcModule : AbpModule
mvcCoreBuilder.AddAbpRazorRuntimeCompilation();
}
mvcCoreBuilder.AddAbpHybridJson();
mvcCoreBuilder.AddAbpJson();
context.Services.ExecutePreConfiguredActions(mvcBuilder);

11
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProviderOptions.cs

@ -62,19 +62,12 @@ public class AspNetCoreApiDescriptionModelProviderOptions
{
if (apiParameterDescription.ModelMetadata is DefaultModelMetadata defaultModelMetadata)
{
var jsonPropertyNameAttribute = (System.Text.Json.Serialization.JsonPropertyNameAttribute)
defaultModelMetadata?.Attributes?.PropertyAttributes?.FirstOrDefault(x => x is System.Text.Json.Serialization.JsonPropertyNameAttribute);
var jsonPropertyNameAttribute = (JsonPropertyNameAttribute)
defaultModelMetadata?.Attributes?.PropertyAttributes?.FirstOrDefault(x => x is JsonPropertyNameAttribute);
if (jsonPropertyNameAttribute != null)
{
return jsonPropertyNameAttribute.Name;
}
var jsonPropertyAttribute = (Newtonsoft.Json.JsonPropertyAttribute)
defaultModelMetadata?.Attributes?.PropertyAttributes?.FirstOrDefault(x => x is Newtonsoft.Json.JsonPropertyAttribute);
if (jsonPropertyAttribute != null)
{
return jsonPropertyAttribute.PropertyName;
}
}
return null;

45
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonInputFormatter.cs

@ -1,45 +0,0 @@
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Json.SystemTextJson;
namespace Volo.Abp.AspNetCore.Mvc.Json;
public class AbpHybridJsonInputFormatter : TextInputFormatter, IInputFormatterExceptionPolicy
{
private readonly SystemTextJsonInputFormatter _systemTextJsonInputFormatter;
private readonly NewtonsoftJsonInputFormatter _newtonsoftJsonInputFormatter;
public AbpHybridJsonInputFormatter(SystemTextJsonInputFormatter systemTextJsonInputFormatter, NewtonsoftJsonInputFormatter newtonsoftJsonInputFormatter)
{
_systemTextJsonInputFormatter = systemTextJsonInputFormatter;
_newtonsoftJsonInputFormatter = newtonsoftJsonInputFormatter;
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
SupportedEncodings.Add(UTF16EncodingLittleEndian);
SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationJson);
SupportedMediaTypes.Add(MediaTypeHeaderValues.TextJson);
SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationAnyJsonSyntax);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
{
return await GetTextInputFormatter(context).ReadRequestBodyAsync(context, encoding);
}
protected virtual TextInputFormatter GetTextInputFormatter(InputFormatterContext context)
{
var typesMatcher = context.HttpContext.RequestServices.GetRequiredService<AbpSystemTextJsonUnsupportedTypeMatcher>();
if (!typesMatcher.Match(context.ModelType))
{
return _systemTextJsonInputFormatter;
}
return _newtonsoftJsonInputFormatter;
}
public virtual InputFormatterExceptionPolicy ExceptionPolicy => InputFormatterExceptionPolicy.MalformedInputExceptions;
}

72
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOptionsSetup.cs

@ -1,72 +0,0 @@
using System.Buffers;
using System.Text.Encodings.Web;
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options;
namespace Volo.Abp.AspNetCore.Mvc.Json;
public class AbpHybridJsonOptionsSetup : IConfigureOptions<MvcOptions>
{
private readonly IOptions<JsonOptions> _jsonOptions;
private readonly IOptions<MvcNewtonsoftJsonOptions> _mvcNewtonsoftJsonOptions;
private readonly ILoggerFactory _loggerFactory;
private readonly ArrayPool<char> _charPool;
private readonly ObjectPoolProvider _objectPoolProvider;
public AbpHybridJsonOptionsSetup(
IOptions<JsonOptions> jsonOptions,
IOptions<MvcNewtonsoftJsonOptions> mvcNewtonsoftJsonOptions,
ILoggerFactory loggerFactory,
ArrayPool<char> charPool,
ObjectPoolProvider objectPoolProvider)
{
_jsonOptions = jsonOptions;
_mvcNewtonsoftJsonOptions = mvcNewtonsoftJsonOptions;
_loggerFactory = loggerFactory;
_charPool = charPool;
_objectPoolProvider = objectPoolProvider;
}
public void Configure(MvcOptions options)
{
var systemTextJsonInputFormatter = new SystemTextJsonInputFormatter(
_jsonOptions.Value,
_loggerFactory.CreateLogger<SystemTextJsonInputFormatter>());
var newtonsoftJsonInputFormatter = new NewtonsoftJsonInputFormatter(
_loggerFactory.CreateLogger<NewtonsoftJsonInputFormatter>(),
_mvcNewtonsoftJsonOptions.Value.SerializerSettings,
_charPool,
_objectPoolProvider,
options,
_mvcNewtonsoftJsonOptions.Value);
options.InputFormatters.RemoveType<SystemTextJsonInputFormatter>();
options.InputFormatters.RemoveType<NewtonsoftJsonInputFormatter>();
options.InputFormatters.Add(new AbpHybridJsonInputFormatter(systemTextJsonInputFormatter, newtonsoftJsonInputFormatter));
var jsonSerializerOptions = _jsonOptions.Value.JsonSerializerOptions;
if (jsonSerializerOptions.Encoder is null)
{
// If the user hasn't explicitly configured the encoder, use the less strict encoder that does not encode all non-ASCII characters.
jsonSerializerOptions = new JsonSerializerOptions(jsonSerializerOptions)
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};
}
var systemTextJsonOutputFormatter = new SystemTextJsonOutputFormatter(jsonSerializerOptions);
var newtonsoftJsonOutputFormatter = new NewtonsoftJsonOutputFormatter(
_mvcNewtonsoftJsonOptions.Value.SerializerSettings,
_charPool,
options);
options.OutputFormatters.RemoveType<SystemTextJsonOutputFormatter>();
options.OutputFormatters.RemoveType<NewtonsoftJsonOutputFormatter>();
options.OutputFormatters.Add(new AbpHybridJsonOutputFormatter(systemTextJsonOutputFormatter, newtonsoftJsonOutputFormatter));
}
}

42
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOutputFormatter.cs

@ -1,42 +0,0 @@
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Json.SystemTextJson;
namespace Volo.Abp.AspNetCore.Mvc.Json;
public class AbpHybridJsonOutputFormatter : TextOutputFormatter
{
private readonly SystemTextJsonOutputFormatter _systemTextJsonOutputFormatter;
private readonly NewtonsoftJsonOutputFormatter _newtonsoftJsonOutputFormatter;
public AbpHybridJsonOutputFormatter(SystemTextJsonOutputFormatter systemTextJsonOutputFormatter, NewtonsoftJsonOutputFormatter newtonsoftJsonOutputFormatter)
{
_systemTextJsonOutputFormatter = systemTextJsonOutputFormatter;
_newtonsoftJsonOutputFormatter = newtonsoftJsonOutputFormatter;
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationJson);
SupportedMediaTypes.Add(MediaTypeHeaderValues.TextJson);
SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationAnyJsonSyntax);
}
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
await GetTextInputFormatter(context).WriteResponseBodyAsync(context, selectedEncoding);
}
protected virtual TextOutputFormatter GetTextInputFormatter(OutputFormatterWriteContext context)
{
var typesMatcher = context.HttpContext.RequestServices.GetRequiredService<AbpSystemTextJsonUnsupportedTypeMatcher>();
if (!typesMatcher.Match(context.ObjectType))
{
return _systemTextJsonOutputFormatter;
}
return _newtonsoftJsonOutputFormatter;
}
}

33
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs

@ -1,33 +0,0 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
namespace Volo.Abp.AspNetCore.Mvc.Json;
public class AbpJsonOptionsSetup : IConfigureOptions<JsonOptions>
{
protected IServiceProvider ServiceProvider { get; }
public AbpJsonOptionsSetup(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public void Configure(JsonOptions options)
{
options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;
options.JsonSerializerOptions.AllowTrailingCommas = true;
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpDateTimeConverter>());
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpNullableDateTimeConverter>());
options.JsonSerializerOptions.Converters.Add(new AbpStringToEnumFactory());
options.JsonSerializerOptions.Converters.Add(new AbpStringToBooleanConverter());
options.JsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter());
}
}

48
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs

@ -1,48 +0,0 @@
using System;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json.Newtonsoft;
using Volo.Abp.Reflection;
using Volo.Abp.Timing;
namespace Volo.Abp.AspNetCore.Mvc.Json;
public class AbpMvcJsonContractResolver : DefaultContractResolver, ITransientDependency
{
private readonly Lazy<AbpJsonIsoDateTimeConverter> _dateTimeConverter;
public AbpMvcJsonContractResolver(IServiceProvider serviceProvider)
{
_dateTimeConverter = new Lazy<AbpJsonIsoDateTimeConverter>(
serviceProvider.GetRequiredService<AbpJsonIsoDateTimeConverter>,
true
);
NamingStrategy = new CamelCaseNamingStrategy();
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
ModifyProperty(member, property);
return property;
}
protected virtual void ModifyProperty(MemberInfo member, JsonProperty property)
{
if (property.PropertyType != typeof(DateTime) && property.PropertyType != typeof(DateTime?))
{
return;
}
if (ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault<DisableDateTimeNormalizationAttribute>(member) == null)
{
property.Converter = _dateTimeConverter.Value;
}
}
}

21
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcNewtonsoftJsonOptionsSetup.cs

@ -1,21 +0,0 @@
using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Volo.Abp.AspNetCore.Mvc.Json;
public class AbpMvcNewtonsoftJsonOptionsSetup : IConfigureOptions<MvcNewtonsoftJsonOptions>
{
protected IServiceProvider ServiceProvider { get; }
public AbpMvcNewtonsoftJsonOptionsSetup(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public void Configure(MvcNewtonsoftJsonOptions options)
{
options.SerializerSettings.ContractResolver = ServiceProvider.GetRequiredService<AbpMvcJsonContractResolver>();
}
}

21
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MediaTypeHeaderValues.cs

@ -1,21 +0,0 @@
using Microsoft.Net.Http.Headers;
namespace Volo.Abp.AspNetCore.Mvc.Json;
/// <summary>
/// https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.NewtonsoftJson/src/MediaTypeHeaderValues.cs
/// </summary>
internal static class MediaTypeHeaderValues
{
public static readonly MediaTypeHeaderValue ApplicationJson = MediaTypeHeaderValue.Parse("application/json").CopyAsReadOnly();
public static readonly MediaTypeHeaderValue TextJson = MediaTypeHeaderValue.Parse("text/json").CopyAsReadOnly();
public static readonly MediaTypeHeaderValue ApplicationAnyJsonSyntax = MediaTypeHeaderValue.Parse("application/*+json").CopyAsReadOnly();
public static readonly MediaTypeHeaderValue ApplicationXml = MediaTypeHeaderValue.Parse("application/xml").CopyAsReadOnly();
public static readonly MediaTypeHeaderValue TextXml = MediaTypeHeaderValue.Parse("text/xml").CopyAsReadOnly();
public static readonly MediaTypeHeaderValue ApplicationAnyXmlSyntax = MediaTypeHeaderValue.Parse("application/*+xml").CopyAsReadOnly();
}

35
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs

@ -1,28 +1,31 @@
using Microsoft.AspNetCore.Mvc;
using System;
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.ObjectPool;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
namespace Volo.Abp.AspNetCore.Mvc.Json;
public static class MvcCoreBuilderExtensions
{
public static IMvcCoreBuilder AddAbpHybridJson(this IMvcCoreBuilder builder)
public static IMvcCoreBuilder AddAbpJson(this IMvcCoreBuilder builder)
{
var abpJsonOptions = builder.Services.ExecutePreConfiguredActions<AbpJsonOptions>();
if (!abpJsonOptions.UseHybridSerializer)
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Transient<IConfigureOptions<MvcNewtonsoftJsonOptions>, AbpMvcNewtonsoftJsonOptionsSetup>());
builder.AddNewtonsoftJson();
return builder;
}
builder.Services.AddOptions<JsonOptions>()
.Configure<IServiceProvider>((options, serviceProvider) =>
{
options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;
options.JsonSerializerOptions.AllowTrailingCommas = true;
options.JsonSerializerOptions.Converters.Add(new AbpStringToEnumFactory());
options.JsonSerializerOptions.Converters.Add(new AbpStringToBooleanConverter());
options.JsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter());
options.JsonSerializerOptions.TypeInfoResolver = new AbpDefaultJsonTypeInfoResolver(serviceProvider
.GetRequiredService<IOptions<AbpSystemTextJsonSerializerModifiersOptions>>());
});
builder.Services.TryAddTransient<DefaultObjectPoolProvider>();
builder.Services.TryAddEnumerable(ServiceDescriptor.Transient<IConfigureOptions<JsonOptions>, AbpJsonOptionsSetup>());
builder.Services.TryAddEnumerable(ServiceDescriptor.Transient<IConfigureOptions<MvcNewtonsoftJsonOptions>, AbpMvcNewtonsoftJsonOptionsSetup>());
builder.Services.TryAddEnumerable(ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, AbpHybridJsonOptionsSetup>());
return builder;
}
}

2
framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs

@ -40,7 +40,7 @@ public abstract class AbpAspNetCoreIntegratedTestBase<TStartup> : AbpTestBaseWit
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<TStartup>();
webBuilder.UseTestServer();
webBuilder.UseAbpTestServer();
})
.UseAutofac()
.ConfigureServices(ConfigureServices);

18
framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpNoopHostLifetime.cs

@ -0,0 +1,18 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
namespace Volo.Abp.AspNetCore.TestBase;
public class AbpNoopHostLifetime : IHostLifetime
{
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public Task WaitForStartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}

19
framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/WebHostBuilderExtensions.cs

@ -0,0 +1,19 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Volo.Abp.AspNetCore.TestBase;
public static class AbpWebHostBuilderExtensions
{
public static IWebHostBuilder UseAbpTestServer(this IWebHostBuilder builder)
{
return builder.ConfigureServices(services =>
{
services.AddScoped<IHostLifetime, AbpNoopHostLifetime>();
services.AddScoped<IServer, TestServer>();
});
}
}

42
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs

@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace Volo.Abp.Auditing;
public class AuditingContractResolver : CamelCasePropertyNamesContractResolver
{
private readonly List<Type> _ignoredTypes;
public AuditingContractResolver(List<Type> ignoredTypes)
{
_ignoredTypes = ignoredTypes;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (_ignoredTypes.Any(ignoredType => ignoredType.GetTypeInfo().IsAssignableFrom(property.PropertyType)))
{
property.ShouldSerialize = instance => false;
return property;
}
if (member.DeclaringType != null && (member.DeclaringType.IsDefined(typeof(DisableAuditingAttribute)) || member.DeclaringType.IsDefined(typeof(JsonIgnoreAttribute))))
{
property.ShouldSerialize = instance => false;
return property;
}
if (member.IsDefined(typeof(DisableAuditingAttribute)) || member.IsDefined(typeof(JsonIgnoreAttribute)))
{
property.ShouldSerialize = instance => false;
}
return property;
}
}

77
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonAuditSerializer.cs

@ -0,0 +1,77 @@
using System.Collections.Concurrent;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Auditing;
public class JsonAuditSerializer : IAuditSerializer, ITransientDependency
{
protected AbpAuditingOptions Options;
public JsonAuditSerializer(IOptions<AbpAuditingOptions> options)
{
Options = options.Value;
}
public string Serialize(object obj)
{
return JsonSerializer.Serialize(obj, CreateJsonSerializerOptions());
}
private static readonly ConcurrentDictionary<string, JsonSerializerOptions> JsonSerializerOptionsCache =
new ConcurrentDictionary<string, JsonSerializerOptions>();
protected virtual JsonSerializerOptions CreateJsonSerializerOptions()
{
return JsonSerializerOptionsCache.GetOrAdd(nameof(JsonAuditSerializer), _ =>
{
var settings = new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
{
Modifiers =
{
jsonTypeInfo =>
{
if (Options.IgnoredTypes.Any(ignoredType => ignoredType.IsAssignableFrom(jsonTypeInfo.Type)) ||
jsonTypeInfo.Type.GetCustomAttributes(typeof(DisableAuditingAttribute), false).Any())
{
if (jsonTypeInfo.Kind == JsonTypeInfoKind.Object)
{
jsonTypeInfo.Properties.Clear();
}
}
foreach (var property in jsonTypeInfo.Properties)
{
if (Options.IgnoredTypes.Any(ignoredType => ignoredType.IsAssignableFrom(property.PropertyType)))
{
property.ShouldSerialize = (_, _) => false;
}
if (property.AttributeProvider != null &&
property.AttributeProvider.GetCustomAttributes(typeof(DisableAuditingAttribute), false).Any())
{
property.ShouldSerialize = (_, _) => false;
}
if (property.PropertyType.DeclaringType != null &&
property.PropertyType.DeclaringType.IsDefined(typeof(DisableAuditingAttribute)))
{
property.ShouldSerialize = (_, _) => false;
}
}
}
}
}
};
return settings;
});
}
}

43
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs

@ -1,43 +0,0 @@
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Auditing;
//TODO: Rename to JsonAuditSerializer
public class JsonNetAuditSerializer : IAuditSerializer, ITransientDependency
{
protected AbpAuditingOptions Options;
public JsonNetAuditSerializer(IOptions<AbpAuditingOptions> options)
{
Options = options.Value;
}
public string Serialize(object obj)
{
return JsonConvert.SerializeObject(obj, GetSharedJsonSerializerSettings());
}
private static readonly object SyncObj = new object();
private static JsonSerializerSettings _sharedJsonSerializerSettings;
private JsonSerializerSettings GetSharedJsonSerializerSettings()
{
if (_sharedJsonSerializerSettings == null)
{
lock (SyncObj)
{
if (_sharedJsonSerializerSettings == null)
{
_sharedJsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new AuditingContractResolver(Options.IgnoredTypes)
};
}
}
}
return _sharedJsonSerializerSettings;
}
}

1
framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj

@ -30,5 +30,6 @@
<ProjectReference Include="..\Volo.Abp.Http\Volo.Abp.Http.csproj" />
<ProjectReference Include="..\Volo.Abp.IdentityModel\Volo.Abp.IdentityModel.csproj" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs

@ -2,17 +2,14 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.LIbs;
using Volo.Abp.Cli.ServiceProxying;
using Volo.Abp.Cli.ServiceProxying.Angular;
using Volo.Abp.Cli.ServiceProxying.CSharp;
using Volo.Abp.Cli.ServiceProxying.JavaScript;
using Volo.Abp.Domain;
using Volo.Abp.Http;
using Volo.Abp.Http.ProxyScripting.Generators.JQuery;
using Volo.Abp.IdentityModel;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Minify;
using Volo.Abp.Modularity;
@ -34,11 +31,6 @@ public class AbpCliCoreModule : AbpModule
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Configure<AbpSystemTextJsonSerializerOptions>(options =>
{
options.UnsupportedTypes.Add(typeof(ResourceMapping));
});
Configure<AbpCliOptions>(options =>
{
options.Commands[HelpCommand.Name] = typeof(HelpCommand);

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs

@ -7,6 +7,7 @@ using Microsoft.Extensions.FileSystemGlobbing;
using Microsoft.Extensions.FileSystemGlobbing.Abstractions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Newtonsoft.Json;
using NuGet.Versioning;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
@ -30,12 +31,9 @@ public class InstallLibsService : IInstallLibsService, ITransientDependency
public ILogger<InstallLibsService> Logger { get; set; }
private readonly IJsonSerializer _jsonSerializer;
public InstallLibsService(IJsonSerializer jsonSerializer, NpmHelper npmHelper)
public InstallLibsService(NpmHelper npmHelper)
{
NpmHelper = npmHelper;
_jsonSerializer = jsonSerializer;
}
public async Task InstallLibsAsync(string directory)
@ -119,7 +117,7 @@ public class InstallLibsService : IInstallLibsService, ITransientDependency
{
return false;
}
using (var reader = File.OpenText(file))
{
return reader.ReadToEnd().Contains("Microsoft.NET.Sdk.Web");
@ -145,7 +143,8 @@ public class InstallLibsService : IInstallLibsService, ITransientDependency
{
var mappingFileContent = await reader.ReadToEndAsync();
var mapping = _jsonSerializer.Deserialize<ResourceMapping>(mappingFileContent
// System.Text.Json doesn't support the property name without quotes.
var mapping = Newtonsoft.Json.JsonConvert.DeserializeObject<ResourceMapping>(mappingFileContent
.Replace("module.exports", string.Empty)
.Replace("=", string.Empty).Trim().TrimEnd(';'));

143
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs

@ -31,9 +31,9 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
protected void ChangeToBasicTheme(ProjectBuildContext context)
{
var defaultThemeName = context.BuildArgs.TemplateName is AppTemplate.TemplateName or AppNoLayersTemplate.TemplateName
? "LeptonXLite"
? "LeptonXLite"
: "LeptonX";
#region MVC Projects
ChangeThemeToBasicForMvcProjects(context, defaultThemeName);
@ -41,14 +41,14 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
#endregion
#region MyCompanyName.MyProjectName.Blazor
ReplacePackageReferenceWithProjectReference(
context,
"/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj",
$"Volo.Abp.AspNetCore.Components.WebAssembly.{defaultThemeName}Theme",
@"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj"
);
ChangeNamespaceAndKeyword(
context,
"/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs",
@ -58,31 +58,40 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
"AbpAspNetCoreComponentsWebAssemblyBasicThemeModule"
);
ChangeNamespaceAndKeyword(
context,
"/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs",
$"Volo.Abp.AspNetCore.Components.Web.{defaultThemeName}Theme.Themes.{defaultThemeName}",
"Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic",
$"AbpAspNetCoreComponentsWebAssembly{defaultThemeName}ThemeModule",
"AbpAspNetCoreComponentsWebAssemblyBasicThemeModule"
);
ChangeNamespace(
context,
"/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs",
$"Volo.Abp.AspNetCore.Components.Web.{defaultThemeName}Theme.Components",
"Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic"
);
#endregion
#region Blazor.Server Projects
ChangeThemeToBasicForBlazorProjects(context, defaultThemeName);
#endregion
#region Angular
var angularPackageName = context.BuildArgs.TemplateName is AppTemplate.TemplateName or AppNoLayersTemplate.TemplateName
? "@abp/ng.theme.lepton-x"
? "@abp/ng.theme.lepton-x"
: "@volosoft/abp.ng.theme.lepton-x";
ReplaceImportPackage(
context,
context,
"/angular/src/app/app.module.ts",
angularPackageName,
angularPackageName,
"@abp/ng.theme.basic"
);
@ -98,7 +107,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
"ThemeLeptonXModule",
"ThemeBasicModule"
);
RemoveLinesByStatement(
context,
"/angular/angular.json",
@ -113,7 +122,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
"HttpErrorComponent, ",
""
);
ChangeModuleImportBetweenStatements(
context,
"/angular/src/app/app.module.ts",
@ -128,11 +137,11 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
protected void ChangeToLeptonTheme(ProjectBuildContext context)
{
#region Common
#region Common
RenameLeptonXFolders(context, folderName: "Lepton");
AddLeptonThemeManagementReferenceToProjects(context);
#endregion
#region MVC Projects
@ -140,16 +149,16 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
ChangeThemeToLeptonForMvcProjects(context);
#endregion
#region MyCompanyName.MyProjectName.Blazor
ReplacePackageReferenceWithProjectReference(
context,
"/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj",
"Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXTheme",
@"..\..\..\..\..\lepton-theme\src\Volo.Abp.AspNetCore.Components.WebAssembly.LeptonTheme\Volo.Abp.AspNetCore.Components.WebAssembly.LeptonTheme.csproj"
);
ChangeNamespaceAndKeyword(
context,
"/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs",
@ -168,7 +177,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
#endregion
#region MyCompanyName.MyProjectName.Blazor.Server && MyCompanyName.MyProjectName.Blazor.Server.Tiered
#region MyCompanyName.MyProjectName.Blazor.Server && MyCompanyName.MyProjectName.Blazor.Server.Tiered
ChangeThemeToLeptonForBlazorServerProjects(context);
@ -177,9 +186,9 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
#region Angular
ReplaceImportPackage(
context,
context,
"/angular/src/app/app.module.ts",
"@volosoft/abp.ng.theme.lepton-x",
"@volosoft/abp.ng.theme.lepton-x",
"@volo/abp.ng.theme.lepton"
);
@ -195,7 +204,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
"ThemeLeptonXModule",
"ThemeLeptonModule"
);
RemoveLinesByStatement(
context,
"/angular/angular.json",
@ -214,7 +223,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
#region MyCompanyName.MyProjectName.Blazor.Server && MyCompanyName.MyProjectName.Blazor.Server.Mongo - (app-nolayers)
ChangeThemeToLeptonForNoLayersBlazorServerProjects(context);
#endregion
}
@ -233,7 +242,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
{
continue;
}
AddProjectReference(file, $@"..\..\..\..\lepton-theme\src\Volo.Abp.LeptonTheme.Management.{projectName}\Volo.Abp.LeptonTheme.Management.{projectName}.csproj");
AddModuleDependency(moduleFile, projectName, $"LeptonThemeManagement{ConvertProjectNameToModuleName($"{projectName}")}Module");
}
@ -241,12 +250,12 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
private void ChangeThemeToLeptonForMvcProjects(ProjectBuildContext context)
{
var projectNames = new[]
var projectNames = new[]
{
".Web", ".HttpApi.Host", ".AuthServer",
".Web", ".HttpApi.Host", ".AuthServer",
"" //for app-nolayers-mvc
};
foreach (var projectName in projectNames)
{
var projectPath = $"/MyCompanyName.MyProjectName{projectName}/MyCompanyName.MyProjectName{projectName}.csproj";
@ -255,20 +264,20 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
{
continue;
}
var moduleFile = ConvertProjectFileToModuleFile(context, projectFile);
if (moduleFile == null)
{
continue;
}
ReplacePackageReferenceWithProjectReference(
context,
projectFile.Name,
"Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX",
@"..\..\..\..\..\lepton-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton\Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.csproj"
);
ChangeNamespaceAndKeyword(
context,
moduleFile.Name,
@ -277,7 +286,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
"LeptonXThemeBundles.Styles.Global",
"LeptonThemeBundles.Styles.Global"
);
ChangeNamespaceAndKeyword(
context,
moduleFile.Name,
@ -286,7 +295,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
"AbpAspNetCoreMvcUiLeptonXThemeModule",
"AbpAspNetCoreMvcUiLeptonThemeModule"
);
RemoveLinesByStatement(
context,
moduleFile.Name,
@ -294,10 +303,10 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
);
}
}
private void AddLeptonThemeManagementReferenceToProjects(ProjectBuildContext context)
{
var projects = new Dictionary<string, string>
var projects = new Dictionary<string, string>
{
{"Domain", "MyCompanyName.MyProjectName.Domain.csproj"},
{"Domain.Shared", "MyCompanyName.MyProjectName.Domain.Shared.csproj"},
@ -306,9 +315,9 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
{"HttpApi", "MyCompanyName.MyProjectName.HttpApi.csproj"},
{"HttpApi.Client", "MyCompanyName.MyProjectName.HttpApi.Client.csproj"}
};
AddUiProjectToProjects(projects, context);
foreach (var project in projects)
{
AddLeptonThemeManagementReference(context, project);
@ -324,7 +333,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
{"HttpApi.Client", "MyCompanyName.MyProjectName.AdministrationService.HttpApi.Client.csproj"},
{"Web", "MyCompanyName.MyProjectName.AdministrationService.Web.csproj"}
};
foreach (var microserviceServiceProject in microserviceServiceProjects)
{
AddLeptonThemeManagementReference(context, microserviceServiceProject);
@ -337,7 +346,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
{
return;
}
switch (context.BuildArgs.UiFramework)
{
case UiFramework.Mvc:
@ -352,8 +361,8 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
break;
}
}
private void AddLeptonThemeManagementReference(ProjectBuildContext context, KeyValuePair<string, string> projectInfo)
private void AddLeptonThemeManagementReference(ProjectBuildContext context, KeyValuePair<string, string> projectInfo)
{
var reference = $@"..\..\..\..\..\lepton-theme\src\Volo.Abp.LeptonTheme.Management.{projectInfo.Key}\Volo.Abp.LeptonTheme.Management.{projectInfo.Key}.csproj";
var projectFile = context.Files.FirstOrDefault(f => !f.Name.Contains("Test") && f.Name.Contains(projectInfo.Value) && f.Name.Contains(".csproj"));
@ -367,7 +376,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
{
return;
}
AddProjectReference(projectFile, reference);
AddModuleDependency(moduleFile, projectInfo.Key, $"LeptonThemeManagement{ConvertProjectNameToModuleName(projectInfo.Key)}Module",
@ -391,12 +400,12 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
lines[i - 2] = lines[i - 2] + "," + Environment.NewLine + $"\ttypeof({dependency})";
}
}
moduleFile.SetLines(lines);
}
protected void ReplacePackageReferenceWithProjectReference(
ProjectBuildContext context,
protected void ReplacePackageReferenceWithProjectReference(
ProjectBuildContext context,
string targetProjectFilePath,
string packageReference,
string projectReference)
@ -406,16 +415,16 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
{
return;
}
file.NormalizeLineEndings();
var lines = file.GetLines();
var lineIndex = lines.FindIndex(line => line.Contains("PackageReference") && line.Contains(packageReference));
if (lineIndex == -1)
{
return;
}
lines[lineIndex] = lines[lineIndex].Replace(lines[lineIndex], $"\t<ProjectReference Include=\"{projectReference}\" />");
file.SetLines(lines);
}
@ -498,13 +507,13 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
{
return;
}
lines[lineIndex] = lines[lineIndex].Replace(oldImportPackage, newImportPackage);
file.SetLines(lines);
}
protected void RemoveLinesByStatement(
ProjectBuildContext context,
ProjectBuildContext context,
string filePath,
string statement)
{
@ -515,7 +524,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
}
file.NormalizeLineEndings();
var lines = file.GetLines();
for (var i = 0; i < lines.Length; i++)
{
@ -529,7 +538,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
}
private void ChangeModuleImportBetweenStatements(
ProjectBuildContext context,
ProjectBuildContext context,
string filePath,
string firstStatement,
string lastStatement,
@ -542,7 +551,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
}
file.NormalizeLineEndings();
var lines = file.GetLines();
var firstLineIndex = lines.FindIndex(line => line.Contains(firstStatement));
var lastLineIndex = lines.FindIndex(line => line.Contains(lastStatement));
@ -551,7 +560,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
{
return;
}
lines[firstLineIndex] = newStatement;
for (var i = firstLineIndex + 1; i <= lastLineIndex; i++)
@ -564,7 +573,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
}
protected void ReplaceMethodNames(
ProjectBuildContext context,
ProjectBuildContext context,
string filePath,
string oldMethodName,
string newMethodName)
@ -576,7 +585,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
}
file.NormalizeLineEndings();
var lines = file.GetLines();
for (var i = 0; i < lines.Length; i++)
{
@ -585,17 +594,17 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
lines[i] = lines[i].Replace(oldMethodName, newMethodName);
}
}
file.SetLines(lines);
}
private static void AddProjectReference(FileEntry file, string reference)
{
if (!file.Name.Contains(".csproj"))
{
return;
}
var doc = new XmlDocument() { PreserveWhitespace = true };
using (var stream = StreamHelper.GenerateStreamFromString(file.Content))
{
@ -647,19 +656,19 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
file.SetContent(doc.OuterXml);
}
}
private static FileEntry ConvertProjectFileToModuleFile(ProjectBuildContext context, FileEntry projectFile)
{
var splittedProjectFileName = projectFile.Name.RemovePostFix("/").Split("/");
splittedProjectFileName = splittedProjectFileName.Take(splittedProjectFileName.Length - 1).ToArray();
var fileName = splittedProjectFileName?.Last();
if (fileName == null)
{
return null;
}
fileName = fileName
.Replace("MyCompanyName.", "")
.Replace(".csproj", "Module")
@ -667,12 +676,12 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
return context.Files.FirstOrDefault(f => f.Name.Contains(splittedProjectFileName.Last() + "/" + fileName) && f.Name.EndsWith("Module.cs"));
}
private static string ConvertProjectNameToModuleName(string moduleName)
{
return moduleName.Replace(".", "");
}
private static void RenameLeptonXFolders(ProjectBuildContext context, string folderName)
{
var leptonXFiles = context.Files.Where(x => x.Name.Contains("LeptonX") && x.IsDirectory);
@ -700,7 +709,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
$"Volo.Abp.AspNetCore.Mvc.UI.Theme.{defaultThemeName}",
@"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj"
);
ChangeNamespaceAndKeyword(
context,
$"/MyCompanyName.MyProjectName{project.Key}/{project.Value}.cs",
@ -720,7 +729,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
);
}
}
private void ChangeThemeToBasicForBlazorProjects(ProjectBuildContext context, string defaultThemeName)
{
var projects = new Dictionary<string, string>
@ -964,4 +973,4 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
);
}
}
}
}

18
framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Configuration/AbpApiProxyScriptingConfiguration.cs

@ -10,22 +10,6 @@ public static class AbpApiProxyScriptingConfiguration
static AbpApiProxyScriptingConfiguration()
{
PropertyNameGenerator = propertyInfo =>
{
var jsonPropertyNameAttribute = propertyInfo.GetSingleAttributeOrNull<System.Text.Json.Serialization.JsonPropertyNameAttribute>(true);
if (jsonPropertyNameAttribute != null)
{
return jsonPropertyNameAttribute.Name;
}
var jsonPropertyAttribute = propertyInfo.GetSingleAttributeOrNull<Newtonsoft.Json.JsonPropertyAttribute>(true);
if (jsonPropertyAttribute != null)
{
return jsonPropertyAttribute.PropertyName;
}
return null;
};
propertyInfo.GetSingleAttributeOrNull<System.Text.Json.Serialization.JsonPropertyNameAttribute>()?.Name;
}
}

3
framework/src/Volo.Abp.Json.Abstractions/FodyWeavers.xml

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

30
framework/src/Volo.Abp.Json.Abstractions/FodyWeavers.xsd

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

20
framework/src/Volo.Abp.Json.Abstractions/Volo.Abp.Json.Abstractions.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>Volo.Abp.Json.Abstractions</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>
</Project>

8
framework/src/Volo.Abp.Json.Abstractions/Volo/Abp/Json/AbpJsonAbstractionsModule.cs

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

21
framework/src/Volo.Abp.Json.Abstractions/Volo/Abp/Json/AbpJsonOptions.cs

@ -0,0 +1,21 @@
using System.Collections.Generic;
namespace Volo.Abp.Json;
public class AbpJsonOptions
{
/// <summary>
/// Formats of input JSON date, Empty string means default format.
/// </summary>
public List<string> InputDateTimeFormats { get; set; }
/// <summary>
/// Format of output json date, Null or empty string means default format.
/// </summary>
public string OutputDateTimeFormat { get; set; }
public AbpJsonOptions()
{
InputDateTimeFormats = new List<string>();
}
}

0
framework/src/Volo.Abp.Json/Volo/Abp/Json/IJsonSerializer.cs → framework/src/Volo.Abp.Json.Abstractions/Volo/Abp/Json/IJsonSerializer.cs

3
framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml

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

30
framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd

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

23
framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Json.Newtonsoft</AssemblyName>
<PackageId>Volo.Abp.Json.Newtonsoft</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.Json.Abstractions\Volo.Abp.Json.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>

38
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpCamelCasePropertyNamesContractResolver.cs

@ -0,0 +1,38 @@
using System;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Json.Newtonsoft;
public class AbpCamelCasePropertyNamesContractResolver : CamelCasePropertyNamesContractResolver, ITransientDependency
{
private readonly Lazy<AbpDateTimeConverter> _dateTimeConverter;
public AbpCamelCasePropertyNamesContractResolver(IServiceProvider serviceProvider)
{
_dateTimeConverter = new Lazy<AbpDateTimeConverter>(
serviceProvider.GetRequiredService<AbpDateTimeConverter>,
true
);
NamingStrategy = new CamelCaseNamingStrategy
{
ProcessDictionaryKeys = false
};
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (AbpDateTimeConverter.ShouldNormalize(member, property))
{
property.Converter = _dateTimeConverter.Value;
}
return property;
}
}

116
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs

@ -0,0 +1,116 @@
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Volo.Abp.Reflection;
using Volo.Abp.Timing;
namespace Volo.Abp.Json.Newtonsoft;
public class AbpDateTimeConverter : DateTimeConverterBase
{
private readonly string _dateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
private readonly DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind;
private readonly CultureInfo _culture = CultureInfo.InvariantCulture;
private readonly IClock _clock;
private readonly AbpJsonOptions _options;
public AbpDateTimeConverter(IClock clock, IOptions<AbpJsonOptions> options)
{
_clock = clock;
_options = options.Value;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime) || objectType == typeof(DateTime?);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var nullable = Nullable.GetUnderlyingType(objectType) != null;
if (reader.TokenType == JsonToken.Null)
{
if (!nullable)
{
throw new JsonSerializationException($"Cannot convert null value to {objectType.FullName}.");
}
return null;
}
if (reader.TokenType == JsonToken.Date)
{
return _clock.Normalize(reader.Value.To<DateTime>());
}
if (reader.TokenType != JsonToken.String)
{
throw new JsonSerializationException($"Unexpected token parsing date. Expected String, got {reader.TokenType}.");
}
var dateText = reader.Value?.ToString();
if (dateText.IsNullOrEmpty() && nullable)
{
return null;
}
if (_options.InputDateTimeFormats.Any())
{
foreach (var format in _options.InputDateTimeFormats)
{
if (DateTime.TryParseExact(dateText, format, _culture, _dateTimeStyles, out var d1))
{
return _clock.Normalize(d1);
}
}
}
var date = !_dateTimeFormat.IsNullOrEmpty() ?
DateTime.ParseExact(dateText, _dateTimeFormat, _culture, _dateTimeStyles) :
DateTime.Parse(dateText, _culture, _dateTimeStyles);
return _clock.Normalize(date);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value != null)
{
value = _clock.Normalize(value.To<DateTime>());
}
if (value is DateTime dateTime)
{
if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal ||
(_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
{
dateTime = dateTime.ToUniversalTime();
}
writer.WriteValue(_options.OutputDateTimeFormat.IsNullOrWhiteSpace()
? dateTime.ToString(_dateTimeFormat, _culture)
: dateTime.ToString(_options.OutputDateTimeFormat, _culture));
}
else
{
throw new JsonSerializationException($"Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {value.GetType()}.");
}
}
internal static bool ShouldNormalize(MemberInfo member, JsonProperty property)
{
if (property.PropertyType != typeof(DateTime) &&
property.PropertyType != typeof(DateTime?))
{
return false;
}
return ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault<DisableDateTimeNormalizationAttribute>(member) == null;
}
}

33
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDefaultContractResolver.cs

@ -0,0 +1,33 @@
using System;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Json.Newtonsoft;
public class AbpDefaultContractResolver : DefaultContractResolver, ITransientDependency
{
private readonly Lazy<AbpDateTimeConverter> _dateTimeConverter;
public AbpDefaultContractResolver(IServiceProvider serviceProvider)
{
_dateTimeConverter = new Lazy<AbpDateTimeConverter>(
serviceProvider.GetRequiredService<AbpDateTimeConverter>,
true
);
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (AbpDateTimeConverter.ShouldNormalize(member, property))
{
property.Converter = _dateTimeConverter.Value;
}
return property;
}
}

18
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs

@ -0,0 +1,18 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.Timing;
namespace Volo.Abp.Json.Newtonsoft;
[DependsOn(typeof(AbpJsonAbstractionsModule), typeof(AbpTimingModule))]
public class AbpJsonNewtonsoftModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddOptions<AbpNewtonsoftJsonSerializerOptions>()
.Configure<AbpCamelCasePropertyNamesContractResolver>((options, contractResolver) =>
{
options.JsonSerializerSettings.ContractResolver = contractResolver;
});
}
}

96
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs

@ -0,0 +1,96 @@
using System;
using System.Collections.Concurrent;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Json.Newtonsoft;
[Dependency(ReplaceServices = true)]
public class AbpNewtonsoftJsonSerializer : IJsonSerializer, ITransientDependency
{
protected IServiceProvider ServiceProvider { get; }
protected IOptions<AbpNewtonsoftJsonSerializerOptions> Options { get; }
public AbpNewtonsoftJsonSerializer(IServiceProvider serviceProvider, IOptions<AbpNewtonsoftJsonSerializerOptions> options)
{
ServiceProvider = serviceProvider;
Options = options;
}
public string Serialize(object obj, bool camelCase = true, bool indented = false)
{
return JsonConvert.SerializeObject(obj, CreateJsonSerializerOptions(camelCase, indented));
}
public T Deserialize<T>(string jsonString, bool camelCase = true)
{
return JsonConvert.DeserializeObject<T>(jsonString, CreateJsonSerializerOptions(camelCase));
}
public object Deserialize(Type type, string jsonString, bool camelCase = true)
{
return JsonConvert.DeserializeObject(jsonString, type, CreateJsonSerializerOptions(camelCase));
}
private static readonly ConcurrentDictionary<object, JsonSerializerSettings> JsonSerializerOptionsCache =
new ConcurrentDictionary<object, JsonSerializerSettings>();
protected virtual JsonSerializerSettings CreateJsonSerializerOptions(bool camelCase = true, bool indented = false)
{
return JsonSerializerOptionsCache.GetOrAdd(new
{
camelCase,
indented
}, _ =>
{
var settings = new JsonSerializerSettings
{
Binder = Options.Value.JsonSerializerSettings.Binder,
CheckAdditionalContent = Options.Value.JsonSerializerSettings.CheckAdditionalContent,
Context = Options.Value.JsonSerializerSettings.Context,
ContractResolver = Options.Value.JsonSerializerSettings.ContractResolver,
ConstructorHandling = Options.Value.JsonSerializerSettings.ConstructorHandling,
Converters = Options.Value.JsonSerializerSettings.Converters,
Culture = Options.Value.JsonSerializerSettings.Culture,
DateFormatHandling = Options.Value.JsonSerializerSettings.DateFormatHandling,
DateFormatString = Options.Value.JsonSerializerSettings.DateFormatString,
DateParseHandling = Options.Value.JsonSerializerSettings.DateParseHandling,
DateTimeZoneHandling = Options.Value.JsonSerializerSettings.DateTimeZoneHandling,
DefaultValueHandling = Options.Value.JsonSerializerSettings.DefaultValueHandling,
Error = Options.Value.JsonSerializerSettings.Error,
EqualityComparer = Options.Value.JsonSerializerSettings.EqualityComparer,
FloatFormatHandling = Options.Value.JsonSerializerSettings.FloatFormatHandling,
FloatParseHandling = Options.Value.JsonSerializerSettings.FloatParseHandling,
Formatting = Options.Value.JsonSerializerSettings.Formatting,
MaxDepth = Options.Value.JsonSerializerSettings.MaxDepth,
MetadataPropertyHandling = Options.Value.JsonSerializerSettings.MetadataPropertyHandling,
MissingMemberHandling = Options.Value.JsonSerializerSettings.MissingMemberHandling,
NullValueHandling = Options.Value.JsonSerializerSettings.NullValueHandling,
ObjectCreationHandling = Options.Value.JsonSerializerSettings.ObjectCreationHandling,
PreserveReferencesHandling = Options.Value.JsonSerializerSettings.PreserveReferencesHandling,
ReferenceLoopHandling = Options.Value.JsonSerializerSettings.ReferenceLoopHandling,
ReferenceResolver = Options.Value.JsonSerializerSettings.ReferenceResolver,
ReferenceResolverProvider = Options.Value.JsonSerializerSettings.ReferenceResolverProvider,
SerializationBinder = Options.Value.JsonSerializerSettings.SerializationBinder,
StringEscapeHandling = Options.Value.JsonSerializerSettings.StringEscapeHandling,
TraceWriter = Options.Value.JsonSerializerSettings.TraceWriter,
TypeNameAssemblyFormat = Options.Value.JsonSerializerSettings.TypeNameAssemblyFormat,
TypeNameHandling = Options.Value.JsonSerializerSettings.TypeNameHandling,
TypeNameAssemblyFormatHandling = Options.Value.JsonSerializerSettings.TypeNameAssemblyFormatHandling
};
settings.ContractResolver = camelCase
? ServiceProvider.GetRequiredService<AbpCamelCasePropertyNamesContractResolver>()
: ServiceProvider.GetRequiredService<AbpDefaultContractResolver>();
if (indented)
{
settings.Formatting = Formatting.Indented;
}
return settings;
});
}
}

5
framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs → framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs

@ -1,14 +1,13 @@
using Newtonsoft.Json;
using Volo.Abp.Collections;
namespace Volo.Abp.Json.Newtonsoft;
public class AbpNewtonsoftJsonSerializerOptions
{
public ITypeList<JsonConverter> Converters { get; }
public JsonSerializerSettings JsonSerializerSettings { get; }
public AbpNewtonsoftJsonSerializerOptions()
{
Converters = new TypeList<JsonConverter>();
JsonSerializerSettings = new JsonSerializerSettings();
}
}

3
framework/src/Volo.Abp.Json.SystemTextJson/FodyWeavers.xml

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

30
framework/src/Volo.Abp.Json.SystemTextJson/FodyWeavers.xsd

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

23
framework/src/Volo.Abp.Json.SystemTextJson/Volo.Abp.Json.SystemTextJson.csproj

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Json.SystemTextJson</AssemblyName>
<PackageId>Volo.Abp.Json.SystemTextJson</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.Json.Abstractions\Volo.Abp.Json.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />
<PackageReference Include="System.Text.Json" Version="$(MicrosoftAspNetCorePackageVersion)" />
</ItemGroup>
</Project>

16
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpDefaultJsonTypeInfoResolver.cs

@ -0,0 +1,16 @@
using System.Text.Json.Serialization.Metadata;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Json.SystemTextJson;
public class AbpDefaultJsonTypeInfoResolver : DefaultJsonTypeInfoResolver, ITransientDependency
{
public AbpDefaultJsonTypeInfoResolver(IOptions<AbpSystemTextJsonSerializerModifiersOptions> options)
{
foreach (var modifier in options.Value.Modifiers)
{
Modifiers.Add(modifier);
}
}
}

37
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs

@ -0,0 +1,37 @@
using System;
using System.Text.Encodings.Web;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
using Volo.Abp.Json.SystemTextJson.Modifiers;
using Volo.Abp.Modularity;
using Volo.Abp.Timing;
namespace Volo.Abp.Json.SystemTextJson;
[DependsOn(typeof(AbpJsonAbstractionsModule), typeof(AbpTimingModule))]
public class AbpJsonSystemTextJsonModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddOptions<AbpSystemTextJsonSerializerOptions>()
.Configure<IServiceProvider>((options, serviceProvider) =>
{
// If the user hasn't explicitly configured the encoder, use the less strict encoder that does not encode all non-ASCII characters.
options.JsonSerializerOptions.Encoder ??= JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
options.JsonSerializerOptions.Converters.Add(new AbpStringToEnumFactory());
options.JsonSerializerOptions.Converters.Add(new AbpStringToBooleanConverter());
options.JsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter());
options.JsonSerializerOptions.TypeInfoResolver = new AbpDefaultJsonTypeInfoResolver(serviceProvider
.GetRequiredService<IOptions<AbpSystemTextJsonSerializerModifiersOptions>>());
});
context.Services.AddOptions<AbpSystemTextJsonSerializerModifiersOptions>()
.Configure<IServiceProvider>((options, serviceProvider) =>
{
options.Modifiers.Add(new AbpDateTimeConverterModifier().CreateModifyAction(serviceProvider));
});
}
}

17
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerProvider.cs → framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializer.cs

@ -6,25 +6,15 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Json.SystemTextJson;
public class AbpSystemTextJsonSerializerProvider : IJsonSerializerProvider, ITransientDependency
public class AbpSystemTextJsonSerializer : IJsonSerializer, ITransientDependency
{
protected AbpSystemTextJsonSerializerOptions Options { get; }
protected AbpSystemTextJsonUnsupportedTypeMatcher AbpSystemTextJsonUnsupportedTypeMatcher { get; }
public AbpSystemTextJsonSerializerProvider(
IOptions<AbpSystemTextJsonSerializerOptions> options,
AbpSystemTextJsonUnsupportedTypeMatcher abpSystemTextJsonUnsupportedTypeMatcher)
public AbpSystemTextJsonSerializer(IOptions<AbpSystemTextJsonSerializerOptions> options)
{
AbpSystemTextJsonUnsupportedTypeMatcher = abpSystemTextJsonUnsupportedTypeMatcher;
Options = options.Value;
}
public bool CanHandle(Type type)
{
return !AbpSystemTextJsonUnsupportedTypeMatcher.Match(type);
}
public string Serialize(object obj, bool camelCase = true, bool indented = false)
{
return JsonSerializer.Serialize(obj, CreateJsonSerializerOptions(camelCase, indented));
@ -40,7 +30,8 @@ public class AbpSystemTextJsonSerializerProvider : IJsonSerializerProvider, ITra
return JsonSerializer.Deserialize(jsonString, type, CreateJsonSerializerOptions(camelCase));
}
private readonly static ConcurrentDictionary<object, JsonSerializerOptions> JsonSerializerOptionsCache = new ConcurrentDictionary<object, JsonSerializerOptions>();
private static readonly ConcurrentDictionary<object, JsonSerializerOptions> JsonSerializerOptionsCache =
new ConcurrentDictionary<object, JsonSerializerOptions>();
protected virtual JsonSerializerOptions CreateJsonSerializerOptions(bool camelCase = true, bool indented = false)
{

20
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerModifiersOptions.cs

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization.Metadata;
using Volo.Abp.Json.SystemTextJson.Modifiers;
namespace Volo.Abp.Json.SystemTextJson;
public class AbpSystemTextJsonSerializerModifiersOptions
{
public List<Action<JsonTypeInfo>> Modifiers { get; }
public AbpSystemTextJsonSerializerModifiersOptions()
{
Modifiers = new List<Action<JsonTypeInfo>>
{
AbpIncludeExtraPropertiesModifiers.Modify,
};
}
}

4
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptions.cs → framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptions.cs

@ -7,8 +7,6 @@ public class AbpSystemTextJsonSerializerOptions
{
public JsonSerializerOptions JsonSerializerOptions { get; }
public ITypeList UnsupportedTypes { get; }
public AbpSystemTextJsonSerializerOptions()
{
JsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web)
@ -16,7 +14,5 @@ public class AbpSystemTextJsonSerializerOptions
ReadCommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true
};
UnsupportedTypes = new TypeList();
}
}

28
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs → framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs

@ -1,5 +1,6 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Options;
@ -21,25 +22,28 @@ public class AbpDateTimeConverter : JsonConverter<DateTime>, ITransientDependenc
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (!_options.DefaultDateTimeFormat.IsNullOrWhiteSpace())
if (_options.InputDateTimeFormats.Any())
{
if (reader.TokenType == JsonTokenType.String)
{
var s = reader.GetString();
if (DateTime.TryParseExact(s, _options.DefaultDateTimeFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1))
foreach (var format in _options.InputDateTimeFormats)
{
return _clock.Normalize(d1);
var s = reader.GetString();
if (DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1))
{
return _clock.Normalize(d1);
}
}
throw new JsonException($"'{s}' can't parse to DateTime({_options.DefaultDateTimeFormat})!");
}
throw new JsonException("Reader's TokenType is not String!");
else
{
throw new JsonException("Reader's TokenType is not String!");
}
}
if (reader.TryGetDateTime(out var d2))
if (reader.TryGetDateTime(out var d3))
{
return _clock.Normalize(d2);
return _clock.Normalize(d3);
}
throw new JsonException("Can't get datetime from the reader!");
@ -47,13 +51,13 @@ public class AbpDateTimeConverter : JsonConverter<DateTime>, ITransientDependenc
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
if (_options.DefaultDateTimeFormat.IsNullOrWhiteSpace())
if (_options.OutputDateTimeFormat.IsNullOrWhiteSpace())
{
writer.WriteStringValue(_clock.Normalize(value));
}
else
{
writer.WriteStringValue(_clock.Normalize(value).ToString(_options.DefaultDateTimeFormat, CultureInfo.CurrentUICulture));
writer.WriteStringValue(_clock.Normalize(value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture));
}
}
}

24
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs → framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs

@ -1,5 +1,6 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Options;
@ -21,20 +22,23 @@ public class AbpNullableDateTimeConverter : JsonConverter<DateTime?>, ITransient
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (!_options.DefaultDateTimeFormat.IsNullOrWhiteSpace())
if (_options.InputDateTimeFormats.Any())
{
if (reader.TokenType == JsonTokenType.String)
{
var s = reader.GetString();
if (DateTime.TryParseExact(s, _options.DefaultDateTimeFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1))
foreach (var format in _options.InputDateTimeFormats)
{
return _clock.Normalize(d1);
var s = reader.GetString();
if (DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1))
{
return _clock.Normalize(d1);
}
}
throw new JsonException($"'{s}' can't parse to DateTime({_options.DefaultDateTimeFormat})!");
}
throw new JsonException("Reader's TokenType is not String!");
else
{
throw new JsonException("Reader's TokenType is not String!");
}
}
if (reader.TryGetDateTime(out var d2))
@ -53,13 +57,13 @@ public class AbpNullableDateTimeConverter : JsonConverter<DateTime?>, ITransient
}
else
{
if (_options.DefaultDateTimeFormat.IsNullOrWhiteSpace())
if (_options.OutputDateTimeFormat.IsNullOrWhiteSpace())
{
writer.WriteStringValue(_clock.Normalize(value.Value));
}
else
{
writer.WriteStringValue(_clock.Normalize(value.Value).ToString(_options.DefaultDateTimeFormat, CultureInfo.CurrentUICulture));
writer.WriteStringValue(_clock.Normalize(value.Value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture));
}
}
}

0
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToBooleanConverter.cs → framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToBooleanConverter.cs

0
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs → framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs

0
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumFactory.cs → framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumFactory.cs

0
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs → framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs

39
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpDateTimeConverterModifier.cs

@ -0,0 +1,39 @@
using System;
using System.Linq;
using System.Text.Json.Serialization.Metadata;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
using Volo.Abp.Reflection;
using Volo.Abp.Timing;
namespace Volo.Abp.Json.SystemTextJson.Modifiers;
public class AbpDateTimeConverterModifier
{
private IServiceProvider _serviceProvider;
public Action<JsonTypeInfo> CreateModifyAction(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
return Modify;
}
private void Modify(JsonTypeInfo jsonTypeInfo)
{
if (ReflectionHelper.GetAttributesOfMemberOrDeclaringType<DisableDateTimeNormalizationAttribute>(jsonTypeInfo.Type).Any())
{
return;
}
foreach (var property in jsonTypeInfo.Properties.Where(x => x.PropertyType == typeof(DateTime) || x.PropertyType == typeof(DateTime?)))
{
if (property.AttributeProvider == null ||
!property.AttributeProvider.GetCustomAttributes(typeof(DisableDateTimeNormalizationAttribute), false).Any())
{
property.CustomConverter = property.PropertyType == typeof(DateTime)
? _serviceProvider.GetRequiredService<AbpDateTimeConverter>()
: _serviceProvider.GetRequiredService<AbpNullableDateTimeConverter>();
}
}
}
}

29
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIgnorePropertiesModifiers.cs

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.Json.Serialization.Metadata;
namespace Volo.Abp.Json.SystemTextJson.Modifiers;
public class AbpIgnorePropertiesModifiers<TClass, TProperty>
where TClass : class
{
private Expression<Func<TClass, TProperty>> _propertySelector;
public Action<JsonTypeInfo> CreateModifyAction(Expression<Func<TClass, TProperty>> propertySelector)
{
_propertySelector = propertySelector;
return Modify;
}
public void Modify(JsonTypeInfo jsonTypeInfo)
{
if (jsonTypeInfo.Type == typeof(TClass))
{
jsonTypeInfo.Properties.RemoveAll(
x => x.AttributeProvider is MemberInfo memberInfo &&
memberInfo.Name == _propertySelector.Body.As<MemberExpression>().Member.Name);
}
}
}

32
framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIncludeExtraPropertiesModifiers.cs

@ -0,0 +1,32 @@
using System;
using System.Linq;
using System.Reflection;
using System.Text.Json.Serialization.Metadata;
using Volo.Abp.Data;
using Volo.Abp.ObjectExtending;
namespace Volo.Abp.Json.SystemTextJson.Modifiers;
public static class AbpIncludeExtraPropertiesModifiers
{
public static void Modify(JsonTypeInfo jsonTypeInfo)
{
if (typeof(IHasExtraProperties).IsAssignableFrom(jsonTypeInfo.Type))
{
var propertyJsonInfo = jsonTypeInfo.Properties
.Where(x => x.AttributeProvider is MemberInfo)
.FirstOrDefault(x =>
x.PropertyType == typeof(ExtraPropertyDictionary) &&
x.AttributeProvider.As<MemberInfo>().Name == nameof(ExtensibleObject.ExtraProperties) &&
x.Set == null);
if (propertyJsonInfo != null)
{
propertyJsonInfo.Set = (obj, value) =>
{
ObjectHelper.TrySetProperty(obj.As<IHasExtraProperties>(), x => x.ExtraProperties, () => value);
};
}
}
}
}

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

Loading…
Cancel
Save