Browse Source

Merge branch 'dev' into liangshiwei/swagger

pull/16574/head
Galip Tolga Erdem 3 years ago
parent
commit
00d32078e7
  1. 14
      .github/scripts/update_versions.py
  2. 16
      .github/workflows/auto-pr.yml
  3. 44
      .github/workflows/publish-release.yml
  4. 2
      .github/workflows/update-versions.yml
  5. 6
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  6. 8
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
  7. 61
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  8. 6
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
  9. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json
  10. 12
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
  11. 2
      common.props
  12. 4
      configureawait.props
  13. 2
      delete-bin-obj.ps1
  14. 45
      docs/en/API/Auto-API-Controllers.md
  15. 17
      docs/en/API/Dynamic-CSharp-API-Clients.md
  16. 27
      docs/en/API/Swagger-Integration.md
  17. 6
      docs/en/Application-Startup.md
  18. 23
      docs/en/Autofac-Integration.md
  19. 8
      docs/en/Background-Jobs-Hangfire.md
  20. 2
      docs/en/Background-Jobs-Quartz.md
  21. 267
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/POST.md
  22. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/abp-conf.png
  23. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/community-talks-2023-4.png
  24. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/cover-image.png
  25. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-conference.png
  26. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-talk.png
  27. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/leptonx-account-layout.png
  28. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/reset-authenticator.png
  29. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-1.png
  30. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-2.png
  31. BIN
      docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-3.png
  32. 4
      docs/en/CLI-New-Command-Samples.md
  33. 15
      docs/en/CLI.md
  34. BIN
      docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/01-microservice-solution.png
  35. BIN
      docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/02-run-single-service.png
  36. BIN
      docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/03-tye-yaml-file.png
  37. BIN
      docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/04-tye-dashboard.png
  38. BIN
      docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/05-example-microservice-solution.png
  39. BIN
      docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/06-abp-studio-kubernetes-tunnel-how-it-works.png
  40. 226
      docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/POST.md
  41. 2
      docs/en/Contribution/How-to-Contribute-abp.io-as-a-frontend-developer.md
  42. 45
      docs/en/Distributed-Event-Bus.md
  43. 19
      docs/en/Entity-Framework-Core.md
  44. 8
      docs/en/Getting-Started-AspNetCore-Application.md
  45. 41
      docs/en/Getting-Started-React-Native.md
  46. 380
      docs/en/Image-Manipulation.md
  47. 33
      docs/en/KB/Windows-Path-Too-Long-Fix.md
  48. 27
      docs/en/Local-Event-Bus.md
  49. 8
      docs/en/Localization.md
  50. 28
      docs/en/Migration-Guides/Abp-7_3.md
  51. 1
      docs/en/Migration-Guides/Index.md
  52. 8
      docs/en/Migration-Guides/docs/en/Migration-Guides/Abp-7_4.md
  53. 6
      docs/en/Modules/Cms-Kit/Blogging.md
  54. 63
      docs/en/Modules/Cms-Kit/Index.md
  55. 8
      docs/en/Modules/Virtual-File-Explorer.md
  56. 6
      docs/en/MongoDB.md
  57. 8
      docs/en/PlugIn-Modules.md
  58. 6
      docs/en/Repositories.md
  59. 8
      docs/en/Road-Map.md
  60. 2
      docs/en/SMS-Sending.md
  61. 2
      docs/en/SignalR-Integration.md
  62. 13
      docs/en/Startup-Templates/Application.md
  63. 2
      docs/en/Text-Templating-Razor.md
  64. 2
      docs/en/UI/Angular/Authorization.md
  65. 41
      docs/en/UI/AspNetCore/Bundling-Minification.md
  66. 56
      docs/en/UI/AspNetCore/Security-Headers.md
  67. 4
      docs/en/UI/AspNetCore/Tag-Helpers/Dropdowns.md
  68. 8
      docs/en/docs-nav.json
  69. BIN
      docs/en/images/layered-project-dependencies-blazor-server.png
  70. BIN
      docs/en/images/layered-project-dependencies-blazor-wasm.png
  71. 2
      docs/zh-Hans/CLI.md
  72. 2
      docs/zh-Hans/Deployment/Clustered-Environment.md
  73. 2
      docs/zh-Hans/Deployment/Index.md
  74. 2
      docs/zh-Hans/docs-nav.json
  75. 63
      framework/Volo.Abp.sln
  76. 4
      framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj
  77. 78
      framework/src/Volo.Abp.AspNetCore.Components.Server/Microsoft/AspNetCore/Authentication/Cookies/CookieAuthenticationOptionsExtensions.cs
  78. 7
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/StandardLayouts.cs
  79. 13
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/AbpThemingOptions.cs
  80. 34
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/DefaultThemeManager.cs
  81. 36
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/DefaultThemeSelector.cs
  82. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/ITheme.cs
  83. 6
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/IThemeManager.cs
  84. 6
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/IThemeSelector.cs
  85. 23
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/ThemeDictionary.cs
  86. 27
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/ThemeExtensions.cs
  87. 24
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/ThemeInfo.cs
  88. 23
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/ThemeNameAttribute.cs
  89. 1
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj
  90. 2
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs
  91. 40
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ClientProxyExceptionEventHandler.cs
  92. 1
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Extensibility/WebAssemblyLookupApiRequestService.cs
  93. 1
      framework/src/Volo.Abp.AspNetCore.Components/Volo.Abp.AspNetCore.Components.csproj
  94. 4
      framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpAspNetCoreComponentsModule.cs
  95. 29
      framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs
  96. 22
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelper.cs
  97. 22
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs
  98. 39
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelperService.cs
  99. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelperService.cs
  100. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperScriptService.cs

14
.github/scripts/update_versions.py

@ -39,14 +39,16 @@ def create_pr():
branch=branch_name, branch=branch_name,
) )
pr = repo.create_pull(title="Update latest-versions.json", try:
body="Automated PR to update the latest-versions.json file.", pr = repo.create_pull(title="Update latest-versions.json",
head=branch_name, base="dev") body="Automated PR to update the latest-versions.json file.",
head=branch_name, base="dev")
except Exception as e:
print(f"Error while creating PR: {e}")
pr.create_review_request(reviewers=["ebicoglu", "gizemmutukurt", "skoc10"]) pr.create_review_request(reviewers=["gizemmutukurt"])
if __name__ == "__dev__": if __name__ == "__main__":
should_create_pr = update_latest_versions() should_create_pr = update_latest_versions()
if should_create_pr: if should_create_pr:
create_pr() create_pr()

16
.github/workflows/auto-pr.yml

@ -1,8 +1,8 @@
name: Merge branch dev with rel-7.2 name: Merge branch dev with rel-7.3
on: on:
push: push:
branches: branches:
- rel-7.2 - rel-7.3
permissions: permissions:
contents: read contents: read
@ -18,13 +18,13 @@ jobs:
ref: dev ref: dev
- name: Reset promotion branch - name: Reset promotion branch
run: | run: |
git fetch origin rel-7.2:rel-7.2 git fetch origin rel-7.3:rel-7.3
git reset --hard rel-7.2 git reset --hard rel-7.3
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v3 uses: peter-evans/create-pull-request@v3
with: with:
branch: auto-merge/rel-7-2/${{github.run_number}} branch: auto-merge/rel-7-3/${{github.run_number}}
title: Merge branch dev with rel-7.2 title: Merge branch dev with rel-7.3
body: This PR generated automatically to merge dev with rel-7.2. Please review the changed files before merging to prevent any errors that may occur. body: This PR generated automatically to merge dev with rel-7.3. Please review the changed files before merging to prevent any errors that may occur.
reviewers: ${{github.actor}} reviewers: ${{github.actor}}
token: ${{ github.token }} token: ${{ github.token }}

44
.github/workflows/publish-release.yml

@ -0,0 +1,44 @@
name: Create Release
on:
workflow_dispatch:
inputs:
tag_name:
description: 'Tag Name'
required: true
prerelease:
description: 'Pre-release?'
required: true
branchName:
description: 'Branch Name'
required: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.branchName }}
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
with:
tag_name: ${{ github.event.inputs.tag_name }}
release_name: ${{ github.event.inputs.tag_name }}
draft: false
prerelease: ${{ github.event.inputs.prerelease }}
- name: Checkout code at tag
uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.tag_name }}
- name: Build Project
run: |
# add your build commands here, depending on your project's requirements.
echo "Build project here"

2
.github/workflows/update-versions.yml

@ -28,6 +28,6 @@ jobs:
- name: Update latest-versions.json and create PR - name: Update latest-versions.json and create PR
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: | run: |
python .github/scripts/update_versions.py python .github/scripts/update_versions.py

6
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json

@ -460,6 +460,10 @@
"ReloadFromSourceConfirmationMessage": "This post will be refreshed from \"{0}\". Do you want to continue?", "ReloadFromSourceConfirmationMessage": "This post will be refreshed from \"{0}\". Do you want to continue?",
"UnitPrice": "Unit Price", "UnitPrice": "Unit Price",
"OverallDiscountAmount": "Overall Discount Amount", "OverallDiscountAmount": "Overall Discount Amount",
"DiscountAmount": "Discount Amount" "DiscountAmount": "Discount Amount",
"FullChangeHistory": "Full Change History",
"Permission:RefreshReleaseLogs": "Refresh Release Logs",
"ReleaseLogs": "Release Logs",
"AuthorUserName": "Author User Name"
} }
} }

8
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json

@ -70,7 +70,7 @@
"MeetTheABP": "Meet the ABP", "MeetTheABP": "Meet the ABP",
"CompleteWebDevelopment": "A Complete Web Development", "CompleteWebDevelopment": "A Complete Web Development",
"Platform": "Platform", "Platform": "Platform",
"ABPDescription": "ABP Framework is a complete infrastructure to create modern web applications by following the software development best practices and conventions.", "ABPDescription": "An open-source framework for web application development for ASP.NET Core. It offers complete infrastructure by following the best practices of software development.",
"StrongInfrastructure": "Strong Infrastructure", "StrongInfrastructure": "Strong Infrastructure",
"CompleteArchitecture": "Complete Architecture", "CompleteArchitecture": "Complete Architecture",
"DeveloperFocused": "Developer Focused", "DeveloperFocused": "Developer Focused",
@ -211,6 +211,10 @@
"RecentActivities": "Recent Activities", "RecentActivities": "Recent Activities",
"SpringCampaign": "Welcome <br>Spring Sale!", "SpringCampaign": "Welcome <br>Spring Sale!",
"SpringCampaign2": "<span>Limited <br> Time Offer!</span>", "SpringCampaign2": "<span>Limited <br> Time Offer!</span>",
"AboutUs": "About Us" "AboutUs": "About Us",
"HowItWorks": "How it works?",
"ReleaseNotes": "Release Notes",
"DetailedChangeNotes" : "Detailed Change Notes",
"SeeTrainings": "See Trainings"
} }
} }

61
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json

@ -161,7 +161,7 @@
"WhatIsTheABPCommercial": "What is ABP Commercial?", "WhatIsTheABPCommercial": "What is ABP Commercial?",
"WhatAreDifferencesThanAbpFramework": "What are the differences between the open source ABP Framework and ABP Commercial?", "WhatAreDifferencesThanAbpFramework": "What are the differences between the open source ABP Framework and ABP Commercial?",
"AbpCommercialMetaTitle": " {0} | ABP Commercial", "AbpCommercialMetaTitle": " {0} | ABP Commercial",
"AbpCommercialMetaDescription": "ABP Commercial is a set of pre-built application modules, rapid development tooling, UI themes and services built on top of the open-source ABP framework.", "AbpCommercialMetaDescription": "A comprehensive web development platform on ABP Framework with pre-built modules, startup templates, rapid dev tools, pro UI themes & premium support.",
"ABPCommercialExplanation": "ABP Commercial is a set of premium modules, tools, themes and services that are built on top of the open source <a target=\"_blank\" href=\"{0}\">ABP framework</a>. ABP Commercial is being developed and supported by the same team behind the ABP framework.", "ABPCommercialExplanation": "ABP Commercial is a set of premium modules, tools, themes and services that are built on top of the open source <a target=\"_blank\" href=\"{0}\">ABP framework</a>. ABP Commercial is being developed and supported by the same team behind the ABP framework.",
"WhatAreDifferencesThanABPFrameworkExplanation": "<p> <a target=\"_blank\" href=\"{0}\">ABP framework</a> is a modular, themeable, microservice compatible application development framework for ASP.NET Core. It provides a complete architecture and a strong infrastructure to let you focus on your own business code rather than repeating yourself for every new project. It is based on the best practices of software development and popular tools you already know. </p> <p> ABP framework is completely free, open source and community-driven. It also provides a free theme and some pre-built modules (e.g. identity management and tenant management).</p>", "WhatAreDifferencesThanABPFrameworkExplanation": "<p> <a target=\"_blank\" href=\"{0}\">ABP framework</a> is a modular, themeable, microservice compatible application development framework for ASP.NET Core. It provides a complete architecture and a strong infrastructure to let you focus on your own business code rather than repeating yourself for every new project. It is based on the best practices of software development and popular tools you already know. </p> <p> ABP framework is completely free, open source and community-driven. It also provides a free theme and some pre-built modules (e.g. identity management and tenant management).</p>",
"VisitTheFrameworkVSCommercialDocument": "Visit the following link for more information <a href=\"{0}\" target=\"_blank\"> {1} </a>", "VisitTheFrameworkVSCommercialDocument": "Visit the following link for more information <a href=\"{0}\" target=\"_blank\"> {1} </a>",
@ -208,7 +208,7 @@
"WhenShouldIRenewMyLicense": "When should I renew my license?", "WhenShouldIRenewMyLicense": "When should I renew my license?",
"WhenShouldIRenewMyLicenseExplanation": "If you renew your license within <strong>{3} days</strong> after your license expires, the following discounts will be applied: Team License {0}; Business License {1}; Enterprise License {2}. However, if you renew your license after <strong>{3} days</strong> since the expiry date of your license, the renewal price will be the same as the license purchase price and there will be no discount on your renewal.", "WhenShouldIRenewMyLicenseExplanation": "If you renew your license within <strong>{3} days</strong> after your license expires, the following discounts will be applied: Team License {0}; Business License {1}; Enterprise License {2}. However, if you renew your license after <strong>{3} days</strong> since the expiry date of your license, the renewal price will be the same as the license purchase price and there will be no discount on your renewal.",
"TrialPlan": "Do you have a trial plan?", "TrialPlan": "Do you have a trial plan?",
"TrialPlanExplanation": "No, there is no trial version for ABP Commercial. You can check the community edition to understand the code quality and approaches. We also offer a 30-day money-back guarantee for the Team license, no questions asked! You can request a refund within the first 30 days. We provide a 60% refund within 30 days for Business and Enterprise licenses. This is because the Business and Enterprise licenses contain the full source-code of all the modules and themes.", "TrialPlanExplanation": "Yes, to start your free trial contact <a href=\"mailto:marketing@abp.io\">marketing@abp.io</a>. We also offer a 30-day money-back guarantee for the Team license, no questions asked! You can request a full refund within the first 30 days of the license purchase. We provide a 60% refund within 30 days for Business and Enterprise licenses. This is because the Business and Enterprise licenses contain the full source-code of all the modules and themes.",
"DoYouAcceptBankWireTransfer": "Do you accept bank wire transfers?", "DoYouAcceptBankWireTransfer": "Do you accept bank wire transfers?",
"DoYouAcceptBankWireTransferExplanation": "Yes, we accept bank wire transfers.<br/>After sending the license fee via bank transfer, send your receipt and requested license type to accounting@volosoft.com.<br/>Our international bank account information:", "DoYouAcceptBankWireTransferExplanation": "Yes, we accept bank wire transfers.<br/>After sending the license fee via bank transfer, send your receipt and requested license type to accounting@volosoft.com.<br/>Our international bank account information:",
"HowToUpgrade": "How to upgrade existing applications when a new version is available?", "HowToUpgrade": "How to upgrade existing applications when a new version is available?",
@ -231,7 +231,7 @@
"ComputerLimitation": "How many computers can a developer login when developing ABP?", "ComputerLimitation": "How many computers can a developer login when developing ABP?",
"ComputerLimitationExplanation": "We specifically permit <strong>{0} computers</strong> per individual/licensed developer. Whenever there is a need for a developer to develop ABP Commercial products on a third machine, an e-mail should be sent to license@abp.io explaining the situation and we will then make the appropriate allocation in our system.", "ComputerLimitationExplanation": "We specifically permit <strong>{0} computers</strong> per individual/licensed developer. Whenever there is a need for a developer to develop ABP Commercial products on a third machine, an e-mail should be sent to license@abp.io explaining the situation and we will then make the appropriate allocation in our system.",
"RefundPolicy": "Do you have a refund policy?", "RefundPolicy": "Do you have a refund policy?",
"RefundPolicyExplanation": "You can request a refund within <strong>30 days</strong> of your license purchase. The Business and Enterprise license types have source-code download option, therefore refunds are not available for the Business and Enterprise (along with any licenses that include a right to receive source-code). In addition, no refunds are made for renewals and second license purchases.", "RefundPolicyExplanation": "You can request a refund within <strong>30 days</strong> of your license purchase. The Business and Enterprise license types have source-code download option, therefore we provide a 60% refund within 30 days for Business and Enterprise licenses. In addition, no refunds are made for renewals and second license purchases.",
"HowCanIRefundVat": "How can I refund VAT?", "HowCanIRefundVat": "How can I refund VAT?",
"HowCanIRefundVatExplanation1": "If you made the payment using 2Checkout, you can refund VAT via your 2Checkout account:", "HowCanIRefundVatExplanation1": "If you made the payment using 2Checkout, you can refund VAT via your 2Checkout account:",
"HowCanIRefundVatExplanation2": "Log in to your <a href=\"https://secure.2checkout.com/cpanel/login.php\" target=\"_blank\">2Checkout</a> account", "HowCanIRefundVatExplanation2": "Log in to your <a href=\"https://secure.2checkout.com/cpanel/login.php\" target=\"_blank\">2Checkout</a> account",
@ -841,6 +841,59 @@
"BlazoriseSupportExplanation2": "Verify your email address by checking your email box. Check your spam box if you don't see an email in your inbox!", "BlazoriseSupportExplanation2": "Verify your email address by checking your email box. Check your spam box if you don't see an email in your inbox!",
"BlazoriseSupportExplanation3": "Log into the Blazorise support website at <a href=\"https://blazorise.com/support/login\">blazorise.com/support/login</a>.", "BlazoriseSupportExplanation3": "Log into the Blazorise support website at <a href=\"https://blazorise.com/support/login\">blazorise.com/support/login</a>.",
"BlazoriseSupportExplanation4": "If you have an active ABP Commercial license, you will also have a Blazorise PRO license. You can get your Blazorise license key at <a href=\"https://blazorise.com/support/user/manage/license\">blazorise.com/support/user/manage/license</a>.", "BlazoriseSupportExplanation4": "If you have an active ABP Commercial license, you will also have a Blazorise PRO license. You can get your Blazorise license key at <a href=\"https://blazorise.com/support/user/manage/license\">blazorise.com/support/user/manage/license</a>.",
"BlazoriseSupportExplanation5": "You can post your questions on the support website and generate a product token for your application." "BlazoriseSupportExplanation5": "You can post your questions on the support website and generate a product token for your application.",
"AbpLiveTrainingPackages": "ABP Live Training Packages",
"Releases": "Releases",
"ReleasesDescription": "Release logs of ABP Commercial.",
"ReleaseDate": "Release Date",
"Labels": "Labels",
"PreRelease": "Pre-release",
"AllTypes": "All Types",
"Enhancement": "Enhancement",
"Bug": "Bug",
"Feature": "Feature",
"AllUIs": "All UI's",
"MVC": "MVC",
"HowItWorks_Page_Title": "How it works?",
"HowItWorks_Page_Description": "ABP Framework extends the .NET platform. So, anything you can do with a plain .NET solution is already possible with the ABP Framework. That makes it easy to get started with a low learning curve.",
"HowItWorks_Description1": "ABP Framework extends the .NET platform. So, anything you can do with a plain .NET solution is already possible with the ABP Framework. That makes it easy to get started with a low learning curve.",
"HowItWorks_Description2": "Once you start learning and using the ABP Framework features, developing your software will be much more enjoyable than ever.",
"HowItWorks_Description3": "This page basically explains how you use the ABP.IO Platform as a .NET developer.",
"CreateANewSolution": "Create a New .NET Solution",
"CreateANewSolution_Description1": "Everything starts by creating a new ABP integrated .NET solution.",
"StartWithStartupTemplates": "Start one of the pre-built <a href=\"/startup-templates\">startup solution templates</a>",
"SimpleMonolithApplicationTemplate": "Simple monolith application template",
"LayeredApplicationTemplate": "Layered application template",
"MicroserviceSolutionTemplate": "Microservice solution template",
"CreateEmptySolutionAndUseAbp": "Or create a new empty .NET solution and install ABP NuGet & NPM <a href=\"https://abp.io/packages\" target=\"_blank\">packages</a> yourself.",
"CreatingSolutionWithMultipleOptions": "There are multiple User Interface and Database options while creating a new solution.",
"UIFrameworkOptions": "UI Framework Options",
"DotnetSolutionWithoutDependency": "Now, you have a regular .NET solution in your local computer that has no dependency to a cloud platform or external service.",
"CheckTheDocumentForDetails": "You can check the <a href=\"{0}\" target=\"_blank\">{1}</a> document for details.",
"UIAndDatabaseIndependent": "ABP can work with any UI and any database provider supported by .NET. \n However, these UI and database providers are pre-integrated and well documented.",
"InstallAbpModules": "Install ABP Modules",
"DevelopYourSolution": "Develop Your Solution",
"DeployAnywhere": "Deploy Anywhere",
"InstallAbpModule_Description1": "ABP is a modular application development framework. Startup solution templates already come with the essential modules installed. \n But there are more application modules you may want to use in your solution.",
"InstallAbpModule_Description2": "Every module consists of a few NuGet and NPM packages and has an installation document. <a href=\"/tools/suite\">ABP Suite</a> does most of the work automatically, then you manually configure or fine tune the module based on its documentation.",
"DevelopYourSolution_Description1": "ABP’s infrastructure makes you <b class=\"text-white\">focus on your own business code</b> by automating the repetitive work and providing pre-built infrastructure and application <a href=\"https://abp.io/features\" target=\"_blank\">features</a>.",
"DevelopYourSolution_Description2": "In the following code block, you can see how the ABP Framework seamlessly integrates into your code and automates the repetitive tasks for you.",
"DevelopYourSolution_Description3": "Even in this short code block, ABP does a lot of things for you.",
"DevelopYourSolution_Description4": "It provides base classes to apply conventions, like \n <a href=\"https://docs.abp.io/en/abp/latest/Dependency-Injection\" target=\"_blank\">dependency injection</a>. Generic \n <a href=\"https://docs.abp.io/en/abp/latest/Repositories\" target=\"_blank\">repository</a> services provide a convenient \n way to interact with the database. Declarative \n <a href=\"https://docs.abp.io/en/abp/latest/Authorization\" target=\"_blank\">authorization</a> works with a fine-tuned permission system.",
"DevelopYourSolution_Description5": "ABP completely automates \n <a href=\"https://docs.abp.io/en/abp/latest/Unit-Of-Work\" target=\"_blank\">unit of work</a> (for database connection and transaction management), \n <a href=\"https://docs.abp.io/en/abp/latest/Exception-Handling\" target=\"_blank\">exception handling</a>, \n <a href=\"https://docs.abp.io/en/abp/latest/Validation\" target=\"_blank\">validation</a>\n and <a href=\"https://docs.abp.io/en/abp/latest/Audit-Logging\" target=\"_blank\">audit logging</a>. It provides many more building blocks to simplify your daily development tasks and focus on your own code while creating production ready \n applications.",
"DevelopYourSolution_Description6": "You can imagine how much that code block can be long and complicated if you would do it all manually.",
"SuiteCrudGenerationInFewSeconds": "In addition to hand coding your solution, you can create fully working advanced CRUD pages in a few minutes using the ABP Suite tooling. It generates the code into your solution, so you can fine tune it based on your custom requirements.",
"DeployAnywhere_Description1": "At the end of the day, you have a pure .NET solution. You can deploy your solution to your own server, to a cloud platform, kubernetes or anywhere you want. You can deploy to as many servers as you want. ABP is a deployment environment agnostic tool.",
"ExpertiseAbpFramework": "Expertise the ABP Framework",
"ExpertiseAbpFramework_Description1": "Want to go beyond basics and get expertise with the ABP.IO Platform?",
"FreeDownload": "Free Download",
"Read": "Read",
"HavingTrouble": "Having Trouble?",
"HavingTrouble_Description1": "Do you have problems with developing your solution? We are here! Use the ABP Support platform \n or send an email to get help directly from the Core ABP Framework team members.",
"WeAreHereToHelp_Description1": "You can browse our help topics or search in the frequently asked questions, \n or you can ask us a question by using the contact form.",
"OtherModules": "Other Modules",
"OtherModules_Description1": "Account, Audit Logging, Chat , CMS Kit,File Management , Forms, GDPR, Identity, Language Management, Payment , Saas and more...",
"HowItWorks_DatabaseProviderOptions": "Database provider options",
"SeeFAQ" : "See FAQ"
} }
} }

6
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json

@ -129,8 +129,8 @@
"TellUsWhatYouNeed": "Bize neye ihtiyacın olduğunu söyle.", "TellUsWhatYouNeed": "Bize neye ihtiyacın olduğunu söyle.",
"YourMessage": "Mesajın", "YourMessage": "Mesajın",
"YourFullName": "Tam adınız", "YourFullName": "Tam adınız",
"EmailField": "E", "EmailField": "E-posta Adresi",
"YourEmailAddress": "E", "YourEmailAddress": "E-posta adresiniz",
"HowMayWeHelpYou": "Size nasıl yardımcı olabiliriz?", "HowMayWeHelpYou": "Size nasıl yardımcı olabiliriz?",
"SendMessage": "Mesaj gönder", "SendMessage": "Mesaj gönder",
"Success": "Başarı", "Success": "Başarı",
@ -808,4 +808,4 @@
"BlazoriseLicense": "Blazorise lisansı satın almamız gerekiyor mu?", "BlazoriseLicense": "Blazorise lisansı satın almamız gerekiyor mu?",
"BlazoriseLicenseExplanation": "Volosoft ve Megabit arasında bir anlaşmamız var, bu anlaşma ile Blazorise lisansı ABP Ticari ürünleri ile birlikte geliyor, bu nedenle müşterilerimizin ekstra bir Blazorise lisansı satın almasına gerek kalmıyor." "BlazoriseLicenseExplanation": "Volosoft ve Megabit arasında bir anlaşmamız var, bu anlaşma ile Blazorise lisansı ABP Ticari ürünleri ile birlikte geliyor, bu nedenle müşterilerimizin ekstra bir Blazorise lisansı satın almasına gerek kalmıyor."
} }
} }

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

@ -181,13 +181,14 @@
"Post_Create_Page_CreateNewPost": "Create New Post", "Post_Create_Page_CreateNewPost": "Create New Post",
"Post_Index_Page_MetaDescription": "ABP Community's purpose is to create a contribution environment for developers who use the ABP framework.", "Post_Index_Page_MetaDescription": "ABP Community's purpose is to create a contribution environment for developers who use the ABP framework.",
"Layout_Title": "{0} | ABP Community", "Layout_Title": "{0} | ABP Community",
"Layout_MetaDescription": "ABP Community is an environment where people can share posts about ABP framework and follows the projects.", "Layout_MetaDescription": "A hub for ABP Framework, .NET, and software development. Access articles, tutorials, news, and contribute to the ABP community.",
"Index_Page_CommunityIntroduction": "This is a hub for ABP Framework, .NET and software development. You can read the articles, watch the video tutorials, get informed about ABP’s development progress and ABP-related events, help other developers and share your expertise with the ABP community.", "Index_Page_CommunityIntroduction": "This is a hub for ABP Framework, .NET and software development. You can read the articles, watch the video tutorials, get informed about ABP’s development progress and ABP-related events, help other developers and share your expertise with the ABP community.",
"TagsInArticle": "Tags in article", "TagsInArticle": "Tags in article",
"IConsentToMedium": "I consent to the publication of this post at https://medium.com/volosoft.", "IConsentToMedium": "I consent to the publication of this post at https://medium.com/volosoft.",
"SearchResultsFor": "Search results for <span class=\"fw-bold\">\"{0}\"</span>", "SearchResultsFor": "Search results for <span class=\"fw-bold\">\"{0}\"</span>",
"SeeMoreVideos": "See more videos", "SeeMoreVideos": "See more videos",
"DiscordPageTitle": "ABP Discord Community", "DiscordPageTitle": "ABP Discord Community",
"ViewVideo": "View Video" "ViewVideo": "View Video",
"AbpCommunityTitleContent": "ABP Community - Open Source ABP Framework"
} }
} }

12
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json

@ -420,14 +420,16 @@
"CreateSolutionFolder": "Create Solution Folder", "CreateSolutionFolder": "Create Solution Folder",
"CreateSolutionFolderOption": "Specifies if the project will be in a new folder in the output folder or directly the output folder.", "CreateSolutionFolderOption": "Specifies if the project will be in a new folder in the output folder or directly the output folder.",
"BooksPageTitle": "ABP Books", "BooksPageTitle": "ABP Books",
"PackageDetailPage_NuGetPackageInstallationOptions": "There are two ways to install <code>{0}</code> NuGet package to your project", "PackageDetailPage_NuGetPackageInstallationOptions": "There are three ways to install <code>{0}</code> NuGet package to your project",
"PackageDetailPage_InstallingWithABPCLI": "1: Installing with the ABP CLI", "PackageDetailPage_InstallingWithABPCLI": "1: Installing with the ABP CLI",
"PackageDetailPage_InstallingWithABPCLIDescription1": "If you haven't installed the <a href=\"https://docs.abp.io/en/abp/latest/CLI\">ABP CLI</a>, first install by executing the following command in a command-line terminal", "PackageDetailPage_InstallingWithABPCLIDescription1": "If you haven't installed the <a href=\"https://docs.abp.io/en/abp/latest/CLI\">ABP CLI</a>, first install by executing the following command in a command-line terminal",
"PackageDetailPage_InstallingWithABPCLIDescription2": "Once you have installed the ABP CLI, open a command-line terminal in the location of the project (<code>.csproj</code> file) you want to install it and execute the following command", "PackageDetailPage_InstallingWithABPCLIDescription2": "Once you have installed the ABP CLI, open a command-line terminal in the location of the project (<code>.csproj</code> file) you want to install it and execute the following command",
"PackageDetailPage_InstallingWithABPCLIDescription3": "It will add the <code>{0}</code> package reference to your project and the <code>{1}</code> dependency to your module class.", "PackageDetailPage_InstallingWithABPCLIDescription3": "It will add the <code>{0}</code> package reference to your project and the <code>{1}</code> dependency to your module class.",
"PackageDetailPage_ManualInstallation": "2: Manual Installation", "PackageDetailPage_ManualInstallation": "2: Installing with the Dotnet CLI",
"PackageDetailPage_ManualInstallationDesription1": "Add <code>{0}</code> NuGet package reference to your project using your IDE or executing the following command", "PackageDetailPage_ManualInstallationDescription1": "Add <code>{0}</code> NuGet package reference to your project using your IDE or executing the following command",
"PackageDetailPage_ManualInstallationDesription2": "Then add the <code>{0}</code> dependency to your <a href=\"https://docs.abp.io/en/abp/latest/Module-Development-Basics\">module class</a> as shown in the following example", "PackageDetailPage_ManualInstallationDescription2": "Then add the <code>{0}</code> dependency to your <a href=\"https://docs.abp.io/en/abp/latest/Module-Development-Basics\">module class</a> as shown in the following example",
"PackageDetailPage_SeeDocumentation": "<a href=\"{0}\">See the documentation</a> to learn how to use this package in your applications." "PackageDetailPage_SeeDocumentation": "<a href=\"{0}\">See the documentation</a> to learn how to use this package in your applications.",
"PackageDetailPage_InstallingUsingPMC": "3: Installing with the Package Manager Console",
"PackageDetailPage_InstallingUsingPMCDescription1": "Open the <strong>Package Manager Console</strong> in Visual Studio (Tools -> Nuget Package Manager -> Package Manager Console) and execute the following command"
} }
} }

2
common.props

@ -1,7 +1,7 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Version>7.3.0</Version> <Version>7.4.0</Version>
<NoWarn>$(NoWarn);CS1591;CS0436</NoWarn> <NoWarn>$(NoWarn);CS1591;CS0436</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl> <PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io/</PackageProjectUrl> <PackageProjectUrl>https://abp.io/</PackageProjectUrl>

4
configureawait.props

@ -1,9 +1,9 @@
<Project> <Project>
<ItemGroup> <ItemGroup Condition="'$(Configuration)' == 'Release'">
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" PrivateAssets="All" /> <PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" PrivateAssets="All" />
<PackageReference Include="Fody" Version="6.6.1"> <PackageReference Include="Fody" Version="6.6.1">
<PrivateAssets>All</PrivateAssets> <PrivateAssets>All</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
</Project> </Project>

2
delete-bin-obj.ps1

@ -1,7 +1,5 @@
Clear-Host Clear-Host
Write-Host "Deleting all BIN and OBJ folders..." -ForegroundColor Cyan Write-Host "Deleting all BIN and OBJ folders..." -ForegroundColor Cyan
Get-ChildItem -Path . -Include bin,obj -Recurse -Directory | ForEach-Object { Get-ChildItem -Path . -Include bin,obj -Recurse -Directory | ForEach-Object {
if ($_.FullName -notmatch "\\node_modules\\") { if ($_.FullName -notmatch "\\node_modules\\") {
Write-Host "Deleting:" $_.FullName -ForegroundColor Yellow Write-Host "Deleting:" $_.FullName -ForegroundColor Yellow

45
docs/en/API/Auto-API-Controllers.md

@ -169,3 +169,48 @@ public class PersonAppService : ApplicationService
```` ````
Disabled `IsMetadataEnabled` which hides this service from API explorer and it will not be discoverable. However, it still can be usable for the clients know the exact API path/route. Disabled `IsMetadataEnabled` which hides this service from API explorer and it will not be discoverable. However, it still can be usable for the clients know the exact API path/route.
## Replace or Remove Controllers.
In addition to [Overriding a Controller](../Customizing-Application-Modules-Overriding-Services.md#example-overriding-a-controller), you can also use a completely independent **Controller** to replace the controller in the framework or module.
They have the same [route](https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-7.0), but can have **different** input and output parameters.
### Replace built-in AbpApplicationConfigurationController
The `ReplaceControllersAttribute` indicates the replaced controller type.
````csharp
[ReplaceControllers(typeof(AbpApplicationConfigurationController))]
[Area("abp")]
[RemoteService(Name = "abp")]
public class ReplaceBuiltInController : AbpController
{
[HttpGet("api/abp/application-configuration")]
public virtual Task<MyApplicationConfigurationDto> GetAsync(MyApplicationConfigurationRequestOptions options)
{
return Task.FromResult(new MyApplicationConfigurationDto());
}
}
public class MyApplicationConfigurationRequestOptions : ApplicationConfigurationRequestOptions
{
}
public class MyApplicationConfigurationDto : ApplicationConfigurationDto
{
}
````
### Remove contoller
Configure `ControllersToRemove` of `AbpAspNetCoreMvcOptions` to remove the controllers.
````csharp
services.Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ControllersToRemove.Add(typeof(AbpLanguagesController));
});
````

17
docs/en/API/Dynamic-CSharp-API-Clients.md

@ -38,20 +38,15 @@ Implement this class in your service application. You can use [auto API controll
## Client Proxy Generation ## Client Proxy Generation
First, add [Volo.Abp.Http.Client](https://www.nuget.org/packages/Volo.Abp.Http.Client) nuget package to your client project: > The startup templates already comes pre-configured for the client proxy generation, in the `HttpApi.Client` project.
If you're not using a startup template, then execute the following command in the folder that contains the .csproj file of your client project:
```` ````
Install-Package Volo.Abp.Http.Client abp add-package Volo.Abp.Http.Client
```` ````
Then add `AbpHttpClientModule` dependency to your module: > If you haven't done it yet, you first need to install the [ABP CLI](../CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.Http.Client).
````csharp
[DependsOn(typeof(AbpHttpClientModule))] //add the dependency
public class MyClientAppModule : AbpModule
{
}
````
Now, it's ready to create the client proxies. Example: Now, it's ready to create the client proxies. Example:
@ -74,8 +69,6 @@ public class MyClientAppModule : AbpModule
`AddHttpClientProxies` method gets an assembly, finds all service interfaces in the given assembly, creates and registers proxy classes. `AddHttpClientProxies` method gets an assembly, finds all service interfaces in the given assembly, creates and registers proxy classes.
> The startup templates already comes pre-configured for the client proxy generation, in the `HttpApi.Client` project.
### Endpoint Configuration ### Endpoint Configuration
`RemoteServices` section in the `appsettings.json` file is used to get remote service address by default. The simplest configuration is shown below: `RemoteServices` section in the `appsettings.json` file is used to get remote service address by default. The simplest configuration is shown below:

27
docs/en/API/Swagger-Integration.md

@ -21,6 +21,8 @@ Open a command line window in the folder of the `Web` or `HttpApi.Host` project
abp add-package Volo.Abp.Swashbuckle abp add-package Volo.Abp.Swashbuckle
``` ```
> If you haven't done it yet, you first need to install the [ABP CLI](../CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.Swashbuckle).
### Manual Installation ### Manual Installation
If you want to manually install; If you want to manually install;
@ -43,7 +45,7 @@ If you want to manually install;
## Configuration ## Configuration
First, we need to use `AddAbpSwaggerGen` extension to configure Swagger in `ConfigureServices` method of our module. First, we need to use `AddAbpSwaggerGen` extension to configure Swagger in `ConfigureServices` method of our module:
```csharp ```csharp
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
@ -63,21 +65,21 @@ public override void ConfigureServices(ServiceConfigurationContext context)
} }
``` ```
Then we can use Swagger UI by calling `UseAbpSwaggerUI` method in the `OnApplicationInitialization` method of our module. Then we can use Swagger UI by calling `UseAbpSwaggerUI` method in the `OnApplicationInitialization` method of our module:
```csharp ```csharp
public override void OnApplicationInitialization(ApplicationInitializationContext context) public override void OnApplicationInitialization(ApplicationInitializationContext context)
{ {
var app = context.GetApplicationBuilder(); var app = context.GetApplicationBuilder();
//... other configarations. //... other configurations.
app.UseAbpSwaggerUI(options => app.UseAbpSwaggerUI(options =>
{ {
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Test API"); options.SwaggerEndpoint("/swagger/v1/swagger.json", "Test API");
}); });
//... other configarations. //... other configurations.
} }
``` ```
@ -103,9 +105,7 @@ For non MVC/Tiered applications, we need to configure Swagger with OAUTH to hand
> ABP Framework uses OpenIddict by default. To get more information about OpenIddict, check this [documentation](../Modules/OpenIddict.md). > ABP Framework uses OpenIddict by default. To get more information about OpenIddict, check this [documentation](../Modules/OpenIddict.md).
To do that, we need to use `AddAbpSwaggerGenWithOAuth` extension to configure Swagger with OAuth issuer and scopes in `ConfigureServices` method of our module:
To do that, we need to use `AddAbpSwaggerGenWithOAuth` extension to configure Swagger with OAuth issuer and scopes in `ConfigureServices` method of our module.
```csharp ```csharp
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
@ -130,17 +130,14 @@ public override void ConfigureServices(ServiceConfigurationContext context)
} }
``` ```
Then we can use Swagger UI by calling `UseAbpSwaggerUI` method in the `OnApplicationInitialization` method of our module. Then we can use Swagger UI by calling `UseAbpSwaggerUI` method in the `OnApplicationInitialization` method of our module:
> Do not forget to set `OAuthClientId` and `OAuthClientSecret`.
```csharp ```csharp
public override void OnApplicationInitialization(ApplicationInitializationContext context) public override void OnApplicationInitialization(ApplicationInitializationContext context)
{ {
var app = context.GetApplicationBuilder(); var app = context.GetApplicationBuilder();
//... other configarations. //... other configurations.
app.UseAbpSwaggerUI(options => app.UseAbpSwaggerUI(options =>
{ {
@ -151,6 +148,8 @@ public override void OnApplicationInitialization(ApplicationInitializationContex
options.OAuthClientSecret("1q2w3e*"); // clientSecret options.OAuthClientSecret("1q2w3e*"); // clientSecret
}); });
//... other configarations. //... other configurations.
} }
``` ```
> Do not forget to set `OAuthClientId` and `OAuthClientSecret`.

6
docs/en/Application-Startup.md

@ -18,12 +18,14 @@ If you [create a new console application with Visual Studio](https://learn.micro
This example uses the [top level statements](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/top-level-statements), so it consists of only a single line of code. This example uses the [top level statements](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/top-level-statements), so it consists of only a single line of code.
The first step is to install the [Volo.Abp.Core](https://www.nuget.org/packages/Volo.Abp.Core) NuGet package, which is the most core NuGet package of the ABP framework. You can install it using the [Package Manager Console](https://learn.microsoft.com/en-us/nuget/consume-packages/install-use-packages-powershell) in Visual Studio: The first step is to install the [Volo.Abp.Core](https://www.nuget.org/packages/Volo.Abp.Core) NuGet package, which is the most core NuGet package of the ABP framework. You can install it using the ABP CLI. Execute the following command in the folder of the .csproj file that you want to install the package on:
````bash ````bash
Install-Package Volo.Abp.Core abp add-package Volo.Abp.Core
```` ````
> If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.Core).
Alternatively, you can use a command-line terminal in the root folder of the project (the folder containing the `MyConsoleDemo.csproj` file, for this example): Alternatively, you can use a command-line terminal in the root folder of the project (the folder containing the `MyConsoleDemo.csproj` file, for this example):
````bash ````bash

23
docs/en/Autofac-Integration.md

@ -6,27 +6,14 @@
> All the [startup templates](Startup-Templates/Index.md) and samples are Autofac integrated. So, most of the time you don't need to manually install this package. > All the [startup templates](Startup-Templates/Index.md) and samples are Autofac integrated. So, most of the time you don't need to manually install this package.
Install [Volo.Abp.Autofac](https://www.nuget.org/packages/Volo.Abp.Autofac) nuget package to your project (for a multi-projects application, it's suggested to add to the executable/web project). If you're not using a startup template, you can use the [ABP CLI](CLI.md) to install it to your project. Execute the following command in the folder that contains the .csproj file of your project (suggested to add it to the executable/web project):
````bash
abp add-package Volo.Abp.Autofac
```` ````
Install-Package Volo.Abp.Autofac
````
Then add `AbpAutofacModule` dependency to your module:
```csharp > If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.Autofac).
using Volo.Abp.Modularity; >
using Volo.Abp.Autofac;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpAutofacModule))]
public class MyModule : AbpModule
{
//...
}
}
```
Finally, configure `AbpApplicationCreationOptions` to replace default dependency injection services by Autofac. It depends on the application type. Finally, configure `AbpApplicationCreationOptions` to replace default dependency injection services by Autofac. It depends on the application type.

8
docs/en/Background-Jobs-Hangfire.md

@ -16,6 +16,8 @@ Open a command line window in the folder of the project (.csproj file) and type
abp add-package Volo.Abp.BackgroundJobs.HangFire abp add-package Volo.Abp.BackgroundJobs.HangFire
```` ````
> If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.BackgroundJobs.HangFire).
### Manual Installation ### Manual Installation
If you want to manually install; If you want to manually install;
@ -52,7 +54,7 @@ After you have installed these NuGet packages, you need to configure your projec
var configuration = context.Services.GetConfiguration(); var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment(); var hostingEnvironment = context.Services.GetHostingEnvironment();
//... other configarations. //... other configurations.
ConfigureHangfire(context, configuration); ConfigureHangfire(context, configuration);
} }
@ -68,7 +70,7 @@ After you have installed these NuGet packages, you need to configure your projec
> You have to configure a storage for Hangfire. > You have to configure a storage for Hangfire.
2. If you want to use hangfire's dashboard, you can add `UseHangfireDashboard` call in the `OnApplicationInitialization` method in `Module` class 2. If you want to use hangfire's dashboard, you can add `UseHangfireDashboard` call in the `OnApplicationInitialization` method in `Module` class:
````csharp ````csharp
public override void OnApplicationInitialization(ApplicationInitializationContext context) public override void OnApplicationInitialization(ApplicationInitializationContext context)
@ -84,7 +86,7 @@ After you have installed these NuGet packages, you need to configure your projec
### Specifying Queue ### Specifying Queue
You can use the [`QueueAttribute`](https://docs.hangfire.io/en/latest/background-processing/configuring-queues.html) to specify the queue. You can use the [`QueueAttribute`](https://docs.hangfire.io/en/latest/background-processing/configuring-queues.html) to specify the queue:
````csharp ````csharp
using System.Threading.Tasks; using System.Threading.Tasks;

2
docs/en/Background-Jobs-Quartz.md

@ -16,6 +16,8 @@ Open a command line window in the folder of the project (.csproj file) and type
abp add-package Volo.Abp.BackgroundJobs.Quartz abp add-package Volo.Abp.BackgroundJobs.Quartz
```` ````
> If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.BackgroundJobs.Quartz).
### Manual Installation ### Manual Installation
If you want to manually install; If you want to manually install;

267
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/POST.md

@ -0,0 +1,267 @@
# ABP.IO Platform 7.3 RC Has Been Released
Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **7.3 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version.
Try this version and provide feedback for a more stable version of ABP v7.3! Thanks to all of you.
## Get Started with the 7.3 RC
Follow the steps below to try version 7.3.0 RC today:
1) **Upgrade** the ABP CLI to version `7.3.0-rc.1` using a command line terminal:
````bash
dotnet tool update Volo.Abp.Cli -g --version 7.3.0-rc.1
````
**or install** it if you haven't before:
````bash
dotnet tool install Volo.Abp.Cli -g --version 7.3.0-rc.1
````
2) Create a **new application** with the `--preview` option:
````bash
abp new BookStore --preview
````
See the [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all the available options.
> You can also use the [Get Started](https://abp.io/get-started) page to generate a CLI command to create a new application.
You can use any IDE that supports .NET 7.x, like [Visual Studio 2022](https://visualstudio.microsoft.com/downloads/).
## Migration Guides
There are a few breaking changes in this version that may affect your application.
Please see the following migration documents, if you are upgrading from v7.2:
* [ABP Framework 7.2 to 7.3 Migration Guide](https://docs.abp.io/en/abp/7.3/Migration-Guides/Abp-7_3)
> If you are using the CMS Kit or CMS Kit Pro module, please don't forget to create a new migration and apply it to your database.
## What's New with ABP Framework 7.3?
In this section, I will introduce some major features released in this version. Here is a brief list of the titles that will be explained in the next sections:
* Introducing the Volo.Abp.Imaging packages
* ABP CLI: switch-to-local command
* Monitoring Distributed Events
* Ordering of the Local Event Handlers
* Nonce attribute support for Content Security Policy (CSP)
* Other News
### Introducing the Volo.Abp.Imaging packages
ABP Framework provides some packages to compress and resize images. Currently, there are four official packages:
* `Volo.Abp.Imaging.Abstractions`: Provides common services for compression and resizing purposes.
* `Volo.Abp.Imaging.AspNetCore`: Provides some attributes for controller actions that can automatically compress and/or resize uploaded files.
* `Volo.Abp.Imaging.ImageSharp`: Implements the image compression & resize operations using the [ImageSharp](https://github.com/SixLabors/ImageSharp) library.
* `Volo.Abp.Imaging.MagickNet`: Implements the image compression & resize operations using the [Magick.NET](https://github.com/dlemstra/Magick.NET) library.
You can use one of these official providers (`ImageSharp` or `Magick.NET`) or implement your own image resizer/compressor contributor and use it in your application.
> See the [Image Manipulation](https://docs.abp.io/en/abp/7.3/Image-Manipulation) documentation to learn more and see the required configurations.
### ABP CLI: switch-to-local command
In this version, ABP CLI introduces a new CLI command: **"switch-to-local"**. The `switch-to-local` command changes all NuGet package references on a solution to local project references for all the `.csproj` files in the specified folder (and all its subfolders with any depth).
**Usage:**
```bash
abp switch-to-local --paths "C:\Github\abp"
```
### Monitoring Distributed Events
ABP Framework allows you to stay informed when your application **receives** or **sends** a distributed event. This enables you to track the event flow within your application and take appropriate actions based on the received or sent distributed events.
You just need to subscribe to one of the `DistributedEventReceived` or `DistributedEventSent` events and take additional actions according to your cases.
**Example: Get informed when your application sends an event to the distributed event bus**
```csharp
public class DistributedEventSentHandler : ILocalEventHandler<DistributedEventSent>, ITransientDependency
{
public async Task HandleEventAsync(DistributedEventSent eventData)
{
// TODO: IMPLEMENT YOUR LOGIC...
}
}
```
> See the documentation to learn more: [https://docs.abp.io/en/abp/7.3/Distributed-Event-Bus](https://docs.abp.io/en/abp/7.3/Distributed-Event-Bus)
### Ordering of the Local Event Handlers
In this version, ABP Framework introduces the `LocalEventHandlerOrder` attribute, which can be used to set the execution order for the event handlers. This can be helpful if you want to handle your local event handlers in a specific order.
**Example:**
```csharp
[LocalEventHandlerOrder(-1)]
public class MyHandler
: ILocalEventHandler<StockCountChangedEvent>,
ITransientDependency
{
public async Task HandleEventAsync(StockCountChangedEvent eventData)
{
//TODO: your implementation
}
}
```
By default, all event handlers have an order value of 0. Thus, if you want to take certain event handlers to be executed before other event handlers, you can set the order value as a negative value.
> See the documentation to learn more: [https://docs.abp.io/en/abp/7.3/Local-Event-Bus](https://docs.abp.io/en/abp/7.3/Local-Event-Bus)
### Nonce attribute support for Content Security Policy (CSP)
ABP Framework supports adding unique value to nonce attribute for script tags which can be used by Content Security Policy to determine whether or not a given fetch will be allowed to proceed for a given element. In other words, it provides a mechanism to execute only correct script tags with the correct nonce value.
This feature is disabled by default. You can enable it by setting the *UseContentSecurityPolicyScriptNonce* property of the `AbpSecurityHeadersOptions` class to **true**:
```csharp
Configure<AbpSecurityHeadersOptions>(options =>
{
//adding script-src nonce
options.UseContentSecurityPolicyScriptNonce = true; //false by default
});
```
> See the [Security Headers](https://docs.abp.io/en/abp/7.3/UI/AspNetCore/Security-Headers) documentation for more information.
### Other News
* Upgraded the [Blazorise](https://blazorise.com/) library to v1.2.3 for Blazor UI. After the upgrade, ensure that all Blazorise-related packages are using v1.2.3 in your application.
* Module Entity Extension support has been added for the CMS Kit module. See [#16572](https://github.com/abpframework/abp/issues/16572) for more information.
If you want to see more details, you can check [the release on GitHub](https://github.com/abpframework/abp/releases/tag/5.3.0-rc.1), which contains a list of all the issues and pull requests were closed with this version.
## What's New with ABP Commercial 7.3?
We've also worked on [ABP Commercial](https://commercial.abp.io/) to align the features and changes made in the ABP Framework. The following sections introduce a few new features coming with ABP Commercial 7.3.
### Account Module - Using Authenticator App for Two-Factor Authentication
In this version, ABP Commercial provides a new **Two-Factor Authentication (2FA) provider** that allows you to log in to an application by scanning a QR Code with an Authenticator App, such as Microsoft Authenticator or Google Authenticator.
You need to apply the following actions to configure an Authenticator and then you are free to log in by using the Authenticator App:
**Step 1 - Enable Two Factor Authentication and Scan the QR Code:**
![](./two-factor-auth-1.png)
**Step 2 - Verify the QR Code with an authenticator app:**
![](./two-factor-auth-2.png)
**Step 3 - Save the recovery codes for later use in case of not being able to login by verifying the QR code:**
![](./two-factor-auth-3.png)
You can disable the two-factor authentication and reset the Authenticator App anytime you want, just by disabling the two-factor authentication or resetting the authenticator:
![](./reset-authenticator.png)
### Upgrade Blazorise to v1.2.3
Upgraded the [Blazorise](https://blazorise.com/) library to v1.2.3 for Blazor UI. If you are upgrading your project to v7.3.0, please ensure that all the Blazorise-related packages are using v1.2.3 in your application. Otherwise, you might get errors due to incompatible versions.
### CMS Kit: Module Entity Extensions
Module entity extension system is a high-level extension system that allows you to define new properties for existing entities of the dependent modules. ABP Framework and ABP Commercial use this system to allow developers to extend entities in different modules.
In this version, Module Entity Extension support has been added for the CMS Kit Pro module.
You can open the `YourProjectNameModuleExtensionConfigurator` class inside the `Domain.Shared` project of your solution and change the `ConfigureExtraProperties` method as shown below to add a new property to the `Poll` entity of the [CMS Kit Pro module](https://docs.abp.io/en/commercial/latest/modules/cms-kit/index):
```csharp
public static void ConfigureExtraProperties()
{
OneTimeRunner.Run(() =>
{
ObjectExtensionManager.Instance.Modules()
.ConfigureCmsKitPro(cmsKitPro =>
{
cmsKitPro.ConfigurePoll(poll =>
{
poll.AddOrUpdateProperty<string>(
"<property-name>",
property =>
{
//configuration for this property
}
)
});
});
});
}
```
> See the [Module Entity Extensions documentation](https://docs.abp.io/en/abp/latest/Module-Entity-Extensions) to learn more.
### LeptonX Account Layout
In this version, Account Layout has been re-designed for LeptonX Theme. You can see the new account layout in the following figure:
![](leptonx-account-layout.png)
> To use this new account layout, ensure that your LeptonX Theme package versions are v2.3+.
## Community News
### ABP Community Talks 2023.4: Angular 16 and ABP v7.3
![](./community-talks-2023-4.png)
In this episode, the core ABP team talked about what's new with ABP v7.3 and Angular 16. You can watch the event from [here](https://www.youtube.com/watch?v=lq6u4vQURcI).
### ABP .NET Conference 2023
![](./abp-conf.png)
We organized ABP .NET Conference 2023 on May 2023 and we are happy to share the success of the conference, which captivated overwhelmingly interested live viewers from all over the world. 13 great line up of speakers which includes .NET experts and Microsoft MVPs delivered captivating talks that resonated with the audiences. Each of the talks attracted a great amount of interest and a lot of questions, sparking curiosity in the attendees.
Thanks to all speakers and attendees for joining our event.
> We shared our takeaways in a blog post, which you can read at [https://blog.abp.io/abp/ABP-.NET-Conference-2023-Wrap-Up](https://blog.abp.io/abp/ABP-.NET-Conference-2023-Wrap-Up).
### Volosoft Attendeed & Sponsored Devnot .NET Conference 2023
![](devnot-conference.png)
We are thrilled to announce that the Volosoft Company proudly attended as one of the Gold Sponsors at the Devnot .NET Conference 2023! We are happy to join and be a sponsor of events and contribute to the software society, empowering developers and driving innovation with the .NET community.
![](devnot-talk.png)
Co-Founder of [Volosoft](https://volosoft.com/) and Lead Developer of the ABP Framework, [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan) gave a word about "Dealing with Concurrency and Multi Threading in .NET" at this event.
> You can check [this blog post](https://volosoft.com/blog/Reflecting-on-Devnot-Dotnet-Conference-2023) if you want to learn more about the Devnot .NET Conference 2023.
### New ABP Community Posts
There are exciting articles contributed by the ABP community as always. I will highlight some of them here:
* [Authority Delegation in ABP Commercial](https://community.abp.io/posts/authority-delegation-in-abp-commercial-3wtljpp0) by [Liang Shiwei](https://github.com/realLiangshiwei)
* [What's new in Angular 16? New Features and Updates](https://community.abp.io/posts/whats-new-in-angular-16-new-features-and-updates-s1izi9br) by [Masum Ulu](https://twitter.com/masumulu)
* [Kubernetes Integrated Microservice Development with ABP Studio](https://community.abp.io/videos/kubernetes-integrated-microservice-development-with-abp-studio-oix9zkp8) by [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan)
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/articles/submit) to the ABP Community.
### New ABP Blog Posts
There are also some exciting blog posts written by the ABP team. You can see the following list for some of those articles:
* [ABP .NET Conference 2023 Wrap Up](https://blog.abp.io/abp/ABP-.NET-Conference-2023-Wrap-Up) by [Bige Beşikçi](https://twitter.com/bigedediki)
* [Meet Volosoft at the Devnot .NET Conference 2023!](https://volosoft.com/blog/Meet-Volosoft-at-the-Devnot-.NET-Conference-2023) by [Roo Xu](https://github.com/Roo1227)
## Conclusion
This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://docs.abp.io/en/abp/7.3/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v7.3 RC and provide feedback to help us release a more stable version.
Thanks for being a part of this community!

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/abp-conf.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 742 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/community-talks-2023-4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-conference.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-talk.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/leptonx-account-layout.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/reset-authenticator.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

4
docs/en/CLI-New-Command-Samples.md

@ -73,9 +73,9 @@ The following commands are for creating MVC UI projects:
_Note that Public Website is only included in PRO templates._ _Note that Public Website is only included in PRO templates._
## Blazor ## Blazor WebAssembly
The following commands are for creating Blazor projects: The following commands are for creating Blazor WASM projects:
* **Entity Framework Core**, no mobile app: * **Entity Framework Core**, no mobile app:

15
docs/en/CLI.md

@ -48,6 +48,7 @@ Here, is the list of all available commands before explaining their details:
* **`logout`**: Logouts from your computer if you've authenticated before. * **`logout`**: Logouts from your computer if you've authenticated before.
* **`bundle`**: Generates script and style references for ABP Blazor and MAUI Blazor project. * **`bundle`**: Generates script and style references for ABP Blazor and MAUI Blazor project.
* **`install-libs`**: Install NPM Packages for MVC / Razor Pages and Blazor Server UI types. * **`install-libs`**: Install NPM Packages for MVC / Razor Pages and Blazor Server UI types.
* **`clear-download-cache`** Clears the templates download cache.
### help ### help
@ -165,6 +166,7 @@ For more samples, go to [ABP CLI Create Solution Samples](CLI-New-Command-Sample
* `--local-framework-ref --abp-path`: Uses local projects references to the ABP framework instead of using the NuGet packages. This can be useful if you download the ABP Framework source code and have a local reference to the framework from your application. * `--local-framework-ref --abp-path`: Uses local projects references to the ABP framework instead of using the NuGet packages. This can be useful if you download the ABP Framework source code and have a local reference to the framework from your application.
* `--no-random-port`: Uses template's default ports. * `--no-random-port`: Uses template's default ports.
* `--skip-installing-libs` or `-sib`: Skip installing client side packages. * `--skip-installing-libs` or `-sib`: Skip installing client side packages.
* `--skip-cache` or `-sc`: Always download the latest from our server and refresh their templates folder cache.
* `--with-public-website`: **Public Website** is a front-facing website for describing your project, listing your products and doing SEO for marketing purposes. Users can login and register on your website with this website. * `--with-public-website`: **Public Website** is a front-facing website for describing your project, listing your products and doing SEO for marketing purposes. Users can login and register on your website with this website.
See some [examples for the new command](CLI-New-Command-Samples.md) here. See some [examples for the new command](CLI-New-Command-Samples.md) here.
@ -362,8 +364,11 @@ abp generate-proxy -t csharp -url https://localhost:44302/
* `--api-name` or `-a`: The name of the API endpoint defined in the `/src/environments/environment.ts`. Default value: `default`. * `--api-name` or `-a`: The name of the API endpoint defined in the `/src/environments/environment.ts`. Default value: `default`.
* `--source` or `-s`: Specifies the Angular project name to resolve the root namespace & API definition URL from. Default value: `defaultProject`. * `--source` or `-s`: Specifies the Angular project name to resolve the root namespace & API definition URL from. Default value: `defaultProject`.
* `--target`: Specifies the Angular project name to place generated code in. Default value: `defaultProject`. * `--target`: Specifies the Angular project name to place generated code in. Default value: `defaultProject`.
* `--module`: Backend module name. Default value: `app`.
* `--entry-point`: Targets the Angular project to place the generated code.
* `--url`: Specifies api definition url. Default value is API Name's url in environment file. * `--url`: Specifies api definition url. Default value is API Name's url in environment file.
* `--prompt` or `-p`: Asks the options from the command line prompt (for the unspecified options). * `--prompt` or `-p`: Asks the options from the command line prompt (for the unspecified options).
* `js`: JavaScript. work in the `*.Web` project directory. There are some additional options for this client: * `js`: JavaScript. work in the `*.Web` project directory. There are some additional options for this client:
* `--output` or `-o`: JavaScript file path or folder to place generated code in. * `--output` or `-o`: JavaScript file path or folder to place generated code in.
* `--module` or `-m`: Specifies the name of the backend module you wish to generate proxies for. Default value: `app`. * `--module` or `-m`: Specifies the name of the backend module you wish to generate proxies for. Default value: `app`.
@ -414,7 +419,7 @@ abp remove-proxy -t csharp --folder MyProxies/InnerFolder
### switch-to-preview ### switch-to-preview
You can use this command to switch your project to latest preview version of the ABP framework. You can use this command to switch your solution or project to latest preview version of the ABP framework.
Usage: Usage:
@ -424,12 +429,12 @@ abp switch-to-preview [options]
#### Options #### Options
* `--solution-directory` or `-sd`: Specifies the directory. The solution should be in that directory or in any of its sub directories. If not specified, default is the current directory. * `--directory` or `-d`: Specifies the directory. The solution or project should be in that directory or in any of its sub directories. If not specified, default is the current directory.
### switch-to-nightly ### switch-to-nightly
You can use this command to switch your project to latest [nightly](Nightly-Builds.md) preview version of the ABP framework packages. You can use this command to switch your solution or project to latest [nightly](Nightly-Builds.md) preview version of the ABP framework packages.
Usage: Usage:
@ -439,7 +444,7 @@ abp switch-to-nightly [options]
#### Options #### Options
* `--solution-directory` or `-sd`: Specifies the directory. The solution should be in that directory or in any of its sub directories. If not specified, default is the current directory. * `--directory` or `-d`: Specifies the directory. The solution or project should be in that directory or in any of its sub directories. If not specified, default is the current directory.
### switch-to-stable ### switch-to-stable
@ -452,7 +457,7 @@ abp switch-to-stable [options]
```` ````
#### Options #### Options
* `--solution-directory` or `-sd`: Specifies the directory. The solution should be in that directory or in any of its sub directories. If not specified, default is the current directory. * `--directory` or `-d`: Specifies the directory. The solution or project should be in that directory or in any of its sub directories. If not specified, default is the current directory.
### switch-to-local ### switch-to-local

BIN
docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/01-microservice-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

BIN
docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/02-run-single-service.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

BIN
docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/03-tye-yaml-file.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 KiB

BIN
docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/04-tye-dashboard.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/05-example-microservice-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

BIN
docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/06-abp-studio-kubernetes-tunnel-how-it-works.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

226
docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/POST.md

@ -0,0 +1,226 @@
# Kubernetes Integrated Microservice Development with .NET and ABP Studio
## Abstract
**Microservice architecture** is a quite common approach to build **highly scalable** solutions with a large development team. While there are standard tools, like **Kubernetes**, to deploy, run and scale your microservices, the **development side** is not as mature as that. It is not easy to develop, run and test a single microservice that **depends on** other microservices and services. **Running** a copy of the entire system in the developer's machine is impractical.
In this article, I will introduce an **efficient** way of creating a **development environment** that is well **integrated to Kubernetes**. In this way, you can just run the microservice you are building and let Kubernetes run all your dependencies in your local machine or a remote server.
I will demonstrate the solution by introducing and using a brand new tool for ABP Developers: **ABP Studio**!
>**This article is based on my *[Kubernetes Integrated Microservice Development with ABP Studio](https://www.youtube.com/watch?v=XiPRcIHJ3NE)* talk performed in [ABP Dotnet Conf'23](https://abp.io/conference). You can watch that talk if you would like watching rather than reading.**
## Topics
Let’s start by introducing the main topics I will cover in this article:
* I will begin by defining the **problem**: Why it is hard to prepare a development environment for a microservice development.
* I will mention and demonstrate how **Microsoft’s Tye project** tries to solve the problem and why it falls short.
* Then I will introduce the **ABP Studio**, a brand new product for .NET developers, which has an efficient solution for **running multi-application solutions** locally.
* Finally, I will offer an efficient way of developing such complex solutions locally by **integrating Kubernetes into our development environment**, and demonstrate how ABP Studio automates it for us.
## Difficulties of a Microservice Development Environment
It is important to understand what is the essential problem when we try to set up a development environment for a microservice solution. To understand the main difficulty, let’s see what a microservice solution looks like:
![example-microservice-solution](01-microservice-solution.png)
A typical microservice solution consists of many components communicating to each other. In this example;
* We have **two applications** for users. One for back-office admin users and one for the end-users of the system, a public website.
* These applications use dedicated **API Gateways** since we are using the Backend For Frontend pattern here.
* There is a separate **authentication service** application to login and manage user accounts.
* Behind the API gateways, we typically have many API applications, called **microservices**. Here, I show only three microservices, but there will be tens of microservices even in a medium-size system. Each of these microservices may have their own databases.
* The microservices typically **interact** with each other using REST API calls or asynchronous messaging through an event bus service, like RabbitMQ here.
There will be much more **supporting services**, like Redis, Elasticsearch and so on. As you see, we have a lot of independent services and applications interacting with each other in a typical microservice solution.
### How to run a single service locally?
Generally, your responsibility is developing **one or a few of these microservices** or applications, not all of them. For example, you may be responsible for developing or testing the Product microservice:
![run-single-service-in-a-microservice-solution](02-run-single-service.png)
All you want to do is to write your code, then run and test your service if it is correctly working. However, to be able to **develop**, **run**, **test** or **debug** the product microservice, all of the service and infrastructure dependencies need to be running and communicating to each other.
Okay, maybe not all, but most of them are needed. Otherwise, you can not open the application UI, login to the system, add products to basket and place an order to see if it is working properly, or you can not **live debug** your service code in case of trouble.
So, how to make the whole system up and running easily to be able to **focus on developing**, testing and debugging the Product microservice?
## The Project Tye
You are not the only one getting trouble to develop, run, test and debug a microservice solution. Microsoft also thought of it and introduced a tool called the [Project Tye](https://github.com/dotnet/tye). With its own words in their GitHub repository:
> Tye is a tool that makes developing, testing, and deploying microservices and distributed applications easier.
Tye can **simplify microservices development** by making it easy to run many services with one command, use dependencies in containers, discover addresses of other services using simple conventions. It can also deploy .NET applications to Kubernetes by automatically creating containers for .NET applications and generating Kubernetes manifests with minimal knowledge or configuration.
The deployment part is not mature and they have to do a lot of work. However, the solution runner part works very well.
Tye project consists of three major components:
* A **YAML file** to configure your services
* A **CLI tool** to run and deploy the solution
* And a **dashboard** to visualize the running services.
### The tye.yaml file
Tye uses a YAML file to configure your solution. It typically contains many service definitions. There are three type of services can be defined in this YAML file:
* You can add a **.NET Project**, so Tye runs it locally with **dotnet run**
* You can add a **container definition**, and Tye runs it using **Docker**
* And an arbitrary **executable application** that can be run using a terminal command
Here, an example content of a `tye.yaml` file:
![tye-yaml-file](03-tye-yaml-file.png)
### The Tye CLI
Once you define your YAML file, Tye can run all the services with a single terminal command: **tye run**. It builds all .NET applications before running them. If you specify the **watch parameter**, it watches the changes in your .NET projects, re-builds and runs them when a change happens. There are also [other commands](https://github.com/dotnet/tye/blob/main/docs/reference/commandline/README.md) to build and deploy your solution.
### The Tye Dashboard
The final major component is the Tye Dashboard. With this dashboard, you can see the **list of the services** with their statuses. You can also view their **logs** and open their **UI** with a single click.
A screenshot from the Tye Dashboard:
![project-tye-dashboard](04-tye-dashboard.png)
### The Example Microservice Solution
I’ve prepared a microservice solution for demos in this article and I will use the same solution in all demos. Here, an overall diagram of the example solution:
![example-microservice-solution](05-example-microservice-solution.png)
We have two web applications, two API Gateways, 5 microservices. 3 of them are shown here: Product, Ordering and Identity microservices. Every microservice has its independent SQL Server database. They communicate through REST API calls and distributed events via RabbitMQ.
### The Project Tye Demo
You can watch my 6-minutes demo to see the Project Tye in action:
<iframe width="560" height="315" src="https://www.youtube.com/embed/S0-z29lMokA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
[Click here to watch the demo on YouTube](https://www.youtube.com/watch?v=S0-z29lMokA)
### Tye: Shortcomings
The demo shows how the Tye project is useful. However, there are many missing points and problems with the current project state. Let’s talk about them;
* The first problem is that it **starts very slow**, because every time you run it, it builds all the services. It takes more than 1 minute for a solution with only ten services.
* It currently can run everything in your **local computer**. Even if you want to develop a single service, running tens of services locally consumes your system resources. You need a lot of RAM and CPU if you want to work a large solution locally.
* The **UI part** is currently very simple. For example, if you want to debug one of your services by running it in Visual Studio, you need to stop all the services, change the YAML file to exclude that service from Tye, then run all the services again. Only after that you can run your service in Visual Studio to debug it as integrated to other services. Obviously this process is not easy and comfortable.
* We can only see the application logs in the UI. **More insights** about the internals of services would be very helpful.
* Tye currently has some **partial documents** in its GitHub repository. However, the documentation is far away from being complete.
* Finally, and most importantly, there is **no active development** on the Tye project on GitHub. It was already an experimental project with its early state, as declared in its GitHub repository.
So, basically, it seems Microsoft has no further interest in this project and you can expect it will be retired in the near future.
## ABP Studio
Okay, now we came to the ABP Studio part. At [Volosoft](https://www.volosoft.com/), we were silently working on the ABP Studio project for more than one year.
ABP Studio is a **cross-platform desktop application** for ABP developers. It is **well integrated** to the ABP Framework and aims to provide a comfortable development environment for you by **automating things**, **providing insights** about your solution, making **develop**, **run** and **deploy** your solutions much easier.
We are planning to release a **beta version** in **Q3 of 2023**. You can expect the following features shipping with the initial release:
* You can **create new ABP solutions** and modules easily with a lot of options.
* You can easily **install or uninstall modules** to your solution.
* You can **explore** the fundamental **structures** of your solution or used modules, like entities, repositories, application services, UI pages, HTTP APIs, database tables and much more.
* You can build **multi-module monolith applications** or distributed microservice solutions by easily adding modules and services into your solution.
* You can easily **run multiple applications** and services with a single click, just like I demonstrated with the Project Tye. However, it has much more features.
* You can run your service by **integrating** it into a **Kubernetes** cluster, so you don’t need to run all your dependencies and all other services in your local development environment. This is the essential topic of this talk and I will later demonstrate how it works.
## ABP Studio Solution Runner
I've prepared a demo of the ABP Studio Solution Runner, but first I want to mention the main features of the solution runner:
* First of all, it can run one, **multiple** or **all services** with a single click. In this way, it is very easy to stop a service, run it in Visual Studio to **test** or **debug**.
* All the services are **connected to ABP Studio** and send their internal data to **visualize** on the ABP Studio UI.
* In the **overall view**, you can see a list of services, view **real-time** HTTP Request and exception counts for each service.
* You can see all details of all **HTTP requests** coming to any service.
* You can see **exception details** as real-time in any service, easily filter and search.
* Just like Tye, you can see the **application logs**. But as more, you can filter logs by log level or search in the log texts.
* Last but not least, ABP Studio has an **integrated Chrome browser** inside it. You can browse the UI of your application without leaving the solution runner.
### ABP Studio Solution Runner Demo
You can watch my 9-minutes demo to see ABP Studio Solution Runner in action:
<iframe width="560" height="315" src="https://www.youtube.com/embed/sSCxyccoHqE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
[Click here to watch the demo on YouTube](https://www.youtube.com/watch?v=sSCxyccoHqE)
## ABP Studio Kubernetes Tunnel
Finally, we came to the essential topic I want to talk about. Until that point, we had a good understanding of the problem and possible solutions. In this part, we will make a final touch to the solution to have **a great development environment for a microservice solution**.
ABP Studio Kubernetes Tunnel System allows you to **connect your local development environment to a local or remote Kubernetes cluster**, where that cluster already runs your microservice solution. In this way, you can access any service in Kubernetes with their service name as DNS, just like they are running in your local computer. This is established with a secure VPN connection.
Secondly, you can **intercept any service** in that cluster, so all the **traffic to the intercepted service is automatically redirected to your service** that is running in your local machine. When your service needs to use any service in Kubernetes, the traffic is redirected back to the cluster, just like your local service is running inside the Kubernetes. In this way, you don’t need to care about how all other services are configured and running. You just focus on the service you are responsible for developing, testing or debugging. You can use your favorite IDE since you are running your service in your local machine as you always do.
The solution runner is a great way of running multiple services locally. However, if your solution consists of hundreds of services, running all them in your local machine will consume your system resources and slow down your development speed. The best news is that: You can use the **Kubernetes Tunnelling combined with all the solution runner features** to have a perfect local microservice development environment.
### How ABP Studio Kubernetes Tunnel works
I am sure that you want to see it in action, but before that, let me explain how the solution works.
![abp-studio-kubernetes-tunnel-how-it-works](06-abp-studio-kubernetes-tunnel-how-it-works.png)
* **Kubernetes cluster** is shown on the right side and your **local development machine** is shown on the left side.
* As you know, when a **user requests a web page** from your web application, the request is accepted by an **Ingress Controller** inside your Kubernetes cluster.
* The Ingress controller forwards the request to your **web application**, which then uses an **API gateway** to consume your microservices.
* Assume that we have the **Product**, **Ordering** and **Identity** microservices.
* These microservices have their own SQL Server **database** and they are also using **RabbitMQ**, **Redis** and some other **infrastructure services**.
* On the other hand, we want to develop, run or test our **Product microservice** in our **own laptop** using our favorite IDE, let’s say using Visual Studio.
* If we don’t make anything special, the **product microservice in the Kubernetes cluster** will be used by the users, as you can expect. Even if you can somehow run the product microservice in your local computer, the Kubernetes system won’t have any knowledge about it. They are in different systems.
* At this point, ABP Studio comes into play. When you **connect** to the Kubernetes cluster with ABP Studio, it first installs a **VPN server** into your cluster and a **VPN client** into your local machine.
* Then it establishes a secure **VPN tunnel** between your computer and the target Kubernetes cluster. In this way, you can access all services in Kubernetes with their internal cluster IP addresses.
* ABP Studio also installs the **ABP Studio Client Proxy Server** pod into the Kubernetes cluster, and the **ABP Studio Proxy Client** into the developer machine. It is used to collect data from the services and show them in the ABP Studio UI, like HTTP Requests, exceptions, or logs as we’ve seen in the solution runner before.
* Finally, ABP Studio also adds **DNS records to your hosts file**, so you can access to internal Kubernetes services directly with their service names, in addition to their IP addresses.
All of these happen when you click the Connect button on the ABP Studio. Now, your computer can use the **internals of the Kubernetes cluster**. But, how the HTTP Requests coming to the Product service in the Kubernetes cluster are **redirected to your local machine**?
* When you want to run and test a service locally, you **intercept the matched service** in the Kubernetes cluster. When you Intercept a service, ABP Studio makes some more changes in your local computer and in your Kubernetes cluster.
* As first, it installs a **pod** and a **service** into the Kubernetes cluster to intercept the requests coming to the Product microservice and **proxies the requests to** a client application in **your local computer**.
* The local client application then **forwards requests** to the Product microservice instance you are running in your local machine. In this way, whenever the Product service is used in Kubernetes, your local product service is executed. You can easily run, test or debug your service as you normally do with your standard IDE, for example with Visual Studio.
* What happens when your local product service needs to **access** the SQL Server database or RabbitMQ, or another microservice in the Kubernetes cluster? It can **directly use** them just like local services, through the **VPN tunnel** we have already created.
* ABP Studio makes a final change in your local product microservice project: It overrides all the **environment variables** with the ones obtained from the product service in the Kubernetes pod. In this way, your local product service instance feels itself in the Kubernetes cluster. Database connection strings and all other settings will be the same with the Kubernetes environment.
Don’t worry, ABP Studio **doesn’t change your local environment variables**. The change only affects the live product service instance, and it is **reverted** when you disable the interception in ABP Studio. Also, when you click the **Disconnect** button in ABP Studio, all the changes made to your cluster and your local computer will be cleared. It won’t leave any sign in your systems.
### ABP Studio Kubernetes Tunnel Demo
So, now we have a fully Kubernetes integrated development environment. Let’s see how it is used in ABP Studio in the following 9-minutes demo:
<iframe width="560" height="315" src="https://www.youtube.com/embed/CeUq2ysz-mQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
[Click here to watch the demo on YouTube](https://www.youtube.com/watch?v=CeUq2ysz-mQ)
## ABP Studio Roadmap
In the next months, the team will be working on the following items:
* Our first goal is to **finalize and stabilize** the current features. We will also **document** how to use them. Only after that, we will open it to customers as a beta version.
* We’ve focused on the development part until now. We also want to add some **deployment** capabilities to ABP Studio in the future.
* Another goal is to make **module customizations** much easier than current by the help of ABP Studio. With ABP Studio, we have completely re-though how to discover and install modules. Based on that, we will also work on a common place to publish and consume application modules for the ABP Framework.
We have other great plans for that product. However, I can not declare them yet as they are secrets for now :) We’ve planned to release the first beta version in **Q3 of 2023**.
I want to notice that ABP Studio is not a new version or replacement of **ABP Suite**. We built the ABP Studio from scratch. Both products will be developed and shipped in parallel. ABP Suite will continue to focus on code generation. ABP Studio doesn’t have any code generation capabilities yet. So, you will use both of them together.
## Summary
Okay let’s summarize what I’ve explained in this article:
* First, I explained **why it is hard to set up a microservice development environment**. We’ve talked about the hardness of developing, running and testing a single microservice that depends on infrastructure services and other microservices.
* I’ve introduced **Project Tye**, a project developed by Microsoft to allow you to easily run multi-application solutions. We made a demo, then discussed its missing points.
* Then I **introduced ABP Studio**, a new product by Volosoft for ABP developers.
As the first important feature, I explained the ABP Studio **Solution Runner** and demonstrated how it works and how you can develop and debug your services.
* Finally, I introduced ABP Studio’s **Kubernetes Tunneling** feature. First, I explained how it works with a complicated diagram. Then I made a short demo to see it in action.
With that final part, we had a **great and easy to use microservice development environment**. It is great, because we can focus on only a single service, while we don’t care about all other parts of the solution. Also, we can save our local development machine system resources by delegating running the dependencies to a remote Kubernetes server.
## See Also
* ABP Dotnet Conf'23 Talk on YouTube: [Kubernetes Integrated Microservice Development with ABP Studio](https://www.youtube.com/watch?v=XiPRcIHJ3NE)

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

@ -55,4 +55,4 @@ Your backend should be running successfully
There is a demo app. The path of the demo app is `npm\ng-packs\apps\dev-app`. The demo app is connected to the packages with local references. Open the terminal in `npm\ng-packs\apps\dev-app` and execute `yarn` or `npm i` in terminal. After the package installed run `npm start` or `yarn start`. There is a demo app. The path of the demo app is `npm\ng-packs\apps\dev-app`. The demo app is connected to the packages with local references. Open the terminal in `npm\ng-packs\apps\dev-app` and execute `yarn` or `npm i` in terminal. After the package installed run `npm start` or `yarn start`.
The repo uses Nx and packages connected with `local references`. The packages path is `”npm\ng-packs\packages` The repo uses Nx and packages connected with `local references`. The packages path is `npm\ng-packs\packages`

45
docs/en/Distributed-Event-Bus.md

@ -185,6 +185,51 @@ If you perform **database operations** and use the [repositories](Repositories.m
> The handler class must be registered to the dependency injection (DI). The sample above uses the `ITransientDependency` to accomplish it. See the [DI document](Dependency-Injection.md) for more options. > The handler class must be registered to the dependency injection (DI). The sample above uses the `ITransientDependency` to accomplish it. See the [DI document](Dependency-Injection.md) for more options.
## Monitoring Distributed Events
The ABP Framework allows you to stay informed when your application **receives** or **sends** a distributed event. This capability enables you to track the event flow within your application and take appropriate actions based on the received or sent distributed events.
### Received Events
The `DistributedEventReceived` local event is published when your application receives an event from the distributed event bus. `DistributedEventReceived` class has the following fields:
- **`Source`:** It represents the source of the distributed event. Source can be `Direct`, `Inbox`, `Outbox`.
- **`EventName`:** It represents the [name](#event-name) of the event received.
- **`EventData`:** It represents the actual data associated with the event received. Since it is of type `object`, it can hold any type of data.
**Example: Get informed when your application receives an event from the distributed event bus**
```csharp
public class DistributedEventReceivedHandler : ILocalEventHandler<DistributedEventReceived>, ITransientDependency
{
public async Task HandleEventAsync(DistributedEventReceived eventData)
{
// TODO: IMPLEMENT YOUR LOGIC...
}
}
```
### Sent Events
The `DistributedEventSent` local event is published when your application sends an event to the distributed event bus. `DistributedEventSent` class has the following fields:
- **`Source`:** It represents the source of the distributed event. Source can be `Direct`, `Inbox`, `Outbox`.
- **`EventName`:** It represents the [name](#event-name) of the event sent.
- **`EventData`:** It represents the actual data associated with the event sent. Since it is of type `object`, it can hold any type of data.
**Example: Get informed when your application sends an event to the distributed event bus**
```csharp
public class DistributedEventSentHandler : ILocalEventHandler<DistributedEventSent>, ITransientDependency
{
public async Task HandleEventAsync(DistributedEventSent eventData)
{
// TODO: IMPLEMENT YOUR LOGIC...
}
}
```
You can seamlessly integrate event-tracking capabilities into your application by subscribing to the `DistributedEventReceived` and `DistributedEventSent` local events as above examples. This empowers you to effectively monitor the messaging flow, diagnose any potential issues, and gain valuable insights into the behavior of your distributed messaging system.
## Pre-Defined Events ## Pre-Defined Events

19
docs/en/Entity-Framework-Core.md

@ -7,24 +7,11 @@ This document explains how to integrate EF Core as an ORM provider to ABP based
`Volo.Abp.EntityFrameworkCore` is the main NuGet package for the EF Core integration. Install it to your project (for a layered application, to your data/infrastructure layer): `Volo.Abp.EntityFrameworkCore` is the main NuGet package for the EF Core integration. Install it to your project (for a layered application, to your data/infrastructure layer):
```` shell ```` shell
Install-Package Volo.Abp.EntityFrameworkCore abp add-package Volo.Abp.EntityFrameworkCore
```` ````
Then add `AbpEntityFrameworkCoreModule` module dependency (`DependsOn` attribute) to your [module](Module-Development-Basics.md): > If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.EntityFrameworkCore).
>
````c#
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpEntityFrameworkCoreModule))]
public class MyModule : AbpModule
{
//...
}
}
````
> Note: Instead, you can directly download a [startup template](https://abp.io/Templates) with EF Core pre-installed. > Note: Instead, you can directly download a [startup template](https://abp.io/Templates) with EF Core pre-installed.

8
docs/en/Getting-Started-AspNetCore-Application.md

@ -18,11 +18,13 @@ This tutorial explains how to start ABP from scratch with minimal dependencies.
## Install Volo.Abp.AspNetCore.Mvc Package ## Install Volo.Abp.AspNetCore.Mvc Package
Volo.Abp.AspNetCore.Mvc is the AspNet Core MVC integration package for ABP. So, install it on your project: You can use the [ABP CLI](CLI.md) to install the Volo.Abp.AspNetCore.Mvc package to your project. Execute the following command in the folder of the .csproj file that you want to install the package on:
````bash
abp add-package Volo.Abp.AspNetCore.Mvc
```` ````
Install-Package Volo.Abp.AspNetCore.Mvc
```` > If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.AspNetCore.Mvc).
## Create the First ABP Module ## Create the First ABP Module

41
docs/en/Getting-Started-React-Native.md

@ -36,17 +36,9 @@ abp new MyCompanyName.MyProjectName -csf -u <angular or mvc> -m react-native
This command will prepare a solution with an **Angular** or an **MVC** (depends on your choice), a **.NET Core**, and a **React Native** project in it. This command will prepare a solution with an **Angular** or an **MVC** (depends on your choice), a **.NET Core**, and a **React Native** project in it.
### 2. Direct Download ### 2. Generating a CLI Command from Get Started Page
You may [download a solution scaffold directly on ABP.io](https://abp.io/get-started) if you are more comfortable with GUI or simply want to try ABP without installing the CLI. You can generate a CLI command on the [get started page of the abp.io website](https://abp.io/get-started). Then, use the command on your terminal to create a new [Startup Template](./Startup-Templates/Index.md).
Please do the following:
1. Click on the "DIRECT DOWNLOAD" tab.
2. Fill out the short form about your project.
3. Click on the "Create now" button.
...and a customized download will start in a few seconds.
## How to Configure & Run the Backend ## How to Configure & Run the Backend
@ -54,26 +46,6 @@ Please do the following:
> When you are using OpenIddict, You should remove 'clientSecret' on Environment.js (if exists) and disable "HTTPS-only" settings. (Openiddict has default since Version 6.0) > When you are using OpenIddict, You should remove 'clientSecret' on Environment.js (if exists) and disable "HTTPS-only" settings. (Openiddict has default since Version 6.0)
### How to disable Https-only in Openiddict.
You should add this code on {{ if Tiered == "No" }}`MyProjectNameHttpApiHostModule`{{ else if Tiered == "Yes" }}`MyProjectNameAuthServerModule`{{ end }}.
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
#if DEBUG
PreConfigure<OpenIddictServerBuilder>(options =>
{
options
.UseAspNetCore()
.DisableTransportSecurityRequirement();
});
#endif
//....
}
```
A React Native application running on an Android emulator or a physical phone **can not connect to the backend** on `localhost`. To fix this problem, it is necessary to run the backend application on your **local IP address**. A React Native application running on an Android emulator or a physical phone **can not connect to the backend** on `localhost`. To fix this problem, it is necessary to run the backend application on your **local IP address**.
{{ if Tiered == "No"}} {{ if Tiered == "No"}}
@ -99,13 +71,14 @@ Run the backend application as described in the [getting started document](Getti
## How to disable the Https-only settings of OpenIddict ## How to disable the Https-only settings of OpenIddict
Go to MyProjectNameHttpApiHostModule.cs under the host project. And put these codes under the `PreConfigureServices` function. Open the {{ if Tiered == "No" }}`MyProjectNameHttpApiHostModule`{{ else if Tiered == "Yes" }}`MyProjectNameAuthServerModule`{{ end }} project and copy-paste the below code-block to the `PreConfigureServices` method:
```csharp ```csharp
#if DEBUG #if DEBUG
PreConfigure<OpenIddictServerBuilder>(options => { PreConfigure<OpenIddictServerBuilder>(options =>
options.UseAspNetCore() {
.DisableTransportSecurityRequirement(); options.UseAspNetCore()
.DisableTransportSecurityRequirement();
}); });
#endif #endif
``` ```

380
docs/en/Image-Manipulation.md

@ -0,0 +1,380 @@
# Image Manipulation
ABP Framework provides services to compress and resize images and implements these services with popular [ImageSharp](https://sixlabors.com/products/imagesharp/) and [Magick.NET](https://github.com/dlemstra/Magick.NET) libraries. You can use these services in your reusable modules, libraries and applications, so you don't depend on a specific imaging library.
> The image resizer/compressor system is designed to be extensible. You can implement your own image resizer/compressor contributor and use it in your application.
## Installation
You can add this package to your application by either using the [ABP CLI](CLI.md) or manually installing it. Using the [ABP CLI](CLI.md) is the recommended approach.
### Using the ABP CLI
Open a command line terminal in the folder of your project (.csproj file) and type the following command:
```bash
abp add-package Volo.Abp.Imaging.Abstractions
```
### Manual Installation
If you want to manually install;
1. Add the [Volo.Abp.Imaging.Abstractions](https://www.nuget.org/packages/Volo.Abp.Imaging.Abstractions) NuGet package to your project:
```
Install-Package Volo.Abp.Imaging.Abstractions
```
2. Add the `AbpImagingAbstractionsModule` to the dependency list of your module:
```csharp
[DependsOn(
//...other dependencies
typeof(AbpImagingAbstractionsModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
```
## Providers
ABP Framework provides two image resizer/compressor implementations out of the box:
* [Magick.NET](#magicknet-provider)
* [ImageSharp](#imagesharp-provider)
You should install one of these provides to make it actually working.
> If none of the provider packages installed into your application, compress/resize operations return the untouched input image.
## IImageResizer
You can [inject](Dependency-Injection.md) the `IImageResizer` service and use it for image resize operations. Here is the available methods of the `IImageResizer` service:
```csharp
public interface IImageResizer
{
/* Works with a Stream object that represents an image */
Task<ImageResizeResult<Stream>> ResizeAsync(
Stream stream,
ImageResizeArgs resizeArgs,
string mimeType = null,
CancellationToken cancellationToken = default
);
/* Works with a byte array that contains an image file */
Task<ImageResizeResult<byte[]>> ResizeAsync(
byte[] bytes,
ImageResizeArgs resizeArgs,
string mimeType = null,
CancellationToken cancellationToken = default
);
}
```
**Example usage:**
```csharp
var result = await _imageResizer.ResizeAsync(
stream, /* A stream object that represents an image */
new ImageResizeArgs
{
Width = 100,
Height = 100,
Mode = ImageResizeMode.Crop
},
mimeType: "image/jpeg"
);
```
> You can use `MimeTypes.Image.Jpeg` constant instead of the `image/jpeg` magic string used in that example.
### ImageResizeArgs
The `ImageResizeArgs` is a class that is used to define the resize operation parameters. It has the following properties:
* `Width`: The width of the resized image.
* `Height`: The height of the resized image.
* `Mode`: The resize mode (see the [ImageResizeMode](#imageresizemode) section for more information).
### ImageResizeMode
The `ImageResizeMode` is an enum that is used to define the resize mode. It has the following values:
```csharp
public enum ImageResizeMode : byte
{
None = 0,
Stretch = 1,
BoxPad = 2,
Min = 3,
Max = 4,
Crop = 5,
Pad = 6,
Default = 7
}
```
> See the [ImageSharp documentation](https://docs.sixlabors.com/api/ImageSharp/SixLabors.ImageSharp.Processing.ResizeMode.html) for more information about the resize modes.
### ImageResizeResult
The `ImageResizeResult` is a generic class that is used to return the result of the image resize operations. It has the following properties:
* `Result`: The resized image (stream or byte array).
* `State`: The result of the resize operation (type: `ImageProcessState`).
### ImageProcessState
The `ImageProcessState` is an enum that is used to return the the result of the image resize operations. It has the following values:
```csharp
public enum ImageProcessState : byte
{
Done = 1,
Canceled = 2,
Unsupported = 3,
}
```
### ImageResizeOptions
`ImageResizeOptions` is an [options object](Options.md) that is used to configure the image resize system. It has the following properties:
* `DefaultResizeMode`: The default resize mode. (Default: `ImageResizeMode.None`)
## IImageCompressor
You can [inject](Dependency-Injection.md) the `IImageCompressor` service and use it for image compression operations. Here is the available methods of the `IImageCompressor` service:
```csharp
public interface IImageCompressor
{
/* Works with a Stream object that represents an image */
Task<ImageCompressResult<Stream>> CompressAsync(
Stream stream,
string mimeType = null,
CancellationToken cancellationToken = default
);
/* Works with a byte array that contains an image file */
Task<ImageCompressResult<byte[]>> CompressAsync(
byte[] bytes,
string mimeType = null,
CancellationToken cancellationToken = default
);
}
```
**Example usage:**
```csharp
var result = await _imageCompressor.CompressAsync(
stream, /* A stream object that represents an image */
mimeType: "image/jpeg"
);
```
### ImageCompressResult
The `ImageCompressResult` is a generic class that is used to return the result of the image compression operations. It has the following properties:
* `Result`: The compressed image (stream or byte array).
* `State`: The result of the compress operation (type: `ImageProcessState`).
### ImageProcessState
The `ImageProcessState` is an enum that is used to return the the result of the image compress operations. It has the following values:
```csharp
public enum ImageProcessState : byte
{
Done = 1,
Canceled = 2,
Unsupported = 3,
}
```
## Magick.NET Provider
`Volo.Abp.Imaging.MagickNet` NuGet package implements the image operations using the [Magick.NET](https://github.com/dlemstra/Magick.NET) library.
## Installation
You can add this package to your application by either using the [ABP CLI](CLI.md) or manually installing it. Using the [ABP CLI](CLI.md) is the recommended approach.
### Using the ABP CLI
Open a command line terminal in the folder of your project (.csproj file) and type the following command:
```bash
abp add-package Volo.Abp.Imaging.MagickNet
```
### Manual Installation
If you want to manually install;
1. Add the [Volo.Abp.Imaging.MagickNet](https://www.nuget.org/packages/Volo.Abp.Imaging.MagickNet) NuGet package to your project:
```
Install-Package Volo.Abp.Imaging.MagickNet
```
2. Add `AbpImagingMagickNetModule` to your [module](Module-Development-Basics.md)'s dependency list:
```csharp
[DependsOn(typeof(AbpImagingMagickNetModule))]
public class MyModule : AbpModule
{
//...
}
```
### Configuration
`MagickNetCompressOptions` is an [options object](Options.md) that is used to configure the Magick.NET image compression system. It has the following properties:
* `OptimalCompression`: Indicates whether the optimal compression is enabled or not. (Default: `false`)
* `IgnoreUnsupportedFormats`: Indicates whether the unsupported formats are ignored or not. (Default: `false`)
* `Lossless`: Indicates whether the lossless compression is enabled or not. (Default: `false`)
## ImageSharp Provider
`Volo.Abp.Imaging.ImageSharp` NuGet package implements the image operations using the [ImageSharp](https://github.com/SixLabors/ImageSharp) library.
## Installation
You can add this package to your application by either using the [ABP CLI](CLI.md) or manually installing it. Using the [ABP CLI](CLI.md) is the recommended approach.
### Using the ABP CLI
Open a command line terminal in the folder of your project (.csproj file) and type the following command:
```bash
abp add-package Volo.Abp.Imaging.ImageSharp
```
### Manual Installation
If you want to manually install;
1. Add the [Volo.Abp.Imaging.ImageSharp](https://www.nuget.org/packages/Volo.Abp.Imaging.ImageSharp) NuGet package to your project:
```
Install-Package Volo.Abp.Imaging.ImageSharp
```
2. Add `AbpImagingImageSharpModule` to your [module](Module-Development-Basics.md)'s dependency list:
```csharp
[DependsOn(typeof(AbpImagingImageSharpModule))]
public class MyModule : AbpModule
{
//...
}
```
### Configuration
`ImageSharpCompressOptions` is an [options object](Options.md) that is used to configure the ImageSharp image compression system. It has the following properties:
* `DefaultQuality`: The default quality of the JPEG and WebP encoders. (Default: `75`)
* [`JpegEncoder`](https://docs.sixlabors.com/api/ImageSharp/SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder.html): The JPEG encoder. (Default: `JpegEncoder` with `Quality` set to `DefaultQuality`)
* [`PngEncoder`](https://docs.sixlabors.com/api/ImageSharp/SixLabors.ImageSharp.Formats.Png.PngEncoder.html): The PNG encoder. (Default: `PngEncoder` with `IgnoreMetadata` set to `true` and `CompressionLevel` set to `PngCompressionLevel.BestCompression`)
* [`WebPEncoder`](https://docs.sixlabors.com/api/ImageSharp/SixLabors.ImageSharp.Formats.Webp.WebpEncoder.html): The WebP encoder. (Default: `WebPEncoder` with `Quality` set to `DefaultQuality`)
**Example usage:**
```csharp
Configure<ImageSharpCompressOptions>(options =>
{
options.JpegEncoder = new JpegEncoder
{
Quality = 60
};
options.PngEncoder = new PngEncoder
{
CompressionLevel = PngCompressionLevel.BestCompression
};
options.WebPEncoder = new WebPEncoder
{
Quality = 65
};
});
```
## ASP.NET Core Integration
`Volo.Abp.Imaging.AspNetCore` NuGet package defines attributes for controller actions that can automatically compress and/or resize uploaded files.
## Installation
You can add this package to your application by either using the [ABP CLI](CLI.md) or manually installing it. Using the [ABP CLI](CLI.md) is the recommended approach.
### Using the ABP CLI
Open a command line terminal in the folder of your project (.csproj file) and type the following command:
```bash
abp add-package Volo.Abp.Imaging.AspNetCore
```
### Manual Installation
If you want to manually install;
1. Add the [Volo.Abp.Imaging.AspNetCore](https://www.nuget.org/packages/Volo.Abp.Imaging.AspNetCore) NuGet package to your project:
```
Install-Package Volo.Abp.Imaging.AspNetCore
```
2. Add `AbpImagingAspNetCoreModule` to your [module](Module-Development-Basics.md)'s dependency list:
```csharp
[DependsOn(typeof(AbpImagingAspNetCoreModule))]
public class MyModule : AbpModule
{
//...
}
```
### CompressImageAttribute
The `CompressImageAttribute` is used to compress the image before. `IFormFile`, `IRemoteStreamContent`, `Stream` and `IEnumrable<byte>` types are supported. It has the following properties:
* `Parameters`: Names of the the parameters that are used to configure the image compression system. This is useful if your action has some non-image parameters. If you don't specify the parameters names, all of the method parameters are considered as image.
**Example usage:**
```csharp
[HttpPost]
[CompressImage] /* Compresses the given file (automatically determines the file mime type) */
public async Task<IActionResult> Upload(IFormFile file)
{
//...
}
```
### ResizeImageAttribute
The `ResizeImageAttribute` is used to resize the image before requesting the action. `IFormFile`, `IRemoteStreamContent`, `Stream` and `IEnumrable<byte>` types are supported. It has the following properties:
* `Parameters`: Names of the the parameters that are used to configure the image resize system. This is useful if your action has some non-image parameters. If you don't specify the parameters names, all of the method parameters are considered as image.
* `Width`: Target width of the resized image.
* `Height`: Target height of the resized image.
* `Mode`: The resize mode (see the [ImageResizeMode](#imageresizemode) section for more information).
**Example usage:**
```csharp
[HttpPost]
[ResizeImage(Width = 100, Height = 100, Mode = ImageResizeMode.Crop)]
public async Task<IActionResult> Upload(IFormFile file)
{
//...
}
```

33
docs/en/KB/Windows-Path-Too-Long-Fix.md

@ -1,10 +1,39 @@
# How to Fix "Filename too long" Error on Windows # How to Fix "Filename too long" Error on Windows
If you encounter the "filename too long" or "unzip" error on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 250 characters. To solve this, [enable the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later). If you encounter the "filename too long" or "unzip" error on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 255 characters.
## Solution 1
Try [enabling the long path option in Windows 10](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later).
If you face long path errors related to Git, try the following command to enable long paths in Windows. If you face long path errors related to Git, try the following command to enable long paths in Windows.
``` ```
git config --system core.longpaths true git config --system core.longpaths true
``` ```
See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path See https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path
## Solution 2
You may encounter a "DirectoryNotFoundException - Could not find a part of the path" exception in Windows while using certain .NET MAUI build tools. This is related to some 32 bit .NET MAUI build tools. To resolve this issue, you can try placing the solution in the root directory of your drive, such as `C:\Projects\`. However, please note that this solution is specific to this particular exception and may not be applicable to all cases of the Windows long path issue.
## Solution 3
You can define an alias for a path in Windows by creating a symbolic link using the `mklink` command in the command prompt. Here's an example:
```
mklink /D C:\MyProject C:\my\long\path\to\solution\
```
> Your **solution (.sln)** file should be in `C:\my\long\path\to\solution\`. Keep in mind that, if you have relative paths in your .csproj file, it will not work!
This command creates a symbolic link named `MyProject` in the root of the `C:` drive that points to the `C:\my\long\path\to\solution\` directory. You can then use `C:\MyProject` to access the contents of the `C:\my\long\path\to\solution\` directory.
> Note that you need to run the command prompt as an administrator to the create symbolic links.
Then you can try building your project with `dotnet build` command.
```
dotnet build C:\MyProject\MyProjectName.sln
```

27
docs/en/Local-Event-Bus.md

@ -149,7 +149,7 @@ namespace AbpDemo
} }
```` ````
That's all. `MyHandler` is **automatically discovered** by the ABP Framework and `HandleEventAsync` is called whenever a `StockCountChangedEvent` occurs. You can inject any service and perform any required logic in your handler class. That's all. `MyHandler` is **automatically discovered** by the ABP Framework and `HandleEventAsync` is called whenever a `StockCountChangedEvent` occurs. You can inject any service and perform any required logic in your handler class.
* **One or more handlers** can subscribe to the same event. * **One or more handlers** can subscribe to the same event.
* A single event handler class can **subscribe to multiple events** by implementing the `ILocalEventHandler<TEvent>` interface for each event type. * A single event handler class can **subscribe to multiple events** by implementing the `ILocalEventHandler<TEvent>` interface for each event type.
@ -158,6 +158,29 @@ If you perform **database operations** and use the [repositories](Repositories.m
> The handler class must be registered to the dependency injection (DI). The sample above uses the `ITransientDependency` to accomplish it. See the [DI document](Dependency-Injection.md) for more options. > The handler class must be registered to the dependency injection (DI). The sample above uses the `ITransientDependency` to accomplish it. See the [DI document](Dependency-Injection.md) for more options.
### LocalEventHandlerOrder Attribute
`LocalEventHandlerOrder` attribute can be used to set the execution order for the event handlers, which can be helpful if you want to handle your event handlers in a specific order.
````csharp
[LocalEventHandlerOrder(-1)]
public class MyHandler
: ILocalEventHandler<StockCountChangedEvent>,
ITransientDependency
{
public async Task HandleEventAsync(StockCountChangedEvent eventData)
{
//TODO: your code that does something on the event
}
}
````
> By default, all event handlers have an order value of 0. Thus, if you want to take certain event handlers to be executed before other event handlers, you can set the order value as a negative value.
#### LocalEventHandlerOrderAttribute Properties
* `Order` (`int`): Used to set the execution order for a certain event handler.
### Transaction & Exception Behavior ### Transaction & Exception Behavior
Event handlers are always executed in the same [unit of work](Unit-Of-Work.md) scope, that means in the same database transaction with the code that published the event. If an event handler throws an exception, the unit of work (database transaction) is rolled back. So, **use try-catch yourself** in the event handler if you want to hide the error. Event handlers are always executed in the same [unit of work](Unit-Of-Work.md) scope, that means in the same database transaction with the code that published the event. If an event handler throws an exception, the unit of work (database transaction) is rolled back. So, **use try-catch yourself** in the event handler if you want to hide the error.
@ -205,7 +228,7 @@ The pre-built event types are;
* `EntityDeletedEventData<T>` is published just after an entity was successfully deleted. * `EntityDeletedEventData<T>` is published just after an entity was successfully deleted.
* `EntityChangedEventData<T>` is published just after an entity was successfully created, updated or deleted. It can be a shortcut if you need to listen any type of change - instead of subscribing to the individual events. * `EntityChangedEventData<T>` is published just after an entity was successfully created, updated or deleted. It can be a shortcut if you need to listen any type of change - instead of subscribing to the individual events.
#### How It Was Implemented? ### How It Was Implemented?
Pre-build events are published when you save changes to the database; Pre-build events are published when you save changes to the database;

8
docs/en/Localization.md

@ -6,11 +6,13 @@ ABP's localization system is seamlessly integrated to the `Microsoft.Extensions.
> This package is already installed by default with the startup template. So, most of the time, you don't need to install it manually. > This package is already installed by default with the startup template. So, most of the time, you don't need to install it manually.
Volo.Abp.Localization is the core package of the localization system. Install it to your project using the package manager console (PMC): You can use the [ABP CLI](CLI.md) to install the Volo.Abp.Localization package to your project. Execute the following command in the folder of the .csproj file that you want to install the package on:
```bash
abp add-package Volo.Abp.Localization
``` ```
Install-Package Volo.Abp.Localization
``` > If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.Localization).
Then you can add **AbpLocalizationModule** dependency to your module: Then you can add **AbpLocalizationModule** dependency to your module:

28
docs/en/Migration-Guides/Abp-7_3.md

@ -0,0 +1,28 @@
# ABP Version 7.3 Migration Guide
This document is a guide for upgrading ABP v7.2 solutions to ABP v7.3. There are a few changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
## OpenIddict - Refactoring of `ClaimsPrincipal`
There are some changes that you might need to fix in your code. You can see the following list of the required changes:
* `AbpOpenIddictClaimDestinationsManager` was renamed as `AbpOpenIddictClaimsPrincipalManager`.
* Use `AbpOpenIddictClaimsPrincipalManager.HandleAsync` instead of `AbpOpenIddictClaimDestinationsManager.SetAsync`, which is removed.
* `AbpDefaultOpenIddictClaimDestinationsProvider` was renamed as `AbpDefaultOpenIddictClaimsPrincipalHandler`.
* `IAbpOpenIddictClaimDestinationsProvider` was renamed as `IAbpOpenIddictClaimsPrincipalHandler`.
* Use `IAbpOpenIddictClaimsPrincipalHandler.HandleAsync` instead of `IAbpOpenIddictClaimDestinationsProvider.SetAsync`, which is removed.
* `AbpOpenIddictClaimDestinationsOptions` was renamed as `AbpOpenIddictClaimsPrincipalOptions`.
Please check [this PR](https://github.com/abpframework/abp/pull/16537) if you encounter any problems related to OpenIddict Module.
## Nonce attribute support for Content Security Policy (CSP)
ABP Framework supports adding unique value to nonce attribute for script tags which can be used by Content Security Policy to determine whether or not a given fetch will be allowed to proceed for a given element. In other words, it provides a mechanism to execute only correct script tags with the correct nonce value.
> See the [Security Headers](../UI/AspNetCore/Security-Headers.md) documentation for more information.
This feature comes with a small restriction. If you use any C# code used inside the script tag, it may cause errors (Because a new `NonceScriptTagHelper` has been added, and it replaces script tags in the HTML contents).
For example, `<script @string.Empty></script>` will no longer work. However, you can use the C# code for an attribute of script tag, for example, `<script src="@string.Empty"></script>` is completely valid and won't cause any problem.
> Note: You should not use any C# code used inside the script tag, even if you don't use this feature. Because it might cause errors.

1
docs/en/Migration-Guides/Index.md

@ -2,6 +2,7 @@
The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../Upgrading.md). The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../Upgrading.md).
- [7.2 to 7.3](Abp-7_3.md)
- [7.1 to 7.2](Abp-7_2.md) - [7.1 to 7.2](Abp-7_2.md)
- [7.0 to 7.1](Abp-7_1.md) - [7.0 to 7.1](Abp-7_1.md)
- [6.0 to 7.0](Abp-7_0.md) - [6.0 to 7.0](Abp-7_0.md)

8
docs/en/Migration-Guides/docs/en/Migration-Guides/Abp-7_4.md

@ -0,0 +1,8 @@
# ABP Version 7.4 Migration Guide
This document is a guide for upgrading ABP v7.3 solutions to ABP v7.4. There are a few changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
## TemplateDefinition
The `LocalizationResource(Type)` of `TemplateDefinition` class is changed to `LocalizationResourceName(string)`.

6
docs/en/Modules/Cms-Kit/Blogging.md

@ -118,4 +118,8 @@ This module follows the [Domain Services Best Practices & Conventions](https://d
- CmsBlogs - CmsBlogs
- CmsBlogPosts - CmsBlogPosts
- CmsBlogFeatures - CmsBlogFeatures
## Entity Extensions
Check the ["Entity Extensions" section of the CMS Kit Module documentation](Index.md#entity-extensions) to see how to extend entities of the Blogging Feature of the CMS Kit module.

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

@ -80,3 +80,66 @@ All tables/collections use the `Cms` prefix by default. Set static properties on
This module uses `CmsKit` for the connection string name. If you don't define a connection string with this name, it fallbacks to the `Default` connection string. This module uses `CmsKit` for the connection string name. If you don't define a connection string with this name, it fallbacks to the `Default` connection string.
See the [connection strings](https://docs.abp.io/en/abp/latest/Connection-Strings) documentation for details. See the [connection strings](https://docs.abp.io/en/abp/latest/Connection-Strings) documentation for details.
## Entity Extensions
[Module entity extension](https://docs.abp.io/en/abp/latest/Module-Entity-Extensions) system is a **high-level** extension system that allows you to **define new properties** for existing entities of the dependent modules. It automatically **adds properties to the entity**, **database**, **HTTP API and user interface** in a single point.
To extend entities of the CMS Kit Pro module, open your `YourProjectNameModuleExtensionConfigurator` class inside of your `DomainShared` project and change the `ConfigureExtraProperties` method like shown below.
```csharp
public static void ConfigureExtraProperties()
{
OneTimeRunner.Run(() =>
{
ObjectExtensionManager.Instance.Modules()
.ConfigureCmsKit(cmsKit =>
{
cmsKit.ConfigureBlog(plan => // extend the Blog entity
{
plan.AddOrUpdateProperty<string>( //property type: string
"BlogDescription", //property name
property => {
//validation rules
property.Attributes.Add(new RequiredAttribute()); //adds required attribute to the defined property
//...other configurations for this property
}
);
});
cmsKit.ConfigureBlogPost(blogPost => // extend the BlogPost entity
{
blogPost.AddOrUpdateProperty<string>( //property type: string
"BlogPostDescription", //property name
property => {
//validation rules
property.Attributes.Add(new RequiredAttribute()); //adds required attribute to the defined property
property.Attributes.Add(
new StringLengthAttribute(MyConsts.MaximumDescriptionLength) {
MinimumLength = MyConsts.MinimumDescriptionLength
}
);
//...other configurations for this property
}
);
});
});
});
}
```
* `ConfigureCmsKit(...)` method is used to configure the entities of the CMS Kit module.
* `cmsKit.ConfigureBlog(...)` is used to configure the **Blog** entity of the CMS Kit module. You can add or update your extra properties of the
**Blog** entity.
* `cmsKit.ConfigureBlogPost(...)` is used to configure the **BlogPost** entity of the CMS Kit module. You can add or update your extra properties of the **BlogPost** entity.
* You can also set some validation rules for the property that you defined. In the above sample, `RequiredAttribute` and `StringLengthAttribute` were added for the property named **"BlogPostDescription"**.
* When you define the new property, it will automatically add to **Entity**, **HTTP API** and **UI** for you.
* Once you define a property, it appears in the create and update forms of the related entity.
* New properties also appear in the datatable of the related page.

8
docs/en/Modules/Virtual-File-Explorer.md

@ -10,9 +10,13 @@ Virtual File Explorer Module provided a simple UI to view all files in [virtual
#### 1- Use ABP CLI #### 1- Use ABP CLI
It is recommended to use the ABP CLI to install the module, open the CMD window in the solution file (`.sln`) directory, and run the following command: It is recommended to use the [ABP CLI](../CLI.md) to install the module, open the CMD window in the solution file (`.sln`) directory, and run the following command:
`abp add-module Volo.VirtualFileExplorer` ```
abp add-module Volo.VirtualFileExplorer
```
> If you haven't done it yet, you first need to install the [ABP CLI](../CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.VirtualFileExplorer.Web).
#### 2- Manually install #### 2- Manually install

6
docs/en/MongoDB.md

@ -4,12 +4,14 @@ This document explains how to integrate MongoDB as a database provider to ABP ba
## Installation ## Installation
`Volo.Abp.MongoDB` is the main nuget package for the MongoDB integration. Install it to your project (for a layered application, to your data/infrastructure layer): `Volo.Abp.MongoDB` is the main NuGet package for the MongoDB integration. Install it to your project (for a layered application, to your data/infrastructure layer), You can use the [ABP CLI](CLI.md) to install it to your project. Execute the following command in the folder of the .csproj file of the layer:
``` ```
Install-Package Volo.Abp.MongoDB abp add-package Volo.Abp.MongoDB
``` ```
> If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.MongoDB).
Then add `AbpMongoDbModule` module dependency to your [module](Module-Development-Basics.md): Then add `AbpMongoDbModule` module dependency to your [module](Module-Development-Basics.md):
```c# ```c#

8
docs/en/PlugIn-Modules.md

@ -61,11 +61,13 @@ Create a simple **Class Library Project** in a solution:
![simple-plugin-library](images/simple-plugin-library.png) ![simple-plugin-library](images/simple-plugin-library.png)
You can add ABP Framework packages you need to use in the module. At least, you should add the `Volo.Abp.Core` package to the project: You can add the ABP Framework packages that you need to use in the module. At least, you should add the `Volo.Abp.Core` package to the project, Execute the following command in the folder of the .csproj file that you want to install the package on:
````bash
abp add-package Volo.Abp.Core
```` ````
Install-Package Volo.Abp.Core
```` If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.Core).
Every [module](Module-Development-Basics.md) must declare a class derived from the `AbpModule`. Here, a simple module class that resolves a service and initializes it on the application startup: Every [module](Module-Development-Basics.md) must declare a class derived from the `AbpModule`. Here, a simple module class that resolves a service and initializes it on the application startup:

6
docs/en/Repositories.md

@ -140,9 +140,9 @@ public async Task<List<PersonDto>> GetListAsync(string filter)
Any standard LINQ method can be used over the `IQueryable` returned from the repository. Any standard LINQ method can be used over the `IQueryable` returned from the repository.
> This sample uses `ToList()` method, but it is **strongly suggested to use the asynchronous methods** to perform database queries, like `ToListAsync()` for this example. > This sample uses `ToList()` method, but it is **strongly suggested to use the asynchronous methods** to perform database queries, like `ToListAsync()` for this example. See the **`IQueryable` & Async Operations** section to learn how you can do it.
>
> See the **IQueryable & Async Operations** section to learn how you can do it. > **Exposing `IQueryable` to outside of a repository** class may leak your data access logic to the application layer. If you want to strictly follow the **layered architecture** principles, you can consider to implement a custom repository class and wrap your data access logic inside your repository class. You can see the ***Custom Repositories*** section to learn how to create custom repository classes for your application.
### Bulk Operations ### Bulk Operations

8
docs/en/Road-Map.md

@ -4,11 +4,11 @@ This document provides a road map, release schedule and planned features for the
## Next Versions ## Next Versions
### v7.3 ### v7.4
The next version will be 7.3 and planned to release the stable 7.3 version in July, 2023. In the version 7.3, we will mostly focus on stabilizing and enhancing existing features, improving the developer experience, as well as adding relatively minor new features. The next version will be 7.4 and planned to release the stable 7.4 version in September, 2023. In the version 7.4, we will mostly focus on stabilizing and enhancing existing features, improving the developer experience, as well as adding relatively minor new features.
See the [7.3 milestone](https://github.com/abpframework/abp/milestone/82) for all the issues we've planned to work on. See the [7.4 milestone](https://github.com/abpframework/abp/milestone/85) for all the issues we've planned to work on.
## Backlog Items ## Backlog Items
@ -28,6 +28,8 @@ Here, a list of major items in the backlog we are considering to work on in the
* [#16342](https://github.com/abpframework/abp/issues/16342) / CmsKit: Meta information for SEO * [#16342](https://github.com/abpframework/abp/issues/16342) / CmsKit: Meta information for SEO
* [#16260](https://github.com/abpframework/abp/issues/16260) / GCP Blob Storage Provider * [#16260](https://github.com/abpframework/abp/issues/16260) / GCP Blob Storage Provider
* [#15932](https://github.com/abpframework/abp/issues/15932) / Introduce ABP Diagnostics Module * [#15932](https://github.com/abpframework/abp/issues/15932) / Introduce ABP Diagnostics Module
* [#16756](https://github.com/abpframework/abp/issues/16756) / Blob Storing - Provider configuration UI
* [#16744](https://github.com/abpframework/abp/issues/16744) / State Management API
You can always check the milestone planning and the prioritized backlog issues on [the GitHub repository](https://github.com/abpframework/abp/milestones) for a detailed road map. The backlog items are subject to change. We are adding new items and changing priorities based on the community feedbacks and goals of the project. You can always check the milestone planning and the prioritized backlog issues on [the GitHub repository](https://github.com/abpframework/abp/milestones) for a detailed road map. The backlog items are subject to change. We are adding new items and changing priorities based on the community feedbacks and goals of the project.

2
docs/en/SMS-Sending.md

@ -17,6 +17,8 @@ Open a command line window in the folder of the project (.csproj file) and type
abp add-package Volo.Abp.Sms abp add-package Volo.Abp.Sms
``` ```
> If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.Sms).
### Manual Installation ### Manual Installation
If you want to manually install; If you want to manually install;

2
docs/en/SignalR-Integration.md

@ -18,6 +18,8 @@ abp add-package Volo.Abp.AspNetCore.SignalR
> You typically want to add this package to the web or API layer of your application, depending on your architecture. > You typically want to add this package to the web or API layer of your application, depending on your architecture.
> If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.AspNetCore.SignalR).
#### Manual Installation #### Manual Installation
If you want to manually install; If you want to manually install;

13
docs/en/Startup-Templates/Application.md

@ -261,6 +261,19 @@ You should run the application with the given order:
* Then run the `.HttpApi.Host` since it is used by the `.Web` application. * Then run the `.HttpApi.Host` since it is used by the `.Web` application.
* Finally, you can run the `.Web` project and login to the application (using `admin` as the username and `1q2w3E*` as the password). * Finally, you can run the `.Web` project and login to the application (using `admin` as the username and `1q2w3E*` as the password).
### Blazor UI
If you choose `Blazor` as the UI Framework (using the `-u blazor` or `-u blazor-server` option), the solution will have a project named `.Blazor`. This project contains the Blazor UI application. According to your choice, it will be a Blazor WebAssembly or Blazor Server application. If Blazor WebAssembly is selected, the solution will also have a `.HttpApi.Host`. This project is an ASP.NET Core application that hosts the backend application for the Blazor single page application.
#### .Blazor Project (Server)
The Blazor Server project is similar to the ASP.NET Core MVC project. It replaces `.Web` project with `.Blazor` in the solution structure above. It has the same folder structure and the same application flow. Since it's an ASP.NET Core application, it can contain **.cshtml** files and **.razor** components at the same time. If routing matches a razor component, the Blazor UI will be used. Otherwise, the request will be handled by the MVC framework.
![abp solution structure blazor server](../images/layered-project-dependencies-blazor-server.png)
#### .Blazor Project (WebAssembly)
The Blazor WebAssembly project is a single page application that runs on the browser. You'll see it as `.Blazor` project in the solution. It uses the `.HttpApi.Host` project to communicate with the backend. It can't be used without the backend application. It contains only **.razor** components. It's a pure client-side application. It doesn't have any server-side code. Everything in this layer will be for the client side.
![abp solution structure blazor wasm](../images/layered-project-dependencies-blazor-wasm.png)
### Angular UI ### Angular UI
If you choose `Angular` as the UI framework (using the `-u angular` option), the solution is being separated into two folders: If you choose `Angular` as the UI framework (using the `-u angular` option), the solution is being separated into two folders:

2
docs/en/Text-Templating-Razor.md

@ -16,6 +16,8 @@ Open a command line window in the folder of the project (.csproj file) and type
abp add-package Volo.Abp.TextTemplating.Razor abp add-package Volo.Abp.TextTemplating.Razor
```` ````
> If you haven't done it yet, you first need to install the [ABP CLI](CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.TextTemplating.Razor).
### Manual Installation ### Manual Installation
If you want to manually install; If you want to manually install;

2
docs/en/UI/Angular/Authorization.md

@ -32,7 +32,7 @@ According to this flow, the user is redirected to an external login page which i
### Resource Owner Password Flow ### Resource Owner Password Flow
If you implemented the [Angular UI account module](./Account-Module) to your project, you can switch the flow to resource owner password flow by changing the OAuth configuration in the _environment.ts_ files as shown below: If you have used the [Angular UI account module](./Account-Module) in your project, you can switch to the resource owner password flow by changing the OAuth configuration in the _environment.ts_ files as shown below:
```js ```js
import { Config } from '@abp/ng.core'; import { Config } from '@abp/ng.core';

41
docs/en/UI/AspNetCore/Bundling-Minification.md

@ -12,27 +12,13 @@ ABP offers a simple, dynamic, powerful, modular and built-in way.
> This package is already installed by default with the startup templates. So, most of the time, you don't need to install it manually. > This package is already installed by default with the startup templates. So, most of the time, you don't need to install it manually.
Install the `Volo.Abp.AspNetCore.Mvc.UI.Bundling` nuget package to your project: If you're not using a startup template, you can use the [ABP CLI](../../CLI.md) to install it to your project. Execute the following command in the folder that contains the .csproj file of your project:
```` ````
install-package Volo.Abp.AspNetCore.Mvc.UI.Bundling abp add-package Volo.Abp.AspNetCore.Mvc.UI.Bundling
```` ````
Then you can add the `AbpAspNetCoreMvcUiBundlingModule` dependency to your module: > If you haven't done it yet, you first need to install the [ABP CLI](../../CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.AspNetCore.Mvc.UI.Bundling).
````C#
using Volo.Abp.Modularity;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpAspNetCoreMvcUiBundlingModule))]
public class MyWebModule : AbpModule
{
//...
}
}
````
## Razor Bundling Tag Helpers ## Razor Bundling Tag Helpers
@ -308,28 +294,13 @@ Using the built-in contributors for standard packages;
> This package is already installed by default in the startup templates. So, most of the time, you don't need to install it manually. > This package is already installed by default in the startup templates. So, most of the time, you don't need to install it manually.
Standard package contributors are defined in the `Volo.Abp.AspNetCore.Mvc.UI.Packages` NuGet package. If you're not using a startup template, you can use the [ABP CLI](../../CLI.md) to install it to your project. Execute the following command in the folder that contains the .csproj file of your project:
To install it to your project:
```` ````
install-package Volo.Abp.AspNetCore.Mvc.UI.Packages abp add-package Volo.Abp.AspNetCore.Mvc.UI.Packages
```` ````
Then add the `AbpAspNetCoreMvcUiPackagesModule` module dependency to your own module; > If you haven't done it yet, you first need to install the [ABP CLI](../../CLI.md). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.AspNetCore.Mvc.UI.Packages).
````C#
using Volo.Abp.Modularity;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpAspNetCoreMvcUiPackagesModule))]
public class MyWebModule : AbpModule
{
//...
}
}
````
### Bundle Inheritance ### Bundle Inheritance

56
docs/en/UI/AspNetCore/Security-Headers.md

@ -19,7 +19,7 @@ ABP Framework allows you to add frequently used security headers into your appli
Configure<AbpSecurityHeadersOptions>(options => Configure<AbpSecurityHeadersOptions>(options =>
{ {
options.UseContentSecurityPolicyHeader = true; //false by default options.UseContentSecurityPolicyHeader = true; //false by default
options.ContentSecurityPolicyValue = "object-src 'none'; form-action 'self'; frame-ancestors 'none'"; options.ContentSecurityPolicyValue = "object-src 'none'; form-action 'self'; frame-ancestors 'none'"; //default value
//adding additional security headers //adding additional security headers
options.Headers["Referrer-Policy"] = "no-referrer"; options.Headers["Referrer-Policy"] = "no-referrer";
@ -43,3 +43,57 @@ app.UseAbpSecurityHeaders();
After that, you have registered the `UseAbpSecurityHeaders` middleware into the request pipeline, the defined security headers will be shown in the response headers as in the figure below: After that, you have registered the `UseAbpSecurityHeaders` middleware into the request pipeline, the defined security headers will be shown in the response headers as in the figure below:
![](../../images/security-response-headers.png) ![](../../images/security-response-headers.png)
## Content Security Policy Script Nonce
Abp Framework provides a property to add a dynamic script-src nonce value to the Content-Security-Policy header. With this feature, it automatically adds a dynamic nonce value to the header side. And with the help of the script tag helper, it adds this [`script nonce`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) value to the script tags on your pages(The `ScriptNonceTagHelper` in the `Volo.Abp.AspNetCore.Mvc.UI.Bundling` namespace must be attached as a taghelper.).
> If you need to add the nonce script manually, you can use 'Html.GetScriptNonce()' to add the nonce value or 'Html.GetScriptNonceAttribute()' to add the nonce attribute value.
This feature is disabled by default. You can enable it by setting the `UseContentSecurityPolicyScriptNonce` property of the `AbpSecurityHeadersOptions` class to `true`.
### Ignore Script Nonce
You can ignore the script nonce for some pages or some selectors. You can use the `IgnoredScriptNoncePaths` and `IgnoredScriptNonceSelectors` properties of the `AbpSecurityHeadersOptions` class.
**Example:**
```csharp
Configure<AbpSecurityHeadersOptions>(options =>
{
//adding script-src nonce
options.UseContentSecurityPolicyScriptNonce = true; //false by default
//ignore script nonce source for these paths
options.IgnoredScriptNoncePaths.Add("/my-page");
//ignore script nonce by Elsa Workflows and other selectors
options.IgnoredScriptNonceSelectors.Add(context =>
{
var endpoint = context.GetEndpoint();
return Task.FromResult(endpoint?.Metadata.GetMetadata<PageRouteMetadata>()?.RouteTemplate == "/{YOURHOSTPAGE}");
});
});
```
### Ignore Abp Security Headers
You can ignore the Abp Security Headers for some actions or pages. You can use the `IgnoreAbpSecurityHeaderAttribute` attribute for this.
**Example:**
```csharp
@using Volo.Abp.AspNetCore.Security
@attribute [IgnoreAbpSecurityHeaderAttribute]
```
**Example:**
```csharp
[IgnoreAbpSecurityHeaderAttribute]
public class IndexModel : AbpPageModel
{
public void OnGet()
{
}
}
```

4
docs/en/UI/AspNetCore/Tag-Helpers/Dropdowns.md

@ -70,8 +70,8 @@ Basic usage:
A value indicates which direction `abp-dropdown-menu` items will be aligned to. Should be one of the following values: A value indicates which direction `abp-dropdown-menu` items will be aligned to. Should be one of the following values:
* `Left` (default value) * `Start` (default value)
* `Right` * `End`
### Additional content ### Additional content

8
docs/en/docs-nav.json

@ -417,6 +417,10 @@
"text": "GUID Generation", "text": "GUID Generation",
"path": "Guid-Generation.md" "path": "Guid-Generation.md"
}, },
{
"text": "Image Manipulation",
"path": "Image-Manipulation.md"
},
{ {
"text": "JSON", "text": "JSON",
"path": "JSON.md" "path": "JSON.md"
@ -1351,6 +1355,10 @@
"text": "Deployment", "text": "Deployment",
"path": "Deployment/Index.md", "path": "Deployment/Index.md",
"items": [ "items": [
{
"text": "Configuring OpenIddict",
"path": "Deployment/Configuring-OpenIddict.md"
},
{ {
"text": "Configuring for Production", "text": "Configuring for Production",
"path": "Deployment/Configuring-Production.md" "path": "Deployment/Configuring-Production.md"

BIN
docs/en/images/layered-project-dependencies-blazor-server.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

BIN
docs/en/images/layered-project-dependencies-blazor-wasm.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

2
docs/zh-Hans/CLI.md

@ -44,6 +44,7 @@ dotnet tool update -g Volo.Abp.Cli
* **`logout`**: 在你的计算机注销认证. * **`logout`**: 在你的计算机注销认证.
* **`bundle`**: 为 ABP Blazor 和 MAUI Blazor 项目生成引用的脚本和样式. * **`bundle`**: 为 ABP Blazor 和 MAUI Blazor 项目生成引用的脚本和样式.
* **`install-libs`**: 为 MVC / Razor Pages 和 Blazor Server UI 类型安装NPM包. * **`install-libs`**: 为 MVC / Razor Pages 和 Blazor Server UI 类型安装NPM包.
* **`clear-download-cache`** 删除下载的模版缓存.
### help ### help
@ -142,6 +143,7 @@ abp new Acme.BookStore
* `--create-solution-folder` 或者 `-csf`: 指定项目是在输出文件夹中的新文件夹中还是直接在输出文件夹中. * `--create-solution-folder` 或者 `-csf`: 指定项目是在输出文件夹中的新文件夹中还是直接在输出文件夹中.
* `--connection-string` 或者 `-cs`: 重写所有 `appsettings.json` 文件的默认连接字符串. 默认连接字符串是 `Server=localhost;Database=MyProjectName;Trusted_Connection=True`. 默认的数据库提供程序是 `SQL Server`. 如果你使用EF Core但需要更改DBMS,可以按[这里所述](Entity-Framework-Core-Other-DBMS.md)进行更改(创建解决方案之后). * `--connection-string` 或者 `-cs`: 重写所有 `appsettings.json` 文件的默认连接字符串. 默认连接字符串是 `Server=localhost;Database=MyProjectName;Trusted_Connection=True`. 默认的数据库提供程序是 `SQL Server`. 如果你使用EF Core但需要更改DBMS,可以按[这里所述](Entity-Framework-Core-Other-DBMS.md)进行更改(创建解决方案之后).
* `--local-framework-ref --abp-path`: 使用对项目的本地引用,而不是替换为NuGet包引用. * `--local-framework-ref --abp-path`: 使用对项目的本地引用,而不是替换为NuGet包引用.
* `--skip-cache` or `-sc`: 从服务器下载最新的模版并更新本地模版缓存.
### update ### update

2
docs/zh-Hans/Deployment/Clustered-Environment.md

@ -1,4 +1,4 @@
# 部署到群集环境 # 部署到集群环境
本文档介绍了在将应用程序部署到**多个应用程序实例同时运行**的集群环境中时应注意的内容, 并解释了如何在基于ABP的应用程序中处理这些内容. 本文档介绍了在将应用程序部署到**多个应用程序实例同时运行**的集群环境中时应注意的内容, 并解释了如何在基于ABP的应用程序中处理这些内容.

2
docs/zh-Hans/Deployment/Index.md

@ -6,4 +6,4 @@
## 指南 ## 指南
* [部署到群集环境](Clustered-Environment.md): 讲解了当你希望同时运行应用程序的多个实例时, 如何来配置应用程序. * [部署到集群环境](Clustered-Environment.md): 讲解了当你希望同时运行应用程序的多个实例时, 如何来配置应用程序.

2
docs/zh-Hans/docs-nav.json

@ -715,7 +715,7 @@
"path": "Deployment/Index.md", "path": "Deployment/Index.md",
"items": [ "items": [
{ {
"text": "部署到群集环境", "text": "部署到集群环境",
"path": "Deployment/Clustered-Environment.md" "path": "Deployment/Clustered-Environment.md"
} }
] ]

63
framework/Volo.Abp.sln

@ -439,6 +439,24 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Ldap.Abstractions"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Ddd.Domain.Shared", "src\Volo.Abp.Ddd.Domain.Shared\Volo.Abp.Ddd.Domain.Shared.csproj", "{0858571B-CE73-4AD6-BD06-EC9F0714D8E9}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Ddd.Domain.Shared", "src\Volo.Abp.Ddd.Domain.Shared\Volo.Abp.Ddd.Domain.Shared.csproj", "{0858571B-CE73-4AD6-BD06-EC9F0714D8E9}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MultiTenancy.Abstractions", "src\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj", "{86F3684C-A0A5-4943-8CFA-AE79E8E3E315}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.Abstractions", "src\Volo.Abp.Imaging.Abstractions\Volo.Abp.Imaging.Abstractions.csproj", "{32F3E84B-D02E-42BD-BC5C-0D211564EF30}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.AspNetCore", "src\Volo.Abp.Imaging.AspNetCore\Volo.Abp.Imaging.AspNetCore.csproj", "{78340A37-219E-4F2D-9AC6-40A7B467EEEC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.ImageSharp", "src\Volo.Abp.Imaging.ImageSharp\Volo.Abp.Imaging.ImageSharp.csproj", "{44467427-E0BE-492C-B9B4-82B362C183C3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.MagickNet", "src\Volo.Abp.Imaging.MagickNet\Volo.Abp.Imaging.MagickNet.csproj", "{F701EDA5-D7EA-4AA7-9C57-83ED50CE72EC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.Abstractions.Tests", "test\Volo.Abp.Imaging.Abstractions.Tests\Volo.Abp.Imaging.Abstractions.Tests.csproj", "{2BE6BDC7-A9A3-4E30-9099-A9EF4813F6FF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.ImageSharp.Tests", "test\Volo.Abp.Imaging.ImageSharp.Tests\Volo.Abp.Imaging.ImageSharp.Tests.csproj", "{1E161A34-10C1-46FA-9EFD-10DD0858A8F5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.MagickNet.Tests", "test\Volo.Abp.Imaging.MagickNet.Tests\Volo.Abp.Imaging.MagickNet.Tests.csproj", "{62B2B8C9-8F24-4D31-894F-C1F0728D32AB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.AspNetCore.Tests", "test\Volo.Abp.Imaging.AspNetCore.Tests\Volo.Abp.Imaging.AspNetCore.Tests.csproj", "{983B0136-384B-4439-B374-31111FFAA286}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -1309,6 +1327,42 @@ Global
{0858571B-CE73-4AD6-BD06-EC9F0714D8E9}.Debug|Any CPU.Build.0 = Debug|Any CPU {0858571B-CE73-4AD6-BD06-EC9F0714D8E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0858571B-CE73-4AD6-BD06-EC9F0714D8E9}.Release|Any CPU.ActiveCfg = Release|Any CPU {0858571B-CE73-4AD6-BD06-EC9F0714D8E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0858571B-CE73-4AD6-BD06-EC9F0714D8E9}.Release|Any CPU.Build.0 = Release|Any CPU {0858571B-CE73-4AD6-BD06-EC9F0714D8E9}.Release|Any CPU.Build.0 = Release|Any CPU
{86F3684C-A0A5-4943-8CFA-AE79E8E3E315}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{86F3684C-A0A5-4943-8CFA-AE79E8E3E315}.Debug|Any CPU.Build.0 = Debug|Any CPU
{86F3684C-A0A5-4943-8CFA-AE79E8E3E315}.Release|Any CPU.ActiveCfg = Release|Any CPU
{86F3684C-A0A5-4943-8CFA-AE79E8E3E315}.Release|Any CPU.Build.0 = Release|Any CPU
{32F3E84B-D02E-42BD-BC5C-0D211564EF30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{32F3E84B-D02E-42BD-BC5C-0D211564EF30}.Debug|Any CPU.Build.0 = Debug|Any CPU
{32F3E84B-D02E-42BD-BC5C-0D211564EF30}.Release|Any CPU.ActiveCfg = Release|Any CPU
{32F3E84B-D02E-42BD-BC5C-0D211564EF30}.Release|Any CPU.Build.0 = Release|Any CPU
{78340A37-219E-4F2D-9AC6-40A7B467EEEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{78340A37-219E-4F2D-9AC6-40A7B467EEEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78340A37-219E-4F2D-9AC6-40A7B467EEEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78340A37-219E-4F2D-9AC6-40A7B467EEEC}.Release|Any CPU.Build.0 = Release|Any CPU
{44467427-E0BE-492C-B9B4-82B362C183C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44467427-E0BE-492C-B9B4-82B362C183C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44467427-E0BE-492C-B9B4-82B362C183C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44467427-E0BE-492C-B9B4-82B362C183C3}.Release|Any CPU.Build.0 = Release|Any CPU
{F701EDA5-D7EA-4AA7-9C57-83ED50CE72EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F701EDA5-D7EA-4AA7-9C57-83ED50CE72EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F701EDA5-D7EA-4AA7-9C57-83ED50CE72EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F701EDA5-D7EA-4AA7-9C57-83ED50CE72EC}.Release|Any CPU.Build.0 = Release|Any CPU
{2BE6BDC7-A9A3-4E30-9099-A9EF4813F6FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2BE6BDC7-A9A3-4E30-9099-A9EF4813F6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2BE6BDC7-A9A3-4E30-9099-A9EF4813F6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2BE6BDC7-A9A3-4E30-9099-A9EF4813F6FF}.Release|Any CPU.Build.0 = Release|Any CPU
{1E161A34-10C1-46FA-9EFD-10DD0858A8F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E161A34-10C1-46FA-9EFD-10DD0858A8F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E161A34-10C1-46FA-9EFD-10DD0858A8F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E161A34-10C1-46FA-9EFD-10DD0858A8F5}.Release|Any CPU.Build.0 = Release|Any CPU
{62B2B8C9-8F24-4D31-894F-C1F0728D32AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{62B2B8C9-8F24-4D31-894F-C1F0728D32AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62B2B8C9-8F24-4D31-894F-C1F0728D32AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62B2B8C9-8F24-4D31-894F-C1F0728D32AB}.Release|Any CPU.Build.0 = Release|Any CPU
{983B0136-384B-4439-B374-31111FFAA286}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{983B0136-384B-4439-B374-31111FFAA286}.Debug|Any CPU.Build.0 = Debug|Any CPU
{983B0136-384B-4439-B374-31111FFAA286}.Release|Any CPU.ActiveCfg = Release|Any CPU
{983B0136-384B-4439-B374-31111FFAA286}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -1530,6 +1584,15 @@ Global
{8764DFAF-D13D-449A-9A5E-5D7F0B2D7FEF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {8764DFAF-D13D-449A-9A5E-5D7F0B2D7FEF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{0F80E95C-41E6-4F23-94FF-FC9D0B8D5D71} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {0F80E95C-41E6-4F23-94FF-FC9D0B8D5D71} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{0858571B-CE73-4AD6-BD06-EC9F0714D8E9} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {0858571B-CE73-4AD6-BD06-EC9F0714D8E9} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{86F3684C-A0A5-4943-8CFA-AE79E8E3E315} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{32F3E84B-D02E-42BD-BC5C-0D211564EF30} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{44467427-E0BE-492C-B9B4-82B362C183C3} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{F701EDA5-D7EA-4AA7-9C57-83ED50CE72EC} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{78340A37-219E-4F2D-9AC6-40A7B467EEEC} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{2BE6BDC7-A9A3-4E30-9099-A9EF4813F6FF} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{1E161A34-10C1-46FA-9EFD-10DD0858A8F5} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{62B2B8C9-8F24-4D31-894F-C1F0728D32AB} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{983B0136-384B-4439-B374-31111FFAA286} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

4
framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj

@ -8,10 +8,6 @@
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="$(MicrosoftAspNetCorePackageVersion)" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.MultiTenancy\Volo.Abp.AspNetCore.MultiTenancy.csproj" /> <ProjectReference Include="..\Volo.Abp.AspNetCore.MultiTenancy\Volo.Abp.AspNetCore.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.AspNetCore.Authentication.OAuth\Volo.Abp.AspNetCore.Authentication.OAuth.csproj" /> <ProjectReference Include="..\Volo.Abp.AspNetCore.Authentication.OAuth\Volo.Abp.AspNetCore.Authentication.OAuth.csproj" />

78
framework/src/Volo.Abp.AspNetCore.Components.Server/Microsoft/AspNetCore/Authentication/Cookies/CookieAuthenticationOptionsExtensions.cs

@ -1,7 +1,9 @@
using System; using System;
using System.Threading.Tasks;
using IdentityModel.Client; using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authentication.Cookies; namespace Microsoft.AspNetCore.Authentication.Cookies;
@ -16,41 +18,67 @@ public static class CookieAuthenticationOptionsExtensions
/// <returns></returns> /// <returns></returns>
public static CookieAuthenticationOptions IntrospectAccessToken(this CookieAuthenticationOptions options, string oidcAuthenticationScheme = "oidc") public static CookieAuthenticationOptions IntrospectAccessToken(this CookieAuthenticationOptions options, string oidcAuthenticationScheme = "oidc")
{ {
var originalHandler = options.Events.OnValidatePrincipal;
options.Events.OnValidatePrincipal = async principalContext => options.Events.OnValidatePrincipal = async principalContext =>
{ {
originalHandler?.Invoke(principalContext); if (principalContext.Principal == null || principalContext.Principal.Identity == null || !principalContext.Principal.Identity.IsAuthenticated)
{
return;
}
var logger = principalContext.HttpContext.RequestServices.GetRequiredService<ILogger<CookieAuthenticationOptions>>();
if (principalContext.Principal != null && principalContext.Principal.Identity != null && principalContext.Principal.Identity.IsAuthenticated) var accessToken = principalContext.Properties.GetTokenValue("access_token");
if (!accessToken.IsNullOrWhiteSpace())
{ {
var accessToken = principalContext.Properties.GetTokenValue("access_token"); var openIdConnectOptions = await GetOpenIdConnectOptions(principalContext, oidcAuthenticationScheme);
if (!accessToken.IsNullOrWhiteSpace()) var response = await openIdConnectOptions.Backchannel.IntrospectTokenAsync(new TokenIntrospectionRequest
{
Address = openIdConnectOptions.Configuration?.IntrospectionEndpoint ?? openIdConnectOptions.Authority.EnsureEndsWith('/') + "connect/introspect",
ClientId = openIdConnectOptions.ClientId,
ClientSecret = openIdConnectOptions.ClientSecret,
Token = accessToken
});
if (response.IsError)
{ {
var openIdConnectOptions = principalContext.HttpContext.RequestServices.GetRequiredService<IOptionsMonitor<OpenIdConnectOptions>>().Get(oidcAuthenticationScheme); logger.LogError(response.Error);
if (openIdConnectOptions.Configuration == null && openIdConnectOptions.ConfigurationManager != null) await SignOutAsync(principalContext);
{ return;
openIdConnectOptions.Configuration = await openIdConnectOptions.ConfigurationManager.GetConfigurationAsync(principalContext.HttpContext.RequestAborted);
}
var response = await openIdConnectOptions.Backchannel.IntrospectTokenAsync(new TokenIntrospectionRequest
{
Address = openIdConnectOptions.Configuration?.IntrospectionEndpoint ?? openIdConnectOptions.Authority.EnsureEndsWith('/') + "connect/introspect",
ClientId = openIdConnectOptions.ClientId,
ClientSecret = openIdConnectOptions.ClientSecret,
Token = accessToken
});
if (response.IsActive)
{
return;
}
} }
principalContext.RejectPrincipal(); if (!response.IsActive)
await principalContext.HttpContext.SignOutAsync(principalContext.Scheme.Name); {
logger.LogError("The access_token is not active.");
await SignOutAsync(principalContext);
return;
}
logger.LogInformation("The access_token is active.");
}
else
{
logger.LogError("The access_token is not found in the cookie properties, Please make sure SaveTokens of OpenIdConnectOptions is set as true.");
await SignOutAsync(principalContext);
} }
}; };
return options; return options;
} }
private async static Task<OpenIdConnectOptions> GetOpenIdConnectOptions(CookieValidatePrincipalContext principalContext, string oidcAuthenticationScheme)
{
var openIdConnectOptions = principalContext.HttpContext.RequestServices.GetRequiredService<IOptionsMonitor<OpenIdConnectOptions>>().Get(oidcAuthenticationScheme);
if (openIdConnectOptions.Configuration == null && openIdConnectOptions.ConfigurationManager != null)
{
openIdConnectOptions.Configuration = await openIdConnectOptions.ConfigurationManager.GetConfigurationAsync(principalContext.HttpContext.RequestAborted);
}
return openIdConnectOptions;
}
private async static Task SignOutAsync(CookieValidatePrincipalContext principalContext)
{
principalContext.RejectPrincipal();
await principalContext.HttpContext.SignOutAsync(principalContext.Scheme.Name);
}
} }

7
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/StandardLayouts.cs

@ -1,6 +1,11 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Layout; using System;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Layout;
public static class StandardLayouts public static class StandardLayouts
{ {
public const string Application = "Application"; public const string Application = "Application";
public const string Account = "Account";
public const string Public = "Public";
public const string Empty = "Empty";
} }

13
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/AbpThemingOptions.cs

@ -0,0 +1,13 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Theming;
public class AbpThemingOptions
{
public ThemeDictionary Themes { get; }
public string DefaultThemeName { get; set; }
public AbpThemingOptions()
{
Themes = new ThemeDictionary();
}
}

34
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/DefaultThemeManager.cs

@ -0,0 +1,34 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Theming;
public class DefaultThemeManager : IThemeManager, IScopedDependency, IServiceProviderAccessor
{
public IServiceProvider ServiceProvider { get; }
public ITheme CurrentTheme => GetCurrentTheme();
private ITheme _currentTheme;
protected IThemeSelector ThemeSelector { get; }
public DefaultThemeManager(
IServiceProvider serviceProvider,
IThemeSelector themeSelector)
{
ServiceProvider = serviceProvider;
ThemeSelector = themeSelector;
}
protected virtual ITheme GetCurrentTheme()
{
if (_currentTheme != null)
{
return _currentTheme;
}
_currentTheme = (ITheme)ServiceProvider.GetRequiredService(ThemeSelector.GetCurrentThemeInfo().ThemeType);
return CurrentTheme;
}
}

36
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/DefaultThemeSelector.cs

@ -0,0 +1,36 @@
using System.Linq;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Theming;
public class DefaultThemeSelector : IThemeSelector, ITransientDependency
{
protected AbpThemingOptions Options { get; }
public DefaultThemeSelector(IOptions<AbpThemingOptions> options)
{
Options = options.Value;
}
public virtual ThemeInfo GetCurrentThemeInfo()
{
if (!Options.Themes.Any())
{
throw new AbpException($"No theme registered! Use {nameof(AbpThemingOptions)} to register themes.");
}
if (Options.DefaultThemeName == null)
{
return Options.Themes.Values.First();
}
var themeInfo = Options.Themes.Values.FirstOrDefault(t => t.Name == Options.DefaultThemeName);
if (themeInfo == null)
{
throw new AbpException("Default theme is configured but it's not found in the registered themes: " + Options.DefaultThemeName);
}
return themeInfo;
}
}

8
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/ITheme.cs

@ -0,0 +1,8 @@
using System;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Theming;
public interface ITheme
{
Type GetLayout(string name, bool fallbackToDefault = true);
}

6
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/IThemeManager.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Theming;
public interface IThemeManager
{
ITheme CurrentTheme { get; }
}

6
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/IThemeSelector.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Theming;
public interface IThemeSelector
{
ThemeInfo GetCurrentThemeInfo();
}

23
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/ThemeDictionary.cs

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Theming;
public class ThemeDictionary : Dictionary<Type, ThemeInfo>
{
public ThemeInfo Add<TTheme>()
where TTheme : ITheme
{
return Add(typeof(TTheme));
}
public ThemeInfo Add(Type themeType)
{
if (ContainsKey(themeType))
{
throw new AbpException("This theme is already added before: " + themeType.AssemblyQualifiedName);
}
return this[themeType] = new ThemeInfo(themeType);
}
}

27
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/ThemeExtensions.cs

@ -0,0 +1,27 @@
using System;
using Volo.Abp.AspNetCore.Components.Web.Theming.Layout;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Theming;
public static class ThemeExtensions
{
public static Type GetApplicationLayout(this ITheme theme, bool fallbackToDefault = true)
{
return theme.GetLayout(StandardLayouts.Application, fallbackToDefault);
}
public static Type GetAccountLayout(this ITheme theme, bool fallbackToDefault = true)
{
return theme.GetLayout(StandardLayouts.Account, fallbackToDefault);
}
public static Type GetPublicLayout(this ITheme theme, bool fallbackToDefault = true)
{
return theme.GetLayout(StandardLayouts.Public, fallbackToDefault);
}
public static Type GetEmptyLayout(this ITheme theme, bool fallbackToDefault = true)
{
return theme.GetLayout(StandardLayouts.Empty, fallbackToDefault);
}
}

24
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/ThemeInfo.cs

@ -0,0 +1,24 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Theming;
public class ThemeInfo
{
public Type ThemeType { get; }
public string Name { get; }
public ThemeInfo([NotNull] Type themeType)
{
Check.NotNull(themeType, nameof(themeType));
if (!typeof(ITheme).IsAssignableFrom(themeType))
{
throw new AbpException($"Given {nameof(themeType)} ({themeType.AssemblyQualifiedName}) should be type of {typeof(ITheme).AssemblyQualifiedName}");
}
ThemeType = themeType;
Name = ThemeNameAttribute.GetName(themeType);
}
}

23
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/ThemeNameAttribute.cs

@ -0,0 +1,23 @@
using System;
using System.Linq;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Theming;
[AttributeUsage(AttributeTargets.Class)]
public class ThemeNameAttribute : Attribute
{
public string Name { get; set; }
public ThemeNameAttribute(string name)
{
Name = name;
}
public static string GetName(Type themeType)
{
return themeType
.GetCustomAttributes(true)
.OfType<ThemeNameAttribute>()
.FirstOrDefault()?.Name ?? themeType.Name;
}
}

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

@ -23,6 +23,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="$(MicrosoftAspNetCorePackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="$(MicrosoftAspNetCorePackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="$(MicrosoftAspNetCorePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
</ItemGroup> </ItemGroup>

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

@ -19,7 +19,7 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly;
typeof(AbpAspNetCoreMvcClientCommonModule), typeof(AbpAspNetCoreMvcClientCommonModule),
typeof(AbpUiModule), typeof(AbpUiModule),
typeof(AbpAspNetCoreComponentsWebModule) typeof(AbpAspNetCoreComponentsWebModule)
)] )]
public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) public override void PreConfigureServices(ServiceConfigurationContext context)

40
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ClientProxyExceptionEventHandler.cs

@ -0,0 +1,40 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus;
using Volo.Abp.Http;
namespace Volo.Abp.AspNetCore.Components.WebAssembly;
public class ClientProxyExceptionEventHandler : ILocalEventHandler<ClientProxyExceptionEventData>, ITransientDependency
{
protected NavigationManager NavigationManager { get; }
protected IAccessTokenProvider AccessTokenProvider { get; }
public ClientProxyExceptionEventHandler(NavigationManager navigationManager, IAccessTokenProvider accessTokenProvider)
{
NavigationManager = navigationManager;
AccessTokenProvider = accessTokenProvider;
}
public virtual async Task HandleEventAsync(ClientProxyExceptionEventData eventData)
{
if (eventData.StatusCode == 401)
{
var result = await AccessTokenProvider.RequestAccessToken();
if (result.Status != AccessTokenResultStatus.Success)
{
NavigationManager.NavigateToLogout("authentication/logout");
return;
}
result.TryGetToken(out var token);
if (token != null && DateTimeOffset.Now >= token.Expires.AddMinutes(-5))
{
NavigationManager.NavigateToLogout("authentication/logout");
}
}
}
}

1
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Extensibility/WebAssemblyLookupApiRequestService.cs

@ -3,7 +3,6 @@ using System.Globalization;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Castle.Components.DictionaryAdapter; using Castle.Components.DictionaryAdapter;
using Fody;
using Volo.Abp.AspNetCore.Components.Web.Extensibility; using Volo.Abp.AspNetCore.Components.Web.Extensibility;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.Authentication; using Volo.Abp.Http.Client.Authentication;

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

@ -18,6 +18,7 @@
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" /> <ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" /> <ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" /> <ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

4
framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpAspNetCoreComponentsModule.cs

@ -4,6 +4,7 @@ using Volo.Abp.AspNetCore.Components.DependencyInjection;
using Volo.Abp.DynamicProxy; using Volo.Abp.DynamicProxy;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping; using Volo.Abp.ObjectMapping;
using Volo.Abp.Security; using Volo.Abp.Security;
using Volo.Abp.Timing; using Volo.Abp.Timing;
@ -13,7 +14,8 @@ namespace Volo.Abp.AspNetCore.Components;
[DependsOn( [DependsOn(
typeof(AbpObjectMappingModule), typeof(AbpObjectMappingModule),
typeof(AbpSecurityModule), typeof(AbpSecurityModule),
typeof(AbpTimingModule) typeof(AbpTimingModule),
typeof(AbpMultiTenancyAbstractionsModule)
)] )]
public class AbpAspNetCoreComponentsModule : AbpModule public class AbpAspNetCoreComponentsModule : AbpModule
{ {

29
framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -21,7 +22,6 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController
var daprSerializer = HttpContext.RequestServices.GetRequiredService<IDaprSerializer>(); var daprSerializer = HttpContext.RequestServices.GetRequiredService<IDaprSerializer>();
var body = (await JsonDocument.ParseAsync(HttpContext.Request.Body)); var body = (await JsonDocument.ParseAsync(HttpContext.Request.Body));
var id = body.RootElement.GetProperty("id").GetString();
var pubSubName = body.RootElement.GetProperty("pubsubname").GetString(); var pubSubName = body.RootElement.GetProperty("pubsubname").GetString();
var topic = body.RootElement.GetProperty("topic").GetString(); var topic = body.RootElement.GetProperty("topic").GetString();
var data = body.RootElement.GetProperty("data").GetRawText(); var data = body.RootElement.GetProperty("data").GetRawText();
@ -32,8 +32,31 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController
} }
var distributedEventBus = HttpContext.RequestServices.GetRequiredService<DaprDistributedEventBus>(); var distributedEventBus = HttpContext.RequestServices.GetRequiredService<DaprDistributedEventBus>();
var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic));
await distributedEventBus.TriggerHandlersAsync(id, distributedEventBus.GetEventType(topic), eventData); if (IsAbpDaprEventData(data))
{
var daprEventData = daprSerializer.Deserialize(data, typeof(AbpDaprEventData)).As<AbpDaprEventData>();
var eventData = daprSerializer.Deserialize(daprEventData.JsonData, distributedEventBus.GetEventType(daprEventData.Topic));
await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(daprEventData.Topic), eventData, daprEventData.MessageId, daprEventData.CorrelationId);
}
else
{
var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic));
await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(topic), eventData);
}
return Ok(); return Ok();
} }
protected virtual bool IsAbpDaprEventData(string data)
{
var document = JsonDocument.Parse(data);
var objects = document.RootElement.EnumerateObject().ToList();
return objects.Count == 5 &&
objects.Any(x => x.Name.Equals("PubSubName", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("Topic", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("MessageId", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("JsonData", StringComparison.CurrentCultureIgnoreCase)) &&
objects.Any(x => x.Name.Equals("CorrelationId", StringComparison.CurrentCultureIgnoreCase));
}
} }

22
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelper.cs

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Mvc.ViewFeatures;
@ -21,6 +22,8 @@ public class AbpDynamicFormTagHelper : AbpTagHelper<AbpDynamicFormTagHelper, Abp
public bool? RequiredSymbols { get; set; } = true; public bool? RequiredSymbols { get; set; } = true;
#region MvcFormTagHelperAttiributes #region MvcFormTagHelperAttiributes
private IDictionary<string, string> _routeValues;
private const string ActionAttributeName = "asp-action"; private const string ActionAttributeName = "asp-action";
private const string AreaAttributeName = "asp-area"; private const string AreaAttributeName = "asp-area";
@ -57,7 +60,22 @@ public class AbpDynamicFormTagHelper : AbpTagHelper<AbpDynamicFormTagHelper, Abp
public string Method { get; set; } public string Method { get; set; }
[HtmlAttributeName(RouteValuesDictionaryName, DictionaryAttributePrefix = RouteValuesPrefix)] [HtmlAttributeName(RouteValuesDictionaryName, DictionaryAttributePrefix = RouteValuesPrefix)]
public IDictionary<string, string> RouteValues { get; set; } public IDictionary<string, string> RouteValues
{
get
{
if (_routeValues == null)
{
_routeValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
return _routeValues;
}
set
{
_routeValues = value;
}
}
#endregion #endregion

22
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs

@ -5,6 +5,7 @@ using System.Text;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading.Tasks; using System.Threading.Tasks;
using Localization.Resources.AbpUi; using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.TagHelpers; using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Mvc.ViewFeatures;
@ -99,14 +100,16 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
{ {
var contentBuilder = new StringBuilder(""); var contentBuilder = new StringBuilder("");
contentBuilder.AppendLine("<div class=\"row\">");
foreach (var item in items.OrderBy(o => o.Order)) foreach (var item in items.OrderBy(o => o.Order))
{ {
contentBuilder.AppendLine(SetColumn(item.HtmlContent)); contentBuilder.AppendLine(SetColumn(item.HtmlContent));
} }
contentBuilder.AppendLine("</div>"); if (TagHelper.ColumnSize != ColumnSize.Undefined && TagHelper.ColumnSize != ColumnSize._)
{
contentBuilder.Insert(0, "<div class=\"row\">");
contentBuilder.AppendLine("</div>");
}
var content = childContent.GetContent(); var content = childContent.GetContent();
if (content.Contains(AbpFormContentPlaceHolder)) if (content.Contains(AbpFormContentPlaceHolder))
@ -316,6 +319,13 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
{ {
return list; return list;
} }
if (IsFile(model.ModelType))
{
list.Add(ModelExplorerToModelExpressionConverter(model));
return list;
}
return model.Properties.Aggregate(list, ExploreModelsRecursively); return model.Properties.Aggregate(list, ExploreModelsRecursively);
} }
@ -368,6 +378,12 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
{ {
return type == typeof(List<SelectListItem>) || type == typeof(IEnumerable<SelectListItem>); return type == typeof(List<SelectListItem>) || type == typeof(IEnumerable<SelectListItem>);
} }
protected virtual bool IsFile(Type type)
{
return typeof(IFormFile).IsAssignableFrom(type) ||
typeof(IEnumerable<IFormFile>).IsAssignableFrom(type);
}
protected virtual bool IsSelectGroup(TagHelperContext context, ModelExpression model) protected virtual bool IsSelectGroup(TagHelperContext context, ModelExpression model)
{ {

39
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelperService.cs

@ -22,11 +22,42 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form.DatePicker;
public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelperService<TTagHelper> public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelperService<TTagHelper>
where TTagHelper : AbpDatePickerBaseTagHelper<TTagHelper> where TTagHelper : AbpDatePickerBaseTagHelper<TTagHelper>
{ {
protected readonly Dictionary<Type,Func<object,string>> SupportedInputTypes = new() { protected readonly Dictionary<Type, Func<object, string>> SupportedInputTypes = new()
{typeof(string), o => DateTime.Parse((string)o).ToString("O")}, {
{typeof(DateTime), o => ((DateTime) o).ToString("O")}, {
typeof(string), o =>
{
if(o is string s && DateTime.TryParse(s, out var dt))
{
return dt.ToString("O");
}
return string.Empty;
}
},
{
typeof(DateTime), o =>
{
if(o is DateTime dt && dt != default)
{
return dt.ToString("O");
}
return string.Empty;
}
},
{typeof(DateTime?), o => ((DateTime?) o)?.ToString("O")}, {typeof(DateTime?), o => ((DateTime?) o)?.ToString("O")},
{typeof(DateTimeOffset), o => ((DateTimeOffset) o).ToString("O")}, {
typeof(DateTimeOffset), o =>
{
if(o is DateTimeOffset dto && dto != default)
{
return dto.ToString("O");
}
return string.Empty;
}
},
{typeof(DateTimeOffset?), o => ((DateTimeOffset?) o)?.ToString("O")} {typeof(DateTimeOffset?), o => ((DateTimeOffset?) o)?.ToString("O")}
}; };

9
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelperService.cs

@ -63,11 +63,14 @@ public class AbpDatePickerTagHelperService : AbpDatePickerBaseTagHelperService<A
protected override void AddBaseTagAttributes(TagHelperAttributeList attributes) protected override void AddBaseTagAttributes(TagHelperAttributeList attributes)
{ {
if (TagHelper.AspFor != null && if (TagHelper.AspFor?.Model != null &&
TagHelper.AspFor.Model != null &&
SupportedInputTypes.TryGetValue(TagHelper.AspFor.Metadata.ModelType, out var convertFunc)) SupportedInputTypes.TryGetValue(TagHelper.AspFor.Metadata.ModelType, out var convertFunc))
{ {
attributes.Add("data-date", convertFunc(TagHelper.AspFor.Model)); var convert = convertFunc(TagHelper.AspFor.Model);
if(!convert.IsNullOrWhiteSpace())
{
attributes.Add("data-date", convert);
}
} }
} }

5
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperScriptService.cs

@ -49,6 +49,9 @@ public class AbpTagHelperScriptService : AbpTagHelperResourceService
var deferText = (defer || Options.DeferScriptsByDefault || Options.DeferScripts.Any(x => file.StartsWith(x, StringComparison.OrdinalIgnoreCase))) var deferText = (defer || Options.DeferScriptsByDefault || Options.DeferScripts.Any(x => file.StartsWith(x, StringComparison.OrdinalIgnoreCase)))
? "defer" ? "defer"
: string.Empty; : string.Empty;
output.Content.AppendHtml($"<script {deferText} src=\"{viewContext.GetUrlHelper().Content(file.EnsureStartsWith('~'))}\"></script>{Environment.NewLine}"); var nonceText = (viewContext.HttpContext.Items.TryGetValue(AbpAspNetCoreConsts.ScriptNonceKey, out var nonce) && nonce is string nonceString && !string.IsNullOrEmpty(nonceString))
? $"nonce=\"{nonceString}\""
: string.Empty;
output.Content.AppendHtml($"<script {deferText} {nonceText} src=\"{viewContext.GetUrlHelper().Content(file.EnsureStartsWith('~'))}\"></script>{Environment.NewLine}");
} }
} }

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

Loading…
Cancel
Save