diff --git a/.github/scripts/update_versions.py b/.github/scripts/update_versions.py index dcbd749796..1f593273bc 100644 --- a/.github/scripts/update_versions.py +++ b/.github/scripts/update_versions.py @@ -1,54 +1,79 @@ import os import json +import re +import xml.etree.ElementTree as ET from github import Github -def update_latest_versions(): - version = os.environ["GITHUB_REF"].split("/")[-1] +def get_target_release_branch(version): + """ + Extracts the first two numbers from the release version (`9.0.5` → `rel-9.0`) + to determine the corresponding `rel-x.x` branch. + """ + match = re.match(r"(\d+)\.(\d+)\.\d+", version) + if not match: + raise ValueError(f"Invalid version format: {version}") - if "rc" in version: - return False + major, minor = match.groups() + target_branch = f"rel-{major}.{minor}" + return target_branch - with open("latest-versions.json", "r") as f: - latest_versions = json.load(f) +def get_version_from_common_props(branch): + """ + Retrieves `Version` and `LeptonXVersion` from the `common.props` file in the specified branch. + """ + g = Github(os.environ["GITHUB_TOKEN"]) + repo = g.get_repo("abpframework/abp") - latest_versions[0]["version"] = version + try: + file_content = repo.get_contents("common.props", ref=branch) + common_props_content = file_content.decoded_content.decode("utf-8") - with open("latest-versions.json", "w") as f: - json.dump(latest_versions, f, indent=2) + root = ET.fromstring(common_props_content) + version = root.find(".//Version").text + leptonx_version = root.find(".//LeptonXVersion").text - return True + return version, leptonx_version + except Exception as e: + raise FileNotFoundError(f"common.props not found in branch {branch}: {e}") -def create_pr(): - g = Github(os.environ["GITHUB_TOKEN"]) - repo = g.get_repo("abpframework/abp") +def update_latest_versions(): + """ + Updates `latest-versions.json` based on the most relevant release branch. + """ + # Get the release version from GitHub reference + release_version = os.environ["GITHUB_REF"].split("/")[-1] # Example: "refs/tags/v9.0.5" → "v9.0.5" + if release_version.startswith("v"): + release_version = release_version[1:] # Convert to "9.0.5" format - branch_name = f"update-latest-versions-{os.environ['GITHUB_REF'].split('/')[-1]}" - base = repo.get_branch("dev") - repo.create_git_ref(ref=f"refs/heads/{branch_name}", sha=base.commit.sha) + # Determine the correct `rel-x.x` branch + target_branch = get_target_release_branch(release_version) + + # Retrieve `common.props` data from the target branch + version, leptonx_version = get_version_from_common_props(target_branch) - # Get the current latest-versions.json file and its sha - contents = repo.get_contents("latest-versions.json", ref="dev") - file_sha = contents.sha + # Skip if the version is a preview or release candidate + if "preview" in version or "rc" in version: + return False - # Update the file in the repo - repo.update_file( - path="latest-versions.json", - message=f"Update latest-versions.json to version {os.environ['GITHUB_REF'].split('/')[-1]}", - content=open("latest-versions.json", "r").read().encode("utf-8"), - sha=file_sha, - branch=branch_name, - ) + # Read the `latest-versions.json` file + with open("latest-versions.json", "r") as f: + latest_versions = json.load(f) - try: - pr = repo.create_pull(title="Update latest-versions.json", - 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}") + # Add the new version entry + new_version_entry = { + "version": version, + "releaseDate": "", + "type": "stable", + "message": "", + "leptonx": { + "version": leptonx_version + } + } + + latest_versions.insert(0, new_version_entry) # Insert the new version at the top - pr.create_review_request(reviewers=["ebicoglu", "gizemmutukurt", "skoc10"]) + # Update the file + with open("latest-versions.json", "w") as f: + json.dump(latest_versions, f, indent=2) -if __name__ == "__main__": - should_create_pr = update_latest_versions() - if should_create_pr: - create_pr() \ No newline at end of file + return True diff --git a/Directory.Packages.props b/Directory.Packages.props index 5edba60ff5..144960a60d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,12 +15,13 @@ + - - - - + + + + @@ -37,6 +38,10 @@ + + + + @@ -51,69 +56,70 @@ - - - - - - - - - - + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + @@ -123,11 +129,11 @@ - - - - - + + + + + @@ -158,18 +164,18 @@ - + - + - + - - - - + + + + diff --git a/README.md b/README.md index 7cf41d47eb..a6199aab9b 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ -# ABP Framework - + ![build and test](https://img.shields.io/github/actions/workflow/status/abpframework/abp/build-and-test.yml?branch=dev&style=flat-square) 🔹 [![codecov](https://codecov.io/gh/abpframework/abp/branch/dev/graph/badge.svg?token=jUKLCxa6HF)](https://codecov.io/gh/abpframework/abp) 🔹 [![NuGet](https://img.shields.io/nuget/v/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) 🔹 [![NuGet (with prereleases)](https://img.shields.io/nuget/vpre/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) 🔹 [![MyGet (nightly builds)](https://img.shields.io/myget/abp-nightly/vpre/Volo.Abp.svg?style=flat-square)](https://abp.io/docs/latest/release-info/nightly-builds) 🔹 [![NuGet Download](https://img.shields.io/nuget/dt/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) 🔹 [![Code of Conduct](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](https://github.com/abpframework/abp/blob/dev/CODE_OF_CONDUCT.md) 🔹 [![CLA Signed](https://cla-assistant.io/readme/badge/abpframework/abp)](https://cla-assistant.io/abpframework/abp) 🔹 [![Discord Shield](https://discord.com/api/guilds/951497912645476422/widget.png?style=shield)](https://abp.io/join-discord) [ABP](https://abp.io/) offers an **opinionated architecture** to build enterprise software solutions with **best practices** on top of the **.NET** and the **ASP.NET Core** platforms. It provides the fundamental infrastructure, production-ready startup templates, pre-built application modules, UI themes, tooling, guides and documentation to implement that architecture properly and **automate the details** and repetitive works as much as possible. -[![ABP Platform](https://github.com/user-attachments/assets/200653c0-0e69-4b47-b76a-3a83460aaab6)](https://abp.io) +[![ABP Platform](https://github.com/user-attachments/assets/c4356ec7-4d0f-4e00-a1d2-fc74ad985fb8)](https://abp.io) + + ## Getting Started diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json index db3249e881..59edeb9031 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/en.json @@ -16,6 +16,7 @@ "IdentityUserNotAvailable:Deleted": "This email address is not available. Reason: Already deleted.", "SelectYourOrganization": "Select your organization", "PleaseSelectOrganization": "Please select an organization to continue", - "Continue": "Continue" + "Continue": "Continue", + "CaptchaExplanation": "Calculate the below mathematical expression and enter the answer." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index ea150de47e..1ea52ff5f5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -607,7 +607,9 @@ "OrganizationDoesNotHaveACreditCardInGateway": "Organization does not have a credit card in the gateway!", "Permission:EditWinners": "Edit Winners", "Permission:ChangeDrawingStatus": "Change Drawing Status", - "Menu:Licenses": "Licensing", + "Menu:LicenseSettings": "License Settings", + "Menu:Licensing": "Licensing", + "Menu:Campaigns": "Campaigns", "OrganizationId": "Organization Id", "RemoveAllWinnersConfirmationMessage": "Are you sure you want to remove all winners?", "AutoRenewals": "Auto Renewals", @@ -665,8 +667,29 @@ "EditAttendees": "Edit attendees", "ExportAttendeesAsExcel": "Export attendees as Excel", "DuplicateRaffle": "Duplicate raffle", + "LicenseMonthsOnNewPurchase": "License Months for New License", + "LicenseMonthsOnRenewPurchase": "License Months for License Renewal", + "SupportQuestionCountPerDeveloperOnRenewLicense": "Support Question Count Per Developer for License Renewal", + "SupportQuestionCountPerDeveloperOnNewLicense": "Support Question Count Per Developer for New License", + "IncludedDeveloperCount": "Included Developer Count", + "CanBuyAdditionalDevelopers": "Can Buy Additional Developers", + "HasEmailSupport": "Has Email Support", + "IsSupportPrivateQuestion": "Can Open Private Support Question", + "AdditionalDeveloperPrice": "Additional Developer Price", + "LicenseUpgradePrice": "License Upgrade Price", + "AdditionalDeveloperUpgradePrice": "Additional Developer Upgrade Price", + "EditLicense{0}": "Edit {0} License", + "CampaignNameAlreadyExists": "Campaign name already exists", + "DiscountRate": "Discount Rate", "Menu:RedisManagement": "Redis Management", "RedisManagement": "Redis Management", - "Permission:RedisManagement": "Redis Management" + "Permission:RedisManagement": "Redis Management", + "UserCleanUp": "User Clean Up", + "Permission:UserCleanUp": "User Clean Up", + "AllowPrivateQuestion": "Allow Private Question", + "Permission:Campaigns": "Campaigns", + "Permission:Licenses": "License Settings", + "BlockUserPolicy": "User Block Policies", + "Permission:BlockUserPolicy": "User Block Policy" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json index 4890226d9a..31f6186258 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json @@ -252,6 +252,7 @@ "DoYouAgreePrivacyPolicy": "By clicking Subscribe button you agree to the Terms & Conditions and Privacy Policy.", "AbpConferenceDescription": "ABP Conference is a virtual event for .NET developers to learn and connect with the community.", "Mobile": "Mobile", - "MetaTwitterCard": "summary_large_image" + "MetaTwitterCard": "summary_large_image", + "IPAddress": "IP Address" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 4856813fe1..b81733d247 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -645,7 +645,7 @@ "ExtendPaymentInfoSection_Description": "By extending/renewing your license, you will continue to get premium support. You will also be able to get major or minor updates for modules and themes. You will be able to continue creating new projects. And you will still be able to use ABP Suite which speeds up your development.", "LicenseRenewalPrice": "License renewal price", "LicensePrice": "License Price", - "TrialLicensePaymentInfoSection_Description": "Purchase license: By purchasing a license, you will continue to get premium support. You will also be able to get major or minor updates for modules and themes. You will be able to continue creating new projects. And you will still be able to use ABP Suite which speeds up your development.
See the license comparison table to check the differences between the license types.", + "TrialLicensePaymentInfoSection_Description": "Purchase license: By purchasing a license, you will continue to get premium support. You will also be able to get major or minor updates for modules and themes. You will be able to continue creating new projects. And you will still be able to use ABP Suite which speeds up your development.
See the license comparison table to check the differences between the license types.", "SelectTargetLicense": "Select Target License", "UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "Yes, extend my license expiration date for 1 year.", "UpgradePaymentInfoSection_WantToExtendLicense": "Do you want to extend your license for 1 more year?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index 08e1687357..bed79bc302 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -505,8 +505,8 @@ "AbpIoPlatformExplanation2": "In the core, it provides an open source and free framework that consists of hundreds of NuGet and NPM packages, each offering different functionalities. The core framework is modular, themeable and microservice compatible, providing a complete architecture and a robust infrastructure. This allows you to focus on your business code rather than repeating yourself for every new project. It is based on the best practices of software development and integrates popular tools you're already familiar with. The framework is completely free, open source and community-driven.", "AbpIoPlatformExplanation3": "The ABP Platform offers free and paid licensing options. Depending on your license type, you can access multiple production-ready startup templates, many pre-built application modules, UI themes, CLI and GUI tooling, support and more.", "WhatAreTheDifferencesBetweenFreeAndPaid": "What are the differences between the free and commercial licenses?", - "WhatAreTheDifferencesBetweenFreeAndPaidExplanation1": "Free (open source) ABP license includes the core framework, basic startup templates, basic modules, basic themes and the community edition of ABP Studio.", - "WhatAreTheDifferencesBetweenFreeAndPaidExplanation2": "Commercial licenses offer additional features, including more startup templates (such as the microservice startup template), professional application modules, a full-featured UI theme, professional editions of ABP Studio, ABP Suite for code generation, more options for mobile startup applications, premium support and some other benefits.", + "WhatAreTheDifferencesBetweenFreeAndPaidExplanation1": "Free (open source) ABP license includes the core framework, basic startup templates, basic modules, basic themes and the community edition of ABP Studio.", + "WhatAreTheDifferencesBetweenFreeAndPaidExplanation2": "Commercial licenses offer additional features, including more startup templates (such as the microservice startup template), professional application modules, a full-featured UI theme, professional editions of ABP Studio, ABP Suite for code generation, more options for mobile startup applications, premium support and some other benefits.", "WhatAreTheDifferencesBetweenFreeAndPaidExplanation3": "For more information about the differences between the license types, please see the pricing page.", "HowDoIUseTheABPIOPlatform": "How do I use the ABP Platform?", "HowDoIUseTheABPIOPlatformExplanation": "ABP Framework extends the .NET platform, meaning 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. See the How it works page to learn how to use the ABP Platform in practice.", @@ -520,12 +520,12 @@ "DowngradeLicensePlanExplanation": "You cannot downgrade your existing license plan. For further information, contact us at info@abp.io.", "LicenseTransferExplanation": "Yes! When you purchase a license, you become the license holder, which grants you access to the organization management page. An organization includes roles for owners and developers. Owners can manage developer seats and assign developers. Each assigned developer will log in to the system using the ABP CLI command and will have permissions for development and support.", "LicenseExtendUpgradeDiff": "What is the difference between license renewal and upgrading?", - "LicenseExtendUpgradeDiffExplanation1": "Renewal: By renewing your license, you will continue to receive premium support and updates, both major and minor, for modules, tools, and themes. Additionally, you will be able to create new projects and use ABP Suite and ABP Studio, which can significantly speed up your development process. When you renew your license, one year is added to your license's expiry date.", + "LicenseExtendUpgradeDiffExplanation1": "Renewal: By renewing your license, you will continue to receive premium support and updates, both major and minor, for modules, tools, and themes. Additionally, you will be able to create new projects and use ABP Suite and ABP Studio, which can significantly speed up your development process. When you renew your license, one year is added to your license's expiry date.", "LicenseExtendUpgradeDiffExplanation2": "Upgrading: By upgrading your license, you will be promoted to a higher license plan, allowing you to receive additional benefits. Check out the pricing page to see the differences between the license plans. On the other hand, when you upgrade, your license expiry date will not change! To extend your license end date, you need to renew your license.", - "WhatHappensWhenLicenseEndsExplanation1": "ABP licenses are perpetual licenses. After your license expires, you can continue developing your project without the obligation to renew. Your license comes with a one-year update and premium support plan out of the box. To receive new features, performance enhancements, bug fixes, and continued support, as well as to use ABP Suite and ABP Studio, you need to renew your license. When your license expires;", + "WhatHappensWhenLicenseEndsExplanation1": "ABP licenses are perpetual licenses. After your license expires, you can continue developing your project without the obligation to renew. Your license comes with a one-year update and premium support plan out of the box. To receive new features, performance enhancements, bug fixes, and continued support, as well as to use ABP Suite and ABP Studio, you need to renew your license. When your license expires;", "WhatHappensWhenLicenseEndsExplanation2": "You can not create new solutions using the pro startup templates, but you can continue developing your existing applications forever.", "WhatHappensWhenLicenseEndsExplanation3": "You will receive updates for the application modules and themes within your MINOR version (excluding RC or Preview versions). For example, if you are using v3.2.0 of a module, you can still receive updates for v3.2.x (v3.2.1, v3.2.5... etc.) of that module. However, you cannot receive updates for the next major or minor version (such as v3.3.0, v3.3.3, 4.x.x.. etc.). For example, if the latest release was v4.4.3 when your license expired and later versions 4.4.4 and 4.5.0 were published, you would have access to v4.4.x but not to v4.5.x.", - "WhatHappensWhenLicenseEndsExplanation4": "You cannot install new application modules and themes added to your solution after your license ends.", + "WhatHappensWhenLicenseEndsExplanation4": "You cannot install pro application modules and themes to your solution.", "WhatHappensWhenLicenseEndsExplanation5": "You cannot use the ABP Suite.", "WhatHappensWhenLicenseEndsExplanation6": "You cannot use the ABP Studio’s pro features (you can use the Community Edition features of ABP Studio)", "WhatHappensWhenLicenseEndsExplanation7": "You will no longer have access to premium support.", @@ -535,7 +535,7 @@ "WhenShouldIRenewMyLicenseExplanation3": "{0} for Business and Enterprise Licenses;", "WhenShouldIRenewMyLicenseExplanation4": "However, if you renew your license more than {0} days after the expiry date, the renewal price will be the same as the initial purchase price of the license, with no discounts applied to your renewal.", "DoesTheSubscriptionRenewAutomaticallyExplanationAutoRenewal": "ABP Platform allows you to auto-renew your license. This is an optional free service. You can toggle this feature when you purchase a new license or later enable it from your organization management page. If you want to turn on or off the auto-renewal, visit the organization management page, go to the 'Payments Method' section and either check or uncheck the 'Automatic Renewal' checkbox. When you turn off the auto-renewal feature, it will be your responsibility to renew your license manually.", - "TrialPlanExplanation": "Yes, to start your free trial, please contact marketing@volosoft.com. We also offer a 30-day money-back guarantee for the Team license, with no questions asked! You can request a full refund within the first 30 days of purchasing the license. For Business and Enterprise licenses, we provide a 60% refund if requested within 30 days of purchase. This policy is due to the inclusion of the full source code for all modules and themes in the Business and Enterprise licenses.", + "TrialPlanExplanation": "Yes, to start your free trial, please contact sales@volosoft.com. We also offer a 30-day money-back guarantee for the Team license, with no questions asked! You can request a full refund within the first 30 days of purchasing the license. For Business and Enterprise licenses, we provide a 60% refund if requested within 30 days of purchase. This policy is due to the inclusion of the full source code for all modules and themes in the Business and Enterprise licenses.", "BlazoriseLicenseExplanation": "We have an agreement between Volosoft and Megabit, according to which the Blazorise license is bundled with the ABP Platform’s commercial licenses. Therefore, our paid users do not need to purchase an additional Blazorise license.", "HowToUpgradeExplanation1": "When you create a new application using the ABP startup templates, all the modules and themes are used as NuGet and NPM packages. This setup allows for easy upgrades to newer versions of the packages.", "HowToUpgradeExplanation2": "In addition to the standard NuGet/NPM upgrades, ABP CLI provides an update command that automatically finds and upgrades all ABP-related packages in your solution.", @@ -546,7 +546,7 @@ "MicroserviceSupportExplanation3": "ABP Platform commercial licenses also includes a microservice startup template which can be used to directly create a production ready base solution for your microservice system.", "MicroserviceSupportExplanation4": "For the non-paid users, we are also providing an example e-commerce solution that you can check to understand how you can build your microservice solution based on the ABP Framework.", "MicroserviceSupportExplanation5": "However, a microservice system is a solution, and every solution will have different requirements, including network topology, communication scenarios, authentication possibilities, database sharding/partitioning decisions, runtime configurations, 3rd party system integrations and many more aspects. The ABP platform provides infrastructure for microservice scenarios, microservice-compatible modules, samples, and documentation to assist in building your own solution. However, don't expect to directly download your ideal, custom solution pre-built for you. You will need to understand it and bring specific parts together based on your requirements.", - "WhereCanIDownloadSourceCodeExplanation": "You can download the source code of all the ABP modules, Angular packages and themes via ABP Suite, ABP Studio or ABP CLI. Check out the forum question: How to download the source-code?", + "WhereCanIDownloadSourceCodeExplanation": "You can download the source code of all the ABP modules, Angular packages and themes via ABP Suite, ABP Studio or ABP CLI. Check out the forum question: How to download the source-code?", "CommercialLicenses": "Commercial Licenses", "WhatIsDifferencePaidLicenses": "What is the difference between a personal license and other types of paid licenses?", "DifferencePaidLicenseExplanation1": "A non-personal paid license is the standard licensing option for enterprises and commercial entities. Licenses are purchased by the company and can be used by anyone within the organization.", @@ -586,10 +586,10 @@ "CreatePostSummaryInfo": "A short summary of the post to be shown on the post list. Maximum length: {0}", "CreatePostCoverInfo": "For creating an effective post, add a cover photo. Upload 16:9 aspect ratio pictures for the best view.
Maximum file size: 1MB.", "CreatePostCoverInfo_Title": "Add a cover image to your post.", - "CreatePostCoverInfo1": " Accepted file types : JPEG, JPG, PNG", - "CreatePostCoverInfo2": " Max file size : 1 MB", - "CreatePostCoverInfo3": " Image proportion : 16:9", - "CreatePostCoverInfo4": " Download a sample cover image ", + "CreatePostCoverInfo1": "Accepted file types : JPEG, JPG, PNG", + "CreatePostCoverInfo2": "Max file size : 1 MB", + "CreatePostCoverInfo3": "Image proportion : 16:9", + "CreatePostCoverInfo4": " Download a sample cover image ", "ThisExtensionIsNotAllowed": "This extension is not allowed.", "TheFileIsTooLarge": "The file is too large.", "GoToThePost": "Go to the Post", @@ -976,7 +976,7 @@ "IsSourceCodeIncludedExplanation1": "Depends on the license type you've purchased:", "IsSourceCodeIncludedExplanation2": "Team: Your solution uses the modules and themes as NuGet and NPM packages. It doesn't include their source code. This way, you can easily upgrade these modules and themes whenever a new version is available. However, you can not get the source code of these modules and themes.", "IsSourceCodeIncludedExplanation3": "Business/Enterprise: In addition to the Team license, you are able to download the source code of any module or theme you need. You can even remove the NuGet/NPM package references for a particular module and add its source code directly to your solution to fully change it.", - "IsSourceCodeIncludedExplanation4": "

Including the source code of a module to your solution gives you the maximum freedom to customize that module. However, it will then not be possible to automatically upgrade the module when a new version is released.

None of the licenses include the ABP Suite and ABP Studio source code, which is external tools that generates code for you and assists your development.

Check out the Plans & Pricing page for other differences between the license types.

", + "IsSourceCodeIncludedExplanation4": "

Including the source code of a module to your solution gives you the maximum freedom to customize that module. However, it will then not be possible to automatically upgrade the module when a new version is released.

None of the licenses include the ABP Suite and ABP Studio source code, which is external tools that generates code for you and assists your development.

Check out the Plans & Pricing page for other differences between the license types.

", "ChangingDevelopers": "Can I change the registered developers of my organization in the future?", "ChangingDevelopersExplanation": "In addition to adding new developers to your license, you can also change the existing developers (you can remove a developer and add a new one to the same seat) without any additional cost.", "WhatHappensWhenLicenseEnds": "What happens when my license period ends?", @@ -1348,7 +1348,7 @@ "ExtendPaymentInfoSection_Description": "By extending/renewing your license, you will continue to get premium support. You will also be able to get major or minor updates for modules and themes. You will be able to continue creating new projects. And you will still be able to use ABP Suite which speeds up your development.", "LicenseRenewalPrice": "License renewal price", "LicensePrice": "License Price", - "TrialLicensePaymentInfoSection_Description": "Purchase license: By purchasing a license, you will continue to get premium support. You will also be able to get major or minor updates for modules and themes. You will be able to continue creating new projects. And you will still be able to use ABP Suite which speeds up your development.
See the license comparison table to check the differences between the license types.", + "TrialLicensePaymentInfoSection_Description": "Purchase license: By purchasing a license, you will continue to get premium support. You will also be able to get major or minor updates for modules and themes. You will be able to continue creating new projects. And you will still be able to use ABP Suite which speeds up your development.
See the license comparison table to check the differences between the license types.", "SelectTargetLicense": "Select Target License", "UpgradePaymentInfoSection_ExtendMyLicenseForOneYear": "Yes, extend my license expiration date for 1 year.", "UpgradePaymentInfoSection_WantToExtendLicense": "Do you want to extend your license for 1 more year?", @@ -1868,6 +1868,24 @@ "GenerateQuote" : "Generate Quote" , "GeneratePriceQuote": "Generate a Price Quote", "Qa:QuestionPageTitle": "Support", - "SelectedTrainingName" : "Trainings" + "SelectedTrainingName" : "Trainings", + "RcStableDifference": "What is the difference between the RC version and the stable version of ABP?", + "RcStableDifferenceExplanation1": "The RC (Release Candidate) version is a pre-release version that allows early access to upcoming features and updates in the ABP project. It is primarily intended for testing purposes and for developers who want to prepare for the upcoming stable release. While it undergoes internal testing, it may still contain unresolved issues and it is not recommended for use in the production environment.", + "RcStableDifferenceExplanation2": "The Stable version is tested and officially supported for production use. It ensures reliability and compatibility.", + "RcStableDifferenceExplanation3": "Use the RC version for testing and early adoption but use the Stable version for production deployment.", + "AddToCalendar": "Add To Calendar", + "AddToGoogleCalendar": "Add To Google Calendar", + "DownloadICSFile": "Download ICS File", + "AddToAppleCalendar": "Add To Apple Calendar", + "AddToOutlookCalendar": "Add To Outlook Calendar", + "FaqIyzicoPaymentIssuesTitle" : "What should I do if I encounter issues while purchasing the Iyzico payment gateway?", + "FaqIyzicoPaymentIssuesExplanation1": "This website uses two payment gateways to receive payments: Iyzico and 2Checkout. The default gateway is Iyzico. When you check the 'Automatic Renewal' option, it will automatically use the Iyzico payment gateway. If you’re experiencing issues while trying to purchase through the Iyzico payment gateway, it could be due to the following reasons:", + "FaqIyzicoPaymentIssuesExplanation2": "Card Type: Iyzico only supports VISA and MasterCard. If you’re using a different card type (e.g., American Express), please switch to the 2Checkout payment gateway.", + "FaqIyzicoPaymentIssuesExplanation3": "3D Secure: If your card has 3D Secure enabled, you’ll be redirected to your card provider’s 3D Secure page to complete the verification process. Once done, you’ll return to Iyzico to finalize the payment. If you encounter any issues with 3D Secure, please contact your card provider for assistance. Sometimes there might be problems with the redirection to the 3D Secure provider, in that case you can disable 3D Secure or contact us.", + "FaqIyzicoPaymentIssuesExplanation4": "If you’re unable to complete the payment through Iyzico, you can use our alternative payment gateway, 2Checkout which supports a wider range of payment options, including:", + "FaqIyzicoPaymentIssuesExplanation5": "Credit/Debit Cards: Visa, MasterCard, American Express, Discover, Diners Club, JCB", + "FaqIyzicoPaymentIssuesExplanation6": "Digital Wallets: PayPal, AliPay, WebMoney", + "FaqIyzicoPaymentIssuesExplanation7": "Alternatively, you can send the license amount directly via bank wire transfer. For our bank account details, please visit: Bank Account Information (use USD currency).", + "FaqIyzicoPaymentIssuesExplanation8": "ABP website doesn't save or process your credit card. We use payment gateways for this and the entire transaction is handled by payment gateways. We have no authority to interfere with the payment process or fix the payment steps. If you have further questions or need additional support, feel free to contact us at abp.io/contact." } } diff --git a/build/common.ps1 b/build/common.ps1 index e2ba5c5566..356f2d8329 100644 --- a/build/common.ps1 +++ b/build/common.ps1 @@ -39,11 +39,13 @@ if ($full -eq "-f") "../templates/module/aspnet-core", "../templates/app/aspnet-core", "../templates/console", - "../templates/wpf", "../templates/app-nolayers/aspnet-core", "../abp_io/AbpIoLocalization", "../source-code" - ) + ) + if ($env:OS -eq "Windows_NT") { + $solutionPaths += "../templates/wpf" + } }else{ Write-host "" Write-host ":::::::::::::: !!! You are in development mode !!! ::::::::::::::" -ForegroundColor red -BackgroundColor yellow diff --git a/common.props b/common.props index a448dccda1..b1355eb36a 100644 --- a/common.props +++ b/common.props @@ -1,8 +1,8 @@ latest - 9.1.0 - 4.1.0 + 9.2.0-preview + 4.2.0-preview $(NoWarn);CS1591;CS0436 https://abp.io/assets/abp_nupkg.png https://abp.io/ diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md new file mode 100644 index 0000000000..bb8bfdf4c7 --- /dev/null +++ b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md @@ -0,0 +1,147 @@ +# ABP Platform 9.1 RC Has Been Released + +We are happy to release [ABP](https://abp.io) version **9.1 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 v9.1! Thanks to you in advance. + +## Get Started with the 9.1 RC + +You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli). + +By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI: + +![studio-switch-to-preview.png](studio-switch-to-preview.png) + +## Migration Guide + +There are no breaking changes in this version that would affect your application. Only you might need to update some constant names due to the OpenIddict 6.0 upgrade, which is explained in the [OpenIddict 6.0 migration guide](https://abp.io/docs/9.1/release-info/migration-guides/openiddict5-to-6). + +## What's New with ABP v9.1? + +In this section, I will introduce some major features released in this version. +Here is a brief list of titles explained in the next sections: + +* Upgraded to Angular 19 +* Upgraded to OpenIddict 6.0 +* New Blazor WASM Bundling System +* Idle Session Warning +* Lazy Expandable Feature for Documentation + +### Upgraded to Angular 19 + +We've upgraded the Angular templates and packages to **Angular 19**. This upgrade brings the latest features and improvements from the Angular ecosystem to ABP-based applications, including better performance and development experience. + +### Upgraded to OpenIddict 6.0 + +OpenIddict 6.0 has been released and we've upgraded the OpenIddict packages to version 6.0 in ABP 9.1. This brings enhanced security features and improved authentication capabilities. The migration is straightforward and mainly involves updating some constant names: + +- `OpenIddictConstants.Permissions.Endpoints.Logout` is now `OpenIddictConstants.Permissions.Endpoints.EndSession` +- `OpenIddictConstants.Permissions.Endpoints.Device` is now `OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization` + +If you're using IdentityModel packages directly, you'll need to upgrade them to the latest stable version (8.3.0). This update ensures your applications stay current with the latest security standards and best practices. + +> Please refer to the [OpenIddict 6.0 migration guide](https://abp.io/docs/9.1/release-info/migration-guides/openiddict5-to-6) for more information. + +### New Blazor WASM Bundling System + +We've implemented a new bundling system for Blazor WebAssembly applications that eliminates the need to manually run the `abp bundle` command. This system automatically handles JavaScript and CSS file bundling at runtime, significantly improving both development experience and application loading performance. + +**Key improvements include:** + +- Automatic bundling of JavaScript and CSS files without manual intervention +- Dynamic file generation through the host application +- Better integration with the ABP module system +- Improved asset management through virtual file system + +The new system is particularly beneficial for modular applications, as it allows modules to contribute their assets automatically to the global bundles. This results in a more maintainable and efficient asset management system for Blazor WebAssembly applications. + +> Please refer to [this documentation](https://abp.io/docs/9.1/framework/ui/blazor/global-scripts-styles) for more information. + +### Idle Session Warning + +We've introduced a new idle session warning feature for the [Account (Pro) Module](https://abp.io/docs/latest/modules/account-pro) that helps manage user sessions more effectively. This security enhancement automatically monitors user activity and manages session timeouts in a user-friendly way. + +![idle-session-settings.png](idle-session-settings.png) + +The feature can be easily configured through the administration interface, where administrators can: + +- Enable/disable the idle session timeout +- Set custom timeout duration in minutes +- Configure when users should be signed out + +When a user becomes inactive for the configured duration, they'll receive a warning dialog: + +![session-expiration-warning.png](session-expiration-warning.png) + +**Key features and behaviors:** + +- Tracks real user activity (mouse movements, keyboard presses) across all tabs +- Works on a per-browser session basis - affects all tabs of the same session +- Maintains session if user is active in any tab of the application +- Provides a countdown timer before automatic sign-out +- Offers options to "Stay signed in" or "Sign out now" + +This feature significantly improves application security while maintaining a smooth user experience by preventing unexpected session expirations and data loss. + +### Lazy Expandable Feature for Documentation + +We've introduced a new lazy expandable feature to the documentation system that significantly improves navigation through large documentation sections. This enhancement addresses common challenges when dealing with extensive documentation hierarchies by introducing smart menu management. + +**Key benefits and features:** + +- **Cleaner Navigation:** The menu stays concise by hiding sub-items until they're needed, reducing visual clutter +- **Better Performance:** Reduces the initial load of the navigation tree by loading sub-items on demand +- **Improved Search Experience:** Makes filtering documentation items more efficient by showing only relevant top-level items +- **Context-Aware Expansion:** Automatically expands relevant sections when viewing specific documentation pages + +The feature works by marking certain documentation sections as "lazy expandable" in the navigation configuration. When users navigate to a document within a lazy expandable section, the system automatically expands the relevant menu items while keeping other sections collapsed. + +This improvement is particularly valuable for complex documentation areas like tutorials, solution templates, and extensive module documentation, where having all navigation items visible at once could be overwhelming. + +An example of lazy expandable feature from the [ABP's BookStore Tutorial](https://abp.io/docs/latest/tutorials/book-store/part-01): + +```json + { + "text": "Book Store Application", + "isLazyExpandable": true, + "path": "tutorials/book-store", + "items": [ + { + "text": "Overview", + "path": "tutorials/book-store", + "isIndex": true + }, + //other items... + ] + } +``` + +![lazy-expandable.png](lazy-expandable.png) + +### Others + +Some other highlights from this release: + +* Updated Iyzico NuGet packages to the latest version, which is used in the [ABP's Payment Module](https://abp.io/docs/latest/modules/payment#payment-module-pro). +* Removed optional _secondaryIds_ from path. See: [#21307](https://github.com/abpframework/abp/pull/21307) +* [CMS Kit Pro](https://abp.io/docs/latest/modules/cms-kit-pro): Added automatic deletion of comments when a blog post is deleted - comments are now automatically removed when their associated blog post is deleted. +* Avoiding global blocking in distributed event handlers (See [#21716](https://github.com/abpframework/abp/pull/21716)). + +## Community News + +### New ABP Community Articles + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Integrating ABP Modules in Your ASP.NET Core Web API Project. A Step-by-Step Guide](https://abp.io/community/articles/integrating-abp-modules-in-your-asp.net-core-web-api-project.-a-stepbystep-guide-jtbyosnr) by [Sajankumar Vijayan](https://abp.io/community/members/connect) +* [ABP Framework: Background Jobs vs Background Workers](https://abp.io/community/articles/abp-framework-background-jobs-vs-background-workers-when-to-use-which-t98pzjv6) — When to Use Which? by [Alper Ebiçoğlu](https://twitter.com/alperebicoglu) +* [The new Unit Test structure in ABP application](https://abp.io/community/articles/the-new-unit-test-structure-in-abp-application-4vvvp2oy) by [Liming Ma](https://github.com/maliming) +* [How to Use OpenAI API with ABP Framework](https://abp.io/community/articles/how-to-use-openai-api-with-abp-framework-rsfvihla) by [Berkan Şaşmaz](https://github.com/berkansasmaz) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community. + +## Conclusion + +This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://abp.io/docs/9.1/release-info/road-map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v9.1 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/cover-image.png b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/cover-image.png new file mode 100644 index 0000000000..0575db3f27 Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/cover-image.png differ diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/idle-session-settings.png b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/idle-session-settings.png new file mode 100644 index 0000000000..7cdb5df408 Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/idle-session-settings.png differ diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/lazy-expandable.png b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/lazy-expandable.png new file mode 100644 index 0000000000..0936bcb024 Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/lazy-expandable.png differ diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/session-expiration-warning.png b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/session-expiration-warning.png new file mode 100644 index 0000000000..1c4082874d Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/session-expiration-warning.png differ diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/studio-switch-to-preview.png b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/studio-switch-to-preview.png new file mode 100644 index 0000000000..32f6d01edb Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/studio-switch-to-preview.png differ diff --git a/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/POST.md b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/POST.md new file mode 100644 index 0000000000..611d8cb41b --- /dev/null +++ b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/POST.md @@ -0,0 +1,46 @@ +# ABP Studio Now Supports MacOS Intel 🚀 + +We are excited to announce that [ABP Studio, our cross-platform desktop application for ABP developers](https://abp.io/studio), now supports Intel-based Mac computers! + +This addition expands our platform compatibility, ensuring that developers using Intel-powered Macs can also benefit from the powerful features of ABP Studio. + +## What is ABP Studio? + +For those who aren't familiar, [ABP Studio](https://abp.io/studio) is a powerful desktop application that makes ABP development faster and easier. It offers: + +* Easy creation of new solutions (from simple applications to microservices) +* Visual architecture management for modular-monolith and microservice solutions +* Solution exploration tools for entities, services, and HTTP APIs +* Simplified running, debugging and monitoring of multi-application or microservice solutions +* Kubernetes cluster integration capabilities +* and more... + +## Extended Platform Support + +ABP Studio has been proudly supporting multiple platforms, and we're excited to add MacOS Intel to the our list of supported architectures. You can now use ABP Studio on: + +* Windows x64 +* Windows ARM +* MacOS Apple Silicon (M1/M2/M3) +* MacOS Intel **(New!)** + +## Why This Matters + +This update is particularly important for developers who are using Intel-based Mac computers. Previously, ABP Studio was only available for Apple Silicon Macs (for MacOS), but we understand that many developers are still using Intel-based Macs. With this release, we're ensuring that all Mac users can access our development tools, regardless of their processor architecture. + +## Getting Started + +Installing ABP Studio on your Intel-based Mac is straightforward: + +1. Go to [abp.io/studio](https://abp.io/studio) +2. Click on the download button and select "MacOS Intel" from the dropdown menu +3. Once downloaded, open the installer package +4. Follow the installation wizard to complete the setup + +![ABP Studio Download Page](abp-studio-macos-intel.png) + +## Conclusion + +As ABP team, we're always looking for ways to improve the developer experience. By supporting Intel-based Macs, we're ensuring that all Mac users can access our development tools, regardless of their processor architecture. + +Stay tuned for more updates and enhancements as we continue to optimize ABP Studio and please provide us with your invaluable feedback. Thanks in advance! diff --git a/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/abp-studio-macos-intel.png b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/abp-studio-macos-intel.png new file mode 100644 index 0000000000..f5d5ca6987 Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/abp-studio-macos-intel.png differ diff --git a/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/cover-image.png b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/cover-image.png new file mode 100644 index 0000000000..80e0d0faf0 Binary files /dev/null and b/docs/en/Blog-Posts/2025-01-22 ABP_Now_Supports_MacOS_Intel/cover-image.png differ diff --git a/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/POST.md b/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/POST.md new file mode 100644 index 0000000000..96096807f1 --- /dev/null +++ b/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/POST.md @@ -0,0 +1,82 @@ +# ABP.IO Platform 9.1 Final Has Been Released! + +We are glad to announce that [ABP](https://abp.io/) 9.1 stable version has been released today. + +## What's New With Version 9.1? + +All the new features were explained in detail in the [9.1 RC Announcement Post](https://abp.io/community/articles/abp-platform-9.1-rc-has-been-released-wws5l00k), so there is no need to review them again. You can check it out for more details. + +## Getting Started with 9.1 + +### Creating New Solutions + +You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli) to create new solutions. + +By default, ABP Studio uses stable versions to create solutions. Therefore, it will be creating the solution with the latest stable version, which is v9.1 for now, so you don't need to specify the version. + +### How to Upgrade an Existing Solution + +You can upgrade your existing solutions with either ABP Studio or ABP CLI. In the following sections, both approaches are explained: + +### Upgrading via ABP Studio + +If you are already using the ABP Studio, you can upgrade it to the latest version to align it with ABP v9.1. ABP Studio periodically checks for updates in the background, and when a new version of ABP Studio is available, you will be notified through a modal. Then, you can update it by confirming the opened modal. See [the documentation](https://abp.io/docs/latest/studio/installation#upgrading) for more info. + +After upgrading the ABP Studio, then you can open your solution in the application, and simply click the **Upgrade ABP Packages** action button to instantly upgrade your solution: + +![](upgrade-abp-packages.png) + +### Upgrading via ABP CLI + +Alternatively, you can upgrade your existing solution via ABP CLI. First, you need to install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet, you can run the following command: + +```bash +dotnet tool install -g Volo.Abp.Studio.Cli +``` + +Or to update the existing CLI, you can run the following command: + +```bash +dotnet tool update -g Volo.Abp.Studio.Cli +``` + +After installing/updating the ABP CLI, you can use the [`update` command](https://abp.io/docs/latest/CLI#update) to update all the ABP related NuGet and NPM packages in your solution as follows: + +```bash +abp update +``` + +You can run this command in the root folder of your solution to update all ABP related packages. + +## Migration Guides + +There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v9.0: [ABP Version 9.1 Migration Guide](https://abp.io/docs/latest/release-info/migration-guides/abp-9-1) + +## Community News + +### New ABP Community Articles + +As always, exciting articles have been contributed by the ABP community. I will highlight some of them here: + +* [URL-Based Localization](https://abp.io/community/articles/urlbased-localization-3ivzinbb) by [Alper Ebiçoğlu](https://twitter.com/alperebicoglu) +* [Building a CRUD API with ABP Framework, ASP.NET Core, and PostgreSQL](https://abp.io/community/articles/building-a-crud-api-with-abp-framework-asp.net-core-and-postgresql-elrj0old) by [Berkan Şaşmaz](https://github.com/berkansasmaz) +* [Encryption and Decryption in ABP Framework](https://abp.io/community/articles/encryption-and-decryption-in-abp-framework-37uqhdwz) by [Liming Ma](https://github.com/maliming) +* [Migrate Your DB from the Web Application - Adding a DB Migration Controller](https://abp.io/community/articles/migrate-your-db-from-the-web-application-adding-a-db-migration-controller-in-abp-framework-x3u3uvk3) by [Alper Ebiçoğlu](https://twitter.com/alperebicoglu) +* [Containerization: Blazor WASM + JWT Web API => Docker](https://abp.io/community/articles/containerization-blazor-wasm-jwt-web-api-docker-i3eirlsf) by [Bart Van Hoey](https://abp.io/community/members/bartvanhoey) +* [Configuring Post-Logout Redirect URI in ABP Based Blazor Applications with OpenIddict](https://abp.io/community/articles/configuring-postlogout-redirect-uri-in-abp-based-blazor-applications-with-openiddict-1t84suxg) by [Engincan Veske](https://github.com/EngincanV) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community. + +### ABP Community Talks 2025.2: Real World Problems and Solutions with AI + +![](community-talks.png) + +In this episode of ABP Community Talks (2025.2), Decision Tree joined us to explore how AI is being leveraged to solve real-world problems, showcasing a practical use case of AI applications. + +> You can re-watch the talk from [here](https://www.youtube.com/watch?v=CXpWjxCIY_E). + +## About the Next Version + +The next feature version will be 9.2. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. diff --git a/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/community-talks.png b/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/community-talks.png new file mode 100644 index 0000000000..2c2dd5a38a Binary files /dev/null and b/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/community-talks.png differ diff --git a/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/cover-image.png b/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/cover-image.png new file mode 100644 index 0000000000..0575db3f27 Binary files /dev/null and b/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/cover-image.png differ diff --git a/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/upgrade-abp-packages.png b/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/upgrade-abp-packages.png new file mode 100644 index 0000000000..ad5e9bd462 Binary files /dev/null and b/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/upgrade-abp-packages.png differ diff --git a/docs/en/Community-Articles/2018-09-24-introducing-the-abp-vnext/594bc2cb4507d5ae91d439e91cf03cc9.png b/docs/en/Community-Articles/2018-09-24-introducing-the-abp-vnext/594bc2cb4507d5ae91d439e91cf03cc9.png new file mode 100644 index 0000000000..22911d4b72 Binary files /dev/null and b/docs/en/Community-Articles/2018-09-24-introducing-the-abp-vnext/594bc2cb4507d5ae91d439e91cf03cc9.png differ diff --git a/docs/en/Community-Articles/2018-09-24-introducing-the-abp-vnext/post.md b/docs/en/Community-Articles/2018-09-24-introducing-the-abp-vnext/post.md new file mode 100644 index 0000000000..9b686632fa --- /dev/null +++ b/docs/en/Community-Articles/2018-09-24-introducing-the-abp-vnext/post.md @@ -0,0 +1,176 @@ +### Introduction +For a while, we were working to design a new major version of the ASP.NET Boilerplate framework. Now, it’s time to share it with the community. We are too excited and we believe that you are too. + +#### Naming +The name of the framework remains same, except we will call it only as “ABP” instead of “ASP.NET Boilerplate”. Because, the “boilerplate” word leads to misunderstandings and does not reflect that it is a framework (instead of some boilerplate code). We continue to use the “ABP” name since it’s the successor of the current ASP.NET Boilerplate framework, except it’s a rewrite. + +### How To Start + +We have created a startup template. You can just create a new project from [abp.io/Templates](https://abp.io/Templates) and start your development. For more information, visit [abp.io](https://abp.io). + +### Why A Complete Rewrite? +Why we spent our valuable time to rewrite it from scratch instead of incremental changes and improvements. Why? + +#### ASP.NET Core +When we first introduced the ABP framework, it was 2013 (5 years ago)! There was no .Net Core & ASP.NET Core and there was no Angular2+. They were all developed from scratch after ABP’s release. + +ASP.NET Core introduced many built-in solutions (extension libraries) for dependency injection, logging, caching, localization, configuration and so on. These are actually independent from the ASP.NET Core and usable for any type of application. + +We were using 3rd-party libraries and our own solutions for these requirements. We immediately integrated to ASP.NET Core features once they were released. But that was an integration, instead of building the ABP framework on top of these extension libraries. For instance, current ASP.NET Boilerplate still depends on Castle Windsor for dependency injection even it’s integrated to ASP.NET Core’s DI system. + +We wanted to depend on these new extension libraries instead of 3rd-party and custom solutions and this changes fundamental structures of the framework. + +#### Self Modularization +While current ABP is already modular itself and consists of dozens of packages, we still wanted to split the functionalities to more fine grained nuget packages. + +For example, the core Abp package contains many features like DDD classes, auditing, authorization, background jobs, event bus, json serialization, localization, multi-tenancy, threading, timing and so on… We wanted to split all these functionality into their own packages and make them optional. + +#### Dropping Support for Legacy Technologies +Yes, the new ABP framework will not support ASP.NET MVC 5.x, Entity Framework 6.x and other legacy technologies. + +These legacy technologies are maintained by Microsoft but no new feature is being added. So, if you are still using these technologies, you can continue with the current ASP.NET Boilerplate framework. We will continue to maintain it, fix bugs and will add new features. + +Dropping support for these legacy libraries will improve our development speed (since we currently duplicate our work for some features) and concentrate on the .Net Core & ASP.NET Core. + +The new ABP framework will be based on .net standard. So, it’s still possible to use full .net framework or .net core with the new ABP framework. + +### Goals +We have learnt much from the community and had experience of developing the current ASP.NET Boilerplate framework. New ABP framework has significant and exciting goals. + +#### Application Modularity +The first goal is to provide a good infrastructure to develop application modules. We think a module as a set of application features with its own database, its own entities, services, APIs, UI pages, components and so on. + +We will create a module market which will contain free & paid application modules. You will also be able to publish your own modules on the market. More information will be coming soon. + +#### Microservices +We are designing the new ABP framework to be ready to develop microservices and communicate them to each other. + +We are designing application modules so that they can be separately deployable as microservices or they can be embedded into a monolithic application. + +We are creating a [specification / best practice documentation](https://abp.io/documents/abp/latest/Best-Practices/Index) for that. + +#### Theming and UI Composition +The new ABP framework will provide a theming infrastructure based on the latest Twitter Bootstrap 4.x. We developed a basic theme that only uses the plain Bootstrap 4.x styling. It’s free and open source. We are also developing premium & paid themes. + +UI Composition is one of the main goals. For this purpose, theme system will provide menus, toolbars and other extensible areas to allow other modules to contribute. + +#### ORM/Database Independence & MongoDB Integration +While current ASP.NET Boilerplate framework has implemented the repository pattern for ORM/Database independence, identity integration module (Abp.Zero* packages) has never worked well with ORMs other than EF. + +With the new ABP framework, the ultimate goal is completely abstract underlying data store system and develop modules EF Core independent. + +We embrace the MongoDB as a first-class citizen database and designing entities and repositories without any relational database or ORM assumption. + +#### More Extensibility +New ABP framework provides more extensibility points and overriding capabilities for built-in services. + +### Some Features +In this section, I will introduce some exciting new features of the new ABP framework. + +#### Bootstrap Tag Helpers +We are creating a library to wrap twitter bootstrap 4.x elements/components into tag helpers. Example: + +````C# + + + + Card title + +

+ This is a sample card component built by ABP bootstrap + card tag helper. ABP has tag helper wrappers for most of + the bootstrap components. +

+
+ Go somewhere → +
+
+```` + +"abp-*" tags are ABP tag helpers to simplify writing HTML for Bootstrap 4.x. + +#### Dynamic Forms +Dynamic forms tag helper allows you to dynamically create forms for given model classes. Example: + +````C# + +```` + +Output: + +![dynamic-forms.png](594bc2cb4507d5ae91d439e91cf03cc9.png) + +It currently supports most used input types and more in the development. + +#### Virtual File System +Virtual File System allows you to embed views, pages, components, javascript, css, json and other type of files into your module assembly/package (dll) and use your assembly in any application. Your virtual files behave just like physical files in the containing application with complete ASP.NET Core Integration. + +Read more [about the Virtual File System](https://medium.com/volosoft/designing-modularity-on-asp-net-core-virtual-file-system-2dd2cc2078bd) and see [its documentation](https://abp.io/documents/abp/latest/Virtual-File-System). + +#### Dynamic Bundling & Minification System +Dynamic bundling & minification system works on the virtual file system and allows modules to create, modify and contribute to bundles in a modular, dynamic and powerful way. An example: + +````C# + + + + + +```` + +This code creates a new style bundle on the fly by including bootstrap (and its dependencies if there are) and two more css files. These files are bundled & minified on production environment, but will be added individually on the development environment. + +See [the documentation](https://abp.io/documents/abp/latest/AspNetCore/Bundling-Minification) for more. + +#### Distributed Event Bus +In current ABP, there is an IEventBus service to trigger and handle events inside the application. In addition to this local event bus, we are creating a distributed event bus abstraction (and RabbitMQ integration) to implement distributed messaging patterns. + +#### Dynamic C# HTTP Client Proxies +ABP was already creating dynamic javascript proxies for all HTTP APIs. This feature does also exists in the new ABP framework. In addition, it now can create dynamic C# proxies for all HTTP APIs. + +### Future Works +All the stuffs mentioned above are already in development. However, we haven’t started some concepts yet. + +#### Single Page Applications +We designed the new framework SPAs in mind. However, we haven’t tried it with any SPA framework and we haven’t prepared a startup template for it yet. + +### What About ASP.NET Boilerplate (Current Version) and ASP.NET Zero? + +We have dedicated development & support teams actively working on the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) and [ASP.NET Zero](https://aspnetzero.com/) projects. These projects have a big community and we are also getting contributions from the community. + +We will continue to make enhancements, add new features and fix bugs for these projects for a long time. So, you can safely continue to use them. + +### Is New ABP Production Ready? +No, not yet. Our first goal is to make fundamental features stable then incrementally complete other features. + +We will frequently release new versions and every new version will probably have breaking changes. We will write breaking changes on the release notes. + +We currently define it experimental. But we hope that this will not continue for a long time. We can not declare a date yet, follow our releases. + +### Packages & Versioning +New ABP framework will start with v1.0 instead of following current ASP.NET Boilerplate's version to reflect the fact that it’s a rewrite. + +We will frequently [release](https://github.com/abpframework/abp/releases) it. You can expect many breaking changes until v1.0. Starting with the v1.0, we will pay attention to not introduce breaking changes in 1.x releases. + +Current ABP’s package names start with [Abp](https://www.nuget.org/packages/Abp) prefix (like Abp.EntityFrameworkCore). New package names start with [Volo.Abp](https://www.nuget.org/packages/Volo.Abp.Core) prefix (like Volo.Abp.EntityFrameworkCore). + +### Which One Should I Start With? +If you are creating a new project, we suggest to continue with the current ASP.NET Boilerplate framework since it’s very mature, feature rich and production ready. + +If you are open to breaking changes and want to have experience on the new framework, you can start with the new ABP. We don’t suggest it yet for projects with close deadlines and go to the production in a short term. + +### Contribution +Just like the current ABP framework, the new framework is available for your contribution. + +* You can send pull requests for code or documentation. +* You can write blog posts or tutorials about it. +* You can try it and share your experiences. +* You can create enhancement and feature requests. +* You can report bugs and other issues. + +See [the contribution guide](https://github.com/abpframework/abp/blob/master/docs/en/Contribution/Index.md). + +### Communication / Links +* **Official web site**: [abp.io](https://abp.io) +* **Github**: [github.com/abpframework](https://github.com/abpframework) +* **Twitter**: [@abpframework](https://twitter.com/abpframework) \ No newline at end of file diff --git a/docs/en/Community-Articles/2019-02-22-microservice-demo-projects-status-and-road-map/d92ca39b02b79d5984d739ec266fd43f.png b/docs/en/Community-Articles/2019-02-22-microservice-demo-projects-status-and-road-map/d92ca39b02b79d5984d739ec266fd43f.png new file mode 100644 index 0000000000..79ad21aee7 Binary files /dev/null and b/docs/en/Community-Articles/2019-02-22-microservice-demo-projects-status-and-road-map/d92ca39b02b79d5984d739ec266fd43f.png differ diff --git a/docs/en/Community-Articles/2019-02-22-microservice-demo-projects-status-and-road-map/post.md b/docs/en/Community-Articles/2019-02-22-microservice-demo-projects-status-and-road-map/post.md new file mode 100644 index 0000000000..e4efde2a9d --- /dev/null +++ b/docs/en/Community-Articles/2019-02-22-microservice-demo-projects-status-and-road-map/post.md @@ -0,0 +1,52 @@ +After [the first announcement](https://abp.io/blog/abp/Abp-vNext-Announcement) on the ABP vNext, we have a lot of improvements on the codebase (1100+ commits on the [GitHub repository](https://github.com/abpframework/abp)). We've created features, samples, documentation and much more. In this post, I want to inform you about some news and the status of the project. + +## Microservice Demo Solution + +One of the major goals of the ABP framework is to provide a [convenient infrastructure to create microservice solutions](https://abp.io/documents/abp/latest/Microservice-Architecture). + +We've been working to develop a microservice solution demo. Initial version was completed and [documented](https://abp.io/documents/abp/latest/Samples/Microservice-Demo). This sample solution aims to demonstrate a simple yet complete microservice solution; + +- Has multiple, independent, self-deployable **microservices**. +- Multiple **web applications**, each uses a different API gateway. +- Has multiple **gateways** / BFFs (Backend for Frontends) developed using the [Ocelot](https://github.com/ThreeMammals/Ocelot) library. +- Has an **authentication service** developed using the [IdentityServer](https://identityserver.io/) framework. It's also a SSO (Single Sign On) application with necessary UIs. +- Has **multiple databases**. Some microservices has their own database while some services/applications shares a database (to demonstrate different use cases). +- Has different types of databases: **SQL Server** (with **Entity Framework Core** ORM) and **MongoDB**. +- Has a **console application** to show the simplest way of using a service by authenticating. +- Uses [Redis](https://redis.io/) for **distributed caching**. +- Uses [RabbitMQ](https://www.rabbitmq.com/) for service-to-service **messaging**. +- Uses [Docker](https://www.docker.com/) & [Kubernates](https://kubernetes.io/) to **deploy** & run all services and applications. +- Uses [Elasticsearch](https://www.elastic.co/products/elasticsearch) & [Kibana](https://www.elastic.co/products/kibana) to store and visualize the logs (written using [Serilog](https://serilog.net/)). + +See [its documentation](https://abp.io/documents/abp/latest/Samples/Microservice-Demo) for a detailed explanation of the solution. + +## Improvements/Features + +We've worked on so many features including **distributed event bus** (with RabbitMQ integration), **IdentityServer4 integration** and enhancements for almost all features. We are continuously refactoring and adding tests to make the framework more stable and production ready. It is [rapidly growing](https://github.com/abpframework/abp/graphs/contributors). + +## Road Map + +There are still too much work to be done before the first stable release (v1.0). You can see [prioritized backlog items](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3ABacklog) on the GitHub repo. + +According to our estimation, we have planned to release v1.0 in Q2 of 2019 (probably in May or June). So, not too much time to wait. We are also very excited for the first stable release. + +We will also work on [the documentation](https://abp.io/documents/abp/latest) since it is far from complete now. + +First release may not include a SPA template. However, we want to prepare a simple one if it can be possible. Haven't decided yet about the SPA framework. Alternatives: **Angular, React and Blazor**. Please write your thought as a comment to this post. + +## Chinese Web Site + +There is a big ABP community in China. They have created a Chinese version of the abp.io web site: https://cn.abp.io/ They are keeping it up to date. Thanks to the Chinese developers and especially to [Liming Ma](https://github.com/maliming). + +## NDC {London} 2019 + +It was a pleasure to be in [NDC {London}](https://ndc-london.com/) 2019 as a partner. We've talked to many developers about the current ASP.NET Boilerplate and the ABP vNext and we got good feedbacks. + +We also had a chance to talk with [Scott Hanselman](https://twitter.com/shanselman) and [Jon Galloway](https://twitter.com/jongalloway). They visited our booth and we talked about the ideas for ABP vNext. They liked features, approaches and the goal of new ABP framework. See some photos and comments on twitter: + +![scott-and-jon.png](d92ca39b02b79d5984d739ec266fd43f.png) + +## Follow It + +* You can star and follow the **GitHub** repository: https://github.com/abpframework/abp +* You can follow the official **Twitter** account for news: https://twitter.com/abpframework \ No newline at end of file diff --git a/docs/en/Community-Articles/2019-06-21-abp-cli-new-templates--features-v018-release/mvc-template-solution.png b/docs/en/Community-Articles/2019-06-21-abp-cli-new-templates--features-v018-release/mvc-template-solution.png new file mode 100644 index 0000000000..ce821eba72 Binary files /dev/null and b/docs/en/Community-Articles/2019-06-21-abp-cli-new-templates--features-v018-release/mvc-template-solution.png differ diff --git a/docs/en/Community-Articles/2019-06-21-abp-cli-new-templates--features-v018-release/post.md b/docs/en/Community-Articles/2019-06-21-abp-cli-new-templates--features-v018-release/post.md new file mode 100644 index 0000000000..f89b846eab --- /dev/null +++ b/docs/en/Community-Articles/2019-06-21-abp-cli-new-templates--features-v018-release/post.md @@ -0,0 +1,87 @@ +ABP v0.18 has been released with [80+ issues](https://github.com/abpframework/abp/milestone/16?closed=1) resolved and [550+ commits](https://github.com/abpframework/abp/compare/0.17.0.0...0.18.0) pushed. + +## Web Site Changes + +[abp.io](https://abp.io) web site is **completely renewed** to highlight the goals and important features of the ABP framework. Document & blog URLs are also changed: + +- `abp.io/documents` moved to [docs.abp.io](https://docs.abp.io). +- `abp.io/blog` moved to [blog.abp.io](https://blog.abp.io). + +## ABP CLI + +ABP CLI (Command Line Interface) is a new global command line tool to perform some common operations for ABP based solutions. Main functions are; + +* **Creating a new application** or module project. +* **Adding a new module** to an application. +* **Updating** all ABP related packages in a solution. + +ABP CLI is now the preferred way to create a new project, while you can still download a new project from the [get started](https://abp.io/get-started) page. + +### Usage + +Install the ABP CLI using a command line window: + +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +Create a new application: + +````bash +abp new Acme.BookStore +```` + +Add a module to an application: + +````bash +abp add-module Volo.Blogging +```` + +Update all ABP related packages in a solution: + +````bash +abp update +```` + +See [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for details. + +## New Templates + +In this release, we've renewed all startup templates. The main goal is to provide better startup templates based on Domain Driven Design layers those also allow to create tiered solutions (where Web and API layers can be physically separated). It also includes unit & integration test projects separated for different layers. + +The image below shows the new startup project for an MVC application. + +![mvc-template-solution](mvc-template-solution.png) + +See the [startup templates document](https://docs.abp.io/en/abp/latest/Startup-Templates/Index) for details. + +## Change Logs + +Here are some other features and enhancements coming with this release: + +* New [Volo.Abp.Dapper](https://www.nuget.org/packages/Volo.Abp.Dapper) package. +* New [Volo.Abp.Specifications](https://www.nuget.org/packages/Volo.Abp.Specifications) package. +* New data seed system with `IDataSeeder` service & `IDataSeedContributor` interface to allow a modular initial data seed system. +* Improved MemoryDB implementation to serialize/deserialize objects stored in memory, so it provides more realistic infrastructure for mocking database in unit/integration tests. +* Added multi-language support for the docs module. Used it for the [ABP documentation](https://docs.abp.io). + +See the [GitHub Release Notes](https://github.com/abpframework/abp/releases/tag/0.18.0) for all features, enhancements & bugfixes in this release. + +## Road Map + +One thing related to the ABP v1.0 release is .NET Core / ASP.NET Core 3.0 release. According to the [.NET Core road map](https://github.com/dotnet/core/blob/master/roadmap.md), 3.0 release has been scheduled for September 2019. + +ASP.NET Core comes with big changes and features. As a big breaking change, it will [only run on .NET Core](https://github.com/aspnet/Announcements/issues/324) (dropping .net standard support), so it will not work with full .net framework anymore. + +We had declared to release v1.0 in 2019 Q2. The main works we should do for v1.0 are; + +* Fill the gaps in current features. +* Refactor & improve the current APIs. +* Fix known bugs. +* Complete the documentation & tutorials. + +In addition to the work we should do, we are also considering to wait ASP.NET Core 3.0 release. Because, if we release ABP v1.0 before ASP.NET Core 3.0, we will have to release ABP v2.0 again in a short time and drop v1.0 support. So, we are considering to publish ABP v1.0 RC with ASP.NET Core 3.0 RC and align the final release date with Microsoft. + +## Want to Contribute? + +Thanks to the community for their support for ABP development. It is very appreciated. If you also want to contribute, see [this guide](https://github.com/abpframework/abp/blob/master/docs/en/Contribution/Index.md) as the beginning. \ No newline at end of file diff --git a/docs/en/Community-Articles/2019-08-16-abp-v019-release-with-new-angular-ui/post.md b/docs/en/Community-Articles/2019-08-16-abp-v019-release-with-new-angular-ui/post.md new file mode 100644 index 0000000000..1fc3391c8b --- /dev/null +++ b/docs/en/Community-Articles/2019-08-16-abp-v019-release-with-new-angular-ui/post.md @@ -0,0 +1,44 @@ +ABP v0.19 has been released with [90 issues](https://github.com/abpframework/abp/milestone/17?closed=1) resolved and [650+ commits](https://github.com/abpframework/abp/compare/0.18.1...0.19.0) pushed. + +## New Features + +### Angular UI + +Finally, ABP has a **SPA UI** option with the latest [Angular](https://angular.io/) framework. Angular integration was not simply creating a startup template. + +* Created a base infrastructure to handle ABP's modularity, theming and some other features. This infrastructure has been deployed as [NPM packages](https://github.com/abpframework/abp/tree/dev/npm/ng-packs/packages). +* Created Angular UI packages for the modules like account, identity and tenant-management. +* Created a minimal startup template that authenticates using IdentityServer and uses the ASP.NET Core backend. This template uses the packages mentioned above. +* Worked on the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) and the [download page](https://abp.io/get-started) to be able to generate projects with the new UI option. +* Created a [tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Angular/Part-I) to jump start with the new UI option. + +We've created the template, document and infrastructure based on the latest Angular tools and trends: + +* Uses [NgBootstrap](https://ng-bootstrap.github.io/) and [PrimeNG](https://www.primefaces.org/primeng/) as the UI component libraries. You can use your favorite library, no problem, but pre-built modules work with these libraries. +* Uses [NGXS](https://ngxs.gitbook.io/ngxs/) as the state management library. + +Angular was the first SPA UI option, but it is not the last. After v1.0 release, we will start to work on a second UI option. Not decided yet, but candidates are Blazor, React and Vue.js. Waiting your feedback. You can thumb up using the following issues: + +* [Blazor](https://github.com/abpframework/abp/issues/394) +* [Vue.js](https://github.com/abpframework/abp/issues/1168) +* [React](https://github.com/abpframework/abp/issues/1638) + +### Widget System + +[Widget system](https://docs.abp.io/en/abp/latest/AspNetCore/Widgets) allows to **define and reuse** widgets for ASP.NET Core MVC applications. Widgets may have their own script and style resources and dependencies to 3rd-party libraries which are managed by the ABP framework. + +### Others + +We've solved many bugs and worked on existing features based on the community feedback. See the [v0.19 milestone](https://github.com/abpframework/abp/milestone/17?closed=1) for all the closed issues. + +## Road Map + +We had decided to wait for **ASP.NET Core 3.0** final release. Microsoft has announced to released it at [.NET Conf](https://www.dotnetconf.net/), between 23-25 September. + +We have planned to finalize our work and move to ASP.NET Core 3.0 (with preview or RC) before its release. Once Microsoft releases it, we will immediately start to upgrade and test with the final release. + +So, you can expect ABP **v1.0** to be released in the **first half of the October**. We are very excited and working hard on it. + +You can follow the progress from [the GitHub milestones](https://github.com/abpframework/abp/milestones). + +We will not add major features until v1.0. \ No newline at end of file diff --git a/docs/en/Community-Articles/2019-09-25-abp-v021-has-been-released-based-on-the-aspnet-core-30/post.md b/docs/en/Community-Articles/2019-09-25-abp-v021-has-been-released-based-on-the-aspnet-core-30/post.md new file mode 100644 index 0000000000..5451f4b647 --- /dev/null +++ b/docs/en/Community-Articles/2019-09-25-abp-v021-has-been-released-based-on-the-aspnet-core-30/post.md @@ -0,0 +1,19 @@ +Just one hour after Microsoft released it, ABP v0.21 [has been released](https://twitter.com/abpframework/status/1176185493119258624) based on the ASP.NET Core 3.0. + +v0.21 has no new feature. It just upgrades to the stable ASP.NET Core 3.0. Check [v0.20 release notes](https://github.com/abpframework/abp/releases/tag/0.20.0) for new features, enhancements and bug fixes. + +## About v1.0 + +ABP framework is getting closer to v1.0. We intent to release it in the middle of this October. In this time, we will test and document more. + +## .NET Conf 2019 + +Microsoft has lunched ASP.NET Core 3.0 in the .NET Conf 2019, a 3-days virtual conference. ABP's lead developer [Halil ibrahim Kalkan](https://twitter.com/hibrahimkalkan) has also talked in the conference to introduce the ABP framework. It was great to be a part of this important event. + +## Techorama Netherlands 2019 + +[Techorama NL](https://techorama.nl/) is one of the biggest conferences in Europe. This year, Volosoft is a sponsor of the conference and will have a booth to talk to software developers about the ABP framework and software development. Our booth wall will look like shown below: + +![volosoft-booth](volosoft-booth.png) + +If you are in the conference, come to out booth to talk about the ABP framework. We will also have nice swags for you :) \ No newline at end of file diff --git a/docs/en/Community-Articles/2019-09-25-abp-v021-has-been-released-based-on-the-aspnet-core-30/volosoft-booth.png b/docs/en/Community-Articles/2019-09-25-abp-v021-has-been-released-based-on-the-aspnet-core-30/volosoft-booth.png new file mode 100644 index 0000000000..3dca4409e4 Binary files /dev/null and b/docs/en/Community-Articles/2019-09-25-abp-v021-has-been-released-based-on-the-aspnet-core-30/volosoft-booth.png differ diff --git a/docs/en/Community-Articles/2019-10-22-abp-v10-has-been-finally-released/post.md b/docs/en/Community-Articles/2019-10-22-abp-v10-has-been-finally-released/post.md new file mode 100644 index 0000000000..0046ada85d --- /dev/null +++ b/docs/en/Community-Articles/2019-10-22-abp-v10-has-been-finally-released/post.md @@ -0,0 +1,25 @@ +Today is the big day! After ~3 years of continuous development, first stable ABP release, 1.0, has been released. Thanks to everyone contributed to the project or tried it so far. + +Start playing with the new ABP framework now: [abp.io/get-started](https://abp.io/get-started) + +## Statistics + +Here, a few GitHub & NuGet statistics about the project: + +* 2,360 stars. +* 5,917 commits. +* 72 contributors. +* 1,136 issues were closed, 276 open. +* 566 PRs were closed, 5 open. +* 39 releases. +* 122,795 downloads on NuGet. + +There was an excellent demand even before the first release. + +## Road Map + +The first priority is to complete the documentation, since there are still a lot of missing documents for the framework features & the modules. Then we will continue to work on the issues on GitHub, based on the labeled priorities. + +See the [GitHub milestone items](https://github.com/abpframework/abp/milestones). + +ABP is a community-driven project. So, we are prioritizing the issues mostly based on the community feedback and demand. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/abp-commercial-demo.png b/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/abp-commercial-demo.png new file mode 100644 index 0000000000..9153adeb86 Binary files /dev/null and b/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/abp-commercial-demo.png differ diff --git a/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/lepton-theme-material.png b/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/lepton-theme-material.png new file mode 100644 index 0000000000..279f4b2cf1 Binary files /dev/null and b/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/lepton-theme-material.png differ diff --git a/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/ndc-2020-volosoft-booth-wall.png b/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/ndc-2020-volosoft-booth-wall.png new file mode 100644 index 0000000000..428ecc284d Binary files /dev/null and b/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/ndc-2020-volosoft-booth-wall.png differ diff --git a/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/ndc-london-volosoft.png b/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/ndc-london-volosoft.png new file mode 100644 index 0000000000..afaed37a7a Binary files /dev/null and b/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/ndc-london-volosoft.png differ diff --git a/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/post.md b/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/post.md new file mode 100644 index 0000000000..2279b01466 --- /dev/null +++ b/docs/en/Community-Articles/2020-01-16-abp-framework-v20-and-the-abp-commercial/post.md @@ -0,0 +1,162 @@ +ABP Framework v2.0 has been released in this week. This post explains why we have released an early major version and what is changed with version 2.0. + +In addition to the v2.0 release, we are excited to announce the **ABP Commercial**, which is a set of professional modules, tools, themes, and services built on top of the open-source ABP framework. + +## ABP Framework v2.0 + +### Why 2.0 instead of 1.2? + +It was planned to release v1.2 after the [v1.1.2](https://github.com/abpframework/abp/releases/tag/1.1.2) release. However, [it is reported](https://github.com/abpframework/abp/issues/2026) that v1.x has some **performance** and **stability** issues on Linux, especially when you deploy your application to **Linux** containers with **low CPU and memory** resources. + +We have investigated the problem deeply and have seen that the root cause of the problem was related to the implementation of **intercepting `async` methods**. Besides, there were some **`async` over `sync`** usages that effected the thread pool optimization. + +Finally, we **solved all the problems** with the great help of the **community**. But we also had some important **design decisions** which cause some **breaking changes** and we had to change the major version number of the framework because of the [semantic versioning](https://semver.org/). + +Most of the applications won't be affected by [the breaking changes](https://github.com/abpframework/abp/releases), or it will be trivial to make these necessary changes. + +### Breaking Changes + +#### Removed Some Sync APIs + +Some of the interceptors are required to use `async` APIs. When they intercept `sync` methods, they need to call `async` over `sync`. This eventually ends up with `async` over `sync` problem. That's why we have [removed some sync APIs](https://github.com/abpframework/abp/pull/2464). + +**`Async` over `sync`** pattern is a classical problem of `C#` when you need to **call an `async` method inside a `sync` method**. While there are some workarounds to this problem, they all have **disadvantages** and it is suggested to **not write** such code at all. You can find many documents related to this topic on the web. + +To avoid this problem, we have removed: + +- `sync` [repository](https://docs.abp.io/en/abp/latest/Repositories) methods (like `insert`, `update`, etc...), +- `sync` APIs of the [unit of work](https://docs.abp.io/en/abp/latest/Unit-Of-Work), +- `sync` APIs of the [background jobs](https://docs.abp.io/en/abp/latest/Background-Jobs), +- `sync` APIs of the [audit logging](https://docs.abp.io/en/abp/latest/Audit-Logging), +- some other rarely used `sync` APIs. + +If you get any compile error, just use the `async` versions of these APIs. + +#### Always Async! + +Beginning from the v2.0, the ABP framework assumes that you are writing your application code `async` first. Otherwise, some framework functionalities may not properly work. + +It is suggested to write `async` to all your [application services](https://docs.abp.io/en/abp/latest/Application-Services), [repository methods](https://docs.abp.io/en/abp/latest/Repositories), controller actions, page handlers. + +Even if your application service method doesn't need to be `async` , set it as `async` , because interceptors perform `async` operations (for authorization, unit of work, etc...). You can return `Task.Completed` from a method that doesn't make an `async` call. + +Example: + +````csharp +public Task GetValueAsync() +{ + //this method doesn't make any async call. + return Task.CompletedTask(42); +} +```` + +The example above normally doesn't need to be `async` because it doesn't perform an `async` call. However, making it `async` helps the ABP framework to run interceptors without `async` over sync calls. + +This rule doesn't force you to write every method `async` . This would not be good and would be tedious. It is only needed for the intercepted services (especially for [application services](https://docs.abp.io/en/abp/latest/Application-Services) and [repository methods](https://docs.abp.io/en/abp/latest/Repositories)) + +#### Other Breaking Changes + +See [the release notes](https://github.com/abpframework/abp/releases/tag/2.0.0) for the other breaking changes. Most of them will not affect your application code. + +### New Features + +This release also contains some new features and tens of enhancements: + +- [#2597](https://github.com/abpframework/abp/pull/2597) New `Volo.Abp.AspNetCore.Serilog` package. +- [#2526](https://github.com/abpframework/abp/issues/2526) Client-side validation for the dynamic `C#` client proxies. +- [#2374](https://github.com/abpframework/abp/issues/2374) `Async` background jobs. +- [#265](https://github.com/abpframework/abp/issues/265) Managing the application shutdown. +- [#2472](https://github.com/abpframework/abp/issues/2472) Implemented `DeviceFlowCodes` and `TokenCleanupService` for the `IdentityServer` module. + +See [the release notes](https://github.com/abpframework/abp/releases/tag/2.0.0) for the complete list of features, enhancements and bug fixes. + +### Documentation + +We have completed some missing documentation with the v2.0 release. In the following weeks, we will mostly focus on the documentation and tutorials. + +## ABP Commercial + +[ABP Commercial](https://commercial.abp.io/) is a set of professional **modules, tools, themes, and services** built on top of the open-source ABP framework. + +- It provides [professional modules](https://commercial.abp.io/modules) in addition to the ABP Framework's free & [open source modules](https://docs.abp.io/en/abp/latest/Modules/Index). +- It includes a beautiful a [UI theme](https://commercial.abp.io/themes) with 5 different styles. +- It provides the [ABP Suite](https://commercial.abp.io/tools/suite); A tool to assist your development to make you more productive. It currently can create full-stack CRUD pages in a few seconds by configuring your entity properties. More functionalities will be added over time. +- [Premium support](https://commercial.abp.io/support) for enterprise companies. + +In addition to these standard set of features, we will provide customer basis services. See the [commercial.abp.io](https://commercial.abp.io/) web site for other details. + +### ABP Framework vs the ABP Commercial + +The ABP Commercial **is not a paid version** of the ABP Framework. You can consider it as **set of additional benefits** for professional companies. You can use it to save your time and develop your product faster. + +ABP Framework is **open source & free** and will always be like that! + +As a principle, we build the main infrastructure as open-source and sell additional pre-built application features, themes, and tools. The main idea similar to the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) & the [ASP.NET Zero](https://aspnetzero.com/) products. + +Buying a commercial license saves your significant time and effort and you can focus on your own business, besides you get dedicated and high priority support. Also, you will be supporting the ABP core team since we are spending most of our time to develop, maintain and support the open-source ABP Framework. + +With the introduction of the ABP Commercial, now ABP becomes a platform. We call it as the **ABP.IO Platform** which consists of the open source ABP Framework and the ABP Commercial. + +### Demo + +If you are wondering how exactly looks like the ABP Commercial application startup template, you can easily [create a demo](https://commercial.abp.io/demo) and see it in action. The demo includes all the pre-built modules and the theme. + +Here, a screenshot from the IdentityServer management module UI: + +![abp-commercial-demo](abp-commercial-demo.png) + +This is another screenshot from a demo application using the material design style of the theme: + +![lepton-theme-material](lepton-theme-material.png) + +### Pricing + +You can build **unlimited projects/products**, sell to **unlimited customers**, host **unlimited servers** without any restriction. Pricing is mostly based on the **developer count**, **support level** and **source code** requirement. There are three main packages; + +- **Team license**: Includes all the modules, themes and tools. Allows developing your product with up to 3 developers. You can buy additional developer licenses. +- **Business license**: Allows downloading the source code of all the modules and the themes. Also, it includes 5 developer licenses by default. You can buy additional developer licenses. +- **Enterprise license**: Provides unlimited and private support in addition to the benefits of the business license. + +See the [pricing page](https://commercial.abp.io/pricing) for details. In addition to the standard packages, we are also providing custom services and custom licensing. [Contact us](https://commercial.abp.io/contact) if you have any questions. + +#### License Comparison + +The license price changes based on your developer count, support level and source-code access. + +##### The Source-Code + +Team license doesn't include the source-code of the pre-built modules & themes. It uses all these modules as **NuGet & NPM packages**. In this way, you can easily **get new features and bug fixes** by just updating the package dependencies. But you can't access their source-code. So you don't have the possibility to embed a module's source code into your application and freely change the source-code. + +Pre-built modules provide some level of **customization** and **extensibility** and allow you to override services, UI parts and so on. We are working on to make them much more customizable and extensible. If you don't need to make major changes in the pre-built modules, the team license will be ideal for you, because it is cheaper and allows you to easily get new features and bug fixes. + +Business and Enterprise licenses allow you to **download the source-code** of any module or the theme when you need it. They also use the same startup template with the team license, so all modules are used as `NuGet` & `NPM` packages by default. But in case of need, you can remove the package dependencies for a module and embed its source-code into your own solution to completely customize it. In this case, upgrading the module will not be as easy as before when a new version is available. You don't have to upgrade it, surely! But if you want, you should do it yourself using some merge tool or Git branch system. + +#### License Lifetime + +ABP Commercial license is **perpetual**, which means you can **use it forever** and continue to develop your applications. + +However, the following services are covered for one year: + +- Premium **support** ends after one year. You can continue to get community support. +- You can not get **updates** of the modules & the themes after one year. You can continue to use the last obtained version. You can even get bug fixes and enhancements for your current major version. +- You can use the **ABP Suite** tool for one year. + +If you want to continue to get these benefits, you can extend your license period. Renewing price is 20% less than the regular price. + +## NDC London 2020 + +Just like the [previous year](https://medium.com/volosoft/impressions-of-ndc-london-2019-f8f391bb7a9c), we are a partner of the famous software development conference: [NDC London](https://ndc-london.com/)! In the previous year, we were there with the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) & [ASP.NET Zero](https://aspnetzero.com/) theme: + +![ndc-london-volosoft](ndc-london-volosoft.png) + +This year, we will be focusing on the **ABP.IO Platform** (The Open Source ABP Framework and the ABP Commercial). Our booth wall will be like that: + +![ndc-london-volosoft](ndc-2020-volosoft-booth-wall.png) + +If you attend to the conference, remember to visit our booth. We would be glad to talk about the ABP platform features, goals and software development in general. + +### Would you like to meet the ABP Team? + +If you are in London and want to have a coffee with us, we will be available at February 1st afternoon. [@hibrahimkalkan](https://twitter.com/hibrahimkalkan) and [@ismcagdas](https://twitter.com/ismcagdas) will be there. + +Just write to info@abp.io if you want to meet :) \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-03-19-abp-framework-v230-has-been-released/post.md b/docs/en/Community-Articles/2020-03-19-abp-framework-v230-has-been-released/post.md new file mode 100644 index 0000000000..55e7ba43af --- /dev/null +++ b/docs/en/Community-Articles/2020-03-19-abp-framework-v230-has-been-released/post.md @@ -0,0 +1,140 @@ +In the days of **coronavirus**, we have released **ABP Framework v2.3** and this post will explain **what's new** with this release and **what we've done** in the last two weeks. + +## About the Coronavirus & Our Team + +**We are very sad** about the coronavirus case. As [Volosoft](https://volosoft.com/) team, we have **remote workers** working in their home in different countries. Beginning from the last week, we've **completely started to work remotely** from home including our main office employees. + +We believe in and pray for that the humanity will overcome this issue in a short time. + +## About the Release Cycle + +Beginning from the ABP v2.1.0, we have started to release feature versions once **in two weeks**, on Thursdays. This is the 3rd release after that decision and we see that it works fine for now and improved our agility. + +We will continue to release **feature versions** (like v2.4, v2.5) in every two weeks. In addition, we may release **hotfix versions** (like v2.3.1, v2.3.2) whenever needed. + +## What's New in ABP Framework v2.3.0 + +We've completed & merged **[104](https://github.com/abpframework/abp/milestone/30?closed=1) issues and pull requests** with **393 commits** in this two weeks development period. + +I will introduce some new features and enhancements introduced with this release. + +### React Native Mobile Application + +We have finally completed the **react native mobile application**. It currently allows you to **login**, manage your **users** and **tenants**. It utilizes the same setting, authorization and localization systems of the ABP Framework. + +A few screenshots from the application: + +![mobile-ui](react-native-ui.png) + +It doesn't have much functionality but it is a **perfect starting point** for your own mobile application since it is completely integrated to the backend and supports multi-tenancy. + +### Angular TypeScript Proxy Generator + +It is common to call a REST endpoint in the server from our Angular applications. In this case, we generally create **services** (those have methods for each service method on he server side) and **model objects** (matches to [DTOs](https://docs.abp.io/en/abp/latest/Data-Transfer-Objects) in the server side). + +In addition to manually creating such server-interacting services, we could use tools like [NSWAG](https://github.com/RicoSuter/NSwag) to generate service proxies for us. But NSWAG has the following problems we've experienced: + +* It generates a **big, single** .ts file which has some problems; + * It get **too large** when your application grows. + * It doesn't fit into the **[modular](https://docs.abp.io/en/abp/latest/Module-Development-Basics) approach** of the ABP framework. +* It creates a bit **ugly code**. We want to have a clean code (just like if we write manually). +* It can not generate the same **method signature** declared in the server side (because swagger.json doesn't exactly reflect the method signature of the backend service). We've created an endpoint that exposes server side method contacts to allow clients generate a better aligned client proxies. + +So, we've decided to create an ABP CLI command to automatically generate the typescript client proxies ([#2222](https://github.com/abpframework/abp/issues/2222)) for your REST API developed with the ABP Framework. + +It is easy to use. Just run the following command in the **root folder** of the angular application: + +````bash +abp generate-proxy +```` + +It only creates proxies only for your own application's services. It doesn't create proxies for the services of the application modules you're using (by default). There are several options. See the [CLI documentation](https://docs.abp.io/en/abp/latest/CLI). + +### CRUD Application Services for Entities with Composite Keys + +` CrudAppService ` is a useful base class to create CRUD application services for your entities. But it doesn't support entities with **composite primary keys**. `AbstractKeyCrudAppService` is the new base class that is developed to support entities with composite primary keys. See [the documentation](https://docs.abp.io/en/abp/latest/Application-Services#abstractkeycrudappservice) for more. + +### Add Source Code of the Modules + +The application startup template comes with some [application modules](https://docs.abp.io/en/abp/latest/Modules/Index) **pre-installed** as **NuGet & NPM packages**. This have a few important advantages: + +* You can **easily [upgrade](https://docs.abp.io/en/abp/latest/CLI#update)** these modules when a new version is available. +* Your solution becomes **cleaner**, so you can focus on your own code. + +However, when you need to make **major customizations** for a depended module, it is not easy as its source code is in your applications. To solve this problem, we've introduces a new command to the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) that **replaces** NuGet packages with their **source code** in your solution. The usage is simple: + +````bash +abp add-module --with-source-code +```` + +This command adds a module with source code or replaces with its source code if it is already added as package references. + +> It is suggested to **save your changes** to your source control system before using this command since it makes a lot of changes in your source code. + +In addition, we've documented how to customize depended modules without changing their source code (see the section below). It is suggested to use modules as packages to easily upgrade them in the future. + +> Source code of the free modules are licensed under **MIT**, so you can freely change them and add into your solution. + +### Switch to Preview + +ABP Framework is rapidly evolving and we are frequently releasing new versions. However, if you want to follow it closer, you can use the **daily preview packages**. + +We've created an ABP CLI command to easily **update to the latest preview packages** for your solution. Run the following command in the root folder of your solution: + +````bash +abp switch-to-preview +```` + +It will change the versions of all ABP related NuGet and NPM packages. You can **switch back to the latest stable** when you want: + +````bash +abp switch-to-stable +```` + +See the [ABP CLI document](https://docs.abp.io/en/abp/latest/CLI#switch-to-preview) fore more. + +### Documentation Improvements + +#### Extending/Customizing Depended Application Modules + +We've created a huge documentation that explains how to customize a depended module without changing its source code. See [the documentation](https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Guide). + +In addition to the documentation, we've revised all the modules ([#3166](https://github.com/abpframework/abp/issues/3166)) to make their services easily extensible & customizable. + +#### EF Core Migration Guide + +We've recently created a guide to explain the migration system that is used by the ABP startup templates. [This guide](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Migrations) also explains how to customize the migration structure, split your modules across multiple databases, reusing a module's table and son on. + +#### Migration from the ASP.NET Boilerplate + +If you have a solution built on the ASP.NET Boilerplate, we've [created a guide](https://docs.abp.io/en/abp/latest/AspNet-Boilerplate-Migration-Guide) that tries to help you if you want to migrate your solution to the new ABP Framework. + +### Some Other Features + +#### The Framework + +* Add `IRepository.GetAsync` and `IRepository.FindAsync` methods ([#3184](https://github.com/abpframework/abp/issues/3148)). + +#### Modules + +* Get password & email address of the admin while creating a new tenant, for the tenant management module ([#3088](https://github.com/abpframework/abp/issues/3088)). +* Elastic search integrated full text search for the docs module ([#2901](https://github.com/abpframework/abp/pull/2901)). +* New Quartz background worker module ([#2762](https://github.com/abpframework/abp/issues/2762)) + +#### Samples + +* Add multi-tenancy support to the microservice demo ([#3032](https://github.com/abpframework/abp/pull/3032)). + +See [the release notes](https://github.com/abpframework/abp/releases/tag/2.3.0) for all feature, enhancement and bugfixes. + +## What's Next? + +We have the following goals for the next few months: + +* Complete the **documentation and samples**, write more tutorials. +* Make the framework and existing modules more **customizable and extensible**. +* Integrate to **gRPC** & implement gRPC endpoint for pre-built modules ([#2882](https://github.com/abpframework/abp/issues/2882)). +* Create a **Blazor UI** for the ABP Framework & implement it for all the modules and startup templates ([#394](https://github.com/abpframework/abp/issues/394)). +* Add **new features** to pre-built modules and create new modules for the [ABP Commercial](https://commercial.abp.io/). + +See [the GitHub milestones](https://github.com/abpframework/abp/milestones) for details. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-03-19-abp-framework-v230-has-been-released/react-native-ui.png b/docs/en/Community-Articles/2020-03-19-abp-framework-v230-has-been-released/react-native-ui.png new file mode 100644 index 0000000000..ab054e7cb0 Binary files /dev/null and b/docs/en/Community-Articles/2020-03-19-abp-framework-v230-has-been-released/react-native-ui.png differ diff --git a/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/abp-commercial-ui-extensions.png b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/abp-commercial-ui-extensions.png new file mode 100644 index 0000000000..252af6b9e4 Binary files /dev/null and b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/abp-commercial-ui-extensions.png differ diff --git a/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/audit-log-entity-changes.png b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/audit-log-entity-changes.png new file mode 100644 index 0000000000..6a1ec44810 Binary files /dev/null and b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/audit-log-entity-changes.png differ diff --git a/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/easy-crm.png b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/easy-crm.png new file mode 100644 index 0000000000..2bfa53cbcc Binary files /dev/null and b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/easy-crm.png differ diff --git a/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/github-contribution-graph.png b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/github-contribution-graph.png new file mode 100644 index 0000000000..e624e75e38 Binary files /dev/null and b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/github-contribution-graph.png differ diff --git a/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/module-entity-extended-ui.png b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/module-entity-extended-ui.png new file mode 100644 index 0000000000..25621aabb7 Binary files /dev/null and b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/module-entity-extended-ui.png differ diff --git a/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/post.md b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/post.md new file mode 100644 index 0000000000..b6c1d3f952 --- /dev/null +++ b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/post.md @@ -0,0 +1,247 @@ +# ABP Framework v2.7.0 Has Been Released! + +The **ABP Framework** & and the **ABP Commercial** v2.7 have been released. We hadn't created blog post for the 2.4, 2.4 and 2.6 releases, so this post will also cover **what's new** with these releases and **what we've done** in the last 2 months. + +## About the Release Cycle & Development + +Reminding that we had started to release a new minor feature version **in every two weeks**, generally on Thursdays. Our goal is to deliver new features as soon as possible. + +We've completed & merged hundreds of issues and pull requests with **1,300+ commits** in the last 7-8 weeks, only for the ABP Framework repository. Daily commit counts are constantly increasing: + +![github-contribution-graph](github-contribution-graph.png) + +ABP.IO Platform is rapidly growing and we are getting more and more contributions from the community. + +## What's New in the ABP Framework? + +### Object Extending System + +In the last few releases, we've mostly focused on providing ways to extend existing modules when you use them as NuGet/NPM Packages. + +The Object Extending System allows module developers to create extensible modules and allows application developers to customize and extend a module easily. + +For example, you can add two extension properties to the user entity of the identity module: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdate(options => + { + options.AddOrUpdateProperty("SocialSecurityNumber"); + options.AddOrUpdateProperty("IsSuperUser"); + } + ); +```` + +It is easy to define validation rules for the properties: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty( + "SocialSecurityNumber", + options => + { + options.Attributes.Add(new RequiredAttribute()); + options.Attributes.Add( + new StringLengthAttribute(32) { + MinimumLength = 6 + } + ); + }); +```` + +You can even write custom code to validate the property. It automatically works for the objects those are parameters of an application service, controller or a page. + +While extension properties of an entity are normally stored in a single JSON formatted field in the database table, you can easily configure to store a property as a table field using the EF Core mapping: + +````csharp +ObjectExtensionManager.Instance + .AddOrUpdateProperty( + "SocialSecurityNumber", + options => + { + options.MapEfCore(b => b.HasMaxLength(32)); + } + ); +```` + +See the [Object Extensions document](https://docs.abp.io/en/abp/latest/Object-Extensions) for details about this system. + +See also the [Customizing the Existing Modules](https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Guide) guide to learn all the possible customization options. + +### Text Templating Package + +[Volo.Abp.TextTemplating](https://www.nuget.org/packages/Volo.Abp.TextTemplating) is a new package introduced with the v2.7.0. Previously, [Volo.Abp.Emailing](https://www.nuget.org/packages/Volo.Abp.Emailing) package had a similar functionality but it was limited, experimental and tightly coupled to the emailing. + +The new text templating package allows you to define text based templates those can be easily localized and reused. You can define layout templates and share the layout from other templates. + +We are currently using it for email sending. A module needs to send an email typically defines a template. Example: + +````xml +

{{L "PasswordReset"}}

+ +

{{L "PasswordResetInfoInEmail"}}

+ + +```` + +This is a typical password reset email template. + +* The template system is based on the open source [Scriban library](https://github.com/lunet-io/scriban). So it supports if conditions, loops and much more. +* `model` is used to pass data to the template (just like the ASP.NET Core MVC). +* `L` is a special function that localizes the given string. + +It is typical to use the same layout for all emails. So, you can define a layout template. This is the standard layout template comes with the framework: + +````xml + + + + + + + {{content}} + + +```` + +A layout should have a `{{content}}` area to render the child content (just like the `RenderBody()` in the MVC). + +It is very easy to override a template content by the final application to customize it. + +Whenever you need to render a template, use the `ITemplateRenderer` service by providing the template name and a model. See the [text templating documentation](https://docs.abp.io/en/abp/latest/Text-Templating) for details. We've even created a UI for the ABP Commercial (see the related section below). + +### Subscribing to the Exceptions + +ABP Framework's [exception handling system](https://docs.abp.io/en/abp/latest/Exception-Handling) automatically handles exceptions and returns an appropriate result to the client. In some cases, you may want to have a callback that is notified whenever an exception occurs. In this way, for example, you can send an email or take any action based on the exception. + +Just create a class derived from the `ExceptionSubscriber` class in your application: + +````csharp +public class MyExceptionSubscriber : ExceptionSubscriber +{ + public override async Task HandleAsync(ExceptionNotificationContext context) + { + //TODO... + } +} +```` + +See the [exception handling](https://docs.abp.io/en/abp/latest/Exception-Handling) document for more. + +### Others + +There are many minor features and enhancements made to the framework in the past releases. Here, a few ones: + +* Added `AbpLocalizationOptions.DefaultResourceType` to set the default resource type for the application. In this way, the localization system uses the default resource whenever the resource was not specified. The latest application startup template already configures it, but you may want to set it for your existing applications. +* Added `IsEnabled` to permission definition. In this way, you can completely disable a permission and hide the related functionality from the application. This can be a way of feature switch for some applications. See [#3486](https://github.com/abpframework/abp/issues/3486) for usage. +* Added Dutch and German localizations to all the localization resources defined by the framework. Thanks to the contributors. + +## What's New in the ABP Commercial + +The goal of the [ABP Commercial](https://commercial.abp.io/) is to provide pre-build application functionalities, code generation tools, professional themes, advanced samples and premium support for ABP Framework based projects. + +We are working on the ABP Commercial in the parallel to align with the ABP Framework features and provide more modules, theme options and tooling. + +This section explains what's going on the ABP Commercial side. + +### Module Entity Extension System + +Module entity extension system is a higher level API that uses the object extension system (introduced above) and provides an easy way to add extension properties to existing entities. A new extension property easily automatically becomes a part of the HTTP API and the User Interface. + +Example: Add a `SocialSecurityNumber` to the user entity of the identity module + +````csharp +ObjectExtensionManager.Instance.Modules() + .ConfigureIdentity(identity => + { + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( //property type: string + "SocialSecurityNumber", //property name + property => + { + //validation rules + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add( + new StringLengthAttribute(64) { + MinimumLength = 4 + } + ); + + //...other configurations for this property + } + ); + }); + }); +```` + +With just such a configuration, the user interface will have the new property (on the table and on the create/edit forms): + +![module-entity-extended-ui](module-entity-extended-ui.png) + +The new property can be easily localized and validated. Currently, it supports primitive types like string, number and boolean, but we planned to add more advanced scenarios by the time (like navigation/lookup properties). + +See the [Module Entity Extensions](https://docs.abp.io/en/commercial/latest/guides/module-entity-extensions) guide to learn how to use it and configure details. + +#### Other Extension Points + +There are also some other pre-defined points to customize and extend the user interface of a depended module: + +* You can add a new action for an entity on the data table (left side on the picture below). +* You can add new buttons (or other controls) to the page toolbar (right side on the picture below). +* You can add custom columns to a data table. + +![abp-commercial-ui-extensions](abp-commercial-ui-extensions.png) + +See the [Customizing the Modules](https://docs.abp.io/en/commercial/latest/guides/customizing-modules) guide to learn all the possible ways to customize a depended module. + +### Text Template Management Module + +We are introducing a new module with the v2.7 release: [Text Template Management](https://docs.abp.io/en/commercial/latest/modules/text-template-management). It is basically used to edit text/email templates (introduced with the ABP Framework 2.7) on the user interface and save changed in the database. + +A screenshot from the content editing for the password reset email template: + +![text-template-content-ui](text-template-content-ui.png) + +This module comes pre-installed when you create a new project. + +### Entity History Views + +Audit logging UI module now shows all the entity changes in the application with property change details. + +![audit-log-entity-changes](audit-log-entity-changes.png) + +You can also check history for an entity when you click to the actions menu for the entity: + +![tenant-entity-changes](tenant-entity-changes.png) + +### More Samples + +We are creating more advanced sample applications built with the ABP Commercial. Easy CRM is one of them which will be available in a few days to the commercial customers. + +Here, a screenshot from the Easy CRM dashboard: + +![easy-crm](easy-crm.png) + +It has accounts, contacts, product groups, products, orders and so on. + +### New Modules + +We continue to improve existing modules and creating new modules. In addition to the new [text template management](https://docs.abp.io/en/commercial/latest/modules/text-template-management) module introduced above; + +* We've recently released a [payment module](https://commercial.abp.io/modules/Volo.Payment) that currently works with PayU and 2Checkout payment gateways. More gateways will be added by the time. +* We've created a simple [Twilio SMS integration](https://docs.abp.io/en/commercial/latest/modules/twilio-sms) module to send SMS over the Twilio. +* We are working on a **chat module** that is currently being developed and will be available in the next weeks. +* We are working on the **organization unit management** system for the identity module to create hierarchical organization units (domain layer will be open source & free). + +More modules, theme and tooling options are being developed for the ABP Commercial and the ABP Framework. + +## ABP Framework vs ABP Commercial + +We ([Volosoft](https://volosoft.com/) - the core team behind the ABP.IO platform), are spending almost equal time on the ABP Framework and the ABP Commercial and we consider the ABP.IO platform as a whole. + +[ABP Framework](https://abp.io/) provides all the infrastructure and application independent framework features to make you more productive, focus on your own business code and implement software development best practices. It provides you a well defined and comfortable development experience without repeating yourself. + +[ABP Commercial](https://commercial.abp.io/) provides pre-built functionalities, themes and tooling to save your time if your requirements involve these functionalities in addition to the premium support for the framework and the pre-built modules. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/tenant-entity-changes.png b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/tenant-entity-changes.png new file mode 100644 index 0000000000..31524187b0 Binary files /dev/null and b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/tenant-entity-changes.png differ diff --git a/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/text-template-content-ui.png b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/text-template-content-ui.png new file mode 100644 index 0000000000..99c7972da3 Binary files /dev/null and b/docs/en/Community-Articles/2020-05-08-abp-framework-v270-has-been-released/text-template-content-ui.png differ diff --git a/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/abp-chat-module.png b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/abp-chat-module.png new file mode 100644 index 0000000000..5ae351ebba Binary files /dev/null and b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/abp-chat-module.png differ diff --git a/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/lepton-abp-default-theme.png b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/lepton-abp-default-theme.png new file mode 100644 index 0000000000..f3c3d16581 Binary files /dev/null and b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/lepton-abp-default-theme.png differ diff --git a/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/lepton-abp-material-theme.png b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/lepton-abp-material-theme.png new file mode 100644 index 0000000000..e22c3003d9 Binary files /dev/null and b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/lepton-abp-material-theme.png differ diff --git a/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/lepton-themes.gif b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/lepton-themes.gif new file mode 100644 index 0000000000..7ce3935ef5 Binary files /dev/null and b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/lepton-themes.gif differ diff --git a/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/post.md b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/post.md new file mode 100644 index 0000000000..5f44990c3c --- /dev/null +++ b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/post.md @@ -0,0 +1,215 @@ +# ABP v2.8.0 Releases & Road Map + +The **ABP Framework** & and the **ABP Commercial** v2.8 have been released. This post will cover **what's new** with these releases and the **middle-term road maps** for the projects. + +## What's New in the ABP Framework 2.8? + +You can see all the changes on the [GitHub release notes](https://github.com/abpframework/abp/releases/tag/2.8.0). This post will only cover the important features/changes. + +### SignalR Integration Package + +We've published [a new package](https://www.nuget.org/packages/Volo.Abp.AspNetCore.SignalR) to integrate SignalR to ABP framework based applications. + +> It is already possible to follow [the standard Microsoft tutorial](https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr) to add [SignalR](https://docs.microsoft.com/en-us/aspnet/core/signalr/introduction) to your application. However, ABP provides a SignalR integration packages those simplify the integration and usage. + +See the [SignalR Integration document](https://docs.abp.io/en/abp/latest/SignalR-Integration) to start with the SignalR. + +#### SignalR Demo Application + +We've also created a simple chat application to demonstrate how to use it. + +![signalr-chat-demo](signalr-chat-demo.png) + + +See [the source code of the application.](https://github.com/abpframework/abp-samples/tree/master/SignalRDemo) + +### Console Application Startup Template + +The new console application template can be used to create a new console application that has the ABP Framework integrated. + +Use ABP CLI to create a new console application, specifying the `console` as the `-t` (template) option: + + +abp new MyApp -t console + + +Thanks to the contribution of [@realLiangshiwei](https://github.com/realLiangshiwei) for this template. + +### RTL Support for the MVC UI & Arabic Localization + +[@kgamalseif](https://github.com/kgamalseif) has contributed a RTL implementation for the MVC UI which looks pretty fine: + +![rtl-ui](rtl-ui.png) + +He also localized all the framework and module resources. Thanks to him for this great contribution. + +### Others + +Some other highlights from this release: + +* Converted HttpApi.Client packages of the modules to .netstandard 2.0 to be compatible with other kind of applications. +* Improved the object extensibility system to better handle UI, localization and validation. +* Implemented disabling background job execution for HangFire & Quartz intergrations. +* New JsTree integration package for the MVC UI. +* Moved all samples to the new [abp-samples](https://github.com/abpframework/abp-samples) repository and created an [index page](https://docs.abp.io/en/abp/latest/Samples/Index) to see all. + +### Deprecations + +* Deprecated the `app.UseMvcWithDefaultRouteAndArea()` and introduced the `app.UseConfiguredEndpoints()` (see [#3880](https://github.com/abpframework/abp/issues/3880)). +* Deprecated the `UsePostgreSql()` and introduced the `UseNpgsql()` for the [Volo.Abp.EntityFrameworkCore.PostgreSql](http://nuget.org/packages/Volo.Abp.EntityFrameworkCore.PostgreSql) package. Switch to `UseNpgsql()` if you are using PostgreSQL. + +Old methods are marked as `Obsolete` and will be removed in the next major versions. + +## What's New in the ABP Commercial 2.8? + +### The New Lepton Theme + +We've completely revised [the lepton theme](https://commercial.abp.io/themes). See with different styles: + +![lepton-themes](lepton-themes.gif) + +Example screenshots from the language management page of the ABP Commercial: + +![lepton-abp-default-theme](lepton-abp-default-theme.png) + +(Default style UI) + +![lepton-abp-material-theme](lepton-abp-material-theme.png) + +(Material style UI) + +[Create a demo](https://commercial.abp.io/demo) to test all the styles in live. You can change the style from the settings page. + +### The New Chat Module + +The first version of [the chat module](https://commercial.abp.io/modules/Volo.Chat) has been released with this version. It has only the MVC / Razor Pages UI. Angular UI is on the way. + +![abp-chat-module](abp-chat-module.png) + +It currently has a simple **real time text messaging** functionality. More features like group messaging, sending images/files are on the road map. + +### Others + +* Implemented [module entity extension](https://docs.abp.io/en/commercial/latest/guides/module-entity-extensions) system for the Angular UI. Also improved the system to better handle float/double/decimal, date, datetime, enum and boolean properties. +* Managing product groups on a tree view for the [EasyCRM sample application](https://docs.abp.io/en/commercial/latest/samples/easy-crm). + +## About the Next Versions + +We publish feature releases in **every 2 weeks**. So, the planned date of the next feature version is **June 04** and the version number is **2.9**. This (probably) will be the **last 2.x version** and the following version will be **3.0**. + +### ABP Framework 2.9 & 3.0 + +#### Organization Unit System + +Organization Unit system for the Identity module was intended to be released with 2.8, but unfortunately we couldn't be sure about the stability of the feature, so deferred it to the 2.9. + +#### gRPC + +We planned to work on a gRPC integrated example application. Then we will plan to create gRPC endpoints for all [pre-built modules](https://docs.abp.io/en/abp/latest/Modules/Index) and to [the startup templates](https://docs.abp.io/en/abp/latest/Startup-Templates/Index). We want to use these endpoints with the new planned [Blazor](https://docs.microsoft.com/en-us/aspnet/core/blazor/) UI option (there is a [huge demand](https://github.com/abpframework/abp/issues/394) on a Blazor UI, we know). It doesn't mean that we'll finish the whole work in 3.0, but we are starting and will continue in 3.0+ versions. + +#### Oracle with EF Core + +We see that the people using Oracle with EF Core has some pains, independent from the ABP Framework. Because there is no stable & free Oracle provider for EF Core 3.1 yet. We only see the [Devart](https://www.devart.com/) has created a [paid package](https://www.nuget.org/packages/Devart.Data.Oracle.EFCore). + +[@ebicoglu](https://github.com/ebicoglu) has [created a gist](https://gist.github.com/ebicoglu/9f364c7eff9d87315af0178866186401) to demonstrate how to use it. We [planned](https://github.com/abpframework/abp/issues/3983) to work on an integration package to make it even easier. + +#### API Documentation + +We are [working](https://github.com/abpframework/abp/issues/1184) to create an API documentation for the framework and build a CD pipeline to automatically publish it in every new release. This will make easier to explore the framework classes. + +#### Sample Application: Using SignalR on a Tiered/Distributed system + +Using SignalR on a distributed/microservice system can be tricky since the services are not connected to clients and can not directly call client functions from the server. One way to overcome this problem is using a distributed message bus (like RabbitMQ) that transfers the message from the service to the web application to deliver to the client. + +We will create an example application and document it to demonstrate such an architecture and how it is easy by using the ABP Framework. + +While this topic is not directly related to the ABP Framework and the problem is not unique to an ABP based application, we find useful to create such guides to developers. + +#### And... + +We will spend more time to write more documentation, implement performance improvements, make more tests, creating more extensibility points and so on. + +### ABP Commercial 2.9 & 3.0 + +#### Organization Unit Management UI + +In parallel to the OU system in the ABP Framework (mentioned above), we are creating a UI to manage the organization units, which will be released with the 2.9. + +#### Angular UI for the Chat Module + +The Chat Module (mentioned above) only has the ASP.NET Core MVC / Razor Pages UI now. We are working to create the Angular UI for this module. + +#### New Module Idea: File Management + +We are looking to create a File Management Module that is used to manage (upload/download) and share files between users. You may think as a very simple and lightweight Google Drive :). + +#### Easy CRM Angular UI + +[Easy CRM](https://docs.abp.io/en/commercial/latest/samples/easy-crm) is a sample application we've released with the previous version of the ABP Commercial. In this version, we've added more features to this application. In the next version, we will work on the Angular UI for it. + +We found this application very useful since it is very close to a real world application compared to the simple [BookStore](https://docs.abp.io/en/commercial/latest/samples/index#book-store) example. + +#### And... + +We are working to improve current [modules](https://commercial.abp.io/modules), [themes](https://commercial.abp.io/themes) and the [tooling](https://commercial.abp.io/tools) to provide a more comfortable developer experience with the version 3.0. + +## The Road Map + +We are frequently asked about the road map of the [ABP Framework](https://abp.io/) and the [ABP Commercial](https://commercial.abp.io/). While we've answered to it in various platforms, with this release, we've adding road map pages for these products to their documentation: + +* [ABP Framework Road Map](https://docs.abp.io/en/abp/latest/Road-Map) +* [ABP Commercial Road Map](https://docs.abp.io/en/commercial/latest/road-map) + +I am also writing the road map here, in the following sections; + +### ABP Framework Road Map + +You can always check the milestone planning and the prioritized backlog issues on [the GitHub repository](https://github.com/abpframework/abp/milestones). + +While we will **continue to add other exciting features**, we will work on the following major items in the middle term: + +* **gRPC integration** and implementation for all the pre-built modules. +* **Blazor UI** for the framework and all the pre-built modules. +* **.NET 5.0**! As Microsoft has announced that the .NET 5.0 will be released in November 2020, we will prepare for this change before and move to the .NET 5.0 just after Microsoft releases it. We hope a smooth transition. + +### ABP Commercial Road Map + +We will work on the same items in parallel to to ABP Framework to implement them in the ABP Commercial side: + +* gRPC integration +* Blazor UI +* .NET 5.0 + +In addition, we will be working on the following items in the middle term: + +* A startup template to create microservice solutions (that has Ocelot, Redis, RabbitMQ, ElasticSearch, IdentityServer... etc. pre-integrated and configured). +* More module extension points. +* Dynamic dashboard system. +* Real-time notification system. +* Subscription and payment system for the SaaS module. +* More authentication options. +* New application modules (we have tens of module ideas and will share by the time - the "file management" announced above was one of them). +* New themes & theme styles (including public/corporate web site themes). + +## BONUS: ABP.IO Platform Road Map + +While the ABP Framework and the ABP Commercial are the fundamental components of the ABP.IO Platform, we want to create a much bigger platform to bring the .NET community together to create reusable modules, share knowledge, help each other by taking the advantage of the ABP Framework's unified and standardized development model. + +So, we have new *.abp.io web site ideas I want to share with the community + +#### market.abp.io + +A platform that is used by developers/companies to publish their reusable application modules, themes, libraries and tools base don the ABP Framework. There will be free/open source and commercial products on this web site. + +#### jobs.abp.io + +We are getting too many emails from companies want to hire developers or other other companies to build their products based on the ABP.IO Platform. We, as [Volosoft](https://volosoft.com/), want to stay in the product side rather than customer basis projects. We generally lead them to experienced developers and companies. + +We have a plan to create a web site to meet each side, so you can find developers for your projects or you find short or long term works to do. + +## Follow the ABP! + +Follow the social media accounts to get informed about happenings on the ABP.IO Platform: + +* [@abpframework](https://twitter.com/abpframework): ABP Framework official Twitter account +* [@abpcommercial](https://twitter.com/abpcommercial): ABP Commercial official Twitter account \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/rtl-ui.png b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/rtl-ui.png new file mode 100644 index 0000000000..34cd6581dd Binary files /dev/null and b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/rtl-ui.png differ diff --git a/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/signalr-chat-demo.png b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/signalr-chat-demo.png new file mode 100644 index 0000000000..c93595511a Binary files /dev/null and b/docs/en/Community-Articles/2020-05-22-abp-v280-releases--road-map/signalr-chat-demo.png differ diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/abp-chat-module.png b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/abp-chat-module.png new file mode 100644 index 0000000000..5ae351ebba Binary files /dev/null and b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/abp-chat-module.png differ diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/abp-commercial-290.png b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/abp-commercial-290.png new file mode 100644 index 0000000000..656ff13177 Binary files /dev/null and b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/abp-commercial-290.png differ diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/abp-framework-290-.png b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/abp-framework-290-.png new file mode 100644 index 0000000000..b64735fb54 Binary files /dev/null and b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/abp-framework-290-.png differ diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/easy-crm-1.png b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/easy-crm-1.png new file mode 100644 index 0000000000..07d7a2b54d Binary files /dev/null and b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/easy-crm-1.png differ diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/lepton-theme.png b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/lepton-theme.png new file mode 100644 index 0000000000..f6a85115e0 Binary files /dev/null and b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/lepton-theme.png differ diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/organization-units.png b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/organization-units.png new file mode 100644 index 0000000000..2a6ad72ffb Binary files /dev/null and b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/organization-units.png differ diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/post.md b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/post.md new file mode 100644 index 0000000000..e9f3daa5a3 --- /dev/null +++ b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/post.md @@ -0,0 +1,300 @@ + +The **ABP Framework** & and the **ABP Commercial** version 2.9 have been released, which are the last versions before v3.0! This post will cover **what's new** with these this release. + +## What's New with the ABP Framework 2.9? + +You can see all the changes on the [GitHub release notes](https://github.com/abpframework/abp/releases/tag/2.9.0). This post will only cover the important features/changes. + +![abp-framework-290-.png](abp-framework-290-.png) + +### Pre-Compiling Razor Pages + +Pre-built pages (for [the application modules](https://docs.abp.io/en/abp/latest/Modules/Index)) and view components were compiling on runtime until this version. Now, they are pre-compiled and we've measured that the application startup time (especially for the MVC UI) has been reduced more than 50%. In other words, it is **two-times faster** than the previous version. The speed change also effects when you visit a page for the first time. + +Here, a test result for the startup application template with v2.8 and v.2.9: + + +### v2.8 +```` +2020-06-04 22:59:04.891 +08:00 [INF] Starting web host. +2020-06-04 22:59:07.662 +08:00 [INF] Now listening on: https://localhost:44391 +2020-06-04 22:59:17.315 +08:00 [INF] Request finished in 7756.6218ms 200 text/html; + +Total: 12.42s +```` +### v2.9 +```` +2020-06-04 22:59:13.720 +08:00 [INF] Starting web host. +2020-06-04 22:59:16.639 +08:00 [INF] Now listening on: https://localhost:44369 +2020-06-04 22:59:18.957 +08:00 [INF] Request finished in 1780.5461ms 200 text/html; + +Total: 5.24s +```` + + +You do nothing to get the benefit of the new approach. [Overriding UI pages/components](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Customization-User-Interface) are also just working as before. We will be working on more performance improvements in the v3.0. + +### Organization Unit System + +[The Identity Module](https://docs.abp.io/en/abp/latest/Modules/Identity) now has the most requested feature: Organization Units! + +Organization unit system is used to create a hierarchical organization tree in your application. You can then use this organization tree to authorize data and functionality in your application. + +The documentation will come soon... + +### New Blob Storing Package + +We've created a new [Blob Storing package](https://www.nuget.org/packages/Volo.Abp.BlobStoring) to store arbitrary binary objects. It is generally used to store the content of the files in your application. This package provides an abstraction, so any application or [module](https://docs.abp.io/en/abp/latest/Module-Development-Basics) can save and retrieve files independent from the actual storing provider. + +There are two storage provider currently implemented: + +* [Volo.Abp.BlobStoring.FileSystem](https://www.nuget.org/packages/Volo.Abp.BlobStoring.FileSystem) package stores objects/files in the local file system. +* [Volo.Abp.BlobStoring.Database](https://github.com/abpframework/abp/tree/dev/modules/blob-storing-database) module stores objects/files in a database. It currently supports [Entity Framework Core](https://docs.abp.io/en/abp/latest/Entity-Framework-Core) (so, you can use [any relational DBMS](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Other-DBMS)) and [MongoDB](https://docs.abp.io/en/abp/latest/MongoDB). + +[Azure BLOB provider](https://github.com/abpframework/abp/issues/4098) will be available with v3.0. You can request other cloud providers or contribute yourself on the [GitHub repository](https://github.com/abpframework/abp/issues/new). + +One of the benefits of the blob storing system is that it allows you to create multiple containers (each container is a blob storage) and use different storage providers for each container. + +**Example: Use the default container to save and get a byte array** + +```csharp +public class MyService : ITransientDependency +{ + private readonly IBlobContainer _container; + + public MyService(IBlobContainer container) + { + _container = container; + } + + public async Task FooAsync() + { + //Save a BLOB + byte[] bytes = GetBytesFromSomeWhere(); + await _container.SaveAsync("my-unique-blob-name", bytes); + + //Retrieve a BLOB + bytes = await _container.GetAllBytesAsync("my-unique-blob-name"); + } +} +``` + +It can work with `byte[]` and `Stream` objects. + +**Example: Use a typed (named) container to save and get a stream** + +````csharp +public class MyService : ITransientDependency +{ + private readonly IBlobContainer _container; + + public MyService(IBlobContainer container) + { + _container = container; + } + + public async Task FooAsync() + { + //Save a BLOB + Stream stream = GetStreamFromSomeWhere(); + await _container.SaveAsync("my-unique-blob-name", stream); + + //Retrieve a BLOB + stream = await _container.GetAsync("my-unique-blob-name"); + } +} +```` + +`TestContainer` is an empty class that has no purpose than identifying the container: + +````csharp +[BlobContainerName("test")] //specifies the name of the container +public class TestContainer +{ + +} +```` + +A typed (named) container can be configured to use a different storing provider than the default one. It is a good practice to always use a typed container while developing re-usable modules, so the final application can configure provider for this container without effecting the other containers. + +**Example: Configure the File System provider for the `TestContainer`** + +````csharp +Configure(options => +{ + options.Containers.Configure(configuration => + { + configuration.UseFileSystem(fileSystem => + { + fileSystem.BasePath = "C:\\MyStorageFolder"; + }); + }); +}); +```` + +See the [blob storing documentation](https://docs.abp.io/en/abp/latest/Blob-Storing) for more information. + +### Oracle Integration Package for Entity Framework Core + +We've created an [integration package for Oracle](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.Oracle.Devart), so you can easily switch to the Oracle for the EF Core. It is tested for the framework and pre-built modules. + +[See the documentation](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Oracle) to start using the Oracle integration package. + +### Automatically Determining the Database Provider + +When you develop a **reusable application module** with EF Core integration, you generally want to develop your module **DBMS independent**. However, there are minor (sometimes major) differences between different DBMSs. If you perform a custom mapping based on the DBMS, you can now use `ModelBuilder.IsUsingXXX()` extension methods: + +````csharp +protected override void OnModelCreating(ModelBuilder modelBuilder) +{ + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity(b => + { + //... + if (modelBuilder.IsUsingPostgreSql()) //Check if using PostgreSQL! + { + b.Property(x => x.Number).HasMaxLength(20); + } + else + { + b.Property(x => x.Number).HasMaxLength(32); + } + }); +} +```` + +Beside the stupid example above, you can configure your mapping however you need! + +### ABP CLI: Translate Command + +`abp translate` is a new command that simplifies to translate [localization](https://docs.abp.io/en/abp/latest/Localization) files when you have multiple JSON localization files in a source control repository. + +The main purpose of this command is to **translate the ABP Framework** localization files (since the [abp repository](https://github.com/abpframework/abp) has tens of localization files to be translated in different folders). + +It is appreciated if you use this command to translate the framework resources **for your mother language**. + +See [the documentation](https://docs.abp.io/en/abp/latest/CLI#translate) to learn how to use it. Also see [the contribution guide](https://docs.abp.io/en/abp/latest/Contribution/Index). + +### The New Virtual File System Explorer Module + +Thanks to [@realLiangshiwei](https://github.com/realLiangshiwei) created and contributed a new module to explore files in the [Virtual File System](https://docs.abp.io/en/abp/latest/Virtual-File-System). It works for MVC UI and shows all the virtual files in the application. Example screenshots: + +![virtual-file-explorer-11](virtual-file-explorer-11.png) + +![virtual-file-explorer-2](virtual-file-explorer-2.png) + +[See the documentation](https://docs.abp.io/en/abp/latest/Modules/Virtual-File-Explorer) to learn how to use it. + +### Sample Application: SignalR with Tiered Architecture + +Implementing SignalR in a distributed/tiered architecture can be challenging. We've created a sample application that demonstrate how to implement it using the [SignalR integration](https://docs.abp.io/en/abp/latest/SignalR-Integration) and the [distributed event bus](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus) system easily. + +See [the source code](https://github.com/abpframework/abp-samples/tree/master/SignalRTieredDemo) of the sample solution. + +**An article is on the road** that will deeply explain the solution. Follow the [@abpframework](https://twitter.com/abpframework) Twitter account. + +![signalr-tiered-demo](signalr-tiered-demo.png) + +*A picture from the article that shows the communication diagram of the solution* + +### About gRPC + +We've created a sample application to show how to create and consume gRPC endpoints in your ABP based applications. + +See [the source code](https://github.com/abpframework/abp-samples/tree/master/GrpcDemo) on GitHub. + +We were planning to create gRPC endpoints for all the pre-built application modules, but we see that ASP.NET Core gRPC integration is not mature enough and doesn't support some common deployment scenarios yet. So, deferring this to the next versions ([see this comment](https://github.com/abpframework/abp/issues/2882#issuecomment-633080242) for more). However, it is pretty standard if you want to use gRPC in your applications. ABP Framework has no issue with gRPC. Just check the [sample application](https://github.com/abpframework/abp-samples/tree/master/GrpcDemo). + +### Others + +* [Time zone system](https://github.com/abpframework/abp/pull/3933) to support different time zones for an application. +* Support for [virtual path deployment](https://github.com/abpframework/abp/issues/4089) on IIS. +* RTL support for the Angular UI. + +See the [GitHub release notes](https://github.com/abpframework/abp/releases/tag/2.9.0) for others updates. + +## What's New with the ABP Commercial 2.9 + +In addition to all the features coming with the ABP Framework, the ABP Commercial has additional features with this release, as always. This section covers the [ABP Commercial](https://commercial.abp.io/?ref=abpio) highlights in the version 2.9. + +![abp-commercial-290](abp-commercial-290.png) + +### Organization Unit Management UI + +We've created the UI for manage organization units, their members and roles for the ABP Commercial [Identity Module](https://commercial.abp.io/modules/Volo.Identity.Pro): + +![organization-units](organization-units.png) + +OU management is available for both of the MVC (Razor Pages) and the Angular user interfaces. + +> See [this entry](https://support.abp.io/QA/Questions/222/Bugs--Problems-v290#answer-3cf5eba3-0bf1-2aa1-cc5e-39f5a0750329) if you're upgrading your solution from an earlier version. + +### Chat Module Angular UI + +We had introduced a new [chat module](https://commercial.abp.io/modules/Volo.Chat) in the previous version, which was only supporting the ASP.NET Core MVC / Razor Pages UI. Now, it has also an Angular UI option. + +![abp-chat-module](abp-chat-module.png) + +*A screenshot from the chat module - two users are sending messages to each other* + +### Easy CRM Angular UI + +Easy CRM is a sample application that is built on the ABP Commercial to provide a relatively complex application to the ABP Commercial customers. In the version 2.7, we have lunched it with MVC / Razor Pages UI. With the 2.9 version, we are releasing the Angular UI for the Easy CRM application. + +![easy-crm-1](easy-crm-1.png) + +*A screenshot from the "Order Details" page of the Easy CRM application.* + +See the [Easy CRM document](https://docs.abp.io/en/commercial/latest/samples/easy-crm) to learn how to download and run it. + +### Module Code Generation for the ABP Suite + +[ABP Suite](https://commercial.abp.io/tools/suite) is a tool that's main feature is to [generate code](https://docs.abp.io/en/commercial/latest/abp-suite/generating-crud-page) for complete CRUD functionality for an entity, from database to the UI layer. + +![suite](suite.png) + +*A screenshot from the ABP Suite: Define the properties of a new entity and let it to create the application code for you!* + +It was working only for [the application template](https://docs.abp.io/en/commercial/latest/startup-templates/application/index) until this release. Now, it supports to generate code for the [module projects](https://docs.abp.io/en/commercial/latest/startup-templates/module/index) too. That's a great way to create reusable application modules by taking the power of the code generation. + +In addition to this main feature, we added many minor enhancements on the ABP Suite in this release. + +> Notice: Generating code for the module template is currently in beta. Please inform us if you find any bug. + +### Lepton Theme + +[Lepton Theme](https://commercial.abp.io/themes) is the commercial theme we've developed for the ABP Commercial; + +* It is 100% bootstrap compatible - so you don't write theme specific HTML! +* Provides different kind of styles - you see the material style in the picture below. +* Provides different kind of layouts (side/top menu, fluid/boxed layout...). +* It is lightweight, responsive and modern. +* And... it is upgradeable with no cost! You just update a NuGet/NPM package to get the new features. + +We've create its own web site: [http://leptontheme.com/](http://leptontheme.com/) + +You can view all the components together, independent from an application: + +![lepton-theme](lepton-theme.png) + +This web site is currently in a very early stage. We will be documenting and improving this web site to be a reference for your development and explore the features of the theme. + +### Coming Soon: The File management Module + +Based on the new blob storing system (introduced above), we've started to build a file management module that is used to manage (navigate/upload/download) a hierarchical file system on your application and share the files between your users and with your customers. + +We plan to release the initial version with the ABP Commercial v3.0 and continue to improve it with the subsequent releases. + +## About the Next Version: 3.0 + +We have added many new features with the [v2.8](https://blog.abp.io/abp/ABP-v2.8.0-Releases-%26-Road-Map) and v2.9. In the next version, we will completely focus on the **documentation, performance improvements** and and other enhancements as well as bug fixes. + +For a long time, we were releasing a new feature version in every 2 weeks. We will continue to this approach after v3.0. But, as an exception to the v3.0, the development cycle will be ~4 weeks. **The planned release date for the v3.0 is the July 1, 2020**. + +## Bonus: Articles! + +Beside developing our products, our team are constantly writing articles/tutorials on various topics. You may want to check the latest articles: + +* [ASP.NET Core 3.1 WebHook Implementation Using Pub/Sub](https://volosoft.com/blog/ASP.NET-CORE-3.1-Webhook-Implementation-Using-Pub-Sub/?ref=abpio) +* [Using Azure Key Vault with ASP.NET Core](https://volosoft.com/blog/Using-Azure-Key-Vault-with-ASP.NET-Core/?ref=abpio) \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/signalr-tiered-demo.png b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/signalr-tiered-demo.png new file mode 100644 index 0000000000..c4ca5e2b14 Binary files /dev/null and b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/signalr-tiered-demo.png differ diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/suite.png b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/suite.png new file mode 100644 index 0000000000..7e08cb3ef3 Binary files /dev/null and b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/suite.png differ diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/virtual-file-explorer-11.png b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/virtual-file-explorer-11.png new file mode 100644 index 0000000000..0db07459ca Binary files /dev/null and b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/virtual-file-explorer-11.png differ diff --git a/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/virtual-file-explorer-2.png b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/virtual-file-explorer-2.png new file mode 100644 index 0000000000..5d4d85755d Binary files /dev/null and b/docs/en/Community-Articles/2020-06-05-abp-framework-v290-has-been-released/virtual-file-explorer-2.png differ diff --git a/docs/en/Community-Articles/2020-07-03-abp-framework-v30-has-been-released/file-management-ui.png b/docs/en/Community-Articles/2020-07-03-abp-framework-v30-has-been-released/file-management-ui.png new file mode 100644 index 0000000000..ea210e53b6 Binary files /dev/null and b/docs/en/Community-Articles/2020-07-03-abp-framework-v30-has-been-released/file-management-ui.png differ diff --git a/docs/en/Community-Articles/2020-07-03-abp-framework-v30-has-been-released/post.md b/docs/en/Community-Articles/2020-07-03-abp-framework-v30-has-been-released/post.md new file mode 100644 index 0000000000..bd727c03e1 --- /dev/null +++ b/docs/en/Community-Articles/2020-07-03-abp-framework-v30-has-been-released/post.md @@ -0,0 +1,180 @@ +We are excited to announce that the **ABP Framework** & and the **ABP Commercial** version 3.0 have been released. As different than the regular release lifecycle, which is 2-weeks, this version has taken 4-weeks with **119 [issues](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3A3.0)** closed, **89 [pull requests](https://github.com/abpframework/abp/pulls?q=is%3Aopen+is%3Apr+milestone%3A3.0)** merged and **798 commits** done in the main framework [repository](https://github.com/abpframework/abp). + +Since this is a **major version**, it also includes some **breaking changes**. Don't panic, the changes are easy to adapt and will be explained below. + +> See the [GitHub release notes](https://github.com/abpframework/abp/releases) for a detailed change log. + +## What's New with the ABP Framework 3.0? + +This post will only cover the important features/changes. You can see all the changes on the [GitHub release notes](https://github.com/abpframework/abp/releases/tag/3.0.0). + +### Angular 10! + +Angular version 10 has just been [released](https://blog.angular.io/version-10-of-angular-now-available-78960babd41) and we've immediately migrated the [startup templates](https://docs.abp.io/en/abp/latest/Startup-Templates/Application) to Angular 10! So, when you [create a new solution](https://abp.io/get-started) with the Angular UI, you will take the advantage of the new Angular. + +We've prepared a [migration guide](https://github.com/abpframework/abp/blob/dev/docs/en/UI/Angular/Migration-Guide-v3.md) for the projects created an older version and want to migrate to Angular 10. + +### The Oracle Integration Package + +We had created [an integration package](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.Oracle.Devart) for the Oracle for EF Core based applications using the Devart's library since the official Oracle EF Core package was not supporting the EF Core 3.1. It now supports as a [beta release](https://www.nuget.org/packages/Oracle.EntityFrameworkCore/3.19.0-beta1). While it is in beta, we've created [the integration package](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.Oracle), so you can use it in your application. + +See [the documentation](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Oracle) for details. + +### Azure BLOB Storage Provider + +We had created a [BLOB storing system](https://docs.abp.io/en/abp/latest/Blob-Storing) in the previous version with a file system and database storage provider. This release introduces the Azure BLOB Storage provider. See [the documentation](https://docs.abp.io/en/abp/latest/Blob-Storing-Azure). + +### Distributed Cache Bulk Operations & the New Redis Cache Package + +The [standard IDistributeCache](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) interface of the ASP.NET Core doesn't contain **bulk operations**, like setting multiple items with a single method/server call. ABP Framework introduces new methods those can be used for bulk operations on the ABP's `IDistributedCache` interface: + +* GetManyAsync / GetMany +* SetManyAsync / SetMany + +Then we needed to implement these new methods for Redis cache and [had to create](https://github.com/abpframework/abp/issues/4483) a Redis integration package which extends the Microsoft's implementation. + +These methods are also used by the ABP Framework to cache settings, features and permissions for a user/role/tenant and brings a **significant performance improvement**. + +See the [caching document](https://docs.abp.io/en/abp/latest/Caching) for details. + +### Embedded Files Manifest Support for the Virtual File System + +Virtual File System now supports to use `GenerateEmbeddedFilesManifest` in your projects to add the **real file/directory structure** of your embedded resources in the compiled assembly. So, you can now access to the files without any file name restriction (previously, some special chars like `.` in the directory names was a problem in some cases) + +See [the documentation](https://docs.abp.io/en/abp/latest/Virtual-File-System) to learn how to take the advantage of new system. + +### New Samples + +Based on the requests from the community, we've prepared two new sample applications: + +* [StoredProcedureDemo](https://github.com/abpframework/abp-samples/tree/master/StoredProcedureDemo) demonstrates how to call stored procedures, views and functions inside a custom repository. +* [OrganizationUnitSample](https://github.com/abpframework/abp-samples/tree/master/OrganizationUnitSample) shows how to use the organization unit system of the [Identity module](https://docs.abp.io/en/abp/latest/Modules/Identity) for your entities. + +### DynamicStringLength & DynamicMaxLength Attributes + +The standard `StringLength` and `MaxLength` data annotation attributes is useful to validate properties of a class when the class is used as a Model or [DTO](https://docs.abp.io/en/abp/latest/Data-Transfer-Objects). However, just like any other attribute, the length values should be literal (constant) values known at **compile time**. + +**Example: Using the `StringLength`** + +```csharp +public class CreateBookDto +{ + public const int MaxNameLength = 128; //CONSTANT! + + [StringLength(MaxNameLength)] + public string Name { get; set; } +} +``` + +ABP Framework now has the `DynamicStringLength` & `DynamicMaxLength` properties to allow to determine the lengths at **runtime**. + +**Example: Using the `DynamicStringLength`** + +```csharp +public class CreateBookDto +{ + public static int MaxNameLength { get; set; } = 128; + + [DynamicStringLength(typeof(CreateBookDto), nameof(MaxNameLength))] + public string Name { get; set; } +} +``` + +`DynamicStringLength` gets a class **type** and the **name** of a static property on this class to read the max length (there is also a minimum length option just like the `StringLength`). + +This allows you to get the max value from a configuration and set on the application startup (generally, in the `PreConfigureServices` method of your [module](https://docs.abp.io/en/abp/latest/Module-Development-Basics)): + +```csharp +CreateBookDto.MaxNameLength = 200; +``` + +This feature is used by the [pre-built application modules](https://docs.abp.io/en/abp/latest/Modules/Index), so you can now override the max lengths of the properties defined in these modules. + +### Auto Distributed Events + +ABP can **automatically publish distributed events** for all entities on their create, update and delete events. That's pretty useful since you commonly interest in these basic events in a distributed system. + +This feature is **mature and [documented](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus#pre-defined-events)** with the v3.0. You can easily configure some or all the entities to be published. + +### IAsyncQueryableExecuter + +When you work with LINQ extension methods, you need to call `ToListAsync()`, `FirstOrDefaultAsync()`... methods on your queries. Unfortunately, these methods are **not standard** LINQ extension methods. They are defined in the [Microsoft.EntityFrameworkCore](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore) package (or in the [MongoDB.Driver](https://www.nuget.org/packages/MongoDB.Driver/) package if you are using the MongoDB). + +So, you need to depend on this package if you want to use the async extension methods. That breaks the layering and makes your application or domain layer depends on the EF Core / MongoDB package. + +`IAsyncQueryableExecuter` is a service defined by the ABP Framework to **execute queries asynchronously without depending the specific provider** (EF Core / MongoDB) package. + +See [the documentation](https://docs.abp.io/en/abp/latest/Repositories#iqueryable-async-operations) to read the details and learn our recommendations. + +### API documentation + +We are now publishing [API documents](https://docs.abp.io/api-docs/abp/3.0/api/index.html) for the ABP Framework and modules in every release. So, you can explore the ABP Framework classes much more easier than before. Click the the **API Documentation** link on the navigation menu of the [documentation](https://docs.abp.io/en/abp/latest/). + +### Package List + +We have [created a page](http://abp.io/packages) to list all the ABP-related official NuGet and NPM packages. + +### Others + +* Implemented front-channel server-side clients [sign out](https://identityserver4.readthedocs.io/en/latest/topics/signout.html) for the identity server. +* `abp.currentUser` (`CurrentUser` service in the Angular UI) now has a `roles` array that contains role names of the current user. +* Upgraded all the NuGet and NPM package dependencies. +* Introduced `ReadOnlyAppService` base class (which has only the get operations) in addition to the `CrudAppService` base class (which has get, create, update and delete operations). + +See the [GitHub release notes](https://github.com/abpframework/abp/releases/tag/3.0.0) for others updates. + +## What's New with the ABP Commercial 3.0? + +In addition to all the features coming with the ABP Framework, the ABP Commercial has additional features with this release, as always. This section covers the [ABP Commercial](https://commercial.abp.io/) highlights in the version 3.0. + +### New File Management Module + +We've created a new module that is used to store and manage files in your application. This new module is based on the [BLOB Storing system](https://docs.abp.io/en/abp/latest/Blob-Storing), so it can use different storage providers to store the file contents. + +**Example screenshot** + +![file-management-ui](file-management-ui.png) + + +You can upload, download and organize files in a hierarchical folder structure. It is also compatible to multi-tenancy and you can determine total size limit for your tenants. In the next versions, we will be working on a "share" system to share files between users in a more controlled way or share your files with your customers with a public link. + +> File Management module is currently available only for the MVC / Razor Pages UI. We are working on the Angular UI and it will be released in the next versions. + +## Breaking Changes + +Since this is a major version, we've redesigned some APIs and introduced a few "easy to fix" breaking changes. + +### ABP Framework + +* Changed some **consts** in the pre-built application modules to static properties that is possible to change by your code. If you've used these consts on an attribute, then use the `DynamicStringLength` as explained above. +* Changed `ConcurrencyStamp` max length to 40. You need to **add a database migration** and update your database after upgrading the ABP Framework. +* Using `~` instead of `^` for NPM package dependencies anymore, to be more stable. + +### ABP Commercial + +* Changed file names for the application logos. Previously, it was using separate logo files for each theme, like `theme1.png`, `theme1-reverse.png`, `theme2.png`, `theme2-reverse.png` (... `6`). Now, we have only two logo files: `logo-light.png` and `logo-dark.png`. So, rename your logo in the `wwwroot/images/logo/` folder for the MVC UI and `/src/assets/images/logo/` folder for the Angular UI. +* We've added the [API documentation](https://docs.abp.io/api-docs/commercial/3.0/api/index.html) for the ABP Commercial too. + +> **Also, see the [migration guide](https://github.com/abpframework/abp/blob/dev/docs/en/UI/Angular/Migration-Guide-v3.md) for Angular UI**. + +## Known Issues + +* 3.0.0 version has a problem with tiered architecture. See [this issue](https://github.com/abpframework/abp/pull/4564) to fix it for your application until we release the v3.0.1. + +## About the Next Versions + +We will continue to release a new minor/feature version in every two weeks. So, the next expected release date is **2020-07-16** for the version **3.1**. + +In the next few versions, we will be focused on the **Blazor UI**, as promised on [the road map](https://docs.abp.io/en/abp/latest/Road-Map). We will continue to improve the documentation, create samples, add other new features and enhancements. Follow the [ABP Framework Twitter account](https://twitter.com/abpframework) for the latest news... + +## Bonus: Articles! + +Beside developing our products, our team are constantly writing articles/tutorials on various topics. You may want to check the latest articles: + +* [What is New in Angular 10?](https://volosoft.com/blog/what-is-new-in-angular-10) +* [Real-Time Messaging In A Distributed Architecture Using ABP, SignalR & RabbitMQ](https://volosoft.com/blog/RealTime-Messaging-Distributed-Architecture-Abp-SingalR-RabbitMQ) +* [How to Use Attribute Directives to Avoid Repetition in Angular Templates](https://volosoft.com/blog/attribute-directives-to-avoid-repetition-in-angular-templates) + +  + +> We’d love to hear from you. Please leave your comments, suggestions, feeedbacks below. diff --git a/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/abp-comm-release-v3.1.png b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/abp-comm-release-v3.1.png new file mode 100644 index 0000000000..13d4de57b4 Binary files /dev/null and b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/abp-comm-release-v3.1.png differ diff --git a/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/abp-framework-release-v3.1.png b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/abp-framework-release-v3.1.png new file mode 100644 index 0000000000..e58db97e0d Binary files /dev/null and b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/abp-framework-release-v3.1.png differ diff --git a/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/email-phone-verification.png b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/email-phone-verification.png new file mode 100644 index 0000000000..2b4c5ac335 Binary files /dev/null and b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/email-phone-verification.png differ diff --git a/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/forgot-password.png b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/forgot-password.png new file mode 100644 index 0000000000..c4bc8bff1d Binary files /dev/null and b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/forgot-password.png differ diff --git a/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/ldap-settings-ui.png b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/ldap-settings-ui.png new file mode 100644 index 0000000000..da77f3bfeb Binary files /dev/null and b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/ldap-settings-ui.png differ diff --git a/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/my-security-logs.png b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/my-security-logs.png new file mode 100644 index 0000000000..10ac509e14 Binary files /dev/null and b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/my-security-logs.png differ diff --git a/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/post.md b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/post.md new file mode 100644 index 0000000000..9a41a8063a --- /dev/null +++ b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/post.md @@ -0,0 +1,311 @@ +Today, we are releasing the **ABP Framework version 3.1 Release Candidate** (RC). The development cycle for this version was **~7 weeks**. It was the longest development cycle for a feature version release ever. We have completed **~150 issues**, merged **~150 PRs** and made **~1,000 commits** only in the main [abp repository](https://github.com/abpframework/abp). See the related [milestone](https://github.com/abpframework/abp/milestone/38?closed=1) on GitHub. + +There were two main reasons of this long development cycle; + +* We've switched to **4-weeks** release cycle (was discussed in [this issue](https://github.com/abpframework/abp/issues/4692)). +* We've [re-written](https://github.com/abpframework/abp/issues/4881) the Angular service proxy generation system using the Angular schematics to make it more stable. There were some problems with the previous implementation. + +This long development cycle brings a lot of new features, improvements and bug fixes. I will highlight the fundamental features and changes in this blog post. + +> `3.1.0` final stable version has been published. See [this post](https://blog.abp.io/abp/ABP-Framework-v3.1-Final-Has-Been-Released) for details. + +## About the Preview/Stable Version Cycle + +As mentioned above, it is planned to release a new stable feature version (like 3.1, 3.2, 3.3...) in every 4-weeks. + +In addition, we are starting to deploy a **preview version** 2-weeks before the stable versions for every feature/major releases. + +Today, we've released `3.1.0-rc.1` as the first preview version. We may release more previews if it is needed until the stable 3.1.0 version. + +**The stable `3.1.0` version will be released on September 3, 2020.** Next RC version, `3.2.0-rc.1`, is planned for September 17, 2020 (2 weeks after the stable 3.1.0 and 2 weeks before the stable 3.2.0). + +We **won't add new features** to a version after publishing the preview version. We only will make **bug fixes** until the stable version. The new features being developed in this period will be available in the next version. + +> We will use `-rc.x` suffix (like `3.1.0-rc.1` and `3.1.0-rc.2`) for preview releases. However, we may also publish with `-preview.x` suffix before RC (Release Candidate) releases, especially for major versions (like 4.0, 5.0...). + +### About the Nightly Builds + +Don't confuse preview versions vs nightly builds. When we say preview, we are mentioning the preview system explained above. + +We will continue to publish **nightly builds** for all the [ABP Framework packages](https://abp.io/packages). Nightly pages are built from the development branch. You can refer to [this document](https://docs.abp.io/en/abp/latest/Nightly-Builds) to learn how to use the nightly packages. + +## Get Started with the RC Versions + +Please try the preview versions and provide feedback to us to release more stable versions. Please open an issue on the [GitHub repository](https://github.com/abpframework/abp/issues/new) if you find a bug or want to give feedback. + +### Update the ABP CLI to the 3.1.0-rc.4 + +Since this is the first preview version, you need to upgrade the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) to the `3.1.0-rc.4` to be able to use the preview features: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 3.1.0-rc.4 +```` + +### New Solutions + +The [ABP.IO](https://abp.io/) platform and the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) are compatible with the RC system. You can select the "preview" option on the [download page](https://abp.io/get-started) or use the "**--preview**" parameter with the ABP CLI [new](https://docs.abp.io/en/abp/latest/CLI?_ga=2.106435654.411298747.1597771169-1910388957.1594128976#new) command: + +````bash +abp new Acme.BookStore --preview +```` + +This command will create a new project with the latest RC/Preview version. Whenever the stable version is released, you can switch to the stable version for your solution using the `abp switch-to-stable` command in the root folder of your solution. + +### Existing Solutions + +If you already have a solution and want to use/test the latest RC/Preview version, use the `abp switch-to-preview` command in the root folder of your solution. You can return back to the latest stable using the `abp switch-to-stable ` command later. + +> Note that the `abp switch-to-preview` command was being used to switch to nightly builds before the v3.1. Now, you should use the `abp switch-to-nightly` for [nightly builds](https://docs.abp.io/en/abp/latest/Nightly-Builds). + +## Breaking Changes / Special Notes + +### ABP & ABP Commercial + +* You may need to upgrade the `Microsoft.Extensions.FileProviders.Embedded` package in your projects to `3.1.6` or a later version. +* If you are using **EF Core**, you may need to **add a new migration** after upgrading the packages. Just run the standard "Add-Migration" command, check the generated migration code and execute the "Update-Database" command to apply changes to the database. +* If you have implemented **social/external logins** for your MVC / Razor Page UI application before, you may want to check [this issue](https://github.com/abpframework/abp/issues/4981). We made some improvements and changes that you may want to take action for your application. Beginning from v3.1, the users created their accounts via social login can still set a local password to login with local username/email & password. +* See the "Angular Service Proxies" section below for the Angular applications. + +### ABP Commercial Only + +* We've **moved favicons** into `/wwwroot/images/favicon/` folder for the ASP.NET Core **MVC / Razor Page UI** applications. There are 10 favicon related files (including the `favicon.ico`) under this directory to better work with different browser and cases. You can create a new application to check this folder and copy the files into your own application. Then you can customize the icons for your own brand (hint: you can use a tool [like that](https://realfavicongenerator.net/) to create the favicons with various formats). +* Removed direct **Twitter & Facebook social login integrations** from the [account module](https://commercial.abp.io/modules/Volo.Account.Pro), for **MVC / Razor Pages UI**. Follow [this documentation](https://github.com/abpframework/abp/blob/dev/docs/en/Authentication/Social-External-Logins.md) to easily add social logins to your applications if you need. The account module provides all the infrastructure to handle social/external logins, you just need to configure it. + +## What's New with the ABP Framework 3.1 RC + +![abp-framework-release-v3.1](abp-framework-release-v3.1.png) + + +### Angular Service Proxies + +ABP provides a system to generate Angular service proxies (with TypeScript) to consume the HTTP APIs of your application. Service proxy generation system **has been completely re-written** with the ABP Framework 3.1. The main goal was to build more stable and feature rich system that is better aligned with other ABP Framework features (like [modularity](https://docs.abp.io/en/abp/latest/Module-Development-Basics)). + +You will continue to use the same `abp generate-proxy` command, however it internally uses an NPM package that implements the command using the Angular schematics. It will come pre-configured for new solutions. However, implement the following steps for existing solutions; + +* Add `@abp/ng.schematics` package to the devDependencies of the Angular project. +* Add `rootNamespace` entry into the `/apis/default/` section in the `/src/environments/environment.ts`, as shown below: + +````json +apis: { + default: { + url: 'https://localhost:44360', + rootNamespace: 'Acme.BookStore' //<-- ADD THIS + }, +} +```` + +`Acme.BookStore` should be replaced by the root namespace of your .NET project. This ensures to not create unnecessary nested folders. + +* Finally, add the following paths to the `tsconfig.base.json` to have a shortcut while importing proxies: + +```json +"paths": { + "@proxy": ["src/app/proxy/index.ts"], + "@proxy/*": ["src/app/proxy/*"] +} +``` + +[See the documentation](https://docs.abp.io/en/abp/3.1/UI/Angular/Service-Proxies) to learn more about the service proxy generation for Angular applications. + +> The [application development tutorial](https://docs.abp.io/en/abp/3.1/Tutorials/Part-1?UI=NG) has been updated based on the new Angular Service proxy system. + +### Authorization Code Flow for the Angular UI + +We were using the **resource owner password authentication** flow for the Angular UI login page. We've implemented **Authorization Code Flow** for the Angular account module and made it **default for new projects**. With this change, the Angular application now redirects to the login page of the MVC UI which was implemented using the Identity Server 4. We also removed the client secret from the Angular side with this change. + +Old behavior remains exist. If you want to switch to the new flow (which is recommended), follow the steps below: + +1) Add `authorization_code` to the `IdentityServerClientGrantTypes` table in the database, for the client used by the Angular UI (the `ClientId` is `YourProjectName_App` by default, in the `IdentityServerClients` table). + +2) Add `http://localhost:4200` to `IdentityServerClientRedirectUris` and `IdentityServerClientPostLogoutRedirectUris` tables for the same client. + +3) Set `RequireClientSecret` to `false` in the `IdentityServerClients` table for the same client. + +> [ABP Commercial](https://commercial.abp.io/) users can make these changes on the [Identity Server Management UI](https://commercial.abp.io/modules/Volo.Identityserver.Ui). + +4) Change the `oAuthConfig` section in the `src/environments/environment.ts` file of the Angular application. + +You can take [this new configuration](https://gist.github.com/hikalkan/e7f6ae7f507b201783682dccaeadc5e3) as a reference. Main changes are; + +* Added `responseType` as `code`. +* Added `redirectUri` +* Added `offline_access` to the `scope`. +* Removed `oidc: false` option. +* Removed the client secret option. + +### Global Feature System + +The new "Global Features" system allows to **enable/disable features of an application or a module** in a central point. It is especially useful if you want to use a module but don't want to bring all its features into your application. If the module was so designed, you can enable only the features you need. + +When you disable a feature; + +* The **database tables** related to that feature should not be created in the database. +* The **HTTP APIs** related to that feature should not be exposed. They returns 404 if they are directly requested. + +So, the goal is that; when you disable a feature, it should behave like that feature doesn't exists in your system at all. + +There is **no way to enable/disable a global feature on runtime**. You should decide it in the development time (remember, even database tables are not being created for disabled global features, so you can't enable it on runtime). + +> "Global Features" system is different than [SaaS/multi-tenancy features](https://docs.abp.io/en/abp/latest/Features), where you can enable/disable features for your tenants on runtime. + +Assume that you are using the [CMS Kit module](https://github.com/abpframework/abp/tree/dev/modules/cms-kit) (this module is in a very early stage) where you only want to enable the comment feature: + +````csharp +GlobalFeatureManager.Instance.Modules.CmsKit().Comments.Enable(); +```` + +You can check if a feature was enabled: + +```csharp +GlobalFeatureManager.Instance.IsEnabled(); +``` + +Or you can add `[RequiresGlobalFeature(...)]` attribute to a controller/page to disable it if the related feature was disabled: + +```csharp +//... +[RequiresGlobalFeature(typeof(CommentsFeature))] +public class CommentController : AbpController +{ + //... +} +``` + +See the issue [#5061](https://github.com/abpframework/abp/issues/5061) until this is fully documented. + +### Social/External Logins + +Implemented the infrastructure for social/external logins in the account module. So, now you can easily configure your application to support social/external logins by [following the documentation](https://github.com/abpframework/abp/blob/dev/docs/en/Authentication/Social-External-Logins.md). Once you configure a provider, a button will appear on the login page to use this provider. + +The social logins will work as expected even if you are using the Angular UI, since the Angular UI uses the MVC login using the authorization code flow implemented with this new version (as explained above). + +### Forgot/Reset Password + +Implemented forgot password / password reset for the account module. + +You can now enter your email address to get an email containing a **password reset link**: + +![forgot-password](forgot-password.png) + +When you click to the link, you are redirected to a password reset page to determine your new password: + +![reset-password](reset-password.png) + +### External Login System + +The standard Social/External Login system (like Facebook login) works via OpenID Connect. That means the user is redirected to the login provider, logins there and redirected to your application. + +While this is pretty nice for most scenarios, sometimes you want a simpler external login mechanism: User enters username & password in your own application's login form and you check the username & password from another source, not from your own database. + +ABP v3.1 introduces an External Login System to check username & password from any source (from an external database, a REST service or from an LDAP / Active Directory server). + +You can check the [issue #4977](https://github.com/abpframework/abp/issues/4977#issuecomment-670006297) until it is fully documented. + +We've implemented LDAP authentication for the ABP Commercial, using this new login extension system (see the ABP Commercial section below). + +### User Security Logs + +The new [Security Log System](https://github.com/abpframework/abp/issues/4492) (of the Identity module) automatically logs all authentication related operations (login, logout, change password...) to a `AbpSecurityLogs` table in the database. + +### New BLOB Storage Providers + +Implemented [AWS](https://github.com/abpframework/abp/blob/dev/docs/en/Blob-Storing-Aws.md) and [Aliyun](https://github.com/abpframework/abp/blob/dev/docs/en/Blob-Storing-Aliyun.md) providers for the [BLOB storing](https://docs.abp.io/en/abp/latest/Blob-Storing) system with this version. + +### Module Entity Extensibility + +We had introduced a entity extension system that allows to add new properties to existing entities of depended modules by a simple configuration. When you add a new property, it appears on the create, edit and list views on the UI and created a new field in the related database table. We've implemented this system for the identity and tenant management modules, so you can extend entities of these modules. See [the documentation](https://github.com/abpframework/abp/blob/dev/docs/en/Module-Entity-Extensions.md). + +### Other Features / Highlights + +Here, some other highlights from this release; + +* UOW level caching system [#4796](https://github.com/abpframework/abp/issues/4796) +* Refactored the console application template to better integrate to the host builder [#5006](https://github.com/abpframework/abp/issues/5006) +* [Volo.Abp.Ldap](https://www.nuget.org/packages/Volo.Abp.Ldap) package now supports multi-tenancy. +* Introduce `BasicAggregateRoot` base class [#4808](https://github.com/abpframework/abp/issues/4808) +* Sets GUID Id in the `InsertAsync` method of the EF Core repository if it was not set by the developer [#4634](https://github.com/abpframework/abp/pull/4634) +* Added `GetPagedListAsync` methods to the repository to simplify paging [#4617](https://github.com/abpframework/abp/pull/4617) +* Configured [Prettier](https://prettier.io/) for the startup template [#4318](https://github.com/abpframework/abp/issues/4318) +* Defined new layout hooks for the MVC UI: before page content & after page content [#4008](https://github.com/abpframework/abp/issues/4008) +* Allow to put static resources (js, css... files) under the Components folder for ASP.NET Core MVC UI. +* Upgraded to AutoMapper 10 and Quartz 3.1 for the related integration packages. + +## What's New with the ABP Commercial v3.1 RC + +![abp-comm-release-v3.1](abp-comm-release-v3.1.png) + +### Security Logs UI + +We've created a UI to report user security logs for authentication related operations, under the Identity Management menu: + +![security-logs-ui](security-logs-ui.png) + +Also, every user can see his/her own security logs by selecting the "My security logs" under the user menu: + +![my-security-logs](my-security-logs.png) + + + +### LDAP Authentication + +We've implemented LDAP authentication using the new external login system explained above. Also, created a UI to configure the server settings: + +![ldap-settings-ui](ldap-settings-ui.png) + +In this way, you can simply check passwords of the users from LDAP in the login page. If given username / password doesn't exists on LDAP, then it fallbacks to the local database, just like before. + +Since it supports **multi-tenancy**, you can enable, disable and configure it for your tenants. + +### Email / Phone Number Verification + +User profile management page now supports to Email & Phone Number verification flow: + +![email-phone-verification](email-phone-verification.png) + +When user clicks to the **verify** button, a verification email/SMS (that has a verification code) sent to the user and the UI waits to submit this code. + +### User Lock + +Implemented to **lock a user** for a given period of time. Locked users can not login to the application for the given period of time: + +![user-lock](user-lock.png) + +### ABP Suite: Angular UI Code Generation Revisited + +Angular UI code generation has been re-written using the Angular Schematics for the ABP Suite. It is now more stable and produces a better application code. + +ABP Suite also supports code generation on module development. + +### Others + +* **Social logins** and **authorization code flow** are also implemented for the ABP Commercial, just as described above. +* Added breadcrumb and file icons for the **file management module**. + +## The ABP Community + +We've lunched the [community.abp.io](https://community.abp.io/) ~two weeks ago with its initial version. It only has "Article submission" system for now. We are developing new exciting features. There will be an update in a few days and we'll publish a new blog post for it. + +## Conclusion + +The main goals of the 3.1 version were; + +* Complete the missing **authentication features** (like social logins, LDAP authentication, authorization code flow for the Angular UI...) for the ABP Framework & ABP Commercial. +* Re-write a stable and feature complete **Angular service proxy generation** system for the ABP Framework and CRUD UI generation system for the ABP Commercial. +* Develop a system to lunch **preview versions** of the platform. `3.1.0-rc.1` was the first preview version that has been published with this new system. +* Complete the fundamental **documentation & tutorials** (we've even created a [video tutorial series](https://www.youtube.com/watch?v=cJzyIFfAlp8&list=PLsNclT2aHJcPNaCf7Io3DbMN6yAk_DgWJ)). + +ABP.IO platform will be more mature & stable with the v3.1. Enjoy Coding! + +  + +## Bonus: Articles! + +Beside developing our products, our team are constantly writing articles/tutorials on various topics. You may want to check the latest articles: + +* [ASP.NET CORE 3.1 Social Login and Multi-Tenancy](https://volosoft.com/blog/ASPNET-CORE-3.1-Social-Login-and-Multi-Tenancy) +* [File Upload/Download with BLOB Storage System in ASP.NET Core & ABP Framework](https://volosoft.com/blog/File-Upload-Download-with-BLOB-Storage-in-ASP.NET-Core-and-ABP) +* [Extracting and Hashing Lazy-Loaded CSS in Angular](https://volosoft.com/blog/Extracting-and-Hashing-Lazy-Loaded-CSS-in-Angular) + +  + +> We’d love to hear from you. Please leave your comments, suggestions, feeedbacks below. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/reset-password.png b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/reset-password.png new file mode 100644 index 0000000000..0dd9c94880 Binary files /dev/null and b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/reset-password.png differ diff --git a/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/security-logs-ui.png b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/security-logs-ui.png new file mode 100644 index 0000000000..65c7380a86 Binary files /dev/null and b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/security-logs-ui.png differ diff --git a/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/user-lock.png b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/user-lock.png new file mode 100644 index 0000000000..f176bf067a Binary files /dev/null and b/docs/en/Community-Articles/2020-08-25-abp-framework-v31-rc-has-been-released/user-lock.png differ diff --git a/docs/en/Community-Articles/2020-09-04-abp-framework-v31-final-has-been-released/post.md b/docs/en/Community-Articles/2020-09-04-abp-framework-v31-final-has-been-released/post.md new file mode 100644 index 0000000000..fdbeb08c0d --- /dev/null +++ b/docs/en/Community-Articles/2020-09-04-abp-framework-v31-final-has-been-released/post.md @@ -0,0 +1,62 @@ +# ABP Framework 3.1 Final Has Been Released + +It is exciting for us to announce that we've released the ABP Framework & ABP Commercial 3.1 today. + +Since all the new features are already explained in details with the [3.1 RC Announcement Post](https://blog.abp.io/abp/ABP-Framework-v3.1-RC-Has-Been-Released), I will not repeat all the details here. Please read [the RC post](https://blog.abp.io/abp/ABP-Framework-v3.1-RC-Has-Been-Released) for **new feature and changes** you may need to do for your solution while upgrading to the version 3.1. + +## Creating New Solutions + +You can create a new solution with the ABP Framework version 3.1 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details. + +## How to Upgrade an Existing Solution + +### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed yet: + +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +### ABP UPDATE Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +````bash +abp update +```` + +After the update command, check [the RC blog post](https://blog.abp.io/abp/ABP-Framework-v3.1-RC-Has-Been-Released) to learn if you need to make any changes in your solution. + +> You may want to see the new [upgrading document](https://docs.abp.io/en/abp/latest/Upgrading). + +## About the version 3.2 + +The planned schedule for the version 3.2 is like that; + +* **September 17, 2020**: 3.2.0-rc.1 (release candidate) +* **October 1, 2020**: 3.2.0 final (stable) + +You can check [the GitHub milestone](https://github.com/abpframework/abp/milestone/39) to see the features/issues we are working on. + +## ABP Community & Articles + +We had lunched the [ABP Community web site](https://community.abp.io/) a few weeks before. The core ABP team and the ABP community have started to create content for the community. + +Here, the last three articles from the ABP Community: + +* [ABP Suite: How to Add the User Entity as a Navigation Property of Another Entity](https://community.abp.io/articles/abp-suite-how-to-add-the-user-entity-as-a-navigation-property-of-another-entity-furp75ex) by [@ebicoglu](https://github.com/ebicoglu) +* [Reuse ABP vNext Modules to Quickly Implement Application Features](https://community.abp.io/articles/reuse-abp-vnext-modules-to-quickly-implement-application-features-tdtmwd9w) by [@gdlcf88](https://github.com/gdlcf88) +* [Using DevExtreme Components With the ABP Framework](https://community.abp.io/articles/using-devextreme-components-with-the-abp-framework-zb8z7yqv) by [@cotur](https://github.com/cotur). + +We are looking for your contributions; You can [submit your article](https://community.abp.io/articles/submit)! We will promote your article to the community. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-09-07-introducing-the-angular-service-proxy-generation/post.md b/docs/en/Community-Articles/2020-09-07-introducing-the-angular-service-proxy-generation/post.md new file mode 100644 index 0000000000..6b9266462f --- /dev/null +++ b/docs/en/Community-Articles/2020-09-07-introducing-the-angular-service-proxy-generation/post.md @@ -0,0 +1,431 @@ +# Introducing the Angular Service Proxy Generation + +ABP Angular Service Proxy System **generates TypeScript services and models** to consume your backend HTTP APIs developed using the ABP Framework. So, you **don't manually create** models for your server side DTOs and perform raw HTTP calls to the server. + +ABP Framework has introduced the **new** Angular Service Proxy Generation system with the **version 3.1**. While this feature was available since the [v2.3](https://blog.abp.io/abp/ABP-Framework-v2_3_0-Has-Been-Released), it was not well covering some scenarios, like inheritance and generic types and had some known problems. **With the v3.1, we've re-written** it using the [Angular Schematics](https://angular.io/guide/schematics) system. Now, it is much more stable and feature rich. + +This post introduces the service proxy generation system and highlights some important features. + +## Installation + +### ABP CLI + +You need to have the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) to use the system. So, install it if you haven't installed before: + +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +If you already have installed it before, you can update to the latest version: + +````shell +dotnet tool update -g Volo.Abp.Cli +```` + +### Project Configuration + +> If you've created your project with version 3.1 or later, you can skip this part since it will be already installed in your solution. + +For a solution that was created before v3.1, follow the steps below to configure the angular application: + +* Add `@abp/ng.schematics` package to the `devDependencies` of the Angular project. Run the following command in the root folder of the angular application: + +````bash +npm install @abp/ng.schematics --save-dev +```` + +- Add `rootNamespace` entry into the `apis/default` section in the `/src/environments/environment.ts`, as shown below: + +```json +apis: { + default: { + ... + rootNamespace: 'Acme.BookStore' + }, +} +``` + +`Acme.BookStore` should be replaced by the root namespace of your .NET project. This ensures to not create unnecessary nested folders while creating the service proxy code. This value is `AngularProxyDemo` for the example solution explained below. + +* Finally, add the following paths to the `tsconfig.base.json` to have a shortcut while importing proxies: + +```json +"paths": { + "@proxy": ["src/app/proxy/index.ts"], + "@proxy/*": ["src/app/proxy/*"] +} +``` + +## Basic Usage + +### Project Creation + +> If you already have a solution, you can skip this section. + +You need to [create](https://abp.io/get-started) your solution with the Angular UI. You can use the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) to create a new solution: + +````bash +abp new AngularProxyDemo -u angular +```` + +#### Run the Application + +The backend application must be up and running to be able to use the service proxy code generation system. + +> See the [getting started](https://docs.abp.io/en/abp/latest/Getting-Started?UI=NG&DB=EF&Tiered=No) guide if you don't know details of creating and running the solution. + +### Backend + +Assume that we have an `IBookAppService` interface: + +````csharp +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace AngularProxyDemo.Books +{ + public interface IBookAppService : IApplicationService + { + public Task> GetListAsync(); + } +} +```` + +That uses a `BookDto` defined as shown: + +```csharp +using System; +using Volo.Abp.Application.Dtos; + +namespace AngularProxyDemo.Books +{ + public class BookDto : EntityDto + { + public string Name { get; set; } + + public DateTime PublishDate { get; set; } + } +} +``` + +And implemented as the following: + +```csharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace AngularProxyDemo.Books +{ + public class BookAppService : ApplicationService, IBookAppService + { + public async Task> GetListAsync() + { + //TODO: get books from a database... + } + } +} +``` + +It simply returns a list of books. You probably want to get the books from a database, but it doesn't matter for this article. + +### HTTP API + +Thanks to the [auto API controllers](https://docs.abp.io/en/abp/latest/API/Auto-API-Controllers) system of the ABP Framework, we don't have to develop API controllers manually. Just **run the backend (*HttpApi.Host*) application** that shows the [Swagger UI](https://swagger.io/tools/swagger-ui/) by default. You will see the **GET** API for the books: + +![swagger](swagger.png) + +### Service Proxy Generation + +Open a **command line** in the **root folder of the Angular application** and execute the following command: + +````bash +abp generate-proxy +```` + +It should produce an output like the following: + +````bash +... +CREATE src/app/proxy/books/book.service.ts (446 bytes) +CREATE src/app/proxy/books/models.ts (148 bytes) +CREATE src/app/proxy/books/index.ts (57 bytes) +CREATE src/app/proxy/index.ts (33 bytes) +```` + +> `generate-proxy` command can take some some optional parameters for advanced scenarios (like [modular development](https://docs.abp.io/en/abp/latest/Module-Development-Basics)). You can take a look at the [documentation](https://docs.abp.io/en/abp/latest/UI/Angular/Service-Proxies). + +#### The Generated Code + +`src/app/proxy/books/book.service.ts`: This is the service that can be injected and used to get the list of books; + +````js +import type { BookDto } from './models'; +import { RestService } from '@abp/ng.core'; +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class BookService { + apiName = 'Default'; + + getList = () => + this.restService.request({ + method: 'GET', + url: `/api/app/book`, + }, + { apiName: this.apiName }); + + constructor(private restService: RestService) {} +} +```` + +`src/app/proxy/books/models.ts`: This file contains the modal classes corresponding to the DTOs defined in the server side; + +````js +import type { EntityDto } from '@abp/ng.core'; + +export interface BookDto extends EntityDto { + name: string; + publishDate: string; +} +```` + +> There are a few more files have been generated to help you import the types easier. + +#### How to Import + +You can now import the `BookService` into any Angular component and use the `getList()` method to get the list of books. + +````js +import { BookService, BookDto } from '../proxy/books'; +```` + +You can also use the `@proxy` as a shortcut of the proxy folder: + +````js +import { BookService, BookDto } from '@proxy/books'; +```` + +### About the Generated Code + +The generated code is; + +* **Simple**: It is almost identical to the code if you've written it yourself. +* **Splitted**: Instead of a single, large file; + * It creates a separate `.ts` file for every backend **service**. **Model** (DTO) classes are also grouped per service. + * It understands the [modularity](https://docs.abp.io/en/abp/latest/Module-Development-Basics), so creates the services for your own **module** (or the module you've specified). +* **Object oriented**; + * Supports **inheritance** of server side DTOs and generates the code respecting to the inheritance structure. + * Supports **generic types**. + * Supports **re-using type definitions** across services and doesn't generate the same DTO multiple times. +* **Well-aligned to the backend**; + * Service **method signatures** match exactly with the services on the backend services. This is achieved by a special endpoint exposed by the ABP Framework that well defines the backend contracts. + * **Namespaces** are exactly matches to the backend services and DTOs. +* **Well-aligned with the ABP Framework**; + * Recognizes the **standard ABP Framework DTO types** (like `EntityDto`, `ListResultDto`... etc) and doesn't repeat these classes in the application code, but uses from the `@abp/ng.core` package. + * Uses the `RestService` defined by the `@abp/ng.core` package which simplifies the generated code, keeps it short and re-uses all the logics implemented by the `RestService` (including error handling, authorization token injection, using multiple server endpoints... etc). + +These are the main motivations behind the decision of creating a service proxy generation system, instead of using a pre-built tool like [NSWAG](https://github.com/RicoSuter/NSwag). + +## Other Examples + +Let me show you a few more examples. + +### Updating an Entity + +Assume that you added a new method to the server side application service, to update a book: + +```csharp +public Task UpdateAsync(Guid id, BookUpdateDto input); +``` + +`BookUpdateDto` is a simple class defined shown below: + +```csharp +using System; + +namespace AngularProxyDemo.Books +{ + public class BookUpdateDto + { + public string Name { get; set; } + + public DateTime PublishDate { get; set; } + } +} +``` + +Let's re-run the `generate-proxy` command: + +````bash +abp generate-proxy +```` + +This command will re-generate the proxies by updating some files. Let's see some of the changes; + +**book.service.ts** + +````js +import type { BookDto, BookUpdateDto } from './models'; +import { RestService } from '@abp/ng.core'; +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class BookService { + apiName = 'Default'; + + getList = () => + this.restService.request({ + method: 'GET', + url: `/api/app/book`, + }, + { apiName: this.apiName }); + + update = (id: string, input: BookUpdateDto) => + this.restService.request({ + method: 'PUT', + url: `/api/app/book/${id}`, + body: input, + }, + { apiName: this.apiName }); + + constructor(private restService: RestService) {} +} +```` + +`update` function has been added to the `BookService` that gets an `id` and a `BookUpdateDto` as the parameters. + +**models.ts** + +````js +import type { EntityDto } from '@abp/ng.core'; + +export interface BookDto extends EntityDto { + name: string; + publishDate: string; +} + +export interface BookUpdateDto { + name: string; + publishDate: string; +} +```` + +Added a new DTO class: `BookUpdateDto`. + +### Advanced Example + +In this example, I want to show a DTO structure using inheritance, generics, arrays and dictionaries. + +I've created an `IOrderAppService` as shown below: + +````csharp +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace AngularProxyDemo.Orders +{ + public interface IOrderAppService : IApplicationService + { + public Task CreateAsync(OrderCreateDto input); + } +} +```` + +`OrderCreateDto` and the related DTOs are as the followings; + +````csharp +using System; +using System.Collections.Generic; +using Volo.Abp.Data; + +namespace AngularProxyDemo.Orders +{ + public class OrderCreateDto : IHasExtraProperties + { + public Guid CustomerId { get; set; } + + public DateTime CreationTime { get; set; } + + //ARRAY of DTOs + public OrderDetailDto[] Details { get; set; } + + //DICTIONARY + public Dictionary ExtraProperties { get; set; } + } + + public class OrderDetailDto : GenericDetailDto //INHERIT from GENERIC + { + public string Note { get; set; } + } + + //GENERIC class + public abstract class GenericDetailDto + { + public Guid ProductId { get; set; } + + public TCount Count { get; set; } + } +} +```` + +When I run the `abp generate-proxy` command again, I see there are some created and updated files. Let's see some important ones; + +`src/app/proxy/orders/order.service.ts` + +````js +import type { OrderCreateDto } from './models'; +import { RestService } from '@abp/ng.core'; +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class OrderService { + apiName = 'Default'; + + create = (input: OrderCreateDto) => + this.restService.request({ + method: 'POST', + url: `/api/app/order`, + body: input, + }, + { apiName: this.apiName }); + + constructor(private restService: RestService) {} +} +```` + +`src/app/proxy/orders/models.ts` + +````js +export interface GenericDetailDto { + productId: string; + count: TCount; +} + +export interface OrderCreateDto { + customerId: string; + creationTime: string; + details: OrderDetailDto[]; + extraProperties: Record; +} + +export interface OrderDetailDto extends GenericDetailDto { + note: string; +} +```` + +## Conclusion + +`abp generate-proxy` is a very handy command that creates all the necessary code to consume your ABP based backend HTTP APIs. It generates a clean code that is well aligned to the backend services and benefits from the power of TypeScript (by using generics, inheritance...). + +## The Documentation + +See [the documentation](https://docs.abp.io/en/abp/latest/UI/Angular/Service-Proxies) for details of the Angular Service Proxy Generation. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-09-07-introducing-the-angular-service-proxy-generation/swagger.png b/docs/en/Community-Articles/2020-09-07-introducing-the-angular-service-proxy-generation/swagger.png new file mode 100644 index 0000000000..1cd24d3ec2 Binary files /dev/null and b/docs/en/Community-Articles/2020-09-07-introducing-the-angular-service-proxy-generation/swagger.png differ diff --git a/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/abp-community-20200917.png b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/abp-community-20200917.png new file mode 100644 index 0000000000..1a3997a6ab Binary files /dev/null and b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/abp-community-20200917.png differ diff --git a/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/account-profile-picture.jpg b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/account-profile-picture.jpg new file mode 100644 index 0000000000..1b57ce4025 Binary files /dev/null and b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/account-profile-picture.jpg differ diff --git a/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/blazor-role-management-img.png b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/blazor-role-management-img.png new file mode 100644 index 0000000000..520ba18b0c Binary files /dev/null and b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/blazor-role-management-img.png differ diff --git a/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/blazorise-github.png b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/blazorise-github.png new file mode 100644 index 0000000000..b5ded34da0 Binary files /dev/null and b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/blazorise-github.png differ diff --git a/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/file-management-module-angular.png b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/file-management-module-angular.png new file mode 100644 index 0000000000..e424056917 Binary files /dev/null and b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/file-management-module-angular.png differ diff --git a/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/host-features.png b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/host-features.png new file mode 100644 index 0000000000..dbfed05104 Binary files /dev/null and b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/host-features.png differ diff --git a/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/post.md b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/post.md new file mode 100644 index 0000000000..6dd9b4dcd6 --- /dev/null +++ b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/post.md @@ -0,0 +1,260 @@ +We are extremely excited today to release the [ABP Framework](https://abp.io/) Release Candidate (and the [ABP Commercial](https://commercial.abp.io/), as always). This release includes an early preview version of the **Blazor UI** for the ABP.IO Platform. + +## The Blazor UI + +While the Blazor UI **should be considered as experimental** for now, it is possible to start to develop your application today. + +### Fundamental Services + +Currently, implemented some important framework features; + +* **Authentication** through the MVC backend using the OpenId Connect authorization code flow. So, all the current login options (login, register, forgot password, external/social logins...) are supported. +* **Authorization**, using the ABP Framework **permissions** as well as the standard authorization system. +* **Localization** just works like the MVC UI. +* **Basic Theme** with the top main menu. +* **Dynamic C# HTTP API proxies**, so you can directly consume your backend API by injecting the application service interfaces. +* Some other **fundamental services** like `ISettingProvider`, `IFeatureChecker`, `ICurrentUser`... + +Also, the standard .net services are already available, like caching, logging, validation and much more. Since the ABP Framework has layered itself, all the non-MVC UI related features are already usable for the Blazor UI. + +### Pre-Built Modules + +Some modules have been implemented; + +* **Identity** module is pre-installed and provides **user, role and permission management**. +* **Profile management** page is implemented to allow to change the password and personal settings. + +### About the Blazorise Library + +We've selected the [Blazorise](https://blazorise.com/) as a fundamental UI library for the Blazor UI. It already supports different HTML/CSS frameworks (like Bootstrap, Bulma, Ant Design...) and significantly increases the developer productivity. + +![blazorise-github](blazorise-github.png) + +We also have good news: **[Mladen Macanović](https://github.com/stsrki)**, the creator of the Blazorise, is **joining to the core ABP Framework team** in the next weeks. We are excited to work with him to bring the power of these two successful projects together. + +### The Tutorial + +We've **updated** the [web application development tutorial](https://docs.abp.io/en/abp/3.2/Tutorials/Part-1?UI=Blazor) for the **Blazor UI**. You can start to develop applications today! The **source code** of the BookStore application developed with this tutorial is [here](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore). + +### Get started with the Blazor UI + +If you want to try the Blazor UI today, follow the instructions below. + +#### Upgrade the ABP CLI + +Install the latest [ABP CLI](https://docs.abp.io/en/abp/3.2/CLI) preview version: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 3.2.0-rc.2 +```` + +#### Create a new Solution + +Then you can create a new solution using the *abp new* command: + +````bash +abp new AbpBlazorDemo -u blazor --preview +```` + +Also, specify the `-t app-pro` parameter if you are an ABP Commercial user. + +> See the ABP CLI documentation for the additional options, like MongoDB database or separated authentication server. + +#### Open the Solution + +Open the generated solution using the latest Visual Studio 2019. You will see a solution structure like the picture below: + +![visual-studio-solution-with-blazor](visual-studio-solution-with-blazor.png) + +#### Run the Application + +* Run the `DbMigrator` project to create the database and seed the initial data. +* Run the `HttpApi.Host` project for the server-side. +* Run the `Blazor` project to start the Blazor UI. + +Use `admin` as the username and `1q2w3E*` as the password to login to the application. + +Here, a screenshot from the role management page of the Blazor UI: + +![blazor-role-management-img](blazor-role-management-img.png) + +## What's New with the ABP Framework 3.2 + +Besides the Blazor UI, there are a lot of issues that have been closed with [the milestone 3.2](https://github.com/abpframework/abp/milestone/39?closed=1). I will highlight some of the major features and changes released with this version. + +### MongoDB ACID Transactions + +[MongoDB integration](https://docs.abp.io/en/abp/3.2/MongoDB) now supports multi-document transactions that comes with the MongoDB 4.x. + +We've **disabled transactions** for solutions use the MongoDB, inside the `YourProjectMongoDbModule.cs` file in the MongoDB project. If your MongoDB server **supports transactions**, you should manually enable it in this class: + +```csharp +Configure(options => +{ + options.TransactionBehavior = UnitOfWorkTransactionBehavior.Auto; +}); +``` + +> Or you can delete this code since this is already the default behavior. + +#### Upgrade Notes + +If you are upgrading an existing solution and your MongoDB server doesn't support transactions, please disable it: + +```csharp +Configure(options => +{ + options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; +}); +``` + +See the [Unit Of Work document](https://docs.abp.io/en/abp/3.2/Unit-Of-Work) to learn more about UOW and transactions. + +Also, add [this file](https://github.com/abpframework/abp/blob/rel-3.2/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.MongoDB/MongoDb/MongoDbMyProjectNameDbSchemaMigrator.cs) into your MongoDB project (remember to change `MongoDbMyProjectNameDbSchemaMigrator` and `IMyProjectNameDbSchemaMigrator` with your own project name). + +#### Integration Tests + +> Transactions are also **disabled for automated integration tests** coming with the application startup template, since the [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library (we use in the test projects) has a problem with the transactions. We've sent a [Pull Request](https://github.com/Mongo2Go/Mongo2Go/pull/101) to fix it and will enable the transactions again when they merge & release it. +> +> If you are upgrading an existing solution and using MongoDB, please disable transactions for the test projects just as described above. + +### Kafka Integration for the Distributed Event Bus + +ABP Framework's [distributed event system](https://docs.abp.io/en/abp/3.2/Distributed-Event-Bus) has been [integrated to RabbitMQ](https://docs.abp.io/en/abp/3.2/Distributed-Event-Bus-RabbitMQ-Integration) before. By the version 3.2, it has a Kafka integration package, named [Volo.Abp.EventBus.Kafka](https://www.nuget.org/packages/Volo.Abp.EventBus.Kafka). + +See the [Kafka integration documentation](https://docs.abp.io/en/abp/3.2/Distributed-Event-Bus-Kafka-Integration) to learn how to install and configure it. + +### Host Features + +[ABP Feature System](https://docs.abp.io/en/abp/3.2/Features) allows you to define features in your application. Then you can enable/disable a feature dynamically on the runtime. It is generally used in a [multi-tenant](https://docs.abp.io/en/abp/3.2/Multi-Tenancy) system to restrict features for tenants, so you can charge extra money for some features in a SaaS application. + +In some cases, you may want to use the same features in the host side (host is you as you are managing the tenants). For this case, we've added a "**Manage Host Features**" button to the Tenant Management page so you can open a modal dialog to select the features for the host side. + +![host-features](host-features.png) + +### AbpHttpClientBuilderOptions + +ABP Framework provides a system to dynamically create C# proxies to consume HTTP APIs from your client applications. `AbpHttpClientBuilderOptions` is a new option class to configure the `HttpClient`s used by the proxy system. + +**Example: Use the [Polly](https://github.com/App-vNext/Polly) library to retry up to 3 times for a failed HTTP request** + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(options => + { + options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) => + { + clientBuilder.AddTransientHttpErrorPolicy(policyBuilder => + policyBuilder.WaitAndRetryAsync( + 3, + i => TimeSpan.FromSeconds(Math.Pow(2, i)) + ) + ); + }); + }); +} +```` + +See the issue [#5304](https://github.com/abpframework/abp/issues/5304) for the details. + +### ABP Build Command + +We are using **mono repository** approach and the [abp repository](https://github.com/abpframework/abp) has tens of solutions and hundreds of projects (the framework, modules, tooling, templates...) with all of them are referencing to each other. + +It gets a significant time to build the whole repository for every Git push. To **optimize** this process, we've created the **abp build** command in the [ABP CLI](https://docs.abp.io/en/abp/3.2/CLI): + +````bash +abp build +```` + +We will use this command to build the abp repository or a solution inside it. However, it is available to everyone in case of need. + +> **Most of the people will not need it**. If you need it, see the [ABP CLI](https://docs.abp.io/en/abp/3.2/CLI) document to learn all the details and options. + +### Other Features, Improvements and Changes + +* Introduced the `DynamicRangeAttribute` that can be used to determine the range values on runtime, just like the `DynamicStringLengthAttribute` was introduced before. +* Improved the feature management modal for multi-tenant applications to group features on the UI and show hierarchically. +* Added `--skip-cli-version-check` option to ABP CLI to improve the performance by bypassing the online version check. +* Angular UI now redirect to MVC UI (the authentication server-side) for profile management page, if the authorization code flow is used (which is the default). +* Account module profile management page is now extensible. You can implement the `IProfileManagementPageContributor` interface and register it using the `ProfileManagementPageOptions` class. +* Improvements and optimizations for the [Angular service proxy generation](https://blog.abp.io/abp/Introducing-the-Angular-Service-Proxy-Generation). + +And a lot of minor improvements and bug fixes. You can see [the milestone 3.2](https://github.com/abpframework/abp/milestone/39?closed=1) for all issues & PRs closed with this version. + +## What's New with the ABP Commercial 3.2 + +### Breaking Changes + +The new *profile picture management* feature uses the [BLOB storing](https://docs.abp.io/en/abp/3.2/Blob-Storing) system, so it needs a Storage Provider. The new **startup template comes with the [Database BLOB Provider](https://docs.abp.io/en/abp/3.2/Blob-Storing-Database) pre-installed**. You can change it if you want to use another BLOB provider (like Azure, AWS or a simple file system). + +**Existing solutions must configure a BLOB provider** after upgrading to the version 3.2. Follow the [BLOB Storing document](https://docs.abp.io/en/abp/3.2/Blob-Storing#blob-storage-providers) to configure the provider yourself. + +### The Blazor UI + +The **experimental** Blazor UI is also available for the ABP Commercial. The [Lepton Theme](https://commercial.abp.io/themes) hasn't been implemented with this initial preview, however we are working on it with the highest priority. + +You can use the [ABP Suite](https://docs.abp.io/en/commercial/latest/abp-suite/index) or the following ABP CLI command to create a new solution with the Blazor UI: + +````bash +abp new AbpBlazorDemo -u blazor -t app-pro --preview +```` + +Please try it and provide feedback to us. Thanks in advance. + +> See the instructions in the *Get started with the Blazor UI* section above to properly create and run your application. + +### File Management Angular UI + +Angular UI for the [File Management](https://commercial.abp.io/modules/Volo.FileManagement) module is available with version 3.2. You can add it to your solution using the ABP Suite. + +![file-management-module-angular](file-management-module-angular.png) + +### Profile Picture Management + +We've added profile picture management for the account module, so a user can select one of the options below for her profile picture; + +* Use the default placeholder as the avatar. +* Use [Gravatar](https://gravatar.com/) service to get the picture matching the email address of the user. +* Upload a file as the profile picture. + +![account-profile-picture](account-profile-picture.jpg) + +### Two Factor Authentication Features + +Created [features](https://docs.abp.io/en/abp/3.2/Features) and [settings](https://docs.abp.io/en/abp/3.2/Settings) to disable, enable or force to use 2FA on login for the tenants and users. + +### Upgrading the ABP Suite + +You can use the following command to upgrade the ABP Suite to the latest preview version: + +```` +abp suite update --preview +```` + +## Other News + +### The ABP Community + +**ABP Community** web site is constantly being improved and new articles are added. We will add "**commenting**" and "**rating**" features to the articles soon to increase the interactivity between the people. + +![abp-community-20200917](abp-community-20200917.png) + +If you have something to share with the ABP community or want to follow the project progress, please check the **[community.abp.io](https://community.abp.io/)**! + +### CMS Kit Project + +We are silently working on a project, named [CMS Kit](https://github.com/abpframework/abp/tree/dev/modules/cms-kit), for a few months. CMS Kit is a set of reusable CMS (Content Management System) components based on the ABP Framework. Some of the components currently being developed: + +* **Comments**; Allows users to comment under something (a blog post, a document, an image... etc). +* **Reactions**; Allows users to give reactions to something (a comment, a picture... etc.) using simple emoji icons. +* **Rating**; Allows users to rate some content from 1 to 5. +* **Newsletter**; Allows you to put a newsletter box to your web site to collect emails from users. +* **Contact**; Put a form to get a message from the web site visitors. + +There are more planned components like articles, tags, votes, favorites, portfolios, image galleries, FAQs... etc. We will document and deploy these components when they get matured and ready to use. Some of them will be open source & free while some of them are paid (included in the [ABP Commercial](https://commercial.abp.io/) license). + +## Feedback + +Please try the ABP Framework 3.2.0 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us to release a more stable version. The planned release date for the [3.2.0 final](https://github.com/abpframework/abp/milestone/43) version is October 01. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/visual-studio-solution-with-blazor.png b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/visual-studio-solution-with-blazor.png new file mode 100644 index 0000000000..097f726bf0 Binary files /dev/null and b/docs/en/Community-Articles/2020-09-18-abp-framework--abp-commercial-32-rc-with-the-new-blazor-ui-/visual-studio-solution-with-blazor.png differ diff --git a/docs/en/Community-Articles/2020-10-02-abp-framework-v32-final-has-been-released/post.md b/docs/en/Community-Articles/2020-10-02-abp-framework-v32-final-has-been-released/post.md new file mode 100644 index 0000000000..41651fb681 --- /dev/null +++ b/docs/en/Community-Articles/2020-10-02-abp-framework-v32-final-has-been-released/post.md @@ -0,0 +1,45 @@ +ABP Framework & ABP Commercial 3.2 have been released today. + +Since all the new features are already explained in detail with the [3.2 RC Announcement Post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-3.2-RC-With-The-New-Blazor-UI), I will not repeat all the details again. Please read [the RC post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-3.2-RC-With-The-New-Blazor-UI) for **new features and changes** you may need to do for your solution while upgrading to version 3.2. + +## Creating New Solutions + +You can create a new solution with the ABP Framework version 3.2 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details. + +## How to Upgrade an Existing Solution + +### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed yet: + +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +### ABP UPDATE Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +````bash +abp update +```` + +After the update command, check [the RC blog post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-3.2-RC-With-The-New-Blazor-UI) to learn if you need to make any changes in your solution. + +> You may want to see the new [upgrading document](https://docs.abp.io/en/abp/latest/Upgrading). + +## About the Next Versions + +The next two versions (3.3 & 4.0) will be mostly related to completing the Blazor UI features and upgrading the ABP Framework & ecosystem to the .NET 5.0. + +The ultimate goal is to complete the version 4.0 with a stable Blazor UI with the fundamental features implemented and publish it just after the Microsoft lunches .NET 5 in this November. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/0f4aa548ce22a256829739f842a3ff54.png b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/0f4aa548ce22a256829739f842a3ff54.png new file mode 100644 index 0000000000..c40b961beb Binary files /dev/null and b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/0f4aa548ce22a256829739f842a3ff54.png differ diff --git a/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/41968da6c558c075cf1239f842a30e29.png b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/41968da6c558c075cf1239f842a30e29.png new file mode 100644 index 0000000000..cfe00ac859 Binary files /dev/null and b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/41968da6c558c075cf1239f842a30e29.png differ diff --git a/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/532b0018b486294ac3e539f842a36433.png b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/532b0018b486294ac3e539f842a36433.png new file mode 100644 index 0000000000..063f0a1ba7 Binary files /dev/null and b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/532b0018b486294ac3e539f842a36433.png differ diff --git a/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/546a89e4112ec73f45ec39f842a3b663.png b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/546a89e4112ec73f45ec39f842a3b663.png new file mode 100644 index 0000000000..920585fbd4 Binary files /dev/null and b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/546a89e4112ec73f45ec39f842a3b663.png differ diff --git a/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/86021f7f983fc9739cfb39f842a29644.png b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/86021f7f983fc9739cfb39f842a29644.png new file mode 100644 index 0000000000..5d332cc996 Binary files /dev/null and b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/86021f7f983fc9739cfb39f842a29644.png differ diff --git a/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/ef376d39f6c5be0a628639f842a448d7.png b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/ef376d39f6c5be0a628639f842a448d7.png new file mode 100644 index 0000000000..0aaeffc6bc Binary files /dev/null and b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/ef376d39f6c5be0a628639f842a448d7.png differ diff --git a/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/post.md b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/post.md new file mode 100644 index 0000000000..eae223b1e1 --- /dev/null +++ b/docs/en/Community-Articles/2020-10-16-abp-framework--abp-commercial-v33-rc-have-been-released/post.md @@ -0,0 +1,284 @@ +> Note that the blog post has been updated for the `3.3.0-rc.2` release. + +We have released the [ABP Framework](https://abp.io/) (and the [ABP Commercial](https://commercial.abp.io/)) `3.3.0-rc.2` today. This blog post introduces the new features and important changes in the new version. + +## Get Started with the 3.3 RC.2 + +If you want to try the version `3.3.0-rc.2` today, follow the steps below; + +1) **Upgrade** the ABP CLI to the version `3.3.0-rc.2` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 3.3.0-rc.2 +```` + +**or install** if you haven't installed before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 3.3.0-rc.2 +```` + +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/3.3/CLI) for all the available options. + +> You can also use the *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the Preview checkbox. + +### Entity Framework Core Migrations + +This release includes changes in the database tables. If you are using EF Core, then you need to **add a new migration** (`Add-Migration`) and **apply changes** (`Update-Database`) to the database after upgrading your project. + +## What's new in the ABP Framework 3.3 + +![abp-fr-note.png](86021f7f983fc9739cfb39f842a29644.png) + +### The Blazor UI + +We had released an experimental early preview version of the Blazor UI with the [previous version](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-3.2-RC-With-The-New-Blazor-UI). In this version, we've completed most of the fundamental infrastructure features and the application modules (like identity and tenant management). + +It currently has almost the same functionalities as the other UI types (Angular & MVC / Razor Pages). + +**Example screenshot**: User management page of the Blazor UI + +![abp-blazor-ui.png](41968da6c558c075cf1239f842a30e29.png) + + +> We've adapted the [Lepton Theme](https://commercial.abp.io/themes) for the ABP Commercial, see the related section below. + +We are still working on the fundamentals. So, the next version may introduce breaking changes of the Blazor UI. We will work hard to keep them with the minimal effect on your application code. + +#### Blazor UI Tutorial + +The [Blazor UI tutorial](https://docs.abp.io/en/abp/3.3/Tutorials/Part-1?UI=Blazor) has been updated for the version `3.3.0-rc.2`. So, you can start the development today! + +#### Breaking Changes on the Blazor UI + +There are some breaking changes with the Blazor UI. If you've built an application and upgrade it, your application might not properly work. See [the migration guide](https://docs.abp.io/en/abp/3.3/Migration-Guides/BlazorUI-3_3) for the changes you need to do after upgrading your application. + +### Automatic Validation for AntiForgery Token for HTTP APIs + +Starting with the version 3.3, all your HTTP API endpoints are **automatically protected** against CSRF attacks, unless you disable it for your application. So, no configuration needed, just upgrade the ABP Framework. + +[See the documentation](https://docs.abp.io/en/abp/3.3/CSRF-Anti-Forgery) to if you want to understand why you need it and how ABP Framework solves the problem. + +### Rebus Integration Package for the Distributed Event Bus + +[Rebus](https://github.com/rebus-org/Rebus) describes itself as "Simple and lean service bus implementation for .NET". There are a lot of integration packages like RabbitMQ and Azure Service Bus for the Rebus. The new [Volo.Abp.EventBus.Rebus](https://www.nuget.org/packages/Volo.Abp.EventBus.Rebus) package allows you to use the Rebus as the [distributed event bus](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus) for the ABP Framework. + +See [the documentation](https://docs.abp.io/en/abp/3.3/Distributed-Event-Bus-Rebus-Integration) to learn how to use Rebus with the ABP Framework. + +### Async Repository LINQ Extension Methods + +You have a problem when you want to use **Async LINQ Extension Methods** (e.g. `FirstOrDefaultAsync(...)`) in your **domain** and **application** layers. These async methods are **not included in the standard LINQ extension methods**. Those are defined by the [Microsoft.EntityFrameworkCore](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore) NuGet package (see [the code](https://github.com/dotnet/efcore/blob/main/src/EFCore/Extensions/EntityFrameworkQueryableExtensions.cs)). To be able to use these `async` methods, you need to reference to the `Microsoft.EntityFrameworkCore` package. + +If you don't want to depend on the EF Core in your business layer, then ABP Framework provides the `IAsyncQueryableExecuter` service to execute your queries asynchronously without depending on the EF Core package. You can see [the documentation](https://docs.abp.io/en/abp/latest/Repositories#option-3-iasyncqueryableexecuter) to get more information about this service. + +ABP Framework version 3.3 takes this one step further and allows you to directly execute the async LINQ extension methods on the `IRepository` interface. + +**Example: Use `CountAsync` and `FirstOrDefaultAsync` methods on the repositories** + +````csharp +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace MyCompanyName.MyProjectName +{ + public class BookAppService : ApplicationService, IBookAppService + { + private readonly IRepository _bookRepository; + + public BookAppService(IRepository bookRepository) + { + _bookRepository = bookRepository; + } + + public async Task DemoAsync() + { + var countAll = await _bookRepository + .CountAsync(); + + var count = await _bookRepository + .CountAsync(x => x.Name.Contains("A")); + + var book1984 = await _bookRepository + .FirstOrDefaultAsync(x => x.Name == "1984"); + } + } +} +```` + +All the standard LINQ methods are supported: *AllAsync, AnyAsync, AverageAsync, ContainsAsync, CountAsync, FirstAsync, FirstOrDefaultAsync, LastAsync, LastOrDefaultAsync, LongCountAsync, MaxAsync, MinAsync, SingleAsync, SingleOrDefaultAsync, SumAsync, ToArrayAsync, ToListAsync*. + +This approach still has a limitation. You need to execute the extension method directly on the repository object. For example, the below usage is **not supported**: + +````csharp +var count = await _bookRepository.Where(x => x.Name.Contains("A")).CountAsync(); +```` + +This is because the object returned from the `Where` method is not a repository object, it is a standard `IQueryable`. In such cases, you can still use the `IAsyncQueryableExecuter`: + +````csharp +var count = await AsyncExecuter.CountAsync( + _bookRepository.Where(x => x.Name.Contains("A")) +); +```` + +`AsyncExecuter` has all the standard extension methods, so you don't have any restriction here. See [the repository documentation](https://docs.abp.io/en/abp/latest/Repositories#iqueryable-async-operations) for all the options you have. + +> ABP Framework does its best to not depend on the EF Core and still be able to use the async LINQ extension methods. However, there is no problem to depend on the EF Core for your application, you can add the `Microsoft.EntityFrameworkCore` NuGet package and use the native methods. + +### Stream Support for the Application Service Methods + +[Application services](https://docs.abp.io/en/abp/latest/Application-Services) are consumed by clients and the parameters and return values (typically [Data Transfer Objects](https://docs.abp.io/en/abp/latest/Data-Transfer-Objects)). In case of the client is a remote application, then these objects should be serialized & deserialized. + +Until the version 3.3, we hadn't suggest to use the `Stream` in the application service contracts, since it is not serializable/deserializable. However, with the version 3.3, ABP Framework properly supports this scenario by introducing the new `IRemoteStreamContent` interface. + +Example: An application service that can get or return streams + +````csharp +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; +using Volo.Abp.Content; + +namespace MyProject.Test +{ + public interface ITestAppService : IApplicationService + { + Task Upload(Guid id, IRemoteStreamContent streamContent); + Task Download(Guid id); + } +} +```` + +The implementation can be as shown below: + +````csharp +using System; +using System.IO; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Services; +using Volo.Abp.Content; + +namespace MyProject.Test +{ + public class TestAppService : ApplicationService, ITestAppService + { + public Task Download(Guid id) + { + var fs = new FileStream("C:\\Temp\\" + id + ".blob", FileMode.OpenOrCreate); + return Task.FromResult( + (IRemoteStreamContent) new RemoteStreamContent(fs) { + ContentType = "application/octet-stream" + } + ); + } + + public async Task Upload(Guid id, IRemoteStreamContent streamContent) + { + using (var fs = new FileStream("C:\\Temp\\" + id + ".blob", FileMode.Create)) + { + await streamContent.GetStream().CopyToAsync(fs); + await fs.FlushAsync(); + } + } + } +} +```` + +> This is just a demo code. Do it better in your production code :) + +Thanks to [@alexandru-bagu](https://github.com/alexandru-bagu) for the great contribution! + +### Other Changes + +* Upgraded all the .NET Core / ASP.NET Core related packages to the version 3.1.8. If you have additional dependencies to the .NET Core / ASP.NET Core related packages, we suggest you to updates your packages to the version 3.1.8 to have the latest bug and security fixes published by Microsoft. +* The blogging module now uses the [BLOB Storing](https://docs.abp.io/en/abp/latest/Blob-Storing) system to store images & files of the blog posts. If you are using this module, then you need to manually migrate the local files to the BLOB Storing system after the upgrade. +* The Angular UI is now redirecting to the profile management page of the MVC UI instead of using its own UI, if you've configured the authorization code flow (which is default since the version 3.2.0). + +## What's new in the ABP Commercial 3.3 + +![abp-co-note.png](532b0018b486294ac3e539f842a36433.png) + +### The Blazor UI + +We have good news for the ABP Commercial Blazor UI too. We have implemented the [Lepton Theme](https://commercial.abp.io/themes) integration, so it is now available with the Blazor UI. Also, implemented most of the fundamental [modules](https://commercial.abp.io/modules). + +**A screenshot from the ABP Commercial startup template with the Blazor UI** + +![abp-commercial-blazor-ui.png](546a89e4112ec73f45ec39f842a3b663.png) + +There are still missing features and modules. However, we are working on it to have a more complete version in the next release. + +#### Breaking Changes on the Blazor UI + +There are some breaking changes with the Blazor UI. If you've built an application and upgrade it, your application might not properly work. See the [ABP Commercial Blazor UI v 3.3 Migration Guide](https://docs.abp.io/en/commercial/3.3/migration-guides/blazor-ui-3_3) for the changes you need to do after upgrading your application. + +#### Known Issues + +When you create a new project, profile management doesn't work, you get an exception because it can't find the `/libs/cropperjs/css/cropper.min.css` file. To fix the issue; + +* Add `"@volo/account": "^3.3.0-rc.2"` to the `package.json` in the `.Host` project. +* Run `yarn` (or `npm install`), then `gulp` on a command line terminal in the root folder of the `.Host` project. + +### Multi-Tenant Social Logins + +[Account module](https://commercial.abp.io/modules/Volo.Account.Pro) now supports to manage the social/external logins in the UI. You can **enable/disable** and **set options** in the settings page. It also supports to use **different credentials for the tenants** and it is also **configured on the runtime**. + +![abp-commercial-setting-account-external-logins.png](0f4aa548ce22a256829739f842a3ff54.png) + +### Linked Accounts + +Linked user system allows you to link other accounts (including account in a different tenant) with your account, so you can switch between different accounts with a single-click. It is practical since you no longer need to logout and login again with entering the credentials of the target account. + +To manage the linked accounts, go to the profile management page from the user menu; + +![abp-commercial-linked-users.png](ef376d39f6c5be0a628639f842a448d7.png) + +### Paypal & Stripe Integrations + +The [Payment Module](https://commercial.abp.io/modules/Volo.Payment) was supporting PayU and 2Checkout providers until the version 3.3. It's now integrated to PayPal and Stripe. See the [technical documentation](https://docs.abp.io/en/commercial/latest/modules/payment) to learn how to use it. + +### ABP Suite Improvements + +We've done a lot of small improvements for the [ABP Suite](https://commercial.abp.io/tools/suite). Some of the enhancements are; + +* Show the previously installed modules as *installed* on the module list. +* Switch between the latest stable, the latest [preview](https://docs.abp.io/en/abp/latest/Previews) and the latest [nightly build](https://docs.abp.io/en/abp/latest/Nightly-Builds) versions of the ABP related packages. +* Moved the file that stores the *previously created entities* into the solution folder to allow you to store it in your source control system. + +### Others + +* Added an option to the Account Module to show reCAPTCHA on the login & the registration forms. + +Besides the new features introduced in this post, we've done a lot of small other enhancements and bug fixes to provide a better development experience and increase the developer productivity. + +## New Articles + +The core ABP Framework team & the community continue to publish new articles on the [ABP Community](https://community.abp.io/) web site. The recently published articles are; + +* [Replacing Email Templates and Sending Emails](https://community.abp.io/articles/replacing-email-templates-and-sending-emails-jkeb8zzh) (by [@EngincanV](https://community.abp.io/members/EngincanV)) +* [How to Add Custom Properties to the User Entity](https://community.abp.io/articles/how-to-add-custom-property-to-the-user-entity-6ggxiddr) (by [@berkansasmaz](https://community.abp.io/members/berkansasmaz)) +* [Using the AdminLTE Theme with the ABP Framework MVC / Razor Pages UI](https://community.abp.io/articles/using-the-adminlte-theme-with-the-abp-framework-mvc-razor-pages-ui-gssbhb7m) (by [@mucahiddanis](https://community.abp.io/members/mucahiddanis)) +* [Using DevExtreme Angular Components With the ABP Framework](https://community.abp.io/articles/using-devextreme-angular-components-with-the-abp-framework-x5nyvj3i) (by [@bunyamin](https://community.abp.io/members/bunyamin)) + +It is appreciated if you want to [submit an article](https://community.abp.io/articles/submit) related to the ABP Framework. + +## About the Next Release + +The next version will be `4.0.0`. We are releasing a major version, since we will move the ABP Framework to .NET 5.0. We see that for most of the applications this will not be a breaking change and we hope you easily upgrade to it. + +The planned 4.0.0-rc.1 (Release Candidate) version date is **November 11**, just after the Microsoft releases the .NET 5.0 final. The planned 4.0.0 final release date is **November 26**. + +Follow the [GitHub milestones](https://github.com/abpframework/abp/milestones) for all the planned ABP Framework version release dates. + +## Feedback + +Please check out the ABP Framework 3.3.0 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us to release a more stable version. The planned release date for the [3.3.0 final](https://github.com/abpframework/abp/milestone/44) version is October 27th. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-10-28-abp-framework--abp-commercial-33-final-have-been-released/post.md b/docs/en/Community-Articles/2020-10-28-abp-framework--abp-commercial-33-final-have-been-released/post.md new file mode 100644 index 0000000000..f8dba5009b --- /dev/null +++ b/docs/en/Community-Articles/2020-10-28-abp-framework--abp-commercial-33-final-have-been-released/post.md @@ -0,0 +1,46 @@ + +ABP Framework & ABP Commercial 3.3.0 have been released today. + +Since all the new features are already explained in details with the [3.3 RC Announcement Post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-v3.3-RC-Have-Been-Released), I will not repeat all the details again. Please read [the RC post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-v3.3-RC-Have-Been-Released) for **new feature and changes** you may need to do for your solution while upgrading to the version 3.3. + +## Creating New Solutions + +You can create a new solution with the ABP Framework version 3.3 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details. + +## How to Upgrade an Existing Solution + +### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed yet: + +````bash +dotnet tool install -g Volo.Abp.Cli +```` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +### ABP UPDATE Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +````bash +abp update +```` + +Run this command in the root folder of your solution. After the update command, check [the RC blog post](https://blog.abp.io/abp/ABP-Framework-ABP-Commercial-v3.3-RC-Have-Been-Released) to learn if you need to make any changes in your solution. + +> You may want to see the new [upgrading document](https://docs.abp.io/en/abp/latest/Upgrading). + +## About the Next Version: 4.0 + +The next version will be 4.0 and it will be mostly related to completing the Blazor UI features and upgrading the ABP Framework & ecosystem to the .NET 5.0. + +The goal is to complete the version 4.0 with a stable Blazor UI with the fundamental features implemented and publish it just after the Microsoft lunches .NET 5 in this November. The planned 4.0 preview release date is November 11th. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/066daf9bcf2e9e2c6bed39f8e7480552.png b/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/066daf9bcf2e9e2c6bed39f8e7480552.png new file mode 100644 index 0000000000..24ae9d86d5 Binary files /dev/null and b/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/066daf9bcf2e9e2c6bed39f8e7480552.png differ diff --git a/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/1ad2d609148d655845ea39f8e73d0894.png b/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/1ad2d609148d655845ea39f8e73d0894.png new file mode 100644 index 0000000000..d349bf0375 Binary files /dev/null and b/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/1ad2d609148d655845ea39f8e73d0894.png differ diff --git a/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/723f7d5553da8714d3f839f8e747c95f.png b/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/723f7d5553da8714d3f839f8e747c95f.png new file mode 100644 index 0000000000..e687049cc9 Binary files /dev/null and b/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/723f7d5553da8714d3f839f8e747c95f.png differ diff --git a/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/post.md b/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/post.md new file mode 100644 index 0000000000..2fd4587ca8 --- /dev/null +++ b/docs/en/Community-Articles/2020-11-17-abpio-platform-v40-rc-has-been-released-based-on-net-50/post.md @@ -0,0 +1,145 @@ +Today, we have released the [ABP Framework](https://abp.io/) (and the [ABP Commercial](https://commercial.abp.io/)) 4.0.0 RC that is based on the **.NET 5.0**. This blog post introduces the new features and important changes in the new version. + +> **The planned release date for the [4.0.0 final](https://github.com/abpframework/abp/milestone/45) version is December 3, 2020**. + +## Get Started with the 4.0 RC + +If you want to try the version `4.0.0` today, follow the steps below; + +1) **Upgrade** the ABP CLI to the version `4.0.0-rc.5` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 4.0.0-rc.5 +```` + +**or install** if you haven't installed before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 4.0.0-rc.5 +```` + +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/3.3/CLI) for all the available options. + +> You can also use the *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. + +## Migrating From 3.x to 4.0 + +The version 4.0 comes with some major changes including the **migration from .NET Core 3.1 to .NET 5.0**. + +We've prepared a **detailed [migration document](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0)** to explain all the changes and the actions you need to take while upgrading your existing solutions. + +## What's new with the ABP Framework 4.0 + +![abp-fr-note.png](723f7d5553da8714d3f839f8e747c95f.png) + +### The Blazor UI + +The Blazor UI is now stable and officially supported. The [web application development tutorial](https://docs.abp.io/en/abp/4.0/Tutorials/Part-1?UI=Blazor) has been updated based on the version 4.0. + +#### abp bundle command + +Introducing the `abp bundle` CLI command to manage static JavaScript & CSS file dependencies of a Blazor application. This command is currently used to add the dependencies to the `index.html` file in the dependency order by respecting to modularity. In the next version it will automatically unify & minify the files. The documentation is being prepared. + +#### Removed the JQuery & Bootstrap JavaScript + +Removed JQuery & Bootstrap JavaScript dependencies for the Blazor UI. + +>There are some other changes in the startup template and some public APIs. Follow the [Migration Guide](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0) to apply changes for existing solutions that you're upgrading from the version 3.3. While we will continue to make improvements add new features, we no longer make breaking changes on the existing APIs until the version 5.0. + +#### Others + +A lot of minor and major improvements have been done for the Blazor UI. Some of them are listed below: + +* Implemented `IComponentActivator` to resolve the component from the `IServiceProvider`. So, you can now inject dependencies into the constructor of your razor component. +* Introduced the `AbpComponentBase` base class that you derive your components from. It has useful base properties that you can use in your pages/components. +* Introduced `IUiNotificationService` service to show toast notifications on the UI. +* Improved the `IUiMessageService` to show message & confirmation dialogs. + +### System.Text.Json + +ABP Framework 4.0 uses the System.Text.Json by default as the JSON serialization library. It, actually, using a hybrid approach: Continues to use the Newtonsoft.Json when it needs to use the features not supported by the System.Text.Json. + +Follow the [Migration Guide](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0) to learn how to configure to use the Newtonsoft.Json for some specific types or switch back to the Newtonsoft.Json as the default JSON serializer. + +### Identity Server 4 Upgrade + +ABP Framework upgrades the [IdentityServer4](https://www.nuget.org/packages/IdentityServer4) library from 3.x to 4.1.1 with the ABP Framework version 4.0. IdentityServer 4.x has a lot of changes. Some of them are **breaking changes in the data structure**. + +Follow the [Migration Guide](https://docs.abp.io/en/abp/4.0/Migration-Guides/Abp-4_0) to upgrade existing solutions. + +### Creating a New Module Inside the Application + +ABP CLI has now a command to create a new module and add it to an existing solution. In this way, you can create modular applications easier than before. + +Example: Create a *ProductManagement* module into your solution. + +````bash +abp add-module ProductManagement --new --add-to-solution-file +```` + +Execute this command in a terminal in the root folder of your solution. If you don't specify the `--add-to-solution-file` option, then the module projects will not be added to the main solution, but the project references still be added. In this case, you need to open the module's solution to develop the module. + +See the [CLI document](https://docs.abp.io/en/abp/4.0/CLI) for other options. + +### WPF Startup Template + +Introducing the WPF startup template for the ABP Framework. Use the ABP CLI new command to create a new WPF application: + +````bash +abp new MyWpfApp -t wpf +```` + +This is a minimalist, empty project template that is integrated to the ABP Framework. + +### New Languages + +**Thanks to the contributors** from the ABP Community, the framework modules and the startup template have been localized to **German** language by [Alexander Pilhar](https://github.com/alexanderpilhar) & [Nico Lachmuth](https://github.com/tntwist) and to **Spanish** language by [Jose Manuel Gonzalez](https://github.com/jmglezgz) and [Washington Acero M.](https://github.com/washyn). + +### Other Notes + +* Upgraded to Angular 11. +* Since [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library not supports transactions, you can use transactions in unit tests for MongoDB. + +## What's new with the ABP Commercial 4.0 + +![abp-co-note.png](066daf9bcf2e9e2c6bed39f8e7480552.png) + +### The Blazor UI + +The Blazor UI for the ABP Commercial is also becomes stable and feature rich with the version 4.0; + +* [ABP Suite](https://commercial.abp.io/tools/suite) now supports to generate CRUD pages for the Blazor UI. +* Completed the [Lepton Theme](https://commercial.abp.io/themes) for the Blazor UI. +* Implemented the [File Management](https://commercial.abp.io/modules/Volo.FileManagement) module for the Blazor UI. + +### The ABP Suite + +While creating create/edit modals with a navigation property, we had two options: A dropdown to select the target entity and a modal to select the entity by searching with a data table. + +Dropdown option now supports **lazy load, search and auto-complete**. In this way, selecting a navigation property becomes much easier and supports large data sets on the dropdown. + +**Example: Select an author while creating a new book** + +![abp-suite-auto-complete-dropdown.png](1ad2d609148d655845ea39f8e73d0894.png) + +With the new version, you can **disable backend code generation** on CRUD page generation. This is especially useful if you want to regenerate the page with a different UI framework, but don't want to regenerate the server side code. + +### Identity Server Management UI Revised + +Completely revised the Identity Server Management UI based on the IDS 4.x changes. + +## About the Next Release + +The next feature version, `4.1.0`, will mostly focus on completing the missing documents, fixing bugs, performance optimizations and improving the Blazor UI features. The planned preview release date for the version `4.1.0` is December 10 and the final (stable) version release date is December 24. + +Follow the [GitHub milestones](https://github.com/abpframework/abp/milestones) for all the planned ABP Framework version release dates. + +## Feedback + +Please check out the ABP Framework 4.0.0 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us to release a more stable version. **The planned release date for the [4.0.0 final](https://github.com/abpframework/abp/milestone/45) version is November 26**. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-12-04-abpio-platform-40-with-net-50-in-the-4th-year/461ed871392027d60be739f93edde364.png b/docs/en/Community-Articles/2020-12-04-abpio-platform-40-with-net-50-in-the-4th-year/461ed871392027d60be739f93edde364.png new file mode 100644 index 0000000000..5c92fb4f5e Binary files /dev/null and b/docs/en/Community-Articles/2020-12-04-abpio-platform-40-with-net-50-in-the-4th-year/461ed871392027d60be739f93edde364.png differ diff --git a/docs/en/Community-Articles/2020-12-04-abpio-platform-40-with-net-50-in-the-4th-year/7585eb53490fa17c62c939f93ede61d6.png b/docs/en/Community-Articles/2020-12-04-abpio-platform-40-with-net-50-in-the-4th-year/7585eb53490fa17c62c939f93ede61d6.png new file mode 100644 index 0000000000..050ed1249e Binary files /dev/null and b/docs/en/Community-Articles/2020-12-04-abpio-platform-40-with-net-50-in-the-4th-year/7585eb53490fa17c62c939f93ede61d6.png differ diff --git a/docs/en/Community-Articles/2020-12-04-abpio-platform-40-with-net-50-in-the-4th-year/post.md b/docs/en/Community-Articles/2020-12-04-abpio-platform-40-with-net-50-in-the-4th-year/post.md new file mode 100644 index 0000000000..5f5f20dce2 --- /dev/null +++ b/docs/en/Community-Articles/2020-12-04-abpio-platform-40-with-net-50-in-the-4th-year/post.md @@ -0,0 +1,86 @@ + +Today, we are extremely happy to release ABP Framework 4.0 with **.NET 5.0 support**! + +## 4 Years of Work + +As a nice coincidence, today is the **4th year** since the first commit made in the [abp repository](https://github.com/abpframework/abp)! So, we can say "*Happy Birthday ABP Framework!*". + +![abp-contribution-graph-4-years.png](461ed871392027d60be739f93edde364.png) + +### Some Statistics + +ABP.IO Platform and the ABP Community is growing. Here, a summary of these 4 years. + +From GitHub, only from the main [abp repository](https://github.com/abpframework/abp); + +* **15,297 commits** done. +* **3,764 issues** are closed. +* **2,133 pull requests** are merged. +* **158 contributors**. +* **88 releases** published. +* **5.2K stars** on GitHub. + +From NuGet & NPM; + +* **220 NuGet** packages & **52 NPM** packages. +* **1,000,000 downloads** only for the core NuGet package. + +From Website; + +* **200,000 visitors**. +* **1,000,000+ sessions**. + +## What's New With 4.0? + +Since all the new features are already explained in details with the [4.0 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-v4.0-RC-Has-Been-Released-based-on-.NET-5.0), I will not repeat all the details again. Please read [the RC post](https://blog.abp.io/abp/ABP.IO-Platform-v4.0-RC-Has-Been-Released-based-on-.NET-5.0) for **new feature and changes** you may need to do for your solution while upgrading to the version 4.0. + +Here, a brief list of major features and changes; + +* Migrated to **.NET 5.0**. +* Stable **Blazor** UI. +* Moved to **System.Text.Json**. +* Upgraded to **IdentityServer** version 4.0. +* **WPF** startup template. + +## Creating New Solutions + +You can create a new solution with the ABP Framework version 4.0 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details. + +## How to Upgrade an Existing Solution + +This is a **major version** and requires some **manual work**, especially related to **.NET 5.0** and **IdentityServer** 4.0 upgrades. + +* See the [MIGRATION GUIDE](https://docs.abp.io/en/abp/latest/Migration-Guides/Abp-4_0) that covers all the details about the upgrade progress. + +* You can also see the [upgrading document](https://docs.abp.io/en/abp/latest/Upgrading). + +## New Guides / Documents + +We are constantly improving the documentation. Our purpose is not only document the ABP Framework, but also write architectural and practical guides for developers. + +### Implementing Domain Driven Design + +[Implementing Domain Driven Design](https://docs.abp.io/en/abp/latest/Domain-Driven-Design-Implementation-Guide) is a practical guide for they want to implement the DDD principles in their solutions. While the implementation details rely on the ABP Framework infrastructure, core concepts, principles and patterns are applicable in any kind of solution, even if it is not a .NET solution. + +![ddd-implementation-guide-sample.png](7585eb53490fa17c62c939f93ede61d6.png) + +### Testing + +The new [Testing document](https://docs.abp.io/en/abp/latest/Testing) discusses different kind of automated tests and explains how you can write tests for your ABP based solutions. + +### UI Documents + +We've created a lot of documents for the [MVC](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Overall), [Blazor](https://docs.abp.io/en/abp/latest/UI/Blazor/Overall) and the [Angular](https://docs.abp.io/en/abp/latest/UI/Angular/Quick-Start) UI. + +## About the Next Version + +The next versions 4.1 will mostly focus on; + +* Improving current features. +* Complete module features for the Blazor UI. +* Improve developer experience and productivity. +* More documentation and examples. + +Planned preview date for the version **4.1 is December 17, 2020**. See the [Road Map](https://docs.abp.io/en/abp/latest/Road-Map) document and [GitHub Milestones](https://github.com/abpframework/abp/milestones) to learn what's planned for the next versions. We are trying to be clear about the coming features and the next release dates. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/0c328649718826cf744439f99633728b.png b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/0c328649718826cf744439f99633728b.png new file mode 100644 index 0000000000..478c8f4f33 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/0c328649718826cf744439f99633728b.png differ diff --git a/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/3374c36d0142fa896bba39f99631b937.png b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/3374c36d0142fa896bba39f99631b937.png new file mode 100644 index 0000000000..45bd98ecd1 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/3374c36d0142fa896bba39f99631b937.png differ diff --git a/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/3ae582c6154776fbb71039f99633f611.png b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/3ae582c6154776fbb71039f99633f611.png new file mode 100644 index 0000000000..4f049c2339 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/3ae582c6154776fbb71039f99633f611.png differ diff --git a/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/4dc15b8c5f46da81c68739f996354058.png b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/4dc15b8c5f46da81c68739f996354058.png new file mode 100644 index 0000000000..1b6a6ff295 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/4dc15b8c5f46da81c68739f996354058.png differ diff --git a/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/4f81a99cc6e49386e98d39f99632228e.png b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/4f81a99cc6e49386e98d39f99632228e.png new file mode 100644 index 0000000000..947e4720af Binary files /dev/null and b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/4f81a99cc6e49386e98d39f99632228e.png differ diff --git a/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/8bb3d261bea682dd7c4a39f996328baf.png b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/8bb3d261bea682dd7c4a39f996328baf.png new file mode 100644 index 0000000000..35bca6a495 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/8bb3d261bea682dd7c4a39f996328baf.png differ diff --git a/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/d5bcdafe37bcb333a24039f9963300b5.png b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/d5bcdafe37bcb333a24039f9963300b5.png new file mode 100644 index 0000000000..d324f29f11 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/d5bcdafe37bcb333a24039f9963300b5.png differ diff --git a/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/ed6fc66747ade597ea2b39f99634f925.png b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/ed6fc66747ade597ea2b39f99634f925.png new file mode 100644 index 0000000000..c3448a3026 Binary files /dev/null and b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/ed6fc66747ade597ea2b39f99634f925.png differ diff --git a/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/post.md b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/post.md new file mode 100644 index 0000000000..8a3267a060 --- /dev/null +++ b/docs/en/Community-Articles/2020-12-21-abpio-platform-v41-rc-has-been-released/post.md @@ -0,0 +1,204 @@ +We have released the [ABP Framework](https://abp.io/) (and the [ABP Commercial](https://commercial.abp.io/)) 4.1.0 RC. This blog post introduces the new features and important changes in this new version. + +> **Notice: [4.1.0 final](https://github.com/abpframework/abp/milestone/47) version has been released at January 6, 2021**. + +## Get Started with the 4.1 RC + +If you want to try the version `4.1.0` today, follow the steps below; + +1) **Upgrade** the ABP CLI to the version `4.1.0-rc.2` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 4.1.0-rc.2 +```` + +**or install** if you haven't installed before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 4.1.0-rc.2 +```` + +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 *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. + +## Breaking Changes + +This version has a minor breaking change if you'd injected a repository by class. This is not a problem for 99% of the applications. However, see [#6677](https://github.com/abpframework/abp/issues/6677) for the solution if that's a breaking change for you. + +## What's new with the ABP Framework 4.1 + +![abp-fr-note-41rc.png](ed6fc66747ade597ea2b39f99634f925.png) + +### Module Entity Extensions + +Module Entity Extension system provides a simple way of adding new properties to an existing entity defined by a module that is used by your application. This feature is now available also for the open source modules (identity and tenant-management). [The documentation](https://docs.abp.io/en/abp/latest/Module-Entity-Extensions) has been moved into the ABP Framework's documentation. + +**Example: Add "SocialSecurityNumber" property to the `IdentityUser` entity** + +````csharp +ObjectExtensionManager.Instance.Modules() + .ConfigureIdentity(identity => + { + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( //property type: string + "SocialSecurityNumber", //property name + property => + { + //validation rules + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add( + new StringLengthAttribute(64) { + MinimumLength = 4 + } + ); + + //...other configurations for this property + } + ); + }); + }); +```` + +The new property becomes available on the UI, API and the database. You can even define navigation properties. This provides an easy way to extend existing modules while using them as NuGet packages. See [the document](https://docs.abp.io/en/abp/latest/Module-Entity-Extensions) for details. + +### Blazor UI Improvements + +Since the Blazor UI is relatively new in the ABP Framework, we continue to add features and make enhancements to fill the gap between other supported UI types. + +#### Bundling & Minification + +In the version 4.1, we had introduced the `abp bundle` command for the Blazor UI to add global script and style files of the depended modules into the `index.html`. It was a preparation for a real bundling & minification system. With the version 4.2, this command has been completed. + +Whenever you add a new module to your Blazor application, just type the `abp bundle` command in a command line terminal; + +* It finds all the global script/style files in your application and the modules your application directly or indirectly depends on, ordered by the module dependencies. +* Bundles all the scripts into a single file and minified the file (same for the styles). +* Add the single bundle file to the `index.html` file. + +Added a configuration into the `appsettings.json` file in the Blazor application in the application startup template to control the bundling mode: + +````js +{ + "AbpCli": { + "Bundle": { + "Mode": "BundleAndMinify" + } + } +} +```` + +Possible values are; + +* `BundleAndMinify`: Bundle all the files into a single file and minify the content. +* `Bundle`: Bundle all files into a single file, but not minify. +* `None`: Add files individually, do not bundle. + +See the [Global Scripts & Styles](https://docs.abp.io/en/abp/latest/UI/Blazor/Global-Scripts-Styles) document for details. + +#### SubmitButton + +`SubmitButton` is a new component that simplifies to save a form: + +````html + +```` + +The main advantages of using this component instead of a standard `Button` with submit type is; It automatically blocks the submit button until the save operation has fully completed. This prevents multiple clicks by user. And it is shorter than doing all manually. See the [document](https://docs.abp.io/en/abp/latest/UI/Blazor/SubmitButton). + +#### Other Blazor UI highlights + +* Implemented some **animations** (like opening/closing modals and dropdowns). +* Automatically **focus** to the first input when you open a modal form. + +Module extensibility system (mentioned above) for the Blazor UI is under development and not available yet. + +## What's new with the ABP Commercial 4.1 + +![abp-co-note-41rc.png](4dc15b8c5f46da81c68739f996354058.png) + +### Blazor UI Improvements + +We continue to complete missing modules and functionalities for the Blazor UI. + +#### Organization Unit Management + +Organization Management UI has been implemented for the Blazor UI. Example screenshot: + +![blazor-organization-units.png](3374c36d0142fa896bba39f99631b937.png) + +#### IdentityServer UI + +IdentityServer Management UI is also available for the Blazor UI now: + +![blazor-identityserver-ui.png](4f81a99cc6e49386e98d39f99632228e.png) + +### Suite: Navigation Property Selection with Typeahead + +We had introduced auto-complete select style navigation property selection. With this release, it is fully supported by all the UI options. So, when you create an CRUD page with ABP Suite for entity that has 1 to Many relation to another entity, you can simply select the target entity with a typeahead style select component. Example screenshot: + +![type-ahead.png](8bb3d261bea682dd7c4a39f996328baf.png) + +### Spanish Language Translation + +We continue to add new language supports for the UI. In this version, translated the UI to **Spanish** language. + +![spanish-commercial-translation.png](d5bcdafe37bcb333a24039f9963300b5.png) + +### Coming: Public Website with Integrated CMS Features + +In the next version, the application startup template will come with a public website application option. CMS Kit module will be installed in the website by default, that means newsletter, contact form, comments and some other new features will be directly usable in your applications. + +An early screenshot from the public website application home page: + +![abp-commercial-public-website.png](0c328649718826cf744439f99633728b.png) + +## Other News + +### ABP Community Contents + +A lot of new contents have been published in the ABP Community Web Site in the last two weeks: + +* [How to Integrate the Telerik Blazor Components to the ABP Blazor UI](https://community.abp.io/articles/how-to-integrate-the-telerik-blazor-components-to-the-abp-blazor-ui-q8g31abb) by [EngincanV](https://github.com/EngincanV) +* [Using DevExpress Blazor UI Components With the ABP Framework](https://community.abp.io/articles/using-devexpress-blazor-ui-components-with-the-abp-framework-wrpoa8rw) by [@berkansasmaz](https://github.com/berkansasmaz) +* [Creating a new UI theme by copying the Basic Theme (for MVC UI)](https://community.abp.io/articles/creating-a-new-ui-theme-by-copying-the-basic-theme-for-mvc-ui-yt9b18io) by [@ebubekirdinc](https://github.com/ebubekirdinc) +* [Using Angular Material Components With the ABP Framework](https://community.abp.io/members/muhammedaltug) by [@muhammedaltug](https://github.com/muhammedaltug) +* [How to export Excel files from the ABP framework](https://community.abp.io/articles/how-to-export-excel-files-from-the-abp-framework-wm7nnw3n) by [bartvanhoey](https://github.com/bartvanhoey) +* [Creating an Event Organizer Application with the ABP Framework & Blazor UI](https://community.abp.io/articles/creating-an-event-organizer-application-with-the-blazor-ui-wbe0sf2z) by [@hikalkan](https://github.com/hikalkan) + +Thanks to all of the contributors. We are waiting for your contributions too. If you want to create content for the ABP Community, please visit [community.abp.io](https://community.abp.io/) website and submit your article. + +#### Be a Superhero on Day 1 with ABP.IO + +Thanks to [@lprichar](http://github.com/lprichar) prepared an awesome introduction video for the ABP.IO Platform: "[Be a Superhero on Day 1 with ABP.IO](https://www.youtube.com/watch?v=ea0Zx9DLcGA)". + +#### New Sample Application: Event Organizer + +This is a new example application developed using the ABP Framework and the Blazor UI. See [this article](https://community.abp.io/articles/creating-an-event-organizer-application-with-the-blazor-ui-wbe0sf2z) for a step by step implementation guide. + +![event-list-ui.png](3ae582c6154776fbb71039f99633f611.png) + +### Github Discussions + +We enabled the [GitHub Discussions for the abp repository](https://github.com/abpframework/abp/discussions) as another place to discuss ideas or get help for the ABP Framework. The ABP core team is spending time participating in discussions and answering to questions as much as possible. + +## About the Next Release(s) + +Beginning from the next version (4.2.0), we are starting to spend more effort on the **CMS Kit module**. The purpose of this module is to provide CMS primitives (e.g. **comments, tags, reactions, contents**...) and features (e.g. **blog, pages, surveys**) as pre-built and reusable components. Current blog module will be a part of the CMS Kit module. + +We will continue to prepare documents, guides, tutorials and examples. And surely, we will continue to make enhancements and optimizations on the current features. + +> The planned preview release date for the version 4.2.0 is January 14, 2021 and the final (stable) version release date is January 28, 2021. + +Follow the [GitHub milestones](https://github.com/abpframework/abp/milestones) for all the planned ABP Framework version release dates. + +## Feedback + +Please check out the ABP Framework 4.1.0 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us to release a more stable version. **The planned release date for the [4.1.0 final](https://github.com/abpframework/abp/milestone/45) version is January 4, 2021**. \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-01-06-abpio-platform-v41-final-has-been-released/post.md b/docs/en/Community-Articles/2021-01-06-abpio-platform-v41-final-has-been-released/post.md new file mode 100644 index 0000000000..68f9c66ff2 --- /dev/null +++ b/docs/en/Community-Articles/2021-01-06-abpio-platform-v41-final-has-been-released/post.md @@ -0,0 +1,49 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 4.1 versions have been released today. + +## What's New With 4.1? + +Since all the new features are already explained in details with the [4.1 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-v4.1-RC-Has-Been-Released), I will not repeat all the details again. See the [RC Blog Post](https://blog.abp.io/abp/ABP.IO-Platform-v4.1-RC-Has-Been-Released) for all the features and enhancements. + +## Creating New Solutions + +You can create a new solution with the ABP Framework version 4.1 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details. + +## How to Upgrade an Existing Solution + +### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +### ABP UPDATE Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## ABP Community + +We started to get more contributions by the community for the [ABP Community](https://community.abp.io/) contents. Thank you all! + +We will be adding **Video Content** sharing system in a short time. We are planning to create short video contents, especially to explore the new features in every release. Again, we will be waiting video contributions by the community :) + +## About the Next Versions + +Planned preview date for the version **4.2 is January 14, 2021**. See the [Road Map](https://docs.abp.io/en/abp/latest/Road-Map) document and [GitHub Milestones](https://github.com/abpframework/abp/milestones) to learn what's planned for the next versions. We are trying to be clear about the coming features and the next release dates. \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/3de6a4bbfd8d8536775339fa29015efd.png b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/3de6a4bbfd8d8536775339fa29015efd.png new file mode 100644 index 0000000000..72413c382c Binary files /dev/null and b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/3de6a4bbfd8d8536775339fa29015efd.png differ diff --git a/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/54bb24af515fbdc810b439fa290916ff.png b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/54bb24af515fbdc810b439fa290916ff.png new file mode 100644 index 0000000000..dae1b2e31a Binary files /dev/null and b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/54bb24af515fbdc810b439fa290916ff.png differ diff --git a/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/56d7c496adc0c24c33b139fa29085a20.png b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/56d7c496adc0c24c33b139fa29085a20.png new file mode 100644 index 0000000000..3a9694b809 Binary files /dev/null and b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/56d7c496adc0c24c33b139fa29085a20.png differ diff --git a/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/7269e47595a878d6cea339fa2900c1a0.png b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/7269e47595a878d6cea339fa2900c1a0.png new file mode 100644 index 0000000000..20d5065b20 Binary files /dev/null and b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/7269e47595a878d6cea339fa2900c1a0.png differ diff --git a/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/8b2ab5592ffa4477392339fa29011429.png b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/8b2ab5592ffa4477392339fa29011429.png new file mode 100644 index 0000000000..f9e3a4f861 Binary files /dev/null and b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/8b2ab5592ffa4477392339fa29011429.png differ diff --git a/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/acbeb3307fc192f57ad839fa29013656.jpg b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/acbeb3307fc192f57ad839fa29013656.jpg new file mode 100644 index 0000000000..b5784519bd Binary files /dev/null and b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/acbeb3307fc192f57ad839fa29013656.jpg differ diff --git a/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/cebf90df69ed4e35791f39fa2900e3fe.png b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/cebf90df69ed4e35791f39fa2900e3fe.png new file mode 100644 index 0000000000..583bebb4d1 Binary files /dev/null and b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/cebf90df69ed4e35791f39fa2900e3fe.png differ diff --git a/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/post.md b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/post.md new file mode 100644 index 0000000000..0f961483aa --- /dev/null +++ b/docs/en/Community-Articles/2021-01-18-abpio-platform-v42-rc-has-been-released/post.md @@ -0,0 +1,249 @@ +Today, we have released the [ABP Framework](https://abp.io/) and the [ABP Commercial](https://commercial.abp.io/) 4.2.0 RC (Release Candidate). This blog post introduces the new features and important changes in this new version. + +> **The planned release date for the [4.2.0 final](https://github.com/abpframework/abp/milestone/48) version is January 28, 2021**. + +## Get Started with the 4.2 RC + +If you want to try the version `4.2.0` today, follow the steps below; + +1) **Upgrade** the ABP CLI to the version `4.2.0-rc.2` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 4.2.0-rc.2 +```` + +**or install** if you haven't installed before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 4.2.0-rc.2 +```` + +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 *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. + +## Migration Guide + +Check [the migration guide](https://docs.abp.io/en/abp/4.2/Migration-Guides/Abp-4_2) for the applications with the version 4.x upgrading to the version 4.2. + +## What's new with the ABP Framework 4.2 + +![104887532-78a79f00-597c-11eb-956a-2e9b77851f23.png](56d7c496adc0c24c33b139fa29085a20.png) + +## IRepository.GetQueryableAsync() + +> **This version comes with an important change about using `IQueryable` features over the [repositories](https://docs.abp.io/en/abp/4.2/Repositories). It is suggested to read this section carefully and apply in your applications.** + +`IRepository` interface inherits `IQueryable`, so you can directly use the standard LINQ extension methods, like `Where`, `OrderBy`, `First`, `Sum`... etc. + +**Example: Using LINQ directly over the repository object** + +````csharp +public class BookAppService : ApplicationService, IBookAppService +{ + private readonly IRepository _bookRepository; + + public BookAppService(IRepository bookRepository) + { + _bookRepository = bookRepository; + } + + public async Task DoItInOldWayAsync() + { + //Apply any standard LINQ extension method + var query = _bookRepository + .Where(x => x.Price > 10) + .OrderBy(x => x.Name); + + //Execute the query asynchronously + var books = await AsyncExecuter.ToListAsync(query); + } +} +```` + +*See [the documentation](https://docs.abp.io/en/abp/4.2/Repositories#iqueryable-async-operations) if you wonder what is the `AsyncExecuter`.* + +Beginning from the version 4.2, the recommended way is using `IRepository.GetQueryableAsync()` to obtain an `IQueryable`, then use the LINQ extension methods over it. + +**Example: Using the new GetQueryableAsync method** + +````csharp +public async Task DoItInNewWayAsync() +{ + //Use GetQueryableAsync to obtain the IQueryable first + var queryable = await _bookRepository.GetQueryableAsync(); + + //Then apply any standard LINQ extension method + var query = queryable + .Where(x => x.Price > 10) + .OrderBy(x => x.Name); + + //Finally, execute the query asynchronously + var books = await AsyncExecuter.ToListAsync(query); +} +```` + +ABP may start a database transaction when you get an `IQueryable` (If current [Unit Of Work](https://docs.abp.io/en/abp/latest/Unit-Of-Work) is transactional). In this new way, it is possible to **start the database transaction in an asynchronous way**. Previously, we could not get the advantage of asynchronous while starting the transactions. + +> **The new way has a significant performance and scalability gain. The old usage (directly using LINQ over the repositories) will be removed in the next major version.** You have a lot of time for the change, but we recommend to immediately take the action since the old usage has a big scalability problem. + +See [the migration guide](https://docs.abp.io/en/abp/4.2/Migration-Guides/Abp-4_2) for the actions you may need to take while upgrading your applications. + +#### About IRepository Async Extension Methods + +Using IRepository Async Extension Methods has no such a problem. The examples below are pretty fine: + +````csharp +var countAll = await _personRepository + .CountAsync(); + +var count = await _personRepository + .CountAsync(x => x.Name.StartsWith("A")); + +var book1984 = await _bookRepository + .FirstOrDefaultAsync(x => x.Name == "John"); +```` + +See the [repository documentation](https://docs.abp.io/en/abp/4.2/Repositories#iqueryable-async-operations) to understand the relation between `IQueryable` and asynchronous operations. + +### Repository Bulk Operations + +This version adds the following methods to the repositories: + +* `InsertManyAsync` +* `UpdateManyAsync` +* `DeleteManyAsync` + +The purpose of these methods to insert, update or delete many entities in one call with a better performance. + +Currently, **MongoDB** provider implements these methods as a single bulk operation since MongoDB API natively supports. But current **Entity Framework Core** implementation is not a real bulk operation. Instead, it does its best with the native API of the EF Core. If you want to implement in a more performant way, you can [customize the bulk operations](https://docs.abp.io/en/abp/4.2/Entity-Framework-Core#customize-bulk-operations) with your own implementation or by using a library. We could find a good open source library for EF Core 5.0 to implement it. + +### Selecting DBMS on Template Creation + +[ABP CLI](https://docs.abp.io/en/abp/4.2/CLI#new) now has an option to specify the DBMS when you use EF Core as the database provider. + +**Example: Select MySQL as the DBMS** + +````bash +abp new BookStore -dbms mysql --preview +```` + +Available options: `SqlServer` (default), `MySQL`, `SQLite`, `Oracle-Devart`, `PostgreSQL`. See the [documentation](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Other-DBMS) to use any other DBMS or switch the DBMS later. + +One change related to this feature is that: Now, the startup template doesn't come with an **initial migration** file. This is because the database migrations are different based on your DBMS preference and should be re-created. However, when you first run the `.DbMigrator` application, it will create the initial migration and create the database just like before. + +> See The Initial Migration section in the [Getting Started](https://docs.abp.io/en/abp/4.2/Getting-Started-Running-Solution?DB=EF#database-migrations) document if you have problems on running the `.DbMigrator` application first time. + +### Swagger UI Login / Authorization + +Testing the swagger UI was requiring some additional work, especially your authentication server is separated from the application that hosts the Swagger UI. + +With the version 4.2, the startup templates come with the authorization pre-configured for you. An Authorize button is available when you open the Swagger UI: + +![swagger-authorize.png](7269e47595a878d6cea339fa2900c1a0.png) + +When you click, it opens a modal to authorize: + +![swagger-authorize-modal.png](cebf90df69ed4e35791f39fa2900e3fe.png) + +When you click to the Authorize button here, you are redirected to the login page to login with your username and password (default username is `admin` and password is `1q2w3E*`). + +> Remember to select the Scopes (typically **select all**) you want to use before clicking to the Authorize button. + +### Angular Unit Testing + +We've improved the modules and the startup template to setup and write unit tests easier with the Angular UI. See the [Angular Unit Testing document](https://docs.abp.io/en/abp/4.2/UI/Angular/Testing) for details. + +### Other News + +* Improved HTTP **request-response performance** by resolving dependencies in a deferred way in the action/page filters, interceptors and some other services. +* Removed `MultipleActiveResultSets` from connection strings for new templates for SQL Server, since the new EF Core gives a warning when using it. If you want to use it, you need to change the connection string yourself. +* Added `HardDeleteAsync` extension method that takes a predicate to delete multiple entities. This extension method is available if the entity [Soft Delete](https://docs.abp.io/en/abp/latest/Data-Filtering). +* Implemented the [Page Alerts](https://docs.abp.io/en/abp/4.2/UI/Angular/Page-Alerts) for the **Angular UI**. +* Implemented [Page Progress](https://docs.abp.io/en/abp/4.2/UI/Blazor/Page-Progress) for the **Blazor UI**. It automatically shows an undetermined progress bar on top of the page while performing an AJAX request. It also proves an API to you if you need to show/hide the progress bar in your code. + +## What's new with the ABP Commercial 4.2 + +![104887528-780f0880-597c-11eb-8da4-cf008bd37c66.png](54bb24af515fbdc810b439fa290916ff.png) + +### Microservice Startup Template + +The new [Microservice Startup Template](https://docs.abp.io/en/commercial/4.2/startup-templates/microservice/index) is a generic solution to start a new microservice solution. + +While we accept that every microservice solution will be different and every system has its own design requirements and trade-offs, we believe such a startup solution is a very useful starting point for most of the solutions, and a useful example for others. + +![microservice-template-diagram.png](8b2ab5592ffa4477392339fa29011429.png) + +*Figure: A simplified overall diagram of the microservice solution.* + +You can [follow the documentation](https://docs.abp.io/en/commercial/4.2/startup-templates/microservice/index) to get started with this startup template. **This template should be considered as an early release**. We will improve it and write a lot of guides. + +If you want to use the ABP Suite to create your solution, then you need to first upgrade it: + +````bash +abp suite update --preview +```` + +If you want, you can directly create a new solution from the command line: + +````bash +abp new Volosoft.MyMicroserviceSystem -t microservice-pro --preview +```` + +Company Name is optional. Solution name could be *MyMicroserviceSystem* for this example. + +### Public Website in the Startup Templates + +As mentioned in the previous release post, we've added a *Public Website* application to the startup templates. It is configured to authenticate through the IdentityServer with a single sign-on system. + +You can use this application to create a landing page for your actual application or a corporate website for your business. An example screenshot: + +![public-website.jpg](acbeb3307fc192f57ad839fa29013656.jpg) + +It uses the same *Lepton Theme*, so you can apply [all the styles](https://commercial.abp.io/themes). The Public Website has a different layout and also has a different setting for the styling (that can be configured in the *Settings / Lepton Theme* page of the main web application). + +> *Public Website* is optional and you need to select the "Public Website" option while creating a new solution using the ABP Suite, or use the `--with-public-website` option while using the `abp new` CLI command. + +### Easy CRM Blazor UI + +[Easy CRM](https://docs.abp.io/en/commercial/latest/samples/easy-crm) is an example application built with the ABP Commercial. MVC (Razor Pages) and Angular UI implementations were already provided. With the version 4.2, we are providing the Blazor UI implementation for this application. + +![easy-crm.png](3de6a4bbfd8d8536775339fa29015efd.png) + +### Other News + +* Implemented Iyzico as a payment gateway provider for the [payment module](https://commercial.abp.io/modules/Volo.Payment) in addition to Paypal, Stripe, 2Checkout and Payu providers. +* ABP Suite supports the new microservice template creation, public website and DBMS selection options. +* Swagger authorization and other features mentioned in the ABP Framework section are already implemented for the ABP Commercial too. + +## ABP Community News + +### Sharing Video Contents + +[community.abp.io](https://community.abp.io/) is a place to share ABP related contents. It started with publishing articles. Now, it supports to publish video contents. [See this example](https://community.abp.io/articles/be-a-superhero-on-day-1-with-abp.io-wvifcy9s). All you need to do is to create a video and upload to YouTube. Then you can [submit](https://community.abp.io/articles/submit) the YouTube link to the ABP Community website. + +### Multi-language support + +We planned ABP Community to publish English-only contents. However, we see that people want to share contents in other languages too. Now, **it is possible to submit a content in any language**. Just select the Language option while submitting your content. + +**When you submit a non-English content, it is not visible to all the visitors by default**. Visitors can see a non-English content only if their browser language or the selected language matches to the content language (there is a language selection at the end of the website). + +### External Contents + +If you want to publish your content anywhere else, but want to post a link of your content, you can select *External Content* option while submitting the post. For example, [this article](https://community.abp.io/articles/aspnet-boilerplate-to-abp-framework-xml-to-json-localization-conversion-0mxyjrzj) is an external article and also written in Chinese language. + +## About the Next Release + +The next feature version will be 4.3.0. It is planned to release the 4.3 RC (Release Candidate) on March 11 and the final version on March 25, 2021. + +We decided to slow down the feature development for the [next milestone](https://github.com/abpframework/abp/milestone/49). We will continue to improve the existing features and introduce new ones, sure, but wanted to have more time for the planning, documentation, creating guides and improving the development experience. + +## Feedback + +Please check out the ABP Framework 4.2.0 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us to release a more stable version. **The planned release date for the [4.2.0 final](https://github.com/abpframework/abp/milestone/48) version is January 28, 2021**. \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-01-29-abpio-platform-42-final-has-been-released/post.md b/docs/en/Community-Articles/2021-01-29-abpio-platform-42-final-has-been-released/post.md new file mode 100644 index 0000000000..ce75c2b453 --- /dev/null +++ b/docs/en/Community-Articles/2021-01-29-abpio-platform-42-final-has-been-released/post.md @@ -0,0 +1,51 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 4.2 versions have been released today. + +## What's New With 4.2? + +Since all the new features are already explained in details with the [4.2 RC Announcement Post](https://blog.abp.io/abp/ABP-IO-Platform-v4-2-RC-Has-Been-Released), I will not repeat all the details again. See the [RC Blog Post](https://blog.abp.io/abp/ABP-IO-Platform-v4-2-RC-Has-Been-Released) for all the features and enhancements. + +## Creating New Solutions + +You can create a new solution with the ABP Framework version 4.2 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details. + +## How to Upgrade an Existing Solution + +### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +### ABP UPDATE Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guide + +Check [the migration guide](https://docs.abp.io/en/abp/latest/Migration-Guides/Abp-4_2) for the applications with the version 4.x upgrading to the version 4.2. + +> It is strongly recommended to check the migration guide for this version. Especially, the new `IRepository.GetQueryableAsync()` method is a core change should be considered after upgrading the solution. + +## About the Next Version + +The next feature version will be 4.3. It is planned to release the 4.3 RC (Release Candidate) on March 11 and the final version on March 25, 2021. + +We decided to slow down the feature development for the [next milestone](https://github.com/abpframework/abp/milestone/49). We will continue to improve the existing features and introduce new ones, sure, but wanted to have more time for the planning, documentation, creating guides and improving the development experience. \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/650b59e4f21de768c47039fb9f7b5658.png b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/650b59e4f21de768c47039fb9f7b5658.png new file mode 100644 index 0000000000..ab8a21eb34 Binary files /dev/null and b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/650b59e4f21de768c47039fb9f7b5658.png differ diff --git a/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/6e2a6211140d5e181b7839fb9f7af1f2.png b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/6e2a6211140d5e181b7839fb9f7af1f2.png new file mode 100644 index 0000000000..034782e3f9 Binary files /dev/null and b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/6e2a6211140d5e181b7839fb9f7af1f2.png differ diff --git a/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/704de57f75e01c54da7e39fb9f7a1a9d.png b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/704de57f75e01c54da7e39fb9f7a1a9d.png new file mode 100644 index 0000000000..96081e817d Binary files /dev/null and b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/704de57f75e01c54da7e39fb9f7a1a9d.png differ diff --git a/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/878e889ad7aaa6c6644939fb9f7aad50.png b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/878e889ad7aaa6c6644939fb9f7aad50.png new file mode 100644 index 0000000000..79d8e3d321 Binary files /dev/null and b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/878e889ad7aaa6c6644939fb9f7aad50.png differ diff --git a/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/8ebd9aac852b5784ac5a39fb9f7d8545.png b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/8ebd9aac852b5784ac5a39fb9f7d8545.png new file mode 100644 index 0000000000..4d5d22e1e9 Binary files /dev/null and b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/8ebd9aac852b5784ac5a39fb9f7d8545.png differ diff --git a/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/a40402b854fdd27d446539fb9f7bbc1d.png b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/a40402b854fdd27d446539fb9f7bbc1d.png new file mode 100644 index 0000000000..c6e1679151 Binary files /dev/null and b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/a40402b854fdd27d446539fb9f7bbc1d.png differ diff --git a/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/cab3b63d4fad58a3b8c039fb9f7c4961.png b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/cab3b63d4fad58a3b8c039fb9f7c4961.png new file mode 100644 index 0000000000..f6077bb4cc Binary files /dev/null and b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/cab3b63d4fad58a3b8c039fb9f7c4961.png differ diff --git a/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/e5d9e0f63668c8d8734e39fb9f7a5d44.png b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/e5d9e0f63668c8d8734e39fb9f7a5d44.png new file mode 100644 index 0000000000..a94cde1266 Binary files /dev/null and b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/e5d9e0f63668c8d8734e39fb9f7a5d44.png differ diff --git a/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/f4984a23c9f2a6f5919639fb9f7c06a1.png b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/f4984a23c9f2a6f5919639fb9f7c06a1.png new file mode 100644 index 0000000000..0547e418a9 Binary files /dev/null and b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/f4984a23c9f2a6f5919639fb9f7c06a1.png differ diff --git a/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/post.md b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/post.md new file mode 100644 index 0000000000..537f8c1f95 --- /dev/null +++ b/docs/en/Community-Articles/2021-04-01-abp-commercial-43-rc-has-been-published/post.md @@ -0,0 +1,137 @@ +ABP Commercial version 4.3 RC (Release Candidate) has been published alongside [ABP Framework 4.3. RC](https://blog.abp.io/abp/ABP-Framework-4.3-RC-Has-Been-Published). I will introduce the new features in this blog post. Here, a list of highlights for this release; + +* The **microservice starter template** is getting more mature. We've also added a **service template** to add new microservices to the solution. +* New option for the application starter template to have a **separate database schema for tenant databases**. +* New **Forms** module to create surveys +* **Enable/disable modules** per edition/tenant. +* **Lepton theme** and **Account module**'s source codes are available with the Team License. + +Here, some other features already covered in the ABP Framework announcement, but worth mentioning here since they are also implemented for the ABP Commercial; + +* **Blazor UI server-side** support +* **Email setting** management UI +* **Module extensibility** system is now available for the **Blazor UI** too. + +> This post doesn't cover the features and changes done on the ABP Framework side. Please also see the **[ABP Framework 4.3. RC blog post](https://blog.abp.io/abp/ABP-Framework-4.3-RC-Has-Been-Published)**. + +## The Migration Guide + +**This upgrade requires some manual work documented in [the migration guide](https://docs.abp.io/en/commercial/4.3/migration-guides/v4_3).** Please read the guide carefully. Even if your application doesn't break on upgrade, you should apply the changes to avoid future release problems. + +## Known Issues + +If you upgrade the ABP CLI to 4.3.0-rc.1 and try to create a new solution using the stable (4.2.x) version, it won't compile because of some missing packages. Use ABP CLI to create solutions with `--preview` option and downgrade to 4.2.2 to create 4.2.2 solutions. This will be fixed in 4.3.0-rc.2. + +## What's New With The ABP Commercial 4.3 + +### The Microservice Starter Template + +We'd introduced an initial version of the [microservice starter template](https://docs.abp.io/en/commercial/4.3/startup-templates/microservice/index) in the [previous version](https://blog.abp.io/abp/ABP-IO-Platform-v4-2-RC-Has-Been-Released). It is getting more mature with this release. We've made a lot of improvements and changes, including; + +* New **"service" template** to add new microservices for the solution. It still requires some manual work to integrate to other services and gateways; however, it makes progress very easy and straightforward. +* Added [Tye](https://github.com/dotnet/tye) configuration to develop and test the solution easier. +* Added [Prometheus](https://prometheus.io/), [Grafana](https://grafana.com/) integrations for monitoring the solution. +* **Automatic database migrations**. Every microservice automatically checks and migrates/seeds its database on startup (concurrency issues are resolved for multiple instances). For multi-tenant systems, tenant databases are also upgraded by the queue. +* For multi-tenant systems, **databases are being created on the fly** for new tenants with separate connection strings. +* Created **separate solution (`.sln`) file** for each microservice, gateway, and application. In this way, you can focus on what you are working on. The main (roof) solution file only includes the executable projects in these solutions. +* All microservices are converted to the standard **layered module structure**, making it easier to align with ABP application development practices. + +After this release, **we will be preparing microservice development guides** based on this startup solution. + +### Separate Tenant Schema + +ABP's multi-tenancy system allows to the creation of dedicated databases for tenants. However, the application startup solution comes with a single database migration path; hence it has a single database schema. As a result, tenant databases have some host-related tables. These tables are not used for tenants, and they are always empty. However, their existence may disturb us as a clean developer. + +With this release, the application startup template provides an option to address this problem. So, if you want, you can have a separate migration path for tenant databases. Of course, this has a cost; You will have two DbContexts for migration purposes, bringing additional complexity to your solution. We've done our best to reduce this complexity and added a README file into the migration assembly. If you prefer this approach, please check that README file. + +You can specify the new `--separate-tenant-schema` parameter while you are creating a new solution using the [ABP CLI](https://docs.abp.io/en/abp/4.3/CLI): + +````bash +abp new Acme.BookStore --separate-tenant-schema +```` + +If you prefer the [ABP Suite](https://docs.abp.io/en/commercial/latest/abp-suite/create-solution) to create solutions, you can check the *Separated tenant schema* option. + +![abp-suite-separate-tenant-schema.png](8ebd9aac852b5784ac5a39fb9f7d8545.png) + +### Creating Tenant Databases On The Fly + +With this release, the separate tenant database feature becomes more mature. When you create a new tenant with specifying a connection string, the **new database is automatically created** with all the tables and the initial seed data if available. So, tenants can immediately start to use the new database. With this change, tenant connection string textboxes come in the tenant creation modal: + +![new-tenant-modal.png](704de57f75e01c54da7e39fb9f7a1a9d.png) + +Besides, we've added an "**Apply database migrations**" action to the tenant management UI to manually trigger the database creation & migration in case you have a problem with automatic migration: + +![tenant-db-migrate.png](e5d9e0f63668c8d8734e39fb9f7a5d44.png) + +Automatic migration only tries one time. If it fails, it writes the exception log and discards this request. For example, this can happen if the connection string is wrong or the database server is not available. In this case, you can manually retry with this action. + +> Note that this feature requires to **make changes in your solution**, if you upgrade from an older version. Because the tenant database creation and migration code are located in the application startup template. See the [version 4.3 migration guide](https://docs.abp.io/en/commercial/4.3/migration-guides/v4_3) for details. + +### New Module: CMS Kit + +CMS Kit module initial version has been released with this version. As stated in the [ABP Framework 4.3 announcement post](https://blog.abp.io/abp/ABP-Framework-4.3-RC-Has-Been-Published), it should be considered premature for now. + +For ABP Commercial application startup template, we are providing an option to include the CMS Kit into the solution while creating new solutions: + +![cms-kit-selection.png](878e889ad7aaa6c6644939fb9f7aad50.png) + +It is available only if you select the *Public web site* option. Once you include CMS Kit, a *Cms* item is shown on the menu: + +![cms-kit-menu.png](6e2a6211140d5e181b7839fb9f7af1f2.png) + +Each CMS Kit feature can be individually enabled/disabled, using the global feature system. Once you disable a feature, it becomes completely invisible; even the related tables are not included in your database. + +CMS Kit features are separated into two categories: Open source (free) features and pro (commercial) features. For now, only newsletter and contact form features are commercial. By the time, we will add more free and commercial features. + +> We will create a separate blog post for the CMS Kit module, so I keep it short. + +### New Module: Forms + +*Forms* is a new module that is being introduced with this version. It looks like the Google Forms application; You dynamically create forms on the UI and send them to people to answer. Then you can get statistics/report and export answers to a CSV file. + +Forms module currently supports the following question types; + +* **Free text** +* Selecting a **single option** from a **dropdown** list or a **radio button** list +* **Multiple choice**: Selecting multiple options from a checkbox list + +**Screenshot: editing form and questions - view responses** + +![forms-edit-report.png](650b59e4f21de768c47039fb9f7b5658.png) + +**Screenshot: answering to the form** + +![forms-answer.png](a40402b854fdd27d446539fb9f7bbc1d.png) + +### Team License Source Code for Modules + +Team License users can't access the source code of modules and themes as a license restriction. You have to buy a Business or Enterprise license to download any module/theme's full source code. However, we got a lot of feedback from the Team License owners on the source code of the account module and the lepton theme. We see that customization of these two modules is highly necessary for most of our customers. + +With this version, we decided to allow Team License holders to download the source code of the **Account Module** and the **Lepton Theme** to freely customize them based on their requirements. + +You can **Replace these modules with their source code** using the ABP Suite: + +![account-lepton-source.png](f4984a23c9f2a6f5919639fb9f7c06a1.png) + +Remember that; when you include the source code in your solution, it is your responsibility to upgrade them when we release new versions (while you don't have to upgrade them). + +### Lepton Theme Public Website Layout + +We'd added a public website application in the application starter template in the previous versions. It was using the public website layout of the Lepton Theme. We realized that the layout of this application is customized or completely changed in most of the solutions. So, with this version, the layout is included inside the application in the downloaded solution. You can freely change it. Before, you had to download it separately and include it in your solution manually. + +### Enable/Disable Modules + +With this release, all modules can be enabled/disabled per edition/tenant. You can allow/disallow modules when you click *Features* action for an edition or tenant: + +![enable-disable-features.png](cab3b63d4fad58a3b8c039fb9f7c4961.png) + +### Other Features/Changes + +* ABP Suite now supports defining *required* navigation properties on code generation. +* **Blazor server-side** (with tiered option) is added for the application and microservice starter templates. +* An **"Email"** tab has been added to the Settings page to configure the email settings. + +## Feedback + +Please check out the ABP Commercial 4.3 RC to help us to release a more stable version. **The planned release date for the 4.3.0 final version is April 21, 2021**. \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-04-01-abp-framework-43-rc-has-been-published/2dbd008296ba5b04d66c39fb9f7330e2.png b/docs/en/Community-Articles/2021-04-01-abp-framework-43-rc-has-been-published/2dbd008296ba5b04d66c39fb9f7330e2.png new file mode 100644 index 0000000000..4e5d2677ca Binary files /dev/null and b/docs/en/Community-Articles/2021-04-01-abp-framework-43-rc-has-been-published/2dbd008296ba5b04d66c39fb9f7330e2.png differ diff --git a/docs/en/Community-Articles/2021-04-01-abp-framework-43-rc-has-been-published/post.md b/docs/en/Community-Articles/2021-04-01-abp-framework-43-rc-has-been-published/post.md new file mode 100644 index 0000000000..f5661e0549 --- /dev/null +++ b/docs/en/Community-Articles/2021-04-01-abp-framework-43-rc-has-been-published/post.md @@ -0,0 +1,193 @@ +> Notice that the **version 4.3.0 stable has already been released**. We've updated the version usages in this post. + +We are super excited to announce the ABP Framework 4.3 RC (Release Candidate). Here, a list of highlights of this release; + +* **CMS Kit** module initial release. +* **Blazor UI server-side** support. +* **Module extensibility** system for the Blazor UI. +* Angular UI **resource owner password** flow comes back. +* **Volo.Abp.EntityFrameworkCore.Oracle** package is now compatible with .NET 5. +* CLI support to easily add the **Basic Theme** into the solution. +* New **IInitLogger** service to write logs before dependency injection phase completed. + +Besides the new features above, we've done many performance improvements, enhancements and bug fixes on the current features. See the [4.3 milestone](https://github.com/abpframework/abp/milestone/49) on GitHub for all changes made on this version. + +This version was a big development journey for us; [~160 issues](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3A4.3-preview) resolved, [~300 PRs](https://github.com/abpframework/abp/pulls?q=is%3Aopen+is%3Apr+milestone%3A4.3-preview) merged and **~1,700 commits** done only in the [main framework repository](https://github.com/abpframework/abp). **Thanks to the ABP Framework team and all the contributors.** + +> ABP Commercial 4.3 RC has also been published. We will write a separate blog post for it. + +## The Migration Guide + +We normally don't make breaking changes in feature versions. However, this version has some small **breaking changes** mostly related to Blazor UI WebAssembly & Server separation. **Please check the [migration guide](https://docs.abp.io/en/abp/4.3/Migration-Guides/Abp-4_3) while upgrading to version 4.3**. + +## Known Issues + +Some minor issues will be fixed in the stable release. You can see the known issues [here](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3A4.3-final). + +## Get Started With The 4.3 + +If you want to try version 4.3 today, follow the steps below; + +1) **Upgrade** the ABP CLI to the version `4.3.0` using a command-line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 4.3.0 +```` + +**or install** if you haven't installed before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 4.3.0 +```` + +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/4.3/CLI) for all the available options. + +> You can also use the *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. + +### Quick Start Tutorial + +If you are new to ABP Framework, we've prepared a [new quick start tutorial](https://docs.abp.io/en/abp/4.3/Tutorials/Todo/Index) that can be pretty helpful to warm up to the ABP Framework. + +## What's New With The ABP Framework 4.3 + +### CMS Kit + +CMS (Content Management System) Kit was a module we worked on for the last couple of months. It is usable now, and we are releasing the initial version with this release. We are considering this module as pre-mature. It will be improved in the next versions. The goal to provide a flexible and extensible CMS infrastructure to .NET community. It currently has the following features; + +* **Pages**: Used to create UI pages with a Markdown + WYSIWYG editor. Once you create a page, it becomes available via URL like `/pages/my-page-url`. +* **Blog**: A built-in blog system that supports multiple blogs with blog posts. +* **Comments**: Allows users to write comments under contents. It is used for blog posts. +* **Tags**: To add tag feature to any content/entity. It is used for blog posts. +* **Reactions**: Allows users to react to content via emojis, like a smile, upvote, downvote, etc. +* **Rating**: This component is used to rate content by users. + +All features are separately usable. For example, you can create an image gallery and reuse the Comments and Tags features for the images. You can enable/disable features individually using the [Global Features System](https://docs.abp.io/en/abp/4.3/global-features). + +> We will create a separate blog post for the CMS Kit module, so I keep it short. + +### Blazor Server Side + +We'd implemented Blazor WebAssembly before. With version 4.3, we have the Blazor Server-Side option too. All the current functionalities are available to the Blazor Server. + +You can select Blazor Server as the UI type while creating a new solution. + +**Example:** + +````bash +abp new Acme.BookStore -u blazor-server +```` + +If you write `blazor` as the UI type, it will create Blazor WebAssembly just as before. + +> You can also select the Blazor Server on the [get started](https://abp.io/get-started) page. + +Blazor Server applications are mixed applications; You can mix the server-side MVC / Razor Pages with the Blazor SPA. This brings an interesting opportunity: MVC / Razor Pages modules can work seamlessly in the Blazor Server applications. For example, the CMS Kit module has no Blazor UI yet, but you can use its MVC UI inside your Blazor Server application. + +> Blazor Server UI has a `--tiered` option just [like](https://docs.abp.io/en/abp/latest/Startup-Templates/Application#tiered-structure) the MVC / Razor Pages UI. This can be used to separate the HTTP API server from the UI server (UI application doesn't directly connect to the database). + +### Blazor UI Module Extensibility + +Module Entity Extensions and some other extensibility features was not supported by the Blazor UI. With this version, we've implemented that system for Blazor UI. + +For anyone wondering what the module entity extensions is, please check [the document](https://docs.abp.io/en/abp/4.3/Module-Entity-Extensions) or [this community video](https://community.abp.io/articles/overview-of-abp-framework-4.1-module-extensions-part-1-n04f7bhf). + +### Email Setting Management UI + +With this release, a new item is added to the main menu to navigate to the setting management page. This page contains the email setting management UI, as shown below: + +![email-settings-page.png](2dbd008296ba5b04d66c39fb9f7330e2.png) + +The setting page is provided by the [setting management module](https://docs.abp.io/en/abp/4.3/Modules/Setting-Management), and it is extensible; You can add your tabs to this page for your application settings. + +### Angular UI Resource Owner Password Flow + +The login page was removed from the Angular UI in previous versions because Authorization Code flow is the recommended approach for SPAs. However, it requires redirecting the user to the authentication server, logging there, and returning to the application. We got a lot of feedback because this brings overhead for simple applications. + +With version 4.3, Angular UI can use its login page with resource owner password flow. Please refer to [the documentation](https://github.com/abpframework/abp/blob/dev/docs/en/UI/Angular/Account-Module.md) to learn how to make it work. + +### Volo.Abp.EntityFrameworkCore.Oracle Package + +We couldn't update the [Oracle.EntityFrameworkCore](https://www.nuget.org/packages/Oracle.EntityFrameworkCore/) package on .NET 5.0 upgrade since it was not supporting .NET 5.0 at that time. Now, it supports .NET 5.0 and we've upgraded the package. + +See [the documentation](https://docs.abp.io/en/abp/4.3/Entity-Framework-Core-Oracle-Official) to learn how to switch to this package for the Oracle database. + +### Add Basic Theme Into Your Solution + +ABP Framework provides a strong theming system. However, the default theme, named the Basic Theme, has a non-styled, base Bootstrap UI. It is expected that you override the styles and UI components of that theme in a serious application. + +There are some articles (see for [mvc](https://community.abp.io/articles/creating-a-new-ui-theme-by-copying-the-basic-theme-for-mvc-ui-yt9b18io) & [blazor](https://community.abp.io/articles/creating-a-new-ui-theme-by-copying-the-basic-theme-for-blazor-ui-qaf5ho1b)) to explain how to include the Basic Theme's source code into your solution to modify it fully. However, it still requires some manual work. + +With this version, ABP CLI providing a command to add the Basic Theme's source code into your solution. Run the following command in a command-line terminal inside the root directory of your solution: + +**MVC UI** + +````bash +abp add-package Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic --with-source-code --add-to-solution-file +```` + +**Blazor Web Assembly UI** + +````bash +abp add-package Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme --with-source-code --add-to-solution-file +abp add-package Volo.Abp.AspNetCore.Components.Web.BasicTheme --with-source-code --add-to-solution-file +```` + +**Blazor Server UI** + +````bash +abp add-package Volo.Abp.AspNetCore.Components.Server.BasicTheme --with-source-code --add-to-solution-file +abp add-package Volo.Abp.AspNetCore.Components.Web.BasicTheme --with-source-code --add-to-solution-file +```` + +As you see, Blazor UI developers should add two packages. The Basic Theme consists of two packages for the Blazor UI: one for wasm/server and one shared. + +**Angular UI** + +Execute the following command in a terminal inside the `angular` folder of your solution: + +````bash +abp add-package @abp/ng.theme.basic --with-source-code +```` + +### IInitLogger + +In ASP.NET Core, logging is not possible before the dependency injection phase is completed. For example, you can't write log in `ConfigureServices` method. However, we sometimes need to write logs in this stage. + +We are introducing the `IInitLogger` service, which allows writing logs inside the `ConfigureServices` method. + +**Example:** + +````csharp +public class MyModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var logger = context.Services.GetInitLogger(); + logger.LogInformation("Some log..."); + } +} +```` + +Logs are written once the service registration phase is completed. It stores the written logs in memory and then writes logs to the actual `ILogger` when ready. + +> Notice: Startup templates come with [Serilog](https://serilog.net/) pre-installed. So, you can write logs everywhere by directly using its static API (ex: `Log.Information("...");`). The `InitLogger` is a way to write pre-initialization logs without depending on a particular logging library. So, it makes it very handy to write logs inside reusable modules. + +### Other Features/Changes + +* [#7423](https://github.com/abpframework/abp/issues/7423) MongoDB repository base aggregation API. +* [#8163](https://github.com/abpframework/abp/issues/8163) Ignoring given files on minification for MVC UI. +* [#7799](https://github.com/abpframework/abp/pull/7799) Added `RequiredPermissionName` to `ApplicationMenuItem` for MVC & Blazor UI to easily show/hide menu items based on user permissions. Also added `RequiredPermissionName` to `ToolbarItem` for the MVC UI for the same purpose. +* [#7523](https://github.com/abpframework/abp/pull/7523) Add more bundle methods to the distributed cache. +* [#8013](https://github.com/abpframework/abp/pull/8013) Handle `JsonProperty` attribute on Angular proxy generation. + +See the [4.3 milestone](https://github.com/abpframework/abp/milestone/49) on GitHub for all changes made on this version. + +## Feedback + +Please check out the ABP Framework 4.3 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us release a more stable version. **The planned release date for the [4.3.0 final](https://github.com/abpframework/abp/milestone/50) version is April 21, 2021**. \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-04-24-abpio-platform-v43-has-been-released/post.md b/docs/en/Community-Articles/2021-04-24-abpio-platform-v43-has-been-released/post.md new file mode 100644 index 0000000000..b4026d1886 --- /dev/null +++ b/docs/en/Community-Articles/2021-04-24-abpio-platform-v43-has-been-released/post.md @@ -0,0 +1,51 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 4.3 versions have been released today. + +## What's New With 4.3? + +Since all the new features are already explained in details with the 4.3 RC announcement posts, I will not repeat all the details again. See the related blog posts for all the features and enhancements; + +* [What's New with the ABP Framework 4.3](https://blog.abp.io/abp/ABP-Framework-4.3-RC-Has-Been-Published) +* [What's new with the ABP Commercial 4.3](https://blog.abp.io/abp/ABP-Commercial-4.3-RC-Has-Been-Published) + +## The Quick Start Tutorial + +With this version, we've created a minimalist [quick start tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Todo/Index) for developers who are new to the ABP Framework. + +## How to Upgrade an Existing Solution + +### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +### ABP UPDATE Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guides + +**Check the migration guides ([for ABP Framework](https://docs.abp.io/en/abp/latest/Migration-Guides/Abp-4_3) & for [ABP Commercial](https://docs.abp.io/en/commercial/latest/migration-guides/v4_3)) for the applications with the version 4.2.x upgrading to the version 4.3.0.** + +## The Road Map + +The next feature version will be 4.4. It is planned to release the 4.4 RC (Release Candidate) at the end of Quarter 2, 2021. See the updated road maps; + +* [ABP Framework Road Map](https://docs.abp.io/en/abp/latest/Road-Map) +* [ABP Commercial Road Map](https://docs.abp.io/en/commercial/latest/road-map) \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-06-15-introducing-the-cms-kit-module/e6d2e4c928d8df2a122939fd21095dc7.png b/docs/en/Community-Articles/2021-06-15-introducing-the-cms-kit-module/e6d2e4c928d8df2a122939fd21095dc7.png new file mode 100644 index 0000000000..24b97e46c6 Binary files /dev/null and b/docs/en/Community-Articles/2021-06-15-introducing-the-cms-kit-module/e6d2e4c928d8df2a122939fd21095dc7.png differ diff --git a/docs/en/Community-Articles/2021-06-15-introducing-the-cms-kit-module/post.md b/docs/en/Community-Articles/2021-06-15-introducing-the-cms-kit-module/post.md new file mode 100644 index 0000000000..257aad056a --- /dev/null +++ b/docs/en/Community-Articles/2021-06-15-introducing-the-cms-kit-module/post.md @@ -0,0 +1,76 @@ +One of the most exciting announcements of the ABP Framework 4.3 release was the initial version of the CMS Kit module. The team had been working hard to release the initial version for months. + +For those who didn't read the [ABP Framework 4.3 release post](https://blog.abp.io/abp/ABP-Framework-4.3-RC-Has-Been-Published), the CMS Kit module adds CMS (Content Management System) capabilities to your application. Some of the CMS Kit features are [open source](https://github.com/abpframework/abp/tree/dev/modules/cms-kit) and free, while others are only available with the [ABP Commercial](https://commercial.abp.io/modules/Volo.CmsKit.Pro). Here, a list of CMS Kit features with the initial version: + +* [**Page**](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Pages) management system to manage dynamic pages with dynamic URLs. +* [**Blogging**](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Blogging) system to create publish blog posts with multiple blog support. +* [**Tagging**](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Tags) system to tag any kind of resource, like a blog post. +* [**Comment**](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Comments) system to add comments feature to any kind of resource, like blog post or a product review page. +* [**Reaction**](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Reactions) system to add reactions (smileys) feature to any kind of resource, like a blog post or a comment. +* [**Rating**](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Ratings) system to add rating feature to any kind of resource. +* [**Newsletter**](https://docs.abp.io/en/commercial/latest/modules/cms-kit/newsletter) system to allow users to subscribe to newsletters (ABP Commercial only). +* [**Contact form**](https://docs.abp.io/en/commercial/latest/modules/cms-kit/contact-form) system to allow users to write message to you (ABP Commercial only). + +## Installation + +CMS Kit module comes installed with [ABP Commercial](https://commercial.abp.io/) startup templates when you create the solution with the public website option. You can run the following command and create a solution with a public website. + +```bash +abp new MyProject --with-public-website +``` + +If you're not using the ABP Commercial or adding the module to an existing solution, [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) allows adding a module to a solution using `add-module` command. + +You can run the following command (in the root folder of the solution) to add the module to an existing solution: + +```bash +abp add-module Volo.CmsKit --skip-db-migrations true +``` + +If you're using the ABP Commercial, run the following command to install the pro version of the module: + +```bash +abp add-module Volo.CmsKit.Pro --skip-db-migrations true +``` + +After adding the module to the solution, you need to configure global features provided this module. The CMS Kit module uses the [global feature](https://docs.abp.io/en/abp/latest/Global-Features) system for all features, which means you can enable or disable features individually. To enable the features in the CMS Kit module, open the `GlobalFeatureConfigurator` class in the `Domain.Shared` project and add the following code to the `Configure` method to enable all features in the CMS kit module. + + ```csharp +GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit => +{ + cmsKit.EnableAll(); +}); + ``` + +If you want to enable specific features, you can change the configuration like: + +````csharp +GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit => +{ + cmsKit.Tags.Enable(); + cmsKit.Comments.Enable(); +}); +```` + +If you're using the ABP Commercial, you need to enable CMS Kit Pro features as well: + +```csharp +GlobalFeatureManager.Instance.Modules.CmsKitPro(cmsKitPro => +{ + cmsKitPro.EnableAll(); +}); +``` + +> If you are using Entity Framework Core, do not forget to add a new migration and update your database after configuring the features. + +We've completed the installation step. Run the project, and you will see the CMS menu item in the main menu: + +![cms-kit-menu.png](e6d2e4c928d8df2a122939fd21095dc7.png) + +> CMS Kit's initial release only supports the MVC UI. We're planning to add Angular and Blazor support in upcoming releases. + +## More + +We've covered the initial features, installation and configuration steps in this post. You can see the [open-source](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Index) and [commercial](https://docs.abp.io/en/commercial/latest/modules/cms-kit/index) documentation to get further information about features and the CMS Kit module. CMS Kit's initial version contains lots of features that you can easily integrate and use in your applications. We're planning to improve the existing features, fixing bugs and adding new features in upcoming releases. If you want to give some feedback or have a feature request, please reach out to us from [GitHub](https://github.com/abpframework/abp). We will be happy to plan the CMS Kit module's future together. + +Thank you! \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/78af8114d6a067fdad1739fd6de94488.gif b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/78af8114d6a067fdad1739fd6de94488.gif new file mode 100644 index 0000000000..ba589cabfc Binary files /dev/null and b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/78af8114d6a067fdad1739fd6de94488.gif differ diff --git a/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/7a3cf29d2aba7b2ba2da39fd6de861a4.png b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/7a3cf29d2aba7b2ba2da39fd6de861a4.png new file mode 100644 index 0000000000..f13fb6b12d Binary files /dev/null and b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/7a3cf29d2aba7b2ba2da39fd6de861a4.png differ diff --git a/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/9b4c6bd70a839fd0781839fd6de9b717.png b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/9b4c6bd70a839fd0781839fd6de9b717.png new file mode 100644 index 0000000000..a7649c1599 Binary files /dev/null and b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/9b4c6bd70a839fd0781839fd6de9b717.png differ diff --git a/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/a828f0a8f5283d73020039fd6de9db2d.png b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/a828f0a8f5283d73020039fd6de9db2d.png new file mode 100644 index 0000000000..87fd79109a Binary files /dev/null and b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/a828f0a8f5283d73020039fd6de9db2d.png differ diff --git a/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/efb3af37378b58e9960839fd6de992e2.png b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/efb3af37378b58e9960839fd6de992e2.png new file mode 100644 index 0000000000..747fcc1d13 Binary files /dev/null and b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/efb3af37378b58e9960839fd6de992e2.png differ diff --git a/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/ff130f8587690cfec96a39fd6de8a340.png b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/ff130f8587690cfec96a39fd6de8a340.png new file mode 100644 index 0000000000..f697b8ec60 Binary files /dev/null and b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/ff130f8587690cfec96a39fd6de8a340.png differ diff --git a/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/post.md b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/post.md new file mode 100644 index 0000000000..583eefab89 --- /dev/null +++ b/docs/en/Community-Articles/2021-06-30-abp-platform-44-rc-has-been-released/post.md @@ -0,0 +1,171 @@ +Today, we have released the [ABP Framework](https://abp.io/) and the [ABP Commercial](https://commercial.abp.io/) version 4.4 RC (Release Candidate). This blog post introduces the new features and important changes in this new version. + +> **The planned release date for the [4.4.0 final](https://github.com/abpframework/abp/milestone/53) version is July 27, 2021**. + +## Get Started with the 4.4 RC + +If you want to try the version 4.4.0 today, follow the steps below; + +1) **Upgrade** the ABP CLI to the version `4.4.0-rc.2` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 4.4.0-rc.2 +```` + +**or install** if you haven't installed before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 4.4.0-rc.2 +```` + +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 *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. + +### Migration Notes + +There is **no breaking change** with this version. However, if you are using Entity Framework Core, you will need to run the `Add-Migration` command to add a new **database migration** since some changes done in the module database mappings. + +## What's new with the ABP Framework 4.4 + +### Removed EntityFrameworkCore.DbMigrations Project + +With this version, we are doing an important change in the application startup solution template. The startup solution was containing an `EntityFrameworkCore.DbMigrations` project that contains a separate `DbContext` class which was responsible to unify the module database mappings and maintain the code-first database migrations. With the v4.4, we've removed that project from the solution. In the new structure, the `EntityFrameworkCore` integration project will be used for database migrations as well as on runtime. + +We'd published [a community article](https://community.abp.io/articles/unifying-dbcontexts-for-ef-core-removing-the-ef-core-migrations-project-nsyhrtna) about that change. Please see the article to understand the motivation behind the change. + +Beside the `DbContext` unification, we've also used the new `ReplaceDbContext` attribute and [replaced](https://github.com/abpframework/abp/blob/ea2205f0855f52015152ae066a5c239af4b8511f/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/MyProjectNameDbContext.cs#L18-L19) the `IIdentityDbContext` and `ITenantManagementDbContext` interfaces to make it possible to perform join queries over repositories for these modules easily. In the next days, we will publish another community article to explain the problem and the solution. However, most of times, you don't need to know these details. + +### Dynamic Menu Management for the CMS Kit Module + +CMS Kit is a set of reusable *Content Management System* features packaged as an ABP application module. We had published the first usable version with the previous release. With this release, we are adding another feature to the CMS Kit module: You can now dynamically arrange the main menu on the UI, which is an essential feature for any kind of content management system. In this way, you can add pages or any kind of arbitrary URLs to the main menu from the UI. + +A screenshot from the menu management page (from the CMS Kit admin side): + +![image.png](7a3cf29d2aba7b2ba2da39fd6de861a4.png) + +And the items rendered in a public website: + +![image.png](ff130f8587690cfec96a39fd6de8a340.png) + +Note that this feature is also available with the open source [CMS Kit module](https://docs.abp.io/en/abp/4.4/Modules/Cms-Kit/Index) (while the screenshots have been taken from the ABP Commercial). + +### Razor Engine Support for Text Templating + +[Text Templating](https://docs.abp.io/en/abp/4.4/Text-Templating) is a system to generate content on runtime by using a model (data) and a template. It was running on the [Scriban](https://github.com/scriban/scriban) templating engine. Beginning from this version, we have a second option: We can use the familiar **razor syntax** to build and render the templates. See the text templating [razor integration document](https://docs.abp.io/en/abp/4.4/Text-Templating-Razor) to get started with the new engine! + +### New Customization Points for DbContext/Entities + +Two new extension methods are added to `ObjectExtensionManager.Instance` to override EF Core mappings of [pre-built application modules](https://docs.abp.io/en/abp/latest/Modules/Index). + +**Example: Change mappings for the `IdentityDbContext` to override mappings for the `IdentityUser` entity** + +````csharp +ObjectExtensionManager.Instance.MapEfCoreDbContext(modelBuilder => +{ + modelBuilder.Entity(b => + { + b.ToTable("MyUsers"); + b.Property(x => x.Email).HasMaxLength(300); + }); +}); +```` + +The startup template contains a class, like `YourProjectNameEfCoreEntityExtensionMappings`, that can be used to place that code. + +### New ABP CLI Commands + +There are new [ABP CLI](https://docs.abp.io/en/abp/4.4/CLI) commands introduced with the v4.4: + +* `abp install-libs` command is used for MVC / Razor Pages and Blazor Server applications to restore the `wwwroot/libs` folder. Previously we were running the `yarn` and `gulp` commands to restore that folder. While the `install-libs` command still uses yarn (if available), it is no longer needed to use `gulp`. +* `abp prompt` command can be used to open a prompt for the ABP CLI and run multiple commands without needing to specify the `abp` command every time. For example, if you run `abp prompt`, then you can directly run `install-libs` instead of `abp install-libs`. Use `exit` to quit from the ABP prompt. +* `abp batch` command can be used to run multiple ABP commands with one command. Prepare a text file, write each command as a line (without the `abp` command prefix), then execute `abp batch ` (ex: `abp batch your_commands.txt`) command to execute all the commands in that file. + +### appsettings.secrets.json + +Added `appsettings.secrets.json` to the startup template that can be used to set your sensitive/secret configuration values. You can ignore this file from source control (by adding to `.gitignore` if you're using git) and keep it only in developer/production machines. + +### Other ABP Framework Improvements + +* [#9350](https://github.com/abpframework/abp/pull/9350) Extracted `IRemoteServiceConfigurationProvider` to get remote service configurations. You can replace this service to get the configuration from any source. +* [#8829](https://github.com/abpframework/abp/pull/8829) Implemented error handler and retry for distributed event bus. +* [#9288](https://github.com/abpframework/abp/issues/9288) Use default CORS policy instead of a named one in the startup template. It is suggested to update your own solutions to make it simpler. +* Translated the framework and module localization strings to Hindi, Italian (thanks to Emanuele Filardo), Finnish, French and Slovak (thanks to [Michal Čadecký](https://www.m2ms.sk/)) languages. + +Beside these, there are a lot of enhancements and bug fixes. See the [4.4-preview milestone](https://github.com/abpframework/abp/milestone/52?closed=1) for all issues and pull requests closed with this version. + +## What's new with the ABP Commercial 4.4 + +### New Features for the SaaS Module + +We've implemented some important features to the [SaaS module](https://commercial.abp.io/modules/Volo.Saas): + +* Integrated to the [Payment module](https://commercial.abp.io/modules/Volo.Payment) and implemented **subscription system** for the SaaS module. +* Allow to make a **tenant active/passive**. In this way, you can take a tenant to passive to prevent the users of that tenant from using the system. In addition, you can set a date to automatically make a tenant passive when the date comes. +* Allow to **limit user count** for a tenant. +* Allow to set **different connection strings** for a tenant for each database/module, which makes possible to create different databases for a tenant for each microservice in a microservice solution. + +### New ABP Suite Code Generation Features + +There are many improvements done for for [ABP Suite](https://commercial.abp.io/tools/suite), including CRUD page generation for the **[microservice solution](https://docs.abp.io/en/commercial/latest/startup-templates/microservice/index) template**. + +### Angular UI: Two Factor Authentication for the Resource Owner Password Flow + +In the previous version, we had implemented the resource owner password authentication flow for the Angular UI, which makes the login process easier for simpler applications. With this release, we've implemented two-factor authentication for that flow. Authorization code flow already supports 2FA. + +### Other ABP Commercial Improvements + +* Added web layers to microservices in the microservice solution. You can use them to create modular UI or override existing pages/components of pre-built modules (e.g. Identity and SaaS). +* ABP Commercial license code has been moved to `appsettings.secrets.json` in the new startup templates. + +Beside these, there are many minor improvements and fixes done in the modules and themes. + +## Other News + +In this section, I will share some news that you may be interested in. + +### New Article: Using Elsa Workflow with ABP Framework + +We have been frequently asked how to use [Elsa Workflows](https://elsa-workflows.github.io/elsa-core/) with the ABP Framework. Finally, we have [created an article](https://community.abp.io/articles/using-elsa-workflow-with-the-abp-framework-773siqi9) to demonstrate it. + +![elsa-overview.gif](78af8114d6a067fdad1739fd6de94488.gif) + +You can [check it](https://community.abp.io/articles/using-elsa-workflow-with-the-abp-framework-773siqi9) to see how to integrate Elsa into an ABP based solution easily. + +### Free E-Book: Implementing Domain Driven Design + +We've published a free e-book for the ABP Community in the beginning of June. This is a practical guide for implementing Domain Driven Design (DDD). While the implementation details are based on the ABP Framework infrastructure, the basic concepts, principles and models can be applied to any solution, even if it is not a .NET solution. + +![ddd-book.png](efb3af37378b58e9960839fd6de992e2.png) + +Thousands of copies are already downloaded. If you haven't seen it yet, [click here to get a free copy of that e-book](https://abp.io/books/implementing-domain-driven-design). + +### The LeptonX Theme + +We have been working on a new ABP theme, named the *LeptonX*, for a long time. The theme will be available for ABP Framework (free - lite version) and ABP Commercial (pro version). It is being finalized in the next weeks and we will release the first version in a short time. + +![leptonx.png](9b4c6bd70a839fd0781839fd6de9b717.png) + +See [this blog post](https://volosoft.com/blog/introducing-the-lepton-theme-next-generation) to learn more about that project. + +### Volosoft & .NET Foundation + +[Volosoft](https://volosoft.com/), the company leads the ABP Framework project, has been a corporate sponsor of the [.NET Foundation](https://dotnetfoundation.org/). We are happy by taking our place among other great sponsors! + +![dotnetfoundation-sponsor-volosoft.png](a828f0a8f5283d73020039fd6de9db2d.png) + +We will continue to contribute to and support open source! See this [blog post for the announcement](https://volosoft.com/blog/Volosoft-Announces-the-NET-Foundation-Sponsorship). + +### Looking for Developer Advocate(s) + +We are actively looking for professional developer advocates for the ABP.IO platform. If you want to create content and touch to the ABP community, please check our [job post](https://github.com/volosoft/vs-home/issues/13). + +## About the Next Version + +The next version will be a major version: 5.0, which will be based on .NET 6.0. We are planning to release it in the end of 2021, short time after the .NET 6.0 release. We will release multiple preview/beta versions before the RC version. See the [road map](https://docs.abp.io/en/abp/latest/Road-Map) for details of the planned works for the version 5.0. diff --git a/docs/en/Community-Articles/2021-07-08-introducing-the-eshoponabp-project/9eade951e022722ac39439fd971f14d1.png b/docs/en/Community-Articles/2021-07-08-introducing-the-eshoponabp-project/9eade951e022722ac39439fd971f14d1.png new file mode 100644 index 0000000000..738194b19c Binary files /dev/null and b/docs/en/Community-Articles/2021-07-08-introducing-the-eshoponabp-project/9eade951e022722ac39439fd971f14d1.png differ diff --git a/docs/en/Community-Articles/2021-07-08-introducing-the-eshoponabp-project/post.md b/docs/en/Community-Articles/2021-07-08-introducing-the-eshoponabp-project/post.md new file mode 100644 index 0000000000..5aa8e5a6ba --- /dev/null +++ b/docs/en/Community-Articles/2021-07-08-introducing-the-eshoponabp-project/post.md @@ -0,0 +1,50 @@ +We are happy to introduce the **eShopOnAbp** project as an example microservice solution built with the ABP Framework by the core ABP team. This solution demonstrates the strength of ABP Framework and using it in a real-life case. The goal of the project is to create a full-featured cloud-native microservices reference application. The project is inspired by the [eShopOnContainers](https://github.com/dotnet-architecture/eShopOnContainers) project and shows how it can be implemented with the ABP Framework. + +> **Project Status**: Currently, the project doesn't have any business logic. We've just brought ABP's pre-built modules (Identity, Tenant Management, IdentityServer, etc) together as a base solution. However, it is fully working and you can now take it as a base solution for your microservice project. From now on, we will build the example application functionalities / business logic on top of it. + +## Source Code + +The source code is available on [abpframework/eShopOnAbp](https://github.com/abpframework/eShopOnAbp) repository. + +## The Big Picture + +The project follows micro-service architecture and overall structure is presented below. + +![overall-solution.png](9eade951e022722ac39439fd971f14d1.png) + +## How to Run? + +You can either run in Visual Studio, or using [Microsoft Tye](https://github.com/dotnet/tye). Tye is a developer tool that makes developing, testing, and deploying micro-services and distributed applications easier. + + ### Requirements + +- .NET 5.0+ +- Docker +- Yarn + +### Instructions + +- Clone the repository ( [eShopOnAbp](https://github.com/abpframework/eShopOnAbp) ) + +- Install Tye (*follow [these steps](https://github.com/dotnet/tye/blob/main/docs/getting_started.md#installing-tye)*) + +- Execute `run-tye.ps1` + +- Wait until all applications are up! + + - You can check running application from tye dashboard ([localhost:8000](http://127.0.0.1:8000/)) + +- After all your backend services are up, start the angular application: + + ```bash + cd apps/angular + yarn start + ``` + +## What's Next? + +We'll work on deployment & CI-CD processes as a next step and build the business logic on. First goal is deploying the entire application on [Kubernetes](https://kubernetes.io/). + +## Feedback + +Your comments and suggestions is important for us. You can ask your questions or post your feedback under [this discussion entry](https://github.com/abpframework/abp/discussions/9536). diff --git a/docs/en/Community-Articles/2021-08-04-abpio-platform-44-final-has-been-released/post.md b/docs/en/Community-Articles/2021-08-04-abpio-platform-44-final-has-been-released/post.md new file mode 100644 index 0000000000..a0ecabbd8d --- /dev/null +++ b/docs/en/Community-Articles/2021-08-04-abpio-platform-44-final-has-been-released/post.md @@ -0,0 +1,40 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 4.4 versions have been released today. + +## What's New With 4.4? + +Since all the new features are already explained in details with the 4.4 RC announcement posts, I will not repeat all the details again. See [the related blog post](https://blog.abp.io/abp/ABP-Platform-4-4-RC-Has-Been-Released) for all the features and enhancements. + +## How to Upgrade an Existing Solution + +### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +### ABP UPDATE Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## The Road Map + +The next feature version will be 5.0. It is planned to release the 5.0 RC (Release Candidate) in November 2021. See the updated road maps; + +* [ABP Framework Road Map](https://docs.abp.io/en/abp/latest/Road-Map) +* [ABP Commercial Road Map](https://docs.abp.io/en/commercial/latest/road-map) \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-08-12-leptonx-theme-for-abp-framework-alpha-release/29aea0fc3b31bf55029e39fe4af7fa02.png b/docs/en/Community-Articles/2021-08-12-leptonx-theme-for-abp-framework-alpha-release/29aea0fc3b31bf55029e39fe4af7fa02.png new file mode 100644 index 0000000000..d45a41008e Binary files /dev/null and b/docs/en/Community-Articles/2021-08-12-leptonx-theme-for-abp-framework-alpha-release/29aea0fc3b31bf55029e39fe4af7fa02.png differ diff --git a/docs/en/Community-Articles/2021-08-12-leptonx-theme-for-abp-framework-alpha-release/b10bc0debf9e083a97c239fe4af7df86.png b/docs/en/Community-Articles/2021-08-12-leptonx-theme-for-abp-framework-alpha-release/b10bc0debf9e083a97c239fe4af7df86.png new file mode 100644 index 0000000000..03547aed6b Binary files /dev/null and b/docs/en/Community-Articles/2021-08-12-leptonx-theme-for-abp-framework-alpha-release/b10bc0debf9e083a97c239fe4af7df86.png differ diff --git a/docs/en/Community-Articles/2021-08-12-leptonx-theme-for-abp-framework-alpha-release/post.md b/docs/en/Community-Articles/2021-08-12-leptonx-theme-for-abp-framework-alpha-release/post.md new file mode 100644 index 0000000000..19cc718755 --- /dev/null +++ b/docs/en/Community-Articles/2021-08-12-leptonx-theme-for-abp-framework-alpha-release/post.md @@ -0,0 +1,214 @@ +We are excited to announce that the **alpha version** of the LeptonX theme has been released! As stated in [this blog post](https://volosoft.com/blog/introducing-the-lepton-theme-next-generation), LeptonX comes in different shapes. For this release, we introduce only ABP based projects with the Angular UI. So, if you are already using the ABP Framework and Angular as the frontend choice, you can integrate these packages into your project today. + +The theme has been deployed with two versions: LeptonX-lite (free) and LeptonX (commercial). + +> **Note that this theme currently only works for the *Angular UI*. Please keep waiting for other UI options.** + +## Open-Source + +This section shows how to replace the basic theme (that comes with open source ABP Framework startup template) with the new LeptonX-lite theme. + +To add `LeptonX-lite` into your project, + +* Install `@abp/ng.theme.lepton-x` NPM package + +`npm install @abp/ng.theme.lepton-x@preview` or + +`yarn add @abp/ng.theme.lepton-x@preview` + +* Then, we need to edit the styles array in `angular.json` to replace the existing style with the new one. + +Replace the following style + +```JSON +{ + "input": "node_modules/bootstrap/dist/css/bootstrap.min.css", + "inject": true, + "bundleName": "bootstrap-ltr.min" +}, +``` + +with + +```json +"node_modules/@volo/ngx-lepton-x.lite/styles/sidemenu-layout.min.css", +"node_modules/bootstrap-icons/font/bootstrap-icons.css", +``` + +* Finally, remove `ThemeBasicModule` from `app.module.ts` and `shared.module.ts`, and import the related modules in `app.module.ts` + +```js +import { ThemeLeptonXModule } from '@abp/ng.theme.lepton-x'; +import { SideMenuLayoutModule } from '@abp/ng.theme.lepton-x/layouts'; + +@NgModule({ + imports: [ + // ... + ThemeLeptonXModule.forRoot(), + SideMenuLayoutModule.forRoot(), + ], + // ... +}) +export class AppModule {} +``` + +Note: If you employ [Resource Owner Password Flow](https://docs.abp.io/en/abp/latest/UI/Angular/Authorization#resource-owner-password-flow) for authorization, you should import the following module as well: + +```js +import { AccountLayoutModule } from '@abp/ng.theme.lepton-x/account'; + +@NgModule({ + // ... + imports: [ + // ... + AccountLayoutModule.forRoot(), + // ... + ], + // ... +}) +export class AppModule {} +``` + +To change the logos and brand color of the `LeptonX`, simply add the following CSS to the `styles.scss` + +```css +:root { + --lpx-logo: url('/assets/images/logo.png'); + --lpx-logo-icon: url('/assets/images/logo-icon.png'); + --lpx-brand: #edae53; +} +``` + +- `--lpx-logo` is used to place the logo in the menu. +- `--lpx-logo-icon` is a square icon used when the menu is collapsed. +- `--lpx-brand` is a color used throughout the application, especially on active elements. + +![lepton-x-lite-dashboard.png](b10bc0debf9e083a97c239fe4af7df86.png) + +![lepton-x-lite-menu-collapsed.png](29aea0fc3b31bf55029e39fe4af7fa02.png) + +## ABP Commercial + +This section shows how to replace the lepton theme (that comes with the ABP Commercial startup template) with the new LeptonX theme. + +To add `LeptonX` into your existing projects, + +* Firstly, install `@volosoft/abp.ng.theme.lepton-x` NPM package + +`npm install @volosoft/abp.ng.theme.lepton-x@preview` or + +`yarn add @volosoft/abp.ng.theme.lepton-x@preview` + +* Then, edit `angular.json` as follows: + +Remove the following config from the `styles` array since LeptonX provides bootstrap as embedded in its CSS. + +```JSON +{ + "input": "node_modules/bootstrap/dist/css/bootstrap.min.css", + "inject": true, + "bundleName": "bootstrap-ltr.min" +}, +``` + +Add the following ones into the `styles` array + +```JSON +{ + "input": "node_modules/@volosoft/ngx-lepton-x/styles/themes/dark.css", + "inject": false, + "bundleName": "lepton-x.dark" +}, +{ + "input": "node_modules/@volosoft/ngx-lepton-x/styles/themes/dim.css", + "inject": false, + "bundleName": "lepton-x.dim" +}, +{ + "input": "node_modules/@volosoft/ngx-lepton-x/styles/themes/light.css", + "inject": false, + "bundleName": "lepton-x.light" +}, +"node_modules/@volosoft/ngx-lepton-x/styles/css/sidemenu-layout.min.css", +"node_modules/bootstrap-icons/font/bootstrap-icons.css", +``` + +Three of them are related to the theming and will be loaded during runtime. That's why they are not injected into the `head` as a style. Hence, the `"inject": false` + +The fourth one depends on which layout you want to use. For now, there is only `sidemenu-layout` available. In the future, there will be many layouts to choose from. + +The last one is `bootstrap-icons` which are being used throughout the components. + +* At last, remove `ThemeLeptonModule` from `app.module.ts` and `shared.module.ts`, and import the following modules in `app.module.ts` + +```js +import { ThemeLeptonXModule } from '@volosoft/abp.ng.theme.lepton-x'; +import { AbpSideMenuLayoutModule } from '@volosoft/abp.ng.theme.lepton-x/layouts'; + +@NgModule({ + // ... + imports: [ + // ... + ThemeLeptonXModule.forRoot(), + AbpSideMenuLayoutModule.forRoot(), // depends on which layout you choose + // ... + ], + // ... +}) +export class AppModule {} +``` + +Note: If you employ [Resource Owner Password Flow](https://docs.abp.io/en/abp/latest/UI/Angular/Authorization#resource-owner-password-flow) for authorization, you should import the following module as well: + +```js +import { AccountLayoutModule } from '@volosoft/abp.ng.theme.lepton-x/account'; + +@NgModule({ + // ... + imports: [ + // ... + AccountLayoutModule.forRoot({ + layout: { + authLayoutImg: '/assets/images/login-bg.jpg', + }, + }), + // ... + ], + // ... +}) +export class AppModule {} +``` + +`authLayoutImg`: (Optional) If not given, a default image will be placed on the authentication pages. + + +* At this point, `LeptonX` theme should be up and running within your application. However, you may need to overwrite some css variables based your needs for every theme available as follows: +```scss +:root { + .lpx-theme-dark { + --lpx-logo: url('/assets/images/logo/logo-light.svg'); + --lpx-logo-icon: url('/assets/images/logo/logo-light-icon.svg'); + --lpx-brand: #edae53; + } + + .lpx-theme-dim { + --lpx-logo: url('/assets/images/logo/logo-light.svg'); + --lpx-logo-icon: url('/assets/images/logo/logo-light-icon.svg'); + --lpx-brand: #f15835; + } + + .lpx-theme-light { + --lpx-logo: url('/assets/images/logo/logo-dark.svg'); + --lpx-logo-icon: url('/assets/images/logo/logo-dark-icon.svg'); + --lpx-brand: #69aada; + } +} +``` + +When the user selects a theme, the corresponding CSS class is added to the `body`, so you can write specific CSS rules to each theme. + +## Conclusion + +In this blog post, I've explained how to use the alpha version of the new LeptonX theme for ABP-based solutions. Please, keep in mind that this is an alpha version, and we will continue to work on the LeptonX theme. The APIs are bound to change and breaking changes may be introduced in future versions. + +We would like you to try it out with the latest version of the ABP Framework and give us feedback at lepton@volosoft.com or open an issue on this repository: https://github.com/volosoft/lepton-theme \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/1b985b5f5bed9358713a3a0043e61af2.png b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/1b985b5f5bed9358713a3a0043e61af2.png new file mode 100644 index 0000000000..5494ad125b Binary files /dev/null and b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/1b985b5f5bed9358713a3a0043e61af2.png differ diff --git a/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/44948ada62c17e46b2473a0043e6bf7b.png b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/44948ada62c17e46b2473a0043e6bf7b.png new file mode 100644 index 0000000000..d35cda4713 Binary files /dev/null and b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/44948ada62c17e46b2473a0043e6bf7b.png differ diff --git a/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/518c1127f772c4cc26e53a004436c1ba.png b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/518c1127f772c4cc26e53a004436c1ba.png new file mode 100644 index 0000000000..545cd61071 Binary files /dev/null and b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/518c1127f772c4cc26e53a004436c1ba.png differ diff --git a/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/97e5fd88057afaea6bbb3a0043e70c00.png b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/97e5fd88057afaea6bbb3a0043e70c00.png new file mode 100644 index 0000000000..671a018dda Binary files /dev/null and b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/97e5fd88057afaea6bbb3a0043e70c00.png differ diff --git a/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/a7dca2286734d7639df73a0043e69a5b.png b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/a7dca2286734d7639df73a0043e69a5b.png new file mode 100644 index 0000000000..b851173ab1 Binary files /dev/null and b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/a7dca2286734d7639df73a0043e69a5b.png differ diff --git a/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/bad6fa7e5605c270f0ca3a0043e7534a.png b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/bad6fa7e5605c270f0ca3a0043e7534a.png new file mode 100644 index 0000000000..bfd2c54599 Binary files /dev/null and b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/bad6fa7e5605c270f0ca3a0043e7534a.png differ diff --git a/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/d95519a64013bdf417ad3a0043e67091.png b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/d95519a64013bdf417ad3a0043e67091.png new file mode 100644 index 0000000000..9df561568c Binary files /dev/null and b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/d95519a64013bdf417ad3a0043e67091.png differ diff --git a/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/df5319bd5c6ea32035ce3a0043e5b8d8.png b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/df5319bd5c6ea32035ce3a0043e5b8d8.png new file mode 100644 index 0000000000..5bc167a388 Binary files /dev/null and b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/df5319bd5c6ea32035ce3a0043e5b8d8.png differ diff --git a/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/e34b85f434a8e361bce13a0043e6e920.png b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/e34b85f434a8e361bce13a0043e6e920.png new file mode 100644 index 0000000000..74574fbd2d Binary files /dev/null and b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/e34b85f434a8e361bce13a0043e6e920.png differ diff --git a/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/post.md b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/post.md new file mode 100644 index 0000000000..ad3e1aca26 --- /dev/null +++ b/docs/en/Community-Articles/2021-11-18-abpio-platform-50-rc1-has-been-released/post.md @@ -0,0 +1,313 @@ +Today, we are excited to release the [ABP Framework](https://abp.io/) and the [ABP Commercial](https://commercial.abp.io/) version **5.0 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version. + +> **The planned release date for the [5.0.0 Stable](https://github.com/abpframework/abp/milestone/57) version is December 14, 2021**. + +Please try this version and provide feedback for a more stable ABP version 5.0! Thank you all. + +## Get Started with the 5.0 RC + +follow the steps below to try the version 5.0.0 RC today; + +1) **Upgrade** the ABP CLI to the version `5.0.0-rc.1` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 5.0.0-rc.1 +```` + +**or install** if you haven't installed before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 5.0.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 *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. + +You can use any IDE that supports .NET 6.0, like **[Visual Studio 2022](https://visualstudio.microsoft.com/downloads/)**. + +### Migration Notes & Breaking Changes + +This is a major version and there are some breaking changes and upgrade steps. Here, a list of important breaking changes in this version: + +* Upgraded to .NET 6.0, so you need to move your solution to .NET 6.0 if you want to use the ABP 5.0. +* Upgraded to Bootstrap 5. This is the most important breaking change in ABP 5.0 and you should take care of it. +* `IRepository` doesn't inherit from `IQueryable` anymore. It was already made obsolete in 4.2. +* Removed NGXS and states from the Angular UI. +* Removed gulp dependency from the MVC / Razor Pages UI in favor of `abp install-libs` command of the ABP CLI. +* Deprecated `EntityCreatingEventData`, `EntityUpdatingEventData`, `EntityDeletingEventData` and `EntityChangingEventData` classes. See [#9897](https://github.com/abpframework/abp/issues/9897). + +Please see the [migration document](https://docs.abp.io/en/abp/5.0/Migration-Guides/Abp-5_0) for all the details. You can also see all [the closed issues and pull requests](https://github.com/abpframework/abp/milestone/51). + +## What's new with 5.0? + +In this section, I will introduce some major features released with this version. + +### Static (Generated) Client Proxies for C# and JavaScript + +Dynamic C# ([see](https://docs.abp.io/en/abp/latest/API/Dynamic-CSharp-API-Clients)) and JavaScript ([see](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Dynamic-JavaScript-Proxies)) client proxy system is one of the most loved features of the ABP Framework. It generates the proxy code on runtime and makes client-to-server calls a breeze. With ABP 5.0, we are providing an alternative approach: You can generate the client proxy code on development-time. + +Development-time client proxy generation has a performance advantage since it doesn't need to obtain the HTTP API definition on runtime. It also makes it easier to consume a (micro)service behind an API Gateway. With dynamic proxies, we should return a combined HTTP API definition from the API Gateway and need to add HTTP API layers of the microservices to the gateway. Static proxies removes this requirement. One disadvantage is that you should re-generate the client proxy code whenever you change your API endpoint definition. Yes, software development always has tradeoffs :) + +Working with static client proxy generation is simple with the ABP CLI. You first need to run the server application, open a command-line terminal, locate to the root folder of your client application, then run the `generate-proxy` command of the ABP CLI. + +#### Creating C# client proxies + +C# client proxies are useful to consume APIs from Blazor WebAssembly applications. It is also useful for microservice to microservice HTTP API calls. Notice that the client application need to have a reference to the application service contracts (typically, the `.Application.Contracts` project in your solution) in order to consume the services. + +**Example usage:** + +````bash +abp generate-proxy -t csharp -u https://localhost:44305 +```` + +`-t` indicates the client type, C# here. `-u` is the URL of the server application. It creates the proxies for the application (the app module) by default. You can specify the module name as `-m ` if you are building a modular system. The following figure shows the generated files: + +![csharp-proxies.png](df5319bd5c6ea32035ce3a0043e5b8d8.png) + +The next step is to enable the static proxy system for your application (or module) using the `AddStaticHttpClientProxies` extension method: + +````csharp +context.Services.AddStaticHttpClientProxies( + typeof(MyApplicationContractsModule).Assembly +); +```` + +You can then inject and use the application service interfaces of these proxies. The usage is same of the [dynamic C# client proxies](https://docs.abp.io/en/abp/latest/API/Dynamic-CSharp-API-Clients). + +When you use static proxies for a module / application, you don't need to dynamic proxies. Find and remove the `context.Services.AddHttpClientProxies(...)` in your solution (typically in the `*.HttpApi.Client` project). + +#### Creating JavaScript client proxies + +JavaScript proxies are useful to consume APIs from MVC / Razor Pages UI. It works on JQuery AJAX API, just like the [dynamic JavaScript proxies](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Dynamic-JavaScript-Proxies). + +**Example usage:** + +````bash +abp generate-proxy -t js -u https://localhost:44305 +```` + +The following figure shows the generated file: + +![js-proxies.png](1b985b5f5bed9358713a3a0043e61af2.png) + +Then you can consume the server-side APIs from your JavaScript code just like the [dynamic JavaScript proxies](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Dynamic-JavaScript-Proxies). + +#### Creating Angular client proxies + +Angular developers knows that the generate-proxy command was already available in ABP's previous versions to create client-side proxy services in the Angular UI. The same functionality continues to be available and already [documented here](https://docs.abp.io/en/abp/latest/UI/Angular/Service-Proxies). + +**Example usage:** + +````bash +abp generate-proxy -t ng -u https://localhost:44305 +```` + +### Transactional Outbox & Inbox for the Distributed Event Bus + +This was one of the most awaited features by distributed software developers. + +The [transactional outbox pattern](https://microservices.io/patterns/data/transactional-outbox.html) is used to publishing distributed events within the same transaction that manipulates the application database. Distributed events are saved into the database inside the same transaction with your data changes, then sent to the message broker (like RabbitMQ or Kafka) by a separate background worker with a re-try system. In this way, it ensures the consistency between your database state and the published events. + +The transactional inbox pattern, on the other hand, saves incoming events into database first, then executes the event handler in a transactional manner and removes the event from the inbox queue in the same transaction. It also ensures that the event is only executed one time by keeping the processed messages for a while and discarding the duplicate events received from the message broker. + +Enabling the inbox and outbox patterns requires a few manual steps for your application. We've created a simple [console application example](https://github.com/abpframework/abp/tree/dev/test/DistEvents), but I will also explain all the steps here. + +#### Pre-requirements + +First of all, you need to have EF Core or MongoDB installed into your solution. It should be already installed if you'd created a solution from the ABP startup template. + +#### Install the packages +For the outbox & inbox functionality, ABP depends on [DistributedLock.Core](https://www.nuget.org/packages/DistributedLock.Core) library which provides a distributed locking system for concurrency control in a distributed environment. There are [many distributed lock providers](https://github.com/madelson/DistributedLock#implementations), including Redis, SqlServer and ZooKeeper. You can use the one you like. Here, I will show the Redis provider. + +Add [DistributedLock.Redis](https://www.nuget.org/packages/DistributedLock.Redis) NuGet package to your project, then add the following code into the ConfigureService method of your ABP module class: + +````csharp +context.Services.AddSingleton(sp => +{ + var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); + return new RedisDistributedSynchronizationProvider(connection.GetDatabase()); +}); +```` + +We are getting the Redis configuration from the `appsettings.json` file, so add the following lines to your `appsettings.json` file: + +````json +"Redis": { + "Configuration": "127.0.0.1" +} +```` + +You can change the IP or customize the configuration based on your environment. + +#### Configure the DbContext + +Open your `DbContext` class, implement the `IHasEventInbox` and the `IHasEventOutbox` interfaces. You should end up by adding two `DbSet` properties into your `DbContext` class: + +````csharp +public DbSet IncomingEvents { get; set; } +public DbSet OutgoingEvents { get; set; } +```` + +Add the following lines inside the `OnModelCreating` method of your `DbContext` class: + +````csharp +builder.ConfigureEventInbox(); +builder.ConfigureEventOutbox(); +```` + +It is similar for MongoDB; implement the `IHasEventInbox` and the `IHasEventOutbox` interfaces. There is no `Configure...` method for MongoDB. + +Now, we've added inbox/outbox related tables to our database schema. Now, for EF Core, use the standard `Add-Migration` and `Update-Database` commands to apply changes into your database (you can skip this step for MongoDB). If you want to use the command-line terminal, run the following commands in the root directory of the database integration project: + +````bash +dotnet ef migrations add "Added_Event_Boxes" +dotnet ef database update +```` + +#### Configure the distributed event bus options + +As the last step, write the following configuration code inside the `ConfigureServices` method of your module class: + +````csharp +Configure(options => +{ + options.Outboxes.Configure(config => + { + config.UseDbContext(); + }); + + options.Inboxes.Configure(config => + { + config.UseDbContext(); + }); +}); +```` + +Replace `YourDbContext` with your `DbContext` class. + +That's all. You can continue to publishing and consuming events just as before. See the [distributed event bus documentation](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus) if you don't know how to use it. + +### Publishing events in transaction + +The previous feature (outbox & inbox) solves the transactional event publishing problem for distributed systems. This feature, publishing events in transaction, solves the problem of executing event handlers in the same transaction that the events are published in for non-distributed applications. With 5.0, all events (local or distributed) are handled in the same transaction. If any handler fails, the transaction is rolled back. If you don't want that, you should use try/catch and ignore the exception inside your event handler. + +Remember that if you don't install a real distributed event provider (like [RabbitMQ](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus-RabbitMQ-Integration) or [Kafka](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus-Kafka-Integration)), the [distributed events](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus) are actually executed in-process, just like the [local events](https://docs.abp.io/en/abp/latest/Local-Event-Bus). So, with this development, all the events become transactional, even if your system is distributed or not. + +No action needed to take. It will just work by default. There is a [deprecation note](https://github.com/abpframework/abp/issues/9897) related to this change (some pre-defined events [will be removed](https://github.com/abpframework/abp/issues/9908) in the next major version since they are not needed anymore) + +### Inactivating a user + +The [Identity module](https://docs.abp.io/en/abp/latest/Modules/Identity) has a new feature to make a user active or inactive. Inactive users can not login to the system. In this way, you can disable a user account without deleting it. An *Active* checkbox is added to the user create/edit dialog to control it on the UI: + +![user-active.png](d95519a64013bdf417ad3a0043e67091.png) + +EF Core developers should add a new database migration since this brings a new field to the `AbpUsers` table. + +### Overriding email settings per tenant + +If you're building a multi-tenant application, it is now possible to override email sending settings per tenant. To make this possible, you should first enable that [feature](https://docs.abp.io/en/abp/latest/Features) to the tenant you want, by clicking the *Actions -> Features* for the tenant. + +![tenant-features.png](a7dca2286734d7639df73a0043e69a5b.png) + +Enable the feature using the checkbox as shown in the following modal: + +![enable-email-tenant.png](44948ada62c17e46b2473a0043e6bf7b.png) + +Then the tenant admin can open the email settings page under the Administration -> Settings menu (on development environment, logout, switch to the tenant and re-login with the tenant admin): + +![email-settings.png](e34b85f434a8e361bce13a0043e6e920.png) + +### Hangfire dashboard permission + +ABP allows to use Hangfire as the background job manager when you install the integration package [as documented](https://docs.abp.io/en/abp/5.0/Background-Jobs-Hangfire). Hangfire's dashboard is used to monitor and control the background job queues. Here, a screenshot from the dashboard: + +![hangfire-dashboard.png](97e5fd88057afaea6bbb3a0043e70c00.png) + +Hangfire's dashboard is not authorized by default, so any user can navigate to the `/hangfire` URL and see/control the jobs. With the ABP version 5.0, we've added a built-in authorization implementation for the Hangfire dashboard. Instead of `app.UseHangfireDashboard();`, you can use the following middleware configuration: + +````csharp +app.UseHangfireDashboard("/hangfire", new DashboardOptions +{ + AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() } +}); +```` + +In this way, only the authenticated users can see the dashboard. However, we suggest to set a permission name, so only the users with that permission can see the dashboard: + +````csharp +app.UseHangfireDashboard("/hangfire", new DashboardOptions +{ + AsyncAuthorization = new[] { + new AbpHangfireAuthorizationFilter("MyPermissionName") + } +}); +```` + +You can define the permission (`MyPermissionName` in this example) using the standard [permission system](https://docs.abp.io/en/abp/5.0/Authorization#permission-system). + +### Introducing AbpControllerBase + +ABP provides an `AbpController` class that you can inherit your MVC controllers from. It provides some pre-injected services to simplify your controllers. With v5.0, we are adding a second base controller class, `AbpControllerBase`, which is more proper to create API controllers (without view features). It is suggested to inherit from the `AbpControllerBase` class to create API controllers, instead of the `AbpController` class. + +**Example:** + +````csharp +[Route("api/products")] +public class ProductController : AbpControllerBase +{ + // TODO: ... +} +```` + +### Automatically setting the TenantId for new entities + +Beginning from the version 5.0, ABP automatically sets the `TenantId` for you when you create a new entity object (that implements the `IMultiTenant` interface). It is done in the constructor of the base `Entity` class (all other base entity and aggregate root classes are derived from the `Entity` class). The `TenantId` is set from the current value of the `ICurrentTenant.Id` property. + +Previously, it was a responsibility of the developer to set `TenantId` for new entities. Now, ABP takes care of it. You only may need to set it if you want to set id of a tenant other than the current tenant. + +This can be a breaking change in rare cases (for example, if you create host side entities from a tenant context and do not explicitly set host entity's `TenantId` to `null`). + +## Community News +### ABP Community Talks 2021.12 + +![community-talks.png](518c1127f772c4cc26e53a004436c1ba.png) + +As the core ABP development team, we've decided to organize monthly live meetings with the ABP community. The first live meeting will be at **December 16, 2021, 17:00 (UTC)** on YouTube. ABP core team members will present some of the new features coming with ABP 5.0. + +**Join this event on the Kommunity platform: https://kommunity.com/volosoft/events/abp-community-talks-4afca9c9** + +You can also [subscribe to the Volosoft channel](https://www.youtube.com/channel/UCO3XKlpvq8CA5MQNVS6b3dQ) for reminders for further ABP events and videos. +### ASP.NET Community Startup! +It was great for us to be invited to Microsoft's [ASP.NET Community Weekly Standup](https://dotnet.microsoft.com/live/community-standup) show, at September 28. There was a very high attention and that made us very happy. Thanks to the ABP Community and all the watchers :) If you've missed the talk, [you can watch it here](https://www.youtube.com/watch?v=vMWM-_ihjwM). + +### Upcoming ABP Book! + +I am currently authoring the first official book for the ABP Framework and it is on [pre-sale on Amazon](https://www.amazon.com/Mastering-ABP-Framework-maintainable-implementing-dp-1801079242/dp/1801079242) now. + +![abp-book-cover.png](bad6fa7e5605c270f0ca3a0043e7534a.png) + +This books is a complete guide to start working with the ABP Framework, explore the ABP features and concepts. It also contains chapters for DDD, modular application development and multi-tenancy to learn and practically work with the ABP architecture to build maintainable software solutions and create SaaS applications. The book will be based on ABP 5.0 and published in the beginning of 2022. You can [pre-order now](https://www.amazon.com/Mastering-ABP-Framework-maintainable-implementing-dp-1801079242/dp/1801079242)! + +### New ABP Community posts + +Here, some of the latest posts added to the [ABP community](https://community.abp.io/): + +* [Many to many relationship with ABP and EF Core](https://community.abp.io/articles/many-to-many-relationship-with-abp-and-ef-core-g7rm2qut) +* [Add a new module to your ABP application](https://community.abp.io/articles/abp-framework-add-a-new-module-to-your-abp-application-eogrfm88) +* [Changing UI Theme for ABP MVC / Razor Pages UI](https://community.abp.io/articles/changing-ui-theme-for-abp-mvc-razor-pages-ui-ravx6a0o) +* [Create a Windows Service with the ABP Framework](https://community.abp.io/articles/create-a-windows-service-with-abp-framework-hop4dtra) +* [Deploy ABP Framework .NET Core tiered application to docker swarm](https://community.abp.io/articles/deploy-abp-framework-dotnet-core-tiered-app-to-docker-swarm-kcrjbjec) +* [Centralized logging for .NET Core ABP microservices application using Seq](https://community.abp.io/articles/centralized-logging-for-.net-core-abp-microservices-app-using-seq-g1xe7e7y) + +Thanks to the ABP Community for all the contents they have published. You can also post your ABP and .NET related (text or video) contents to the ABP Community. + +## Conclusion + +The ABP version 5.0 is coming with important changes (like .NET 6 and Bootstrap 5) and features. In this blog post, I summarized the news about that new version. Please try it and provide feedback by opening issues on [the GitHub repository](https://github.com/abpframework/abp). Thank you all! \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-12-15-abpio-platform-50-final-has-been-released/36c5e78b69024dd6792a3a00cff9e1ea.png b/docs/en/Community-Articles/2021-12-15-abpio-platform-50-final-has-been-released/36c5e78b69024dd6792a3a00cff9e1ea.png new file mode 100644 index 0000000000..545cd61071 Binary files /dev/null and b/docs/en/Community-Articles/2021-12-15-abpio-platform-50-final-has-been-released/36c5e78b69024dd6792a3a00cff9e1ea.png differ diff --git a/docs/en/Community-Articles/2021-12-15-abpio-platform-50-final-has-been-released/post.md b/docs/en/Community-Articles/2021-12-15-abpio-platform-50-final-has-been-released/post.md new file mode 100644 index 0000000000..5465ed1fe5 --- /dev/null +++ b/docs/en/Community-Articles/2021-12-15-abpio-platform-50-final-has-been-released/post.md @@ -0,0 +1,45 @@ +We are very excited to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 5.0 versions today. It was a big development cycle, and finally it is available! + +## What's new with 5.0? + +Since all the new features are already explained in details with the [5.0 RC.1 Announcement Post](https://blog.abp.io/abp/ABP-IO-Platform-5.0-RC-1-Has-Been-Released), I will not repeat all the details again. See the [RC Blog Post](https://blog.abp.io/abp/ABP-IO-Platform-5.0-RC-1-Has-Been-Released) for all the features and enhancements. + +## Getting started with 5.0 + +### Creating new solutions + +You can create a new solution with the ABP Framework version 5.0 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +Type the following command in a command-line terminal to install the ABP CLI version 5.0: + +````bash +dotnet tool install -g Volo.Abp.Cli --version 5.0.0 +```` + +To upgrade your existing ABP CLI installation: + +````bash +dotnet tool update -g Volo.Abp.Cli --version 5.0.0 +```` + +Then you can create a new solution using the `abp new` command: + +````bash +abp new Acme.BookStore +```` + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details. + +### Upgrading existing solutions + +Check [the migration guide](https://docs.abp.io/en/abp/latest/Migration-Guides/Abp-5_0) for the applications with the version 4.x upgrading to the version 5.0. Also see [the upgrading guide](https://docs.abp.io/en/abp/latest/Upgrading) to understand how to update existing solutions. + +## ABP Community Talks 2021.12 + +![community-talks.png](36c5e78b69024dd6792a3a00cff9e1ea.png) + +As the core ABP development team, we've decided to organize monthly live meetings with the ABP community. The first live meeting will be at **December 16, 2021, 17:00 (UTC)** on YouTube. ABP core team members will present some of the new features coming with ABP 5.0. + +**Join this event on the Kommunity platform: https://kommunity.com/volosoft/events/abp-community-talks-4afca9c9** + +See you in the event! \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/04c9be6a819f74d7d7003a0165ff0d88.png b/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/04c9be6a819f74d7d7003a0165ff0d88.png new file mode 100644 index 0000000000..98057eb97c Binary files /dev/null and b/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/04c9be6a819f74d7d7003a0165ff0d88.png differ diff --git a/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/1b50e6d6317b84f963ab3a016602cca7.png b/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/1b50e6d6317b84f963ab3a016602cca7.png new file mode 100644 index 0000000000..70bb96046f Binary files /dev/null and b/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/1b50e6d6317b84f963ab3a016602cca7.png differ diff --git a/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/3104802a0898db35a15c3a0166002a3f.png b/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/3104802a0898db35a15c3a0166002a3f.png new file mode 100644 index 0000000000..4c489854f0 Binary files /dev/null and b/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/3104802a0898db35a15c3a0166002a3f.png differ diff --git a/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/79374b567169e34b283f3a016603708f.png b/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/79374b567169e34b283f3a016603708f.png new file mode 100644 index 0000000000..75e93a6fdd Binary files /dev/null and b/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/79374b567169e34b283f3a016603708f.png differ diff --git a/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/post.md b/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/post.md new file mode 100644 index 0000000000..e1c319ea4e --- /dev/null +++ b/docs/en/Community-Articles/2022-01-13-abpio-platform-v51-has-been-released/post.md @@ -0,0 +1,143 @@ +Today, we are releasing the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version 5.1 (with a version number `5.1.1`). This blog post introduces the new features and important changes in this new version. + +## Get Started with 5.1 + +Follow the steps below to try the 5.1 version today: + +1) **Upgrade** the ABP CLI to the latest version using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g +```` + +**or install** if you haven't installed it before: + +````bash +dotnet tool install Volo.Abp.Cli -g +```` + +2) Create a **new application**: + +````bash +abp new BookStore +```` + +Check out the [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all the available options. + +> You can also use the *Direct Download* tab on the [Get Started](https://abp.io/get-started) page. + +You can use any IDE that supports .NET 6.x development (e.g. [Visual Studio 2022](https://visualstudio.microsoft.com/downloads/)). + +### Migration Notes & Breaking Changes + +This is a minor feature release, mostly with enhancements and improvements based on [version 5.0](https://blog.abp.io/abp/ABP-IO-Platform-5-0-Final-Has-Been-Released). There aren't any breaking changes except for the Angular UI upgrade. ABP 5.1 startup templates use **Angular 13**. + +### Angular UI + +**If you want to upgrade the ABP Framework but want to continue with Angular 12**, add the following section to the `package.json` file of the Angular project: + +````json +"resolutions": { + "ng-zorro-antd": "^12.1.1", + "@ng-bootstrap/ng-bootstrap": "11.0.0-beta.2" + } +```` + +## What's New with the ABP Framework 5.1? + +In this section, I will introduce some major features released with this version. + +### The New Hosting Model + +The ABP startup application template now uses the new ASP.NET Core hosting APIs ([check out the Microsoft's minimal APIs document](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0)) on application startup ([check out the exact place in the ABP startup template](https://github.com/abpframework/abp/blob/46cdfbe7b06c93690181633be4e96bf62e7f34e2/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/Program.cs#L33-L40)). So, the `Startup.cs` file has been removed. + +Old-style hosting logic will continue to work as long as ASP.NET Core supports it. It is recommended to switch to the new model if it's possible for your solution. Check out [this guide](https://docs.abp.io/en/abp/latest/Migration-Guides/Upgrading-Startup-Template) if you need to know how to do that. + +### Asynchronous Startup Lifecycle Methods + +The new hosting model allows us to execute asynchronous code on application initialization in the [ABP module](https://docs.abp.io/en/abp/latest/Module-Development-Basics) classes. If you are using the new hosting model (which is default with 5.1 startup templates), you can override the `Async` versions of the module lifecycle methods. + +For example, you can now override the `ConfigureServicesAsync` (instead of `ConfigureServices`) or `OnApplicationInitializationAsync` (instead of `OnApplicationInitialization`) as shown in the following code block: + +````csharp +public class MyModule : AbpModule +{ + public override async Task ConfigureServicesAsync(ServiceConfigurationContext context) + { + /* You can use await here and safely execute other async methods */ + } + + public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context) + { + /* You can use await here and safely execute other async methods */ + } +} +```` + +If you override both the asynchronous and synchronous versions of the same method, only the asynchronous one will be executed. So, override only one of them based on your needs. + +### eShopOnABP Is Getting More Stable + +Our team is working to finalize the [eShopOnAbp](https://github.com/abpframework/eShopOnAbp) example solution, which is a reference **microservice solution** built with the ABP Framework. They will explain the project status and show what's done in the next **ABP Community Talks** meeting (Check out the *ABP Community Talks 2021.1* section at the bottom of this post). + +### The New ABP.IO Design! + +We've been working on a new design for the [abp.io](https://abp.io/) websites for a while. We are adding the final touches; the new design will be live very soon. Here's a screenshot from the design work: + +![new-abp-io-design.png](04c9be6a819f74d7d7003a0165ff0d88.png) + +The [ABP Commercial](https://commercial.abp.io/) and [ABP Community](https://community.abp.io/) websites will also have new designs as part of this update. + +### Other Changes + +Here are some other notable changes that come with this release: + +* Support markdown in [CMS-Kit comments ](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Comments)feature ([#10792](https://github.com/abpframework/abp/pull/10792)) +* Used file scoped namespaces for all the ABP Framework source code :) ([#10552](https://github.com/abpframework/abp/pull/10696)) + +All issues & PRs in [5.1 milesone](https://github.com/abpframework/abp/milestone/60?closed=1). + +### About ABP Commercial + +The core team is also working on ABP Commercial (which provides pre-built modules, themes, tooling and support on top of the ABP Framework). We've done a lot of minor improvements and fixes to the modules and tooling. + +There's some exciting news about the **LeptonX theme**; We are working on making it available in the **MVC (Razor Pages)** and **Blazor** UI options too (in addition to Angular UI). We are also adding more components, layout options, demo pages, etc... We are planning to release a beta version in the next weeks. Here's an animated GIF from the dashboard we've prepared as a demonstration: + +![leptonx-dash-2.png](1b50e6d6317b84f963ab3a016602cca7.png) + +If you are wondering what is the LeptonX project, please check out this [blog post](https://blog.abp.io/abp/LeptonX-Theme-for-ABP-Framework-Alpha-Release). + +As another visible functionality, we've added a new feature to the [CMS Kit Pro](https://docs.abp.io/en/commercial/latest/modules/cms-kit/index) module that is used to forward a URL to another URL. This is a screenshot from the management UI: + +![url-forward.png](3104802a0898db35a15c3a0166002a3f.png) + +This feature can be used to create short URLs in your application (like URL shortening services providers) or forward old pages to their new URLs. + +In addition to the new features shipped in every minor version, we are working on long-term projects for ABP.IO Platform and ABP Commercial (a little secret for now :). We will have announcements once these projects get more stable. + +## Community News + +### ABP Community Talks 2021.1 + +![abp-community-talks-2022-1.png](79374b567169e34b283f3a016603708f.png) + +This is the second episode of the ABP Community Talks and we are talking about microservice development with the ABP Framework, based on the [eShopOnAbp](https://github.com/abpframework/eShopOnAbp) reference solution. We will also briefly talk about the changes that come with ABP version 5.1. This **live meeting** will be on **January 20, 2022, 17:00 (UTC)** on YouTube. + +**Join this event on the Kommunity platform: https://kommunity.com/volosoft/events/abp-community-talks-20221-microservice-development-acd0f44b** + +You can also [subscribe to Volosoft YouTube channel](https://www.youtube.com/channel/UCO3XKlpvq8CA5MQNVS6b3dQ) for reminders of further ABP events and videos. + +### New ABP Community Posts + +Here are some of the recent posts added to the [ABP community](https://community.abp.io/): + +* [Minimal API development with the ABP Framework](https://community.abp.io/articles/minimal-api-with-abp-hello-world-part-1-sg5i44p8) by [@antosubash](https://github.com/antosubash) (three parts, video tutorial). +* [Integrating the Syncfusion MVC Components to the ABP MVC UI](https://community.abp.io/articles/integrating-the-syncfusion-mvc-components-to-the-abp-mvc-ui-0gpkr1if) by [@EngincanV](https://github.com/EngincanV). +* [Add Tailwind CSS to your ABP Blazor UI](https://community.abp.io/articles/add-tailwindcss-to-your-abp-blazor-ui-vidiwzcy) by [@antosubash](https://github.com/antosubash) (video tutorial). +* [Import external users into the users Table from an ABP Framework application](https://community.abp.io/articles/import-external-users-into-the-users-table-from-an-abp-framework-application-7lnyw415) by [@bartvanhoey](https://github.com/bartvanhoey). + +Thanks to the ABP Community for all the contents they have published. You can also [post your ABP and .NET related (text or video) contents](https://community.abp.io/articles/submit) to the ABP Community. + +## Conclusion + +In this blog post, I summarized the news about the new version and the ABP Community. Please try it and provide feedback by opening issues on the [GitHub repository](https://github.com/abpframework/abp). Thank you all! \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/1c453b5c819a46c9e8583a028146680e.png b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/1c453b5c819a46c9e8583a028146680e.png new file mode 100644 index 0000000000..ffd64b4ec0 Binary files /dev/null and b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/1c453b5c819a46c9e8583a028146680e.png differ diff --git a/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/48b7bb8717413c1f78323a028146a77b.png b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/48b7bb8717413c1f78323a028146a77b.png new file mode 100644 index 0000000000..a0cf54ee9a Binary files /dev/null and b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/48b7bb8717413c1f78323a028146a77b.png differ diff --git a/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/59e40287b10caca3a7b33a0281462c37.png b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/59e40287b10caca3a7b33a0281462c37.png new file mode 100644 index 0000000000..61f3f3edf5 Binary files /dev/null and b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/59e40287b10caca3a7b33a0281462c37.png differ diff --git a/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/9168547a7e70ca84f1a53a028145fc71.png b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/9168547a7e70ca84f1a53a028145fc71.png new file mode 100644 index 0000000000..d2cd8b67bb Binary files /dev/null and b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/9168547a7e70ca84f1a53a028145fc71.png differ diff --git a/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/a4df6d07407c698f36a53a02814594e7.png b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/a4df6d07407c698f36a53a02814594e7.png new file mode 100644 index 0000000000..6005edde7f Binary files /dev/null and b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/a4df6d07407c698f36a53a02814594e7.png differ diff --git a/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/post.md b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/post.md new file mode 100644 index 0000000000..be89ccb092 --- /dev/null +++ b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/post.md @@ -0,0 +1,195 @@ +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **5.2 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version. + +> **The planned release date for the [5.2.0 Stable](https://github.com/abpframework/abp/milestone/66) version is April 05, 2022**. + +Please try this version and provide feedback for a more stable ABP version 5.2! Thank you all. + +## Get Started with the 5.2 RC + +Follow the steps below to try the version 5.2.0 RC today: + +1) **Upgrade** the ABP CLI to version `5.2.0-rc.1` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 5.2.0-rc.1 +```` + +​ **or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 5.2.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 *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. + +You can use any IDE that supports .NET 6.x, like **[Visual Studio 2022](https://visualstudio.microsoft.com/downloads/)**. + +## Migration Guides + +Please see the migration guides if you are upgrading from 5.x versions: + +* [ABP Framework 5.x to 5.2 migration guide](https://docs.abp.io/en/abp/5.2/Migration-Guides/Abp-5_2) +* [ABP Commercial 5.x to 5.2 migration guide](https://docs.abp.io/en/commercial/5.2/migration-guides/index) + +## What's New with ABP Framework 5.2? + +In this section, I will introduce some major features released with this version. Here, a brief list of titles explained in the next sections: + +* Single-layer Solution Template +* API Versioning +* libs Folder Has been Removed from Source Control +* Hiding the Default ABP Endpoints from Swagger UI +* Custom Global CSS and JavaScript for the CMS Kit module +* Other news + + +Let's begin with the first item. + +### Single-layer Solution Template + +ABP's [application startup template](https://docs.abp.io/en/abp/latest/Startup-Templates/Application) is a well-organized and layered solution to create maintainable business applications. However, some developers find it a little bit complex for simple and short-term applications. For such applications, we've created a new startup template that has no layering and built as simple as possible. It has the same functionality, features and modules on runtime, but the development model is minimal and everything is in the single project (`csproj`), as shown in the following figure: + +![single-layer-solution.png](a4df6d07407c698f36a53a02814594e7.png) + +Use the `app-nolayers` as the template name while creating your solution: + +````bash +abp new BookStore -t app-nolayers --preview +```` + +[ABP Commercial](https://commercial.abp.io/) developers can use the `app-nolayers-pro` as the startup template: + +````csharp +abp new BookStore -t app-nolayers-pro --preview +```` + +> There is a bug for the `app-nolayers-pro` related to the licensing system, which will be fixed with 5.2.0-rc.2: `appsettings.secrets.json` is missing in the project folder (should be near to `appsettings.json` and contains the license code normally). As a workaround, create a new solution with the layered startup template, find and copy that file to the single-layer solution. + +One note about the single-layer project is it doesn't have Blazor WebAssembly UI, because it requires 3 projects at least (one server-side, one UI and one shared library project between these two). We will consider to add Blazor UI support based on your feedback. You can continue to develop Blazor WASM projects using the standard layered solution template. + +#### Database Migrations for EF Core + +After creating your solution, you need to create the database before running the application. We've added a parameter to the application that can be specified to migrate the database and seed the initial data. Open the project's directory (that contains the `csproj` file) in a command-line terminal and type the following command: + +````bash +dotnet run --migrate-database +```` + +It will run, migrate the database and exit. You can then run the application as normal. + +You could use the standard `dotnet ef database update` command (or `Update-Database` command in Visual Studio's Package Manager Console). It can successfully create the database tables. However, it doesn't seed the initial data that is necessary to run the application. + +To keep the solution simple, we haven't added an external application (like the `DbMigrator` in the layered application startup template) to migrate the database. + +Using the same application to migrate the database is simple and useful for development environment, and it can also be used in production environment. However, there are other ways of migrating a database. Please read more on [Microsoft's documentation](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations). + +#### Other UI and Database Options + +The new single-layer solution template also supports Angular and Blazor UI, and MongoDB for the database side. For the UI, you can use `mvc` (default), `angular` or `blazor-server` with the `-u` (or `--ui`) parameter. For the database provider, you can use `ef` (default) or `mongodb` with the `-d` (or `--database-provider`) parameter. Example: + +````bash +abp new BookStore -t app-nolayers -u angular -d mongodb --preview +```` + +This will create a single layer template with Angular as the UI framework and MongoDB as the database provider. + +#### Single-Layer Tutorial + +[Hamza Albreem](https://twitter.com/st_braim) has created a video tutorial to explain how to develop a simple application with this startup template. + +![video-single-layer-tutorial.png](9168547a7e70ca84f1a53a028145fc71.png) + +You can [watch it here](https://community.abp.io/posts/developing-a-minimalist-application-with-the-abp-framework-mvad01ca). + +### API Versioning + +API versioning has always been possible with the ABP Framework, but we haven't had a documentation for it. With version 5.2, we've created a document to explain how to implement API versioning for your applications and add versioning support to your standard application service classes. See the [documentation here](https://docs.abp.io/en/abp/5.2/API/API-Versioning). + +### libs Folder Has been Removed from Source Control + +> **NOTICE: This can be a breaking change for your development environment and CI/CD pipelines. So, please read it carefully and take the necessary actions.** + +When you create solutions with MVC (Razor Pages) or Blazor Server UI, your application will have a `wwwroot/libs` folder in the UI project as shown below: + +![libs-folder.png](59e40287b10caca3a7b33a0281462c37.png) + +The `libs` folder contains all the client-side (mostly JavaScript and CSS) library dependencies. For example, in the figure above, the `bootstap` folder contains the necessary files for the Bootstrap library. The folder's content is copied from the `node_modules` folder (it only copies the minimum files to make the library work, not the whole folder) with ABP CLI's `abp install-libs` command. + +Before version 5.2, the `libs` folder was coming with the startup template and committed into your source control system (e.g. Git). With version 5.2, this folder is excluded from the source control by default, so every developer getting the solution must run `abp install-libs` in the UI project's root directory to install these libraries. This approach saves a huge amount of size of the solution. For example, the initial size of an MVC UI application reduces from `9.83MB` to `0.23MB` (you read it right!). + +When you create a new solution with ABP CLI, `abp install-libs` command is automatically executed, so your application directly works. However, if your teammates (or CI/CD system) get the solution from the source control, they should run the `abp install-libs` before running the solution. If you don't want that, you can simply remove the `**/wwwroot/libs/*` line from the `.gitignore` file in the root folder of your solution, then the `libs` folder is added to your source control again (if you are using a source control system other than Git, you should apply your system's rules to include/exclude that folder). + +### Hiding the Default ABP Endpoints from Swagger UI + +[Engincan Veske](https://twitter.com/EngincanVeske) had written [an article](https://community.abp.io/posts/how-to-hide-abp-related-endpoints-on-swagger-ui-mb2w01fe) to explain how to hide ABP's default endpoints from Swagger UI. Then We thought that could be a good built-in option in the ABP Framework and added a `HideAbpEndpoints` method to the `AddAbpSwaggerGen` method, which can be used as in the following code example: + +````csharp +services.AddAbpSwaggerGen( + options => + { + //... other options + + //Hides ABP Related endpoints on Swagger UI + options.HideAbpEndpoints(); + } +) +```` + +After that, ABP's default endpoints will still be functional, but will be hidden in Swagger UI. + +### Custom Global CSS and JavaScript for the CMS Kit module + +We are improving the [CMS Kit module](https://docs.abp.io/en/abp/5.2/Modules/Cms-Kit/Index) and adding new features constantly. A new feature with version 5.2 is a global resources system, where you can write custom JavaScript or CSS code on the application's UI (added a new page for it), which will be immediately available in all your application pages: + +![cms-kit-global-resources.png](1c453b5c819a46c9e8583a028146680e.png) + +In this way, you can customize your application's look and behavior on runtime. See [the documentation](https://docs.abp.io/en/abp/5.2/Modules/Cms-Kit/Global-Resources) for more information. + +> Note that the [pages](https://docs.abp.io/en/abp/5.2/Modules/Cms-Kit/Pages) feature already have a page-basis script/style editor. But this new feature allows you to write script/style that is applied to all pages of your application. + +### Other news + +* Upgraded the [Blazorise](https://blazorise.com/) library to v1.0 for Blazor UI. After the upgrade, ensure that all Blazorise-related packages are using v1.0 in your application. + +If you want to see more details, you can check [the release on GitHub](https://github.com/abpframework/abp/releases/tag/5.2.0-rc.1), that contains a list of all issues and pull requests closed with this version. + +## What's New with ABP Commercial 5.2? + +We've also made many enhancements for [ABP Commercial](https://commercial.abp.io/), and also made the necessary changes and improvements to align with the v5.2 release of the ABP Framework. For example, the **single-layer solution template** is also available for ABP Commercial as explained above. + +### Many to Many Relations on Code Generation + +One exciting new feature with ABP Commercial v5.2 is supporting many-to-many entity relations while generating CRUD code with [ABP Suite](https://commercial.abp.io/tools/suite). + +When you open ABP Suite v5.2, you will see an "Add navigation collection" button in the Navigation tab. Here, you can click that button, select the target entity and other options: + +![suite-many-to-many-entity-relation.png](48b7bb8717413c1f78323a028146a77b.png) + +With this new feature, you can automatically generate advanced user interfaces without touching the code, then customize the generated code to implement your business logic. + +## Community News + +We organized the 3rd live [ABP Community Talks](https://community.abp.io/events) event on February 23rd. ABP community has a good interest in these events and we will continue to organize such a live event in every month. March's event will be announced in a few days. [Follow us on twitter](https://twitter.com/abpframework). + +[ABP Community](https://community.abp.io/) website is being a huge resource of articles and video tutorials on the ABP Framework and .NET. There have been 93 articles/tutorials submitted so far. Here's a list of a few contents posted in the last weeks: + +* [Ahmet Urel](https://twitter.com/YellowDraqon) submitted a series of articles to demonstrate the usage of [MudBlazor](https://www.mudblazor.com/) library with the ABP Framework Blazor UI: [Part 1](https://community.abp.io/posts/mudblazor-theme-in-abp-blazor-webassembly-ae23zz17), [Part 2](https://community.abp.io/posts/mudblazor-theme-in-abp-blazor-webassembly-part-2-tkvrvyvm) and [Part 3](https://community.abp.io/posts/mudblazor-theme-in-abp-blazor-webassembly-part-3-c8hwx00l). +* [Enis Necipoğlu](https://twitter.com/EnisNecipoglu) has created two articles for ABP & **.NET MAUI** integration: See [Part 1](https://community.abp.io/posts/integrating-maui-client-via-using-openid-connect-aqjjwsdf) and [Part 2](https://community.abp.io/posts/using-abp-client-proxies-in-maui-with-openid-connect-em7x1s8k). [Bart Van Hoey](https://twitter.com/bartvanhoey) also created [an article](https://community.abp.io/posts/abp-framework-consumed-by-a-.net-maui-app-e74fmblw) for .NET MAUI and the ABP Framework. +* [Enis Necipoğlu](https://twitter.com/EnisNecipoglu) has also created [an article](https://community.abp.io/posts/using-autofilterer-with-abp-framework-uuqv81jm) to demonstrate how to use his own open source [AutoFilterer](https://github.com/enisn/AutoFilterer) library with the ABP Framework. +* [Jonathan Potts](https://github.com/jonathanpotts) has created his first ABP Community article that shows how to use Bootswatch themes with the ABP Framework. [See it here](https://community.abp.io/posts/customizing-the-abp-basic-theme-with-bootswatch-4luoqzr0). + +Thanks to all the contributors. It is appreciated if you want to submit your post and share your knowledge with the ABP community: https://community.abp.io/posts/submit + +## Conclusion + +This version was mostly about minor features and enhancements for existing features, and getting the framework, architecture and solution structure more mature. Currently, we are working on middle and long term features, changes and goals. You can find most of them on the [road map here](https://docs.abp.io/en/abp/5.2/Road-Map). + +The planned release date for the [5.2.0 Stable](https://github.com/abpframework/abp/milestone/66) version is April 05, 2022. Please try the ABP v5.2 RC and provide feedback to have a more stable release. diff --git a/docs/en/Community-Articles/2022-04-05-abpio-platform-52-final-has-been-released/post.md b/docs/en/Community-Articles/2022-04-05-abpio-platform-52-final-has-been-released/post.md new file mode 100644 index 0000000000..52849e78d1 --- /dev/null +++ b/docs/en/Community-Articles/2022-04-05-abpio-platform-52-final-has-been-released/post.md @@ -0,0 +1,49 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 5.2 versions have been released today. + +## What's New With 5.2? + +Since all the new features are already explained in details with the [5.2 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-5-2-RC-Has-Been-Published), I will not repeat all the details again. See the [RC Blog Post](https://blog.abp.io/abp/ABP.IO-Platform-5-2-RC-Has-Been-Published) for all the features and enhancements. + +## Creating New Solutions + +You can create a new solution with the ABP Framework version 5.2 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +## How to Upgrade an Existing Solution + +### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +### ABP UPDATE Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guide + +Check [the migration guide](https://docs.abp.io/en/abp/5.2/Migration-Guides/Abp-5_2) for the applications with the version 5.x upgrading to the version 5.2. + +## About the Next Version + +The next feature version will be 5.3. It is planned to release the 5.3 RC (Release Candidate) on May 03 and the final version on May 31, 2022. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). + +Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problem with this version. \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-04-18-abp-community-talks-20223/b8cdde094516786c107d3a0359023e6c.png b/docs/en/Community-Articles/2022-04-18-abp-community-talks-20223/b8cdde094516786c107d3a0359023e6c.png new file mode 100644 index 0000000000..cc1deb74c1 Binary files /dev/null and b/docs/en/Community-Articles/2022-04-18-abp-community-talks-20223/b8cdde094516786c107d3a0359023e6c.png differ diff --git a/docs/en/Community-Articles/2022-04-18-abp-community-talks-20223/post.md b/docs/en/Community-Articles/2022-04-18-abp-community-talks-20223/post.md new file mode 100644 index 0000000000..fcd7043594 --- /dev/null +++ b/docs/en/Community-Articles/2022-04-18-abp-community-talks-20223/post.md @@ -0,0 +1,66 @@ + ABP Community Talks is the event where we gather as ABP Framework’s Community members to talk, and share ideas on a monthly basis. Before the talks, we collect ideas from our contributors, trending topics in the industry, ABP Platform’s news and updates, and more, to select the topics that will be talked about in every episode. After the topics are certain, we announce them on our social media and community channels. + + You are always welcome and encouraged to join, ask questions, make suggestions, or even be in the talks to make presentations about the topics that you think would be beneficial for the ABP Community. + +###### ABP Community Talks Facts: + * ABP Community Talks are scheduled to be held on a monthly basis. + * ABP Community Talks are and always will be completely free to attend. Everyone is welcome to join, ask questions and make suggestions before, during and after the event. + * ABP Community Talks are created and announced on [Kommunity](https://kommunity.com/volosoft/events). + * ABP Community Talks are announced regularly on [ABP Framework Twitter Account](https://twitter.com/abpframework), [Volosoft LinkedIn account](https://www.linkedin.com/company/volosoft), [Volosoft Facebook Account](https://www.facebook.com/volosoftcompany), [ABP Community Discord Server](https://discord.gg/CrYrd5vcGh). We highly encourage everyone to follow us and make suggestions. + * ABP Community Talks are available to watch after the event on YouTube. See [ABP Community Talks YouTube Playlist](https://www.youtube.com/playlist?list=PLsNclT2aHJcOsPustEkzG6DywiO8eh0lB). + +# ABP Community Talks 2022.3 + +> [WATCH FULL ABP Community Talks 2022.3](https://www.youtube.com/watch?v=lB3iXQccaV4) + + This was the 4th episode of ABP Community Talks in which [Jon Galloway](https://twitter.com/jongalloway), [Lee Richardson,](https://twitter.com/lprichar) and [Anto Subash](https://twitter.com/antosubash) being present as speakers! We talked about [ABP 5.2 Release](https://blog.abp.io/abp/ABP-IO-Platform-5-2-Final-Has-Been-Released), Domain-Driven Design, [Mastering ABP Framework Book](https://www.packtpub.com/product/mastering-abp-framework/9781801079242), the [EventHub solution](https://www.openeventhub.com/). + +![164219611-2c46e9d8-1689-4c5f-a783-42f18003f239.png](b8cdde094516786c107d3a0359023e6c.png) + + Special thanks to our sponsors [.Net Foundation](https://dotnetfoundation.org/) and [Packt Publishing](https://www.packtpub.com/). + +# The EventHub Solution + EventHub solution is an open-source reference application for implementing Domain Driven Design with the ABP Framework where you can reach from [EventHub’s GitHub Page](https://github.com/volosoft/eventhub). It is created for the ABP Framework book, therefore, its source code is explained in the Mastering ABP Framework Book. + + Since it is thought of as a real-world, live application, it is accessible from [here](https://www.openeventhub.com/) and configured to run with Kubernetes & Project Tye. It consists of two applications. The first is Main Website to be used by end-users, built with ASP.NET Core Razor Pages, and Admin Application built with Blazor WASM. There is also an authentication server that is built with the IdentityServer 4. Additionally, Two API endpoints (one for each web application), and Background Service. + + You can use the EventHub solution to create actual events like Meet Ups or bigger events where people can register, see your previous and upcoming events, you can arrange reminder emails, and do much more! + + If you would like to use the EventHub solution, you can take a look at the source code from [EventHub’s Github Page](https://github.com/volosoft/eventhub). For in depth information, you can [buy the Mastering ABP Framework Book](https://www.packtpub.com/product/mastering-abp-framework/9781801079242). + +# Mastering the ABP Book + The Mastering ABP Book can be referenced for every detail. The book takes you from the beginning, explaining all the concepts and features and correct order and gives you a good understanding of ABP Framework and its philosophy. It also discussed dot.net and general software development perspectives, alternatives approaches and minimal. + +###### Table of Content: +**Part 1** Introduction +
1. Modern Software Development and ABP Framework +
2. Getting Started with ABP Framework +
3. Step-By-Step Application Development +
4. Understanding the Reference Solution + +**Part 2** Fundamentals of ABP Framework +
5. Exploring the ASP.NET Core and ABP Infrastructure +
6. Working with the Data Access Infrastructure +
7. Exploring Cross-Cutting Concerns +
8. Using the Features and Services of ABP + +**Part 3** Implementing Domain-Driven Design +
9. Understanding Domain-Driven Design +
10. DDD — The Domain Layer +
11. DDD — The Application Layer + +**Part 4** User Interface and API Development +
12. Working with MVC/Razor Pages +
13. Working with the Blazor WebAssembly UI +
14. Building HTTP APIs and Real-Time Services + +**Part 5** Miscellaneous +
15. Working with Modularity +
16. Implementing Multi-Tenancy +
17. Building Automated Tests + +# How to purchase the Mastering ABP Framework book +You can have 25% off on Mastering ABP Framework paperback with “**25ABP**” Discount Code +* Discount is valid between April 7-May 7, 2022 to [purchase in Packt Publishing](https://www.packtpub.com/product/mastering-abp-framework/9781801079242) with 25% off, +* Discount is valid between April 7-April 21, 2022 to [purchase in Amazon US](https://www.amazon.com/gp/mpc/A2945M1X0HIWNL) with 25% off using “**25ABP**” Discount code. + diff --git a/docs/en/Community-Articles/2022-04-19-official-abp-discord-server-is-here/post.md b/docs/en/Community-Articles/2022-04-19-official-abp-discord-server-is-here/post.md new file mode 100644 index 0000000000..5d099cc1c3 --- /dev/null +++ b/docs/en/Community-Articles/2022-04-19-official-abp-discord-server-is-here/post.md @@ -0,0 +1,65 @@ + We are excited to announce Official ABP Discord Server is created! You can join the ABP Discord Community by clicking [here](https://discord.gg/wbcQAsUrs9). + + In the first week of opening ABP Discord Server, member amount reached more than 500. We are grateful to and blessed by your interest. Thanks to all of you! This also made us sure that an ABP Discord Server was actually a need for the community members to interact with each other. + + ABP Community is growing by the second, and we are grateful for all your contributions towards ABP Framework. We noticed that ABP Community’s communication were significant on ABP Framework’s GitHub, we wanted to take it to the next level and have an area where all of us can easily chat with each other. +> [Join ABP Discord Server Now](https://discord.gg/wbcQAsUrs9) + +# What Can You Do on ABP Community Discord Server? + + ABP Discord Server is a multi-channel official server consisting ABP Core Team, community members and anyone who is interested in following ABP Platform closer. + + In ABP Discord Server, we plan to have: +* Discord-special events such as mini talks, discussions on stage channel. +* Showcases for community members, so it would be inspiring for others, and if you want to brag a little bit about your work, you can do it, too :). +* An area where people can look for developers who are experienced in ABP Framework. +* People socialize with each other to talk about common interests and just chat in general. +* Make announcements, so the ABP Discord Server community members would be the first ones to hear about the latest ABP-related news. +* Real-time GitHub issues to make it easier for community members to follow ABP Framework GitHub. +* Collect suggestions to broaden the variety of what we have to offer to our community. + + To demonstrate the current use of ABP Discord Server, it is better to mention open channels with their purposes which are listed below. ABP Discord Server is not limited to include only these channels, we will improve it as needed. + +- **Info:** This is the area where moderators post about rules, announcements, partners, etc + +- **Community:** This is where the actual magic of ABP Discord Server happens. + * **General:** As you can tell from its name, this is the channel where you can talk about ABP in general. + * **Ideas:** In this channel, you can give suggestions or share your ideas with ABP Core Team members on how to improve ABP platform, community members’ work, Discord Server, etc. + * **Tips:** In this channel, you can share the tips you think would be beneficial for the other community members. (Your first tip before entering ABP Discord Server: ABP Core Team also shares tips/new documents as being members of ABP Community) + * **Questions:** We know it can be long to get answers from other community members via ABP Framework GitHub issues. So, you can use Questions channel as you use GitHub issues page to get answers from community members more quickly. + * **Help:** In this channel, you can ask for other members’ help or simply offer help to other community members. (Please not that this is not a support channel from ABP Core Team) + * **UI-Angular:** If you are using ABP Framework with Angular, this is the place for you to talk about anything related Angular. + * **UI-Blazor:** If you are using ABP Framework with Blazor, this is the place for you to talk about anything related to Blazor. + * **UI-MVC:** If you are using ABP Framework with MVC, this is the place for you to talk about anything related to MVC. + * **ABP Community Talks:** As you may or may not know, we, as ABP Core Team, are doing a Community Talks on a monthly basis for you in which we talk about the latest news, trends, etc. In this channel, we ask for your opinion to select the topics for the following episodes, make announcements regarding ABP Community Talks. You can reach to Community Talks playlist from [here](https://youtube.com/playlist?list=PLsNclT2aHJcOsPustEkzG6DywiO8eh0lB). + * **Showcase:** In this channel, you can share what you have created using ABP Framework, your tutorials, posts related to ABP Framework, and brag about your work overall if you want to :). + * **Jobs:** It is created especially to simplify the recruitment process of ABP Framework experienced developers with employers. You can use this channel to look for opportunities or seek for developers who are experienced in ABP Framework. + * **Github Issues:** If you want to follow ABP Framework GitHub closer, this is the channel for you. Opened pull requests, closed pull requests, opened issues, closed issues are automatically published in here on real-time. + * **Dotnet General:** If you want to talk about topics that include Dotnet in general, rather than being specific for ABP Framework, you can use this channel. + * **ASP.NET Boilerplate:** Since ABP is the framework that is built on ASP.NET Boilerplate(which is created by ABP Core Team, also). So, even if you are not a developer of ABP Platform, but ASP.NET Boilerplate; you are welcome to talk about Boilerplate in this channel! + * **Off-Topic:** This is the channel where you are free to talk about anything! When we say anything, we mean anything! +- **Voice Channel:** There are 4 voice channels for community members to have public voice calls with each other to talk about anything they would like to. And, 1 stage channel to take Special-for-Discord Events by ABP Core Team. + +# How Can You Join To ABP Discord Server? + + You can join ABP Discord Server by simply clicking to [https://discord.gg/abp](https://discord.gg/wbcQAsUrs9). + + We are excited to welcome you in ABP Discord Server! + +> [Click Here to Join ABP Discord Server Now](https://discord.gg/wbcQAsUrs9) + +### What is Discord? + + Discord is a free instant communication platform where people can send text messages, make voice calls, video chat, send files, and many more. Discord itself defines the platform as “Your Place to Talk and Hang Out”. You can say, it works like any other chat app such as Skype, or Slack. Despite this remains true, that’s not all Discord has to offer. + +### What is Discord Server? + + Discord pivoted to a place where communities gather in specific servers to communicate with people who has common interests on Discord Servers in which users can socialize and exchange ideas, share tips and simply chat with each other about that specific topic they are interested in. + + Usually, Discord Servers include multi-channels to divide topics to be discussed within. To give an example, there are “General”, “Ideas”, “Tips”, “Questions”, “UI-Angular”, “UI-Blazor”, “UI-MVC”, and many more channels in ABP Discord Community. This way, specific ideas about specific topics are easier to follow and read for everyone, and the topics are not lost, easier to follow and read for everyone. + +### What are Discord Servers Used For? + + In Discord Servers, users communicate with each other in a way that is convenient for them. Discord allows people to make voice calls, video chats, or simply text messages. Communities are created by wether fans of a specific topic(games, open-source frameworks, NFT, etc.) or by the official authorities of that specific topic(game creator, framework core team, creator of a token, etc). + + In ABP Community Discord Server’s case, it is a server created by official authorities with core team being present in the server along with the community members. Even though it is created for the framework community members to communicate with each other easily, everyone who is interested in following the latest news about ABP Platform are welcome to [join ABP Discord Server](https://discord.gg/wbcQAsUrs9)! \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/1b869f1f0b84f697a7c93a03bfaf6d80.png b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/1b869f1f0b84f697a7c93a03bfaf6d80.png new file mode 100644 index 0000000000..1f048819b3 Binary files /dev/null and b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/1b869f1f0b84f697a7c93a03bfaf6d80.png differ diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/3e5a0fc742becf26e4f63a03bfaed423.png b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/3e5a0fc742becf26e4f63a03bfaed423.png new file mode 100644 index 0000000000..1015f7ce18 Binary files /dev/null and b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/3e5a0fc742becf26e4f63a03bfaed423.png differ diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/4a70b5a48f8355ad109b3a03bfafa75a.png b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/4a70b5a48f8355ad109b3a03bfafa75a.png new file mode 100644 index 0000000000..bee6caac75 Binary files /dev/null and b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/4a70b5a48f8355ad109b3a03bfafa75a.png differ diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/5b994aa1669cb6cea61a3a03bfae47a3.png b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/5b994aa1669cb6cea61a3a03bfae47a3.png new file mode 100644 index 0000000000..736d3b7a88 Binary files /dev/null and b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/5b994aa1669cb6cea61a3a03bfae47a3.png differ diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/5c10f5ca174e232103ac3a03bfaff95e.gif b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/5c10f5ca174e232103ac3a03bfaff95e.gif new file mode 100644 index 0000000000..8f301559ee Binary files /dev/null and b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/5c10f5ca174e232103ac3a03bfaff95e.gif differ diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/b77ff680a3fcd77048863a03bfaf4694.png b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/b77ff680a3fcd77048863a03bfaf4694.png new file mode 100644 index 0000000000..5beb5551ac Binary files /dev/null and b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/b77ff680a3fcd77048863a03bfaf4694.png differ diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/c905db6b3949f07077b63a03bfb1fd0f.png b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/c905db6b3949f07077b63a03bfb1fd0f.png new file mode 100644 index 0000000000..ee5f374ff4 Binary files /dev/null and b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/c905db6b3949f07077b63a03bfb1fd0f.png differ diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/ccec571a20bc6673befe3a03bfaf1878.png b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/ccec571a20bc6673befe3a03bfaf1878.png new file mode 100644 index 0000000000..c617f9348a Binary files /dev/null and b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/ccec571a20bc6673befe3a03bfaf1878.png differ diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/e4464b33ec38e091736b3a03bfae9ab3.png b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/e4464b33ec38e091736b3a03bfae9ab3.png new file mode 100644 index 0000000000..124aa35ecf Binary files /dev/null and b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/e4464b33ec38e091736b3a03bfae9ab3.png differ diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/linkedin-twitter.png b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/linkedin-twitter.png new file mode 100644 index 0000000000..8c731bd878 Binary files /dev/null and b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/linkedin-twitter.png differ diff --git a/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/post.md b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/post.md new file mode 100644 index 0000000000..eb157010b8 --- /dev/null +++ b/docs/en/Community-Articles/2022-05-10-abpio-platform-53-rc-has-been-published/post.md @@ -0,0 +1,257 @@ +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **5.3 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version. + +> **The planned release date for the [5.3.0 Stable](https://github.com/abpframework/abp/milestone/69) version is June 14, 2022**. + +Please try this version and provide feedback for a more stable ABP version 5.3! Thank you all. + +## Get Started with the 5.3 RC + +Follow the steps below to try version 5.3.0 RC today: + +1) **Upgrade** the ABP CLI to version `5.3.0-rc.1` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 5.3.0-rc.1 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 5.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 *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. + +You can use any IDE that supports .NET 6.x, like **[Visual Studio 2022](https://visualstudio.microsoft.com/downloads/)**. + +## Migration Guides + +This version comes with a few breaking changes, so please see the migration guides if you are upgrading from **v5.2**: + +* [ABP Framework 5.2 to 5.3 migration guide](https://docs.abp.io/en/abp/5.3/Migration-Guides/Abp-5_3) +* [ABP Commercial 5.2 to 5.3 migration guide](https://docs.abp.io/en/commercial/5.3/migration-guides/v5_3) + +## What's New with ABP Framework 5.3? + +In this section, I will introduce some major features released with this version. Here is a brief list of titles explained in the next sections: + +* Single-layer option added to the [*Get Started*](https://abp.io/get-started) page +* PWA Support for Startup Templates +* Introduced the `Volo.Abp.Gdpr.Abstractions` package +* Batch Publish Events from Outbox to the Event Bus +* Improvements on **eShopOnAbp** Project & E-Book Announcement +* LeptonX Lite Documentations & Project Status & Roadmap +* OpenIddict Module & Keycloack Integration +* Deployment Documentations +* Other News + +### Single-layer Option on *Get Started* Page + +We've created a new startup template named `app-nolayers` and [announced](https://blog.abp.io/abp/ABP.IO-Platform-5-2-RC-Has-Been-Published) it in the previous version. In this version, we've also added this startup template option to the *Get Started* page. + +*You can examine the screenshot below to see how to create an `app-nolayers` template from the ["Get Started"](https://abp.io/get-started) page:* + +![app-nolayers-get-started.png](5b994aa1669cb6cea61a3a03bfae47a3.png) + +### PWA Support for Startup Templates + +ABP v5.3 application startup template now supports PWA for Blazor WASM & Angular UIs. To create a startup template with the PWA support, you can use the `--pwa` parameter. + +Example: + +```bash +abp new MyProgressiveWebApp -t app -u blazor --pwa +``` + +### Introducing the `Volo.Abp.Gdpr.Abstractions` Package + +A new `Volo.Abp.Gdpr.Abstractions` package has been added to the framework. This is an abstraction package, so doesn't contain any actual GDPR implementation. It defines some classes and interfaces to put a standard for who want to implement a GDPR module that can run in a modular or microservice system. + +At that point, we are introducing the **GDPR Module** for the ABP Commercial customers and this module does the GDPR-related operations on behalf of you, such as *"Download/Delete Personal Data"*. I'll describe the **GDPR Module** later in this blog post. + +> Please see the **GDPR Module** section below to learn more about this module. + +### Batch Publish Events from Outbox to the Event Bus + +We introduced the "Transactional Outbox & Inbox Patterns" in [**ABP v5.0**](https://blog.abp.io/abp/ABP-IO-Platform-5.0-RC-1-Has-Been-Released), it was one of the most awaited features by several software developers. + +We've made some optimizations for the **Batch Event Publishing** in this version, you can examine the related development from [here](https://github.com/abpframework/abp/pull/11243). After the optimization, the results are impressive. It is enabled by default (if you have configured [event outbox](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus#outbox-inbox-for-transactional-events)), so you don't need to any manual configuration. + +### Improvements on eShopOnAbp Project & E-Book Announcement + +There are some developments on the [eShopOnAbp project](https://github.com/abpframework/eShopOnAbp) made in this version. You can see the brief descriptions of some of the improvements below: + +* Local certificates have been created to use while working in Kubernetes and also Helm Charts have been updated. See [#107](https://github.com/abpframework/eShopOnAbp/pull/107). +* The Order Management page has been created. See [#92](https://github.com/abpframework/eShopOnAbp/pull/92). +* Database migration event handlers have been removed and "Distributed Locking" is now used for database migrations. See [#85](https://github.com/abpframework/eShopOnAbp/pull/85) and [#102](https://github.com/abpframework/eShopOnAbp/pull/102). +* Switched from Ocelot to YARP as the gateway. See [#97](https://github.com/abpframework/eShopOnAbp/pull/97). + +We have exciting news to share with the community, we're working on an "ABP Microservice Development" e-book. In this book, we're using the eShopOnAbp project as a reference microservice solution and we're trying to explain our experiences during the microservice application development process through this project. + +We're planning to create this book in nine chapters and make it available after the third chapter is written. After that, you will be able to download this free e-book from the [abp.io](https://abp.io/) website. + +### LeptonX Lite Documentations & Project Status & Roadmap + +It is finally here, we've released the **1.0.0-beta.1** and **1.0.0-beta.2** versions for the **LeptonX Lite**. + +![leptonx-lite-documentations.png](e4464b33ec38e091736b3a03bfae9ab3.png) + +Lepton X Lite documents have been written for the three UI types within this version. You can see the related documentation from the screenshot above. You can follow these documents and try the new **LeptonX Lite Theme**. + +We don't suggest using the **beta.1** and **beta.2** versions on production but we highly demand you to test **LeptonX Lite** and provide feedback to us. It's really important for us to be able to release a more stable version. Thanks in advance. + +For the following versions (beta.3 and RC versions), we will focus on: + +* Fixing the reported bugs from the community +* Providing documentations as much as possible +* Adding new custom pages to the demo + +### OpenIddict Module & Keycloack Integration + +We have [announced the plan of replacing the IdentityServer](https://github.com/abpframework/abp/issues/11989). ABP currently uses **IdentityServer4** to add **OAuth** features as built-in on the server-side. However, since *IdentityServer4's support ends at the end of the year 2022*. Its replacement is Duende IdentityServer, which is not a free software anymore. (see [more](https://blog.duendesoftware.com/posts/20220111_fair_trade/)) + +Therefore, we've decided to completely drop the **IdentityServer4** from the ABP platform and implement the [OpenIddict](https://github.com/openiddict/openiddict-core) and install onto the startup templates. + +We've implemented both open source and commercial OpenIddict modules, we plan to remove Identity Server and replace it with OpenIddict for template projects in **ABP v6.0**. Please check [#12084](https://github.com/abpframework/abp/pull/12084) to see the development made on the open-source side. + +We're creating the documentation for the OpenIddict Module, if you want to have general knowledge about this module, you can check the documentation from [here](https://github.com/abpframework/abp/blob/dev/docs/en/Modules/OpenIddict.md). Currently, this is a draft documentation but it gives overall knowledge about the OpenIddict Module, we'll complete this documentation in ABP v6.0 and you'll be able to read it completely. + +Currently, we are also working on Keycloak integration possibilities in parallel to the OpenIddict integration research and we've prepared some samples that you can examine. You can see [#154](https://github.com/abpframework/abp-samples/pull/154) and [#158](https://github.com/abpframework/abp-samples/pull/158). + +### Deployment Documentations + +Deploying an ABP-based application is not so different than deploying any .NET or ASP.NET Core application. You can deploy it to a cloud provider (e.g. Azure, AWS, Google Could) or on-premise server, IIS or any other web server. However, we wanted to prepare a "Deployment Guide" to mention the important points and considerations. + +![deployment-documentation.png](3e5a0fc742becf26e4f63a03bfaed423.png) + +In the [Deploying to a Clustered Environment](https://docs.abp.io/en/abp/5.3/Deployment/Clustered-Environment) documentation, we've documented the topics that you should consider when you are developing your application to a clustered environment and explained how you can deal with these topics in your ABP-based application. + +### Other News + +* Global Features were only accessible from the C# code. From this version and on, Global Features can be also provided from application configurations. See [#12043](https://github.com/abpframework/abp/pull/12043). +* Getting the user's detailed information (name, surname and phone number) from external login. See [#12085](https://github.com/abpframework/abp/pull/12085). +* Date Pipes for Angular. See [#11909](https://github.com/abpframework/abp/issues/11909). + +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 closed with this version. + +## What's New with ABP Commercial 5.3? + +### GDPR Module + +> **GDPR (General Data Protection Regulation)** is a regulation in EU law on data protection and known as the toughest privacy and security law in the world. GDPR applies to any organization operating within the EU, as well as any organizations outside of the EU which offer goods or services to customers or businesses in the EU. + +With this version, we are introducing the new **GDPR Module**. This was one of the most awaited features, so we've prioritized it and implemented it in this version. + +The GDPR Module is pre-installed in the [startup templates](https://docs.abp.io/en/commercial/5.3/startup-templates/index) for MVC. So, no need to manually install it. When you create a new startup template, you can directly use this module. We'll also implement this module for the other UI types as soon as possible and also add extra functionality such as "Cookie Consent" and more. + +Currently, there are two main functions of this module and they are "Download Personal Data" and "Delete Personal Data". + +![gdpr-user-menu.png](ccec571a20bc6673befe3a03bfaf1878.png) + +There is a "Personal Data" section in the user menu as in the screenshot above and when you click on this section, you'll be redirected to the "Personal Data" page. On that page, you can either request to "Download Personal Data" or "Delete Personal Data". + +![gdpr-personal-data-page.png](b77ff680a3fcd77048863a03bfaf4694.png) + +After you've requested to download "Personal Data", you need to wait for 1 hour by default (you can configure the related option). Because the GDPR module is developed by considering the distributed systems and therefore a specific time should be passed to ensure all the published events are handled and all personal data is collected. + +### CMS Kit Pro - Polling Feature + +We've added a **Polling** feature to the **CMS Kit Pro** module. This feature allows you to use a questionnaire/voting system in your application easily. You can create a question, define some options for it and the poll will be created for you. You can see the example poll in the screenshot below: + +![poll-question-example.png](1b869f1f0b84f697a7c93a03bfaf6d80.png) + +Also, there is an admin side of the Polling Feature. You can easily manage your polls in your admin (back-office) project. You can create, update, delete and show the results of the poll on the Polls page: + +![poll-questions.png](4a70b5a48f8355ad109b3a03bfafa75a.png) + +### OAuth Resource Owner Password as External Login Provider + +> The Resource Owner Password flow allows for the exchanging of the username and password of a user for an access token. When using the resource owner password credentials grant, the user provides the credentials (username and password) directly to the application. + +Now, you can login by entering a username and password from an OAuth server. + +Example: Use OAuth external login provider with Keycloak: + +![oauth-external-provider.gif](5c10f5ca174e232103ac3a03bfaff95e.gif) + +### Suite New Features & Enhancements + +In this version, there are some enhancements and new features in **Suite** and they are listed briefly below: + +* It's now possible to create an **app-nolayers (Application - single layer)** template via Suite and also code-generation is supported for the **app-nolayers** template with this version. +* Suite now allows users to see and download its logs. +* Suite now allows generating code via CLI. If you have a JSON file that contains code blocks, like entity configurations, you can use the `abp suite generate` command to generate CRUD pages based on it. + +Example: + +```bash +abp suite generate -e C:\Users\.suite\entities\Country.json -s C:\Users\my-proj\SuiteProj\SuiteProj.sln +``` + +### Suite Webinar: Take a closer look at the code generation + +![](linkedin-twitter.png) + +We've organized a webinar for Suite and in this webinar, we've talked about ABP Suite's capabilities, important features and more... + +You can watch the event from [here](https://www.youtube.com/watch?v=RFArBh60RSA&t=3s), if you haven't watched it yet. + +### Docker Compose Configurations for Single Layer Startup Template + +Dockerfiles, docker-compose files and build script files have been added to the Single Layer Startup Template (app-nolayers) with this version. + +And this way, applications created with this template now can be deployed more easily. + +### Microservice Solution Enhancements + +There are some enhancements made in the Microservice Solution. You can see the list of these enhancements: + +* Initial migration on the template has been updated with the small improvement that was made in the **Language Management** module. +* Database migration event handlers have been removed and "Distributed Locking" is now used for the database migrations. + +### PWA Support for the Application Pro Template + +Application Pro template also supports the PWA for Blazor WASM & Angular UIS. To create a startup template with the PWA support, you can use the `--pwa` parameter. +Example: + +```bash +abp new MyProgressiveWebApp -t app-pro -u blazor --pwa +``` + +## Community News + +### New ABP Community Posts + +* [Anto Subash](https://twitter.com/antosubash) created a series named ["Microservice with ABP"](https://blog.antosubash.com/posts/abp-microservice-series) and shared a couple of video posts about the ABP Microservice solution. +* [Francisco Kadzi](https://github.com/CiscoNinja) has created his first ABP Community article that shows how to ["Customize ABP Angular Application UI with AdminLTE"](https://community.abp.io/posts/customize-abp-angular-application-ui-with-adminlte.-7qu1m67s). +* [Jack Fistelmann](https://github.com/nebula2) has created an article to introduce a helpful project extension to speed up development on Visual Studio. You can read the article [here](https://community.abp.io/posts/using-switch-startup-project-extension-for-visual-studio-52yyw27v). +* [Jack Fistelmann](https://github.com/nebula2) has also created an article to show how you can generate PDF files with the `Sycyber.Core` package in ABP-based applications. You can read it [here](https://community.abp.io/posts/generate-pdfs-in-an-abp-framework-project-using-scryber.core-x9yh1vfa). +* [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan) has created an article to show ["Dealing with Multiple Implementations of a Service in ASP.NET Core & ABP Dependency Injection"](https://community.abp.io/posts/dealing-with-multiple-implementations-of-a-service-in-asp.net-core-abp-dependency-injection-ysfp4ho2) with examples. +* [Manoj Kumar](https://community.abp.io/members/manojkumar.t@shloklabs.com) submitted a new article about how to use "ABP authentication in a Flutter application". It was a frequently asked topic, which you can read [here](https://community.abp.io/posts/flutter-web-authentication-from-abp-mp6l2ehx). +* [Engincan Veske](https://twitter.com/EngincanVeske) created a new community article to show "Concurrency Check/Control in ABP". You can read it [here](https://community.abp.io/posts/handle-concurrency-with-ef-core-in-an-abp-framework-project-with-asp.net-core-mvc-jlkc3w8f). + +### ABP Community Talks 2022.4: How can you contribute to the open source ABP Framework? (May 10, 2022 - 17:00 UTC) + +![community-talks-2022.4.png](c905db6b3949f07077b63a03bfb1fd0f.png) + +We've [asked you to pick the topic of the next Community Talks](https://twitter.com/abpframework/status/1514567683072745474?s=20&t=rJfHrB3DYDNsk2EXS8zBBQ) and you've chosen the "How to contribute to open source ABP Framework?" for the next talk topic. So, in this Community Talk, we will be talking about "How to contribute to ABP Framework" with one of the top contributors of the ABP Framework, [Ismail Yılmaz](https://github.com/iyilm4z). The event will be on **May 10, 2022, at 17:00 (UTC)** on YouTube. + +> You can register for the event from [here](https://kommunity.com/volosoft/events/abp-community-talks-20224-how-to-contribute-to-the-open-source-abp-framework-d9b50664), if you haven't registered yet. + +You can also [subscribe to the Volosoft channel](https://www.youtube.com/channel/UCO3XKlpvq8CA5MQNVS6b3dQ) to be informed about future ABP events and videos. + +### Discord Server + +We've created an official ABP Discord server so the ABP Community can interact with each other and created a blog-post to introduce it. You can read the [ABP Discord Server announcement post](https://blog.abp.io/abp/Official-ABP-Discord-Server-is-Here) to learn more about the ABP Discord Server. + +Thanks to the ABP Community, **700+** people joined our Discord Server so far and it grows every day. + +You can join our Discord Server from [here](https://discord.gg/abp), if you haven't yet. \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-06-15-abpio-platform-53-final-has-been-released/post.md b/docs/en/Community-Articles/2022-06-15-abpio-platform-53-final-has-been-released/post.md new file mode 100644 index 0000000000..58b1bdd8c7 --- /dev/null +++ b/docs/en/Community-Articles/2022-06-15-abpio-platform-53-final-has-been-released/post.md @@ -0,0 +1,67 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 5.3 versions have been released today. + +## What's New with 5.3? + +Since all the new features are already explained in details with the [5.3 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-5.3-RC-Has-Been-Published), I will not repeat all the details again. See the [RC Blog Post](https://blog.abp.io/abp/ABP.IO-Platform-5.3-RC-Has-Been-Published) for all the features and enhancements. + +## Getting Started with 5.3 + +### Creating New Solutions + +You can create a new solution with the ABP Framework version 5.3 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to Upgrade an Existing Solution + +#### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading Existing Solutions with the ABP Update Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guides + +Check the following migration guides for the applications with version 5.2 that are upgrading to version 5.3. + +* [ABP Framework 5.2 to 5.3 migration guide](https://docs.abp.io/en/abp/5.3/Migration-Guides/Abp-5_3) +* [ABP Commercial 5.2 to 5.3 migration guide](https://docs.abp.io/en/commercial/5.3/migration-guides/v5_3) + +## Community News + +### New ABP Community Posts + +Here are some of the recent posts added to the [ABP Community](https://community.abp.io/): + +* [Integrating Elsa .NET Workflows with ABP Commercial](https://community.abp.io/posts/integrating-elsa-.net-workflows-with-abp-commercial-io32k420) by [kirtik](https://community.abp.io/members/kirtik). +* [ABP's Conventional Dependency Injection](https://community.abp.io/posts/abps-conventional-dependency-injection-948toiqy) by [iyilm4z](https://github.com/iyilm4z). +* [How to implement Single Sign-On with ABP commercial application](https://community.abp.io/posts/how-to-implement-single-signon-with-abp-commercial-application-m5ek38y9) by [kirtik](https://community.abp.io/members/kirtik). +* [Introduce DTM for Multi-Tenant Multi-Database Scene](https://community.abp.io/posts/introduce-dtm-for-multitenant-multidatabase-scene-23ziikbe) by [gdlcf88](https://github.com/gdlcf88). + +Thanks to the ABP Community for all the contents they have published. You can also [post your ABP related (text or video) contents](https://community.abp.io/articles/submit) to the ABP Community. + +## About the Next Version + +The next feature version will be 6.0. It is planned to release the 6.0 RC (Release Candidate) on July 19 and the final version on August 16, 2022. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). + +Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/0212cca486b68bf476fe3a055694c57c.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/0212cca486b68bf476fe3a055694c57c.png new file mode 100644 index 0000000000..97e6160211 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/0212cca486b68bf476fe3a055694c57c.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/107a46b6a11909e76a493a055693b308.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/107a46b6a11909e76a493a055693b308.png new file mode 100644 index 0000000000..badedb60d5 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/107a46b6a11909e76a493a055693b308.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/1117c53c9c54182c4a333a055690ac73.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/1117c53c9c54182c4a333a055690ac73.png new file mode 100644 index 0000000000..3b90b515c1 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/1117c53c9c54182c4a333a055690ac73.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/1ec02e85fdc0bbc18dad3a055693f4a9.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/1ec02e85fdc0bbc18dad3a055693f4a9.png new file mode 100644 index 0000000000..b635ffbd5e Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/1ec02e85fdc0bbc18dad3a055693f4a9.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/20555333aa1878334f3f3a0556941a69.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/20555333aa1878334f3f3a0556941a69.png new file mode 100644 index 0000000000..271aeac8fd Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/20555333aa1878334f3f3a0556941a69.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/3a8ef4d97b96ae7af0e63a0556939ec5.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/3a8ef4d97b96ae7af0e63a0556939ec5.png new file mode 100644 index 0000000000..37c428b75e Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/3a8ef4d97b96ae7af0e63a0556939ec5.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/3c0c1c5334f762cf31143a0556935e7b.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/3c0c1c5334f762cf31143a0556935e7b.png new file mode 100644 index 0000000000..00ba2882d2 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/3c0c1c5334f762cf31143a0556935e7b.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/549f9e8744eb851795593a055694546b.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/549f9e8744eb851795593a055694546b.png new file mode 100644 index 0000000000..5b1ca8baf8 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/549f9e8744eb851795593a055694546b.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/6987cdadeca846db8bb93a055690e15a.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/6987cdadeca846db8bb93a055690e15a.png new file mode 100644 index 0000000000..9d38d48772 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/6987cdadeca846db8bb93a055690e15a.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/7e18226b6f26818fdc453a055694d92b.jpg b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/7e18226b6f26818fdc453a055694d92b.jpg new file mode 100644 index 0000000000..314c44d58e Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/7e18226b6f26818fdc453a055694d92b.jpg differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/84cc472a6483f21627993a0556927eb8.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/84cc472a6483f21627993a0556927eb8.png new file mode 100644 index 0000000000..109a07be2b Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/84cc472a6483f21627993a0556927eb8.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/85fcf0dd5a1f01af3ca03a0556906f28.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/85fcf0dd5a1f01af3ca03a0556906f28.png new file mode 100644 index 0000000000..703f80f07d Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/85fcf0dd5a1f01af3ca03a0556906f28.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/b258d774491c8d28fcf33a055692d4e7.gif b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/b258d774491c8d28fcf33a055692d4e7.gif new file mode 100644 index 0000000000..645346abc6 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/b258d774491c8d28fcf33a055692d4e7.gif differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/b2ce491beab4168e936f3a055693d46b.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/b2ce491beab4168e936f3a055693d46b.png new file mode 100644 index 0000000000..7a510943ab Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/b2ce491beab4168e936f3a055693d46b.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/b6f8a1832a64ae3326743a0556911c4a.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/b6f8a1832a64ae3326743a0556911c4a.png new file mode 100644 index 0000000000..c742d208aa Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/b6f8a1832a64ae3326743a0556911c4a.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/bdc91213aacae19219cd3a0556920c43.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/bdc91213aacae19219cd3a0556920c43.png new file mode 100644 index 0000000000..ffb20ca798 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/bdc91213aacae19219cd3a0556920c43.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/e4bb2df32971fc6981553a0556933473.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/e4bb2df32971fc6981553a0556933473.png new file mode 100644 index 0000000000..46d4ce47e1 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/e4bb2df32971fc6981553a0556933473.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/f850b8fc54a9f9d23b333a0556936d26.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/f850b8fc54a9f9d23b333a0556936d26.png new file mode 100644 index 0000000000..0fbc244b04 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/f850b8fc54a9f9d23b333a0556936d26.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/fb3b7014926fa8ce6b5c3a05569304a6.png b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/fb3b7014926fa8ce6b5c3a05569304a6.png new file mode 100644 index 0000000000..44e5195e1f Binary files /dev/null and b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/fb3b7014926fa8ce6b5c3a05569304a6.png differ diff --git a/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/post.md b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/post.md new file mode 100644 index 0000000000..470a0c6c0d --- /dev/null +++ b/docs/en/Community-Articles/2022-07-28-abpio-platform-60-rc-has-been-published/post.md @@ -0,0 +1,333 @@ +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **6.0 RC** (release candidate). This blog post introduces the new features and important changes in this new version. + +> **The planned release date for the [6.0.0 Stable](https://github.com/abpframework/abp/milestone/71) version is September 26, 2022**. + +Try this version and provide feedback for the stable ABP v6.0! Thank you to all. + +## Get Started with the 6.0 RC + +Follow the steps below to try version 6.0.0 RC today: + +1) **Upgrade** the ABP CLI to version `6.0.0-rc.4` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 6.0.0-rc.4 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 6.0.0-rc.4 +```` + +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 *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. + +You can use any IDE that supports .NET 6.x, like **[Visual Studio 2022](https://visualstudio.microsoft.com/downloads/)**. + +## Migration Guides + +There are breaking changes in this version that may affect your application. +Please see the following migration documents, if you are upgrading from v5.3.0: + +* [ABP Framework 5.3 to 6.0 Migration Guide](https://docs.abp.io/en/abp/6.0/Migration-Guides/Abp-6_0) +* [ABP Commercial 5.3 to 6.0 Migration Guide](https://docs.abp.io/en/commercial/6.0/migration-guides/v6_0) + +## What's New with ABP Framework 6.0? + +In this section, I will introduce some major features released in this version. Here is a brief list of titles explained in the next sections: + +* **LeptonX Lite** is now the **default theme** for startup templates. +* Optional PWA support is added to [*Get Started*](https://abp.io/get-started) page. +* Introducing the **OpenIddict Module** and switching to OpenIddict for the startup templates. +* New **.NET MAUI** Startup Template. +* Introducing the `ITransientCachedServiceProvider` interface. +* Introducing the dynamic components for Blazor UI. +* Improvements in ABP CLI. +* Introducing the `Volo.Abp.RemoteServices` package. +* Create/Update user accounts for external logins. +* Sending test email in the setting page for MVC and Blazor user interfaces. +* Improvements on the **eShopOnAbp** project. +* Other news... + +### LeptonX Lite Theme on Startup Templates + +![leptonx-lite-theme.png](85fcf0dd5a1f01af3ca03a0556906f28.png) + +With this version, startup templates (`app` and `app-nolayers` templates) use the **LeptonX Lite** as the default theme. However, it's still possible to create a project with **Basic Theme** either using the **ABP CLI** or downloading the project via [*Get Started*](https://abp.io/get-started) page on the [abp.io](https://abp.io/) website. + +#### via ABP CLI + +To create a new project with **Basic Theme**, you can use the `--theme` option as below: + +```bash +abp new Acme.BookStore --theme basic --preview +``` + +#### via Get Started page + +Also, you can create a new project with **LeptonX Lite** or **Basic Theme** on *Get Started* page. + +![get-started-page.png](1117c53c9c54182c4a333a055690ac73.png) + +> The "Preview" checkbox should be checked to be able to see the theme selection section on the *Get Started* page. + + + +### Optional PWA Support is Added to the Get Started Page + +We've introduced the PWA (Progressive Web Application) support for the startup templates for Angular & Blazor WASM UIs in **v5.3**. In this version, we also added this PWA support to the [*Get Started*](https://abp.io/get-started) page on the [abp.io](https://abp.io/) website. + +![pwa-support-get-started-page.png](6987cdadeca846db8bb93a055690e15a.png) + +If you check the "Progressive Web Application" checkbox while creating an application, the all required configurations will be done for you and you will get the benefit of PWA features in your application. + + + +### Introducing the **OpenIddict Module** and Switching to OpenIddict in the Startup Templates + +We already [announced the plan of replacing the IdentityServer with OpenIddict](https://github.com/abpframework/abp/issues/11989). + +Therefore, we have created the `OpenIddict` module in this version and switched to **OpenIddict** in the startup templates. The ABP Framework uses this module to add **OAuth** features to the applications. We created documentation for the **OpenIddict Module**. + +- You can see the following document to **learn about the OpenIddict Module**: + [https://docs.abp.io/en/abp/6.0/Modules/OpenIddict](https://docs.abp.io/en/abp/6.0/Modules/OpenIddict) +- You can check out the following migration guide to learn **how to migrate to OpenIddict**: + [https://docs.abp.io/en/abp/6.0/Migration-Guides/IdentityServer_To_OpenIddict](https://docs.abp.io/en/abp/6.0/Migration-Guides/IdentityServer_To_OpenIddict) + +> We will continue to ship Identity Server packages for a while but in the long term, you may need to replace it, because Identity Server support ends at the end of 2022. Please see the [announcement](https://github.com/abpframework/abp/issues/11989) for more info. + +### New .NET MAUI Startup Template + +![maui-template.png](b6f8a1832a64ae3326743a0556911c4a.png) + +ABP Framework provides .NET MAUI startup templates with **v6.0.0**. You can create a new .NET MAUI project with the command below: + +```bash +abp new Acme.BookStore -t maui --preview +``` + + +### Introducing the `ITransientCachedServiceProvider` + +`ICachedServiceProvider` interface is used to resolve the cached services within a new scope. We created a new interface to resolve cached services **without creating scopes**. It's called `ITransientCachedServiceProvider`. The difference between `ICachedServiceProvider` and `ITransientCachedServiceProvider` is; `ITransientCachedServiceProvider` is transient. Check out [this issue](https://github.com/abpframework/abp/issues/12918) for more information. + + +### Introducing the dynamic layout components for Blazor UI + +ABP Framework provides different ways of customizing the UI and one of them is to use [Layout Hooks](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Layout-Hooks) in MVC. The **Layout Hook System** allows you to add code to some specific parts of the layout and all layouts of the themes provided by the ABP Framework implement these hooks. + +However, Blazor UI doesn't have such a system yet and we are planning to implement [Layout Hooks for the Blazor UI](https://github.com/abpframework/abp/issues/6261) in version 7.0. + +We are introducing the dynamic layout components for the Blazor UI to be able to add components to the Blazor layouts. + +You can configure the `AbpDynamicLayoutComponentOptions` to render your components in the layout, as below: + +```csharp +Configure(options => +{ + options.Components.Add(typeof(MyBlazorComponent), null); +}); +``` + +### Improvements in ABP CLI + +There are some enhancements in [ABP CLI](https://docs.abp.io/en/abp/6.0/CLI). You can see the brief list of some of these improvements below: + +* You can list all available templates by using the `abp list-templates` command with v6.0. See [#13083](https://github.com/abpframework/abp/pull/13083). +* You can select the theme when creating a new project by specifying the `--theme` option. You can see the *LeptonX Lite Theme on the Startup Templates* section above for an example. +* `abp update` command has been updating the version of the main application until now. With v6.0.0, this command updates all package versions **inside all solutions in the sub-folders**. Checkout the issue [#12735](https://github.com/abpframework/abp/pull/12738) for more information. + +### Introducing the `Volo.Abp.RemoteService` Package + +A new `Volo.Abp.RemoteService` package has been added to the framework. Some of the classes that are related to the remote service configurations such as `AbpRemoteServiceOptions` class moved from `Volo.Abp.Http.Client` to this package. In this way, it became more reusable for further usages. + +### Create/Update User Accounts For External Logins + +If a user authenticates from an external provider like `Keycloak`, the user is being redirected to this external provider, and comes back to the main application. In this process, the user's data is not being saved in the main application's database. With this version, ABP saves the user information and lists in the users page. And this fixes permission management, user information mismatches and other issues. For more info, see [the related issue](https://github.com/abpframework/abp/issues/12203). + + +### Sending test email on the setting page for MVC and Blazor UIs + +"Sending Test Email" feature is added to the [Setting Management](https://docs.abp.io/en/abp/6.0/Modules/Setting-Management) module, which allows checking the email settings are configured properly and sending emails successfully to the target email address. + +![setting-management-emailing.png](bdc91213aacae19219cd3a0556920c43.png) + +After configuring the email settings such as the target email address, you can click the "Send" button to send a test email to see if everything went well. + +> Note that this feature will be implemented for the Angular UI in the stable v6.0. + +### Improvements on eShopOnAbp Project + +The following improvements have been made on [eShopOnAbp project](https://github.com/abpframework/eShopOnAbp) with this version: + +* Some improvements have been made on the Admin Application for Order Management for Angular UI. See [#110](https://github.com/abpframework/eShopOnAbp/pull/110). +* `SignalR` error on Kubernetes & Docker Compose has been fixed. See [#113](https://github.com/abpframework/eShopOnAbp/pull/113). +* Configurations have been made for some services on the `docker-compose.yml` file. See [#112](https://github.com/abpframework/eShopOnAbp/pull/112). +* Gateway Redirect Loop problem on Kubernetes has been fixed. See [the commit](https://github.com/abpframework/eShopOnAbp/commit/6413ef15c91cd8a5309050b63bb4dbca23587607). + +### Other News + +* Autofac library has been upgraded to **v6.4.0**. Please see [#12816](https://github.com/abpframework/abp/pull/12816) for more info. +* Performance Improvements have been made in the **Settings Module** and tabs on the *Settings* page are lazy loading now. +* Some improvements have been made in the CMS Kit Module. You can see the improvements from [here](https://github.com/abpframework/abp/issues/11965). + +If you want to see more details, you can check [the release on GitHub](https://github.com/abpframework/abp/releases/tag/6.0.0-rc.1), which contains a list of all the issues and pull requests closed in this version. + +## What's New with ABP Commercial 6.0? + +### LeptonX Theme is the Default Theme + +With this version, the startup templates (`app-pro`, `app-nolayers-pro` and `microservice-pro` templates) use the **LeptonX Theme** as the default theme. However, it's still possible to create a new project with **Lepton Theme** or **Basic Theme**, either using the **ABP CLI** or **ABP Suite**. + +#### via ABP CLI + +To create a new project with **Lepton Theme** or **Basic Theme**, you can use the `--theme` option as below. For "Basic Theme" specify the theme name as `--theme basic`. + +```bash +abp new Acme.BookStore --theme lepton --preview +``` + + +#### via ABP Suite + +Also, you can create a new project with **Lepton Theme** or **Basic Theme** from ABP Suite. + +![suite-create-new-solution.png](84cc472a6483f21627993a0556927eb8.png) + +### Switching to OpenIddict in the Startup Templates + +We have also switched to the **OpenIddict** for the startup templates for ABP Commercial as explained above. + +### New .NET MAUI Mobile + +![maui-mobile-option.gif](b258d774491c8d28fcf33a055692d4e7.gif) + +ABP Commercial has been providing a [React Native](https://docs.abp.io/en/commercial/latest/getting-started-react-native) mobile app since with the very early versions. Alternative to this application, we created a new .NET MAUI mobile app. To create a new `app-pro` ABP project with the .NET MAUI mobile app, you can use the command below: + +```bash +abp new Acme.BookStore -t app-pro --mobile maui +``` + +> Note that, when Microsoft supports `WebAuthenticator` on Windows, we'll also support it to work on Windows OS. + +### GDPR: Cookie Consent + +![cookie-banner.png](fb3b7014926fa8ce6b5c3a05569304a6.png) + +With this version, the **Cookie Consent** feature has been added to the **GDPR** module. It's enabled by default for the new startup templates. There are two pages in the templates: "Cookie Policy" page and "Privacy Policy" page. + +If you want to disable/hide the "Cookie Consent", you can simply open the startup project module class and set the `IsEnabled` property as **false** for the **AddAbpCookieConsent** method as below: + +```csharp +context.Services.AddAbpCookieConsent(options => +{ + options.IsEnabled = false; //disabled + options.CookiePolicyUrl = "/CookiePolicy"; + options.PrivacyPolicyUrl = "/PrivacyPolicy"; +}); +``` + +> These pages are used to build up the cookie consent text and you can change the content or url of these pages by your needs. + +If you want to use the Cookie Consent feature of the GDPR module in your existing project, please see the [GDPR Module](https://docs.abp.io/en/commercial/6.0/modules/gdpr) documentation for configurations. + +### Improvements/Developments on CMS Kit Poll + +Some improvements have been made on the Poll System of CMS Kit module as listed below: + +* The Widget rendering and Admin side for the Blazor UI improvements. +* A Widget can be picked from the editor as seen in the image below. + +![poll-add-widget.png](e4bb2df32971fc6981553a0556933473.png) + +### Blazor UI for the Chat Module + +Chat Module is now also available for the Blazor UI after the MVC and Angular UIs. You can read the [Chat Module](https://docs.abp.io/en/commercial/6.0/modules/chat) documentation to get the overall knowledge about the module and add to your application. + +![blazor-chat-module-1.png](3c0c1c5334f762cf31143a0556935e7b.png) + +![blazor-chat-module-2.png](f850b8fc54a9f9d23b333a0556936d26.png) + +### Blazor Admin UI for CMS Kit Module + +All admin side **CMS Kit** and **CMS Kit Pro** features have been implemented for the Blazor UI. Blazor UI will only be available to ABP Commercial customers. + +![cms-blog-blazor.png](3a8ef4d97b96ae7af0e63a0556939ec5.png) + +![cms-blog-post-blazor.png](107a46b6a11909e76a493a055693b308.png) + +### Suite: Excel Export + +With v6.0, now it's possible to export the records as Excel for Blazor & MVC UIs. Angular UI is still in-progress, and we will implement it with the stable v6.0 release. Check the "Excel export" checkbox to add this feature. + +![excel-export.png](b2ce491beab4168e936f3a055693d46b.png) + +A new Excel Export button is being located at the top of the generated page as seen below: + +![export-excel-page.png](1ec02e85fdc0bbc18dad3a055693f4a9.png) + +Then, you can download the records as `.xlsx` format by clicking the "Excel Export" button. Note that the exported Excel list is the filtered list. + +### ABP Suite: Optional PWA Support + +With this version, it's possible to add the [PWA (Progressive Web App)](https://web.dev/progressive-web-apps/?gclid=Cj0KCQjwxIOXBhCrARIsAL1QFCY0IB-W5k-lsXmRCbm00sl4nyBIYynAX3IdJkjyizyNUjuCE8zeu24aApxtEALw_wcB) support for Blazor & Angular UIs while creating the application via Suite. + +![suite-pwa-support.png](20555333aa1878334f3f3a0556941a69.png) + +You just need to check the "Progressive web application" checkbox, when creating a new application. Then, ABP Suite will add the PWA support to your application. When you publish your application, you get the full benefits of PWA features such as offline support. + +### Other News + +#### Explainer Videos + +We are creating explainer videos for the ABP Commercial Modules to provide an overview. Within this milestone, we've created four new explainer videos: + +* [Audit Logging Module](https://www.youtube.com/watch?v=NzSuFBpqfsc) +* [Identity Module](https://www.youtube.com/watch?v=W87jA_GBE54) +* [SaaS Module](https://www.youtube.com/watch?v=xXlaaXP6qqQ) +* [Forms Module](https://www.youtube.com/watch?v=MousWEPfrA8) + +You can subscribe to [Volosoft's YouTube channel](https://www.youtube.com/channel/UCO3XKlpvq8CA5MQNVS6b3dQ) to be informed about future ABP events and videos. + +### Trial License is now available! + +![pricing-page.png](549f9e8744eb851795593a055694546b.png) + +If you are considering purchasing a new ABP Commercial license, and you want to see ABP in action then, check out https://commercial.abp.io/pricing and click the "**FREE TRIAL**" button. + +## Community News + +### New ABP Community Posts + +* [Alper Ebicoglu](https://twitter.com/alperebicoglu) has created a new community article to give a full overview of .NET MAUI. You can read it [here](https://community.abp.io/posts/all-about-.net-maui-gb4gkdg5). +* [Anto Subash](https://twitter.com/antosubash) has created a new video content to show "State Management in Blazor with Fluxor". You can read it [here](https://community.abp.io/posts/blazor-state-management-with-fluxor-raskpv19). +* [Learn ABP Framework](https://community.abp.io/members/learnabp) has also created a new video content to show "How to install LeptonX Lite Theme for ABP Framework 5.3 MVC UI". You can read it [here](https://community.abp.io/posts/how-to-install-leptonx-lite-theme-on-abp-framework-5.3-mvc-ui-epzng137). +* [Kirti Kulkarni](https://twitter.com/kirtimkulkarni) has created three new community articles. You can use the links below to read the articles: + * [Integrating the file management module with ABP Commercial application](https://community.abp.io/posts/integrating-the-file-management-module-with-abp-commercial-application-qd6v4dsr) + * [Work with PDF's in ABP Commercial Project using PDFTron](https://community.abp.io/posts/work-with-pdfs-in-abp-commercial-project-using-pdftron-tjw0hlgu) + * [Create a custom login page in ABP Commercial Angular app](https://community.abp.io/posts/create-a-custom-login-page-in-abp-commercial-angular-app-r2huidx7) +* [Don Boutwell](https://community.abp.io/members/dboutwell) has created his first ABP Community article. You can read it from [here](https://community.abp.io/posts/password-required-redis-with-abp-framework-and-docker-94old5rm). + +### Volosoft Has Attended the DNF Summit 2022 + +![dnf-summit.png](0212cca486b68bf476fe3a055694c57c.png) + +Core team members of ABP Framework, [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan) and [Alper Ebicoglu](https://twitter.com/alperebicoglu) have attended the [DNF Summit](https://t.co/ngWnBLiAn5) on the 20th of July. Halil Ibrahim Kalkan talked about the creation of the ABP Framework and Alper Ebicoglu showed how easy to create a project with ABP Framework within 15 minutes. + +Watch the DNF Summit session 👉 https://www.youtube.com/embed/VL0ewZ-0ruo + +![dnf-summit-attendees.jpg](7e18226b6f26818fdc453a055694d92b.jpg) + +## Conclusion + +This version comes with some features and enhancements to the existing features. You can see the [Road Map](https://docs.abp.io/en/abp/6.0/Road-Map) documentation to learn about the release schedule and planned features for the next releases. The planned release date for the [6.0.0 Stable](https://github.com/abpframework/abp/milestone/71) version is September 26, 2022. Please try the ABP v6.0 RC and provide feedback to us. + +Thanks for being a part of this community! \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-10-06-abpio-platform-60-final-has-been-released/048cddf521a29aaafbeb3a06cece21da.png b/docs/en/Community-Articles/2022-10-06-abpio-platform-60-final-has-been-released/048cddf521a29aaafbeb3a06cece21da.png new file mode 100644 index 0000000000..4e75f63a1e Binary files /dev/null and b/docs/en/Community-Articles/2022-10-06-abpio-platform-60-final-has-been-released/048cddf521a29aaafbeb3a06cece21da.png differ diff --git a/docs/en/Community-Articles/2022-10-06-abpio-platform-60-final-has-been-released/post.md b/docs/en/Community-Articles/2022-10-06-abpio-platform-60-final-has-been-released/post.md new file mode 100644 index 0000000000..db7dfd186f --- /dev/null +++ b/docs/en/Community-Articles/2022-10-06-abpio-platform-60-final-has-been-released/post.md @@ -0,0 +1,79 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 6.0 versions have been released today. + +## What's new with ABP 6.0? + +All the new features are explained in detail in the [6.0 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-6.0-RC-Has-Been-Published). See the [RC Blog Post](https://blog.abp.io/abp/ABP.IO-Platform-6.0-RC-Has-Been-Published) for all the features and enhancements. This is the stable version of 6.0. You can safely upgrade your existing solution or create a new production-level solution. + +## Getting started with 6.0 + +### Creating new solutions + +You can create a new solution with the ABP Framework version 6.0 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to upgrade an existing solution + +#### Install/Update the ABP CLI + +Firstly, install the ABP CLI or upgrade to the latest version. + +If you haven't installed it yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading existing solutions with the ABP Update command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP-related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration guides + +Check the following migration guides for the applications with version 5.3 that are upgrading to version 6.0: + +* [ABP Framework 5.3 to 6.0 Migration Guide](https://docs.abp.io/en/abp/6.0/Migration-Guides/Abp-6_0) +* [ABP Commercial 5.3 to 6.0 Migration Guide](https://docs.abp.io/en/commercial/6.0/migration-guides/v6_0) + +## Community news + +### New ABP community posts + +Here are some of the recent posts added to the [ABP Community](https://community.abp.io/): + +* [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan) has created two new community articles: + * [Consuming gRPC Services from Blazor WebAssembly Application Using gRPC-Web](https://community.abp.io/posts/consuming-grpc-services-from-blazor-webassembly-application-using-grpcweb-dqjry3rv) + * [Using gRPC with the ABP Framework](https://community.abp.io/posts/using-grpc-with-the-abp-framework-2dgaxzw3) +* [Malik Masis](https://twitter.com/malikmasis) also has created two new community articles: + * [Consuming HTTP APIs from a .NET Client Using ABP's Client Proxy System](https://community.abp.io/posts/consuming-http-apis-from-a-.net-client-using-abps-client-proxy-system-xriqarrm) + * [Using MassTransit via eShopOnAbp](https://community.abp.io/posts/using-masstransit-via-eshoponabp-8amok6h8) +* [Xeevis](https://community.abp.io/members/Xeevis) has created her/his first community article, that shows [Prerendering in Blazor WASM applications](https://community.abp.io/posts/prerendering-blazor-wasm-application-with-abp-6.x-2v8590g3). +* [Don Boutwell](https://community.abp.io/members/dboutwell) has created two new community articles: + * [Logging to Datadog from ABP framework](https://community.abp.io/posts/logging-to-datadog-from-abp-framework-fm4ozds4) + * [Configuring Multiple DbContexts in an ABP Framework Project](https://community.abp.io/posts/configuring-multiple-dbcontexts-in-an-abp-framework-project-uoz5is3o) +* [Kirti Kulkarni](https://twitter.com/kirtimkulkarni) has created a new community article: [Deploying ABP angular application to Azure and App Insights integration](https://community.abp.io/posts/deploying-abp-angular-application-to-azure-and-app-insights-integration-4jrhtp01) + +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. + +## ABP by numbers +We have worked for 22 weeks on the 6.0 release. During this time, we closed 589 GitHub issues and merged 601 pull requests. For the new features and bug fixes, we made 3421 GitHub commits. We published 321 NuGet and 49 NPM packages. 50 contributors took part in this release, and 19 are first-time contributors. Thanks to everyone taking part in this version. + +![image.png](048cddf521a29aaafbeb3a06cece21da.png) + +## About the next version + +The next feature version will be 7.0. It is planned to release the 7.0 RC (Release Candidate) on November 15 and the final version on December 13, 2022. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). + +Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/1.png b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/1.png new file mode 100644 index 0000000000..8e6a25600f Binary files /dev/null and b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/1.png differ diff --git a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/2.png b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/2.png new file mode 100644 index 0000000000..d758ca86cf Binary files /dev/null and b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/2.png differ diff --git a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/3.png b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/3.png new file mode 100644 index 0000000000..dcca72e932 Binary files /dev/null and b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/3.png differ diff --git a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/POST.md b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/POST.md index 8f45279b3d..e147058f67 100644 --- a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/POST.md +++ b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/POST.md @@ -2,17 +2,72 @@ ## ITokenExtensionGrant -Create a class that inherits `ITokenExtensionGrant`, and then register it with the framework. +Create a `MyTokenExtensionGrant` class that inherits `ITokenExtensionGrant`, and then register it with the framework. -In the `MyTokenExtensionGrant` class below we try to get the token details, The `ForbidResult` handles the failure case and `SignInResult` returns a new token response, You can pass more parameters to implement business checks. +```cs +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + //... + PreConfigure(builder => + { + builder.Configure(openIddictServerOptions => + { + openIddictServerOptions.GrantTypes.Add(MyTokenExtensionGrant.ExtensionGrantName); + }); + }); + //... +} + +public override void ConfigureServices(ServiceConfigurationContext context) +{ + //... + Configure(options => + { + options.Grants.Add(MyTokenExtensionGrant.ExtensionGrantName, new MyTokenExtensionGrant()); + }); + //... +} +``` + +## Generate a new token response + +In the `MyTokenExtensionGrant` class below we have two methods to get a new token using a user token or user API key. You can choose one of them based on your business. + +These methods are just examples. Please add more logic to validate input data. ```cs +using System.Collections.Immutable; +using System.Security.Principal; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using OpenIddict.Abstractions; +using OpenIddict.Server; +using OpenIddict.Server.AspNetCore; +using Volo.Abp.Identity; +using Volo.Abp.OpenIddict; +using Volo.Abp.OpenIddict.ExtensionGrantTypes; +using IdentityUser = Volo.Abp.Identity.IdentityUser; +using SignInResult = Microsoft.AspNetCore.Mvc.SignInResult; + +namespace OpenIddict.Demo.Server.ExtensionGrants; + public class MyTokenExtensionGrant : ITokenExtensionGrant { public const string ExtensionGrantName = "MyTokenExtensionGrant"; public string Name => ExtensionGrantName; + public async Task HandleAsync(ExtensionGrantContext context) + { + // You can get a new token using any of the following methods based on your business. + // They are just examples. You can implement your own logic here. + + return await HandleUserAccessTokenAsync(context); + return await HandleUserApiKeyAsync(context); + } + + public async Task HandleUserAccessTokenAsync(ExtensionGrantContext context) { var userToken = context.Request.GetParameter("token").ToString(); @@ -26,6 +81,9 @@ public class MyTokenExtensionGrant : ITokenExtensionGrant }!)); } + // We will validate the user token + // The Token is issued by the OpenIddict server, So we can validate it using the introspection endpoint + var transaction = await context.HttpContext.RequestServices.GetRequiredService().CreateTransactionAsync(); transaction.EndpointType = OpenIddictServerEndpointType.Introspection; transaction.Request = new OpenIddictRequest @@ -64,23 +122,92 @@ public class MyTokenExtensionGrant : ITokenExtensionGrant })); } + // We have validated the user token and got the user id + var userId = principal.FindUserId(); var userManager = context.HttpContext.RequestServices.GetRequiredService(); var user = await userManager.GetByIdAsync(userId.Value); var userClaimsPrincipalFactory = context.HttpContext.RequestServices.GetRequiredService>(); var claimsPrincipal = await userClaimsPrincipalFactory.CreateAsync(user); - claimsPrincipal.SetScopes(principal.GetScopes()); - claimsPrincipal.SetResources(await GetResourcesAsync(context, principal.GetScopes())); - //abp version < 7.3 - await context.HttpContext.RequestServices.GetRequiredService().SetAsync(claimsPrincipal); + // Prepare the scopes + var scopes = GetScopes(context); + + claimsPrincipal.SetScopes(scopes); + claimsPrincipal.SetResources(await GetResourcesAsync(context, scopes)); + await context.HttpContext.RequestServices.GetRequiredService().HandleAsync(context.Request, principal); + return new SignInResult(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, claimsPrincipal); + } - //For abp version >= 7.3 - await context.HttpContext.RequestServices.GetRequiredService().HandleAsync(context.Request, claimsPrincipal); + protected async Task HandleUserApiKeyAsync(ExtensionGrantContext context) + { + var userApiKey = context.Request.GetParameter("user_api_key").ToString(); + + if (string.IsNullOrEmpty(userApiKey)) + { + return new ForbidResult( + new[] {OpenIddictServerAspNetCoreDefaults.AuthenticationScheme}, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidRequest + }!)); + } + + // Here we can validate the user API key and get the user id + if (false) // Add your own logic here + { + // If the user API key is invalid + return new ForbidResult( + new[] {OpenIddictServerAspNetCoreDefaults.AuthenticationScheme}, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidRequest + }!)); + } + + // Add your own logic to get the user by API key + var userManager = context.HttpContext.RequestServices.GetRequiredService(); + var user = await userManager.FindByNameAsync("admin"); + if (user == null) + { + return new ForbidResult( + new[] {OpenIddictServerAspNetCoreDefaults.AuthenticationScheme}, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidRequest + }!)); + } + + // Create a principal for the user + var userClaimsPrincipalFactory = context.HttpContext.RequestServices.GetRequiredService>(); + var claimsPrincipal = await userClaimsPrincipalFactory.CreateAsync(user); + + // Prepare the scopes + var scopes = GetScopes(context); + + claimsPrincipal.SetScopes(scopes); + claimsPrincipal.SetResources(await GetResourcesAsync(context, scopes)); + await context.HttpContext.RequestServices.GetRequiredService().HandleAsync(context.Request, claimsPrincipal); return new SignInResult(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, claimsPrincipal); } + private ImmutableArray GetScopes(ExtensionGrantContext context) + { + // Prepare the scopes + // The scopes must be defined in the OpenIddict server + + // If you want to get the scopes from the request, you have to add `scope` parameter in the request + // scope: AbpAPI profile roles email phone offline_access + + //var scopes = context.Request.GetScopes(); + + // If you want to set the scopes here, you can use the following code + var scopes = new[] { "AbpAPI", "profile", "roles", "email", "phone", "offline_access" }.ToImmutableArray(); + + return scopes; + } + private async Task> GetResourcesAsync(ExtensionGrantContext context, ImmutableArray scopes) { var resources = new List(); @@ -98,38 +225,24 @@ public class MyTokenExtensionGrant : ITokenExtensionGrant } ``` -```cs -public override void PreConfigureServices(ServiceConfigurationContext context) -{ - //... - PreConfigure(builder => - { - builder.Configure(openIddictServerOptions => - { - openIddictServerOptions.GrantTypes.Add(MyTokenExtensionGrant.ExtensionGrantName); - }); - }); - //... -} +### Get a new token using user access token -public override void ConfigureServices(ServiceConfigurationContext context) -{ - //... - Configure(options => - { - options.Grants.Add(MyTokenExtensionGrant.ExtensionGrantName, new MyTokenExtensionGrant()); - }); - //... -} -``` +* Get a user token using the `password` grant type. +![Http request 1](1.png) -![Http request 1](postman1.png) +* Use the user token to get a new token using the `HandleUserAccessTokenAsync` method. -![Http request 2](postman2.png) +![Http request 2](2.png) -## Source code +### Get a new token using user API key + +* Directly get a new token using the `HandleUserApiKeyAsync` method. -https://github.com/abpframework/abp/commit/3210f138454697647689b4868c8d4b7b3da02d44 +![Http request 3](3.png) + +## Source code + +https://github.com/abpframework/abp/blob/dev/modules/openiddict/app/OpenIddict.Demo.Server/ExtensionGrants/MyTokenExtensionGrant.cs diff --git a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman1.png b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman1.png deleted file mode 100644 index e7ec1ccce0..0000000000 Binary files a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman1.png and /dev/null differ diff --git a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman2.png b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman2.png deleted file mode 100644 index b44e756ed5..0000000000 Binary files a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman2.png and /dev/null differ diff --git a/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/1686b2c9b7c4f24e825d3a07afe68750.png b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/1686b2c9b7c4f24e825d3a07afe68750.png new file mode 100644 index 0000000000..49ab9a97c1 Binary files /dev/null and b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/1686b2c9b7c4f24e825d3a07afe68750.png differ diff --git a/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/552094437245394af26b3a07afe7c07b.jpg b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/552094437245394af26b3a07afe7c07b.jpg new file mode 100644 index 0000000000..82179e3362 Binary files /dev/null and b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/552094437245394af26b3a07afe7c07b.jpg differ diff --git a/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/e3241810b6d9885128c03a07afe72f3a.gif b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/e3241810b6d9885128c03a07afe72f3a.gif new file mode 100644 index 0000000000..479b83ce2b Binary files /dev/null and b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/e3241810b6d9885128c03a07afe72f3a.gif differ diff --git a/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/f6372b06f40fa2da9d993a07afe78654.png b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/f6372b06f40fa2da9d993a07afe78654.png new file mode 100644 index 0000000000..c6c3134934 Binary files /dev/null and b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/f6372b06f40fa2da9d993a07afe78654.png differ diff --git a/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/post.md b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/post.md new file mode 100644 index 0000000000..cf3f6eaace --- /dev/null +++ b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/post.md @@ -0,0 +1,308 @@ +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **7.0 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.0! Thanks to all of you. + +## Get Started with the 7.0 RC + +Follow the steps below to try version 7.0.0 RC today: + +1) **Upgrade** the ABP CLI to version `7.0.0-rc.3` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 7.0.0-rc.3 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 7.0.0-rc.3 +```` + +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 for creating 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 breaking changes in this version that may affect your application. +Please see the following migration documents, if you are upgrading from v6.x: + +* [ABP Framework 6.x to 7.0 Migration Guide](https://docs.abp.io/en/abp/7.0/Migration-Guides/Abp-7_0) +* [ABP Commercial 6.x to 7.0 Migration Guide](https://docs.abp.io/en/commercial/7.0/migration-guides/v7_0) + +## What's New with ABP Framework 7.0? + +In this section, I will introduce some major features released in this version. Here is a brief list of titles explained in the next sections: + +* Upgraded to .NET 7.0 +* Upgraded to OpenIddict 4.0 +* Dapr Integration +* Integration Services +* Dynamic Permissions and Features +* External Localization Infrastructure +* Distributed Entity Cache Service +* Layout Hooks for the Blazor UI +* Improvements on the eShopOnAbp project + +### Upgraded to .NET 7.0 + +We've upgraded the ABP Framework to .NET 7.0, so you need to move your solutions to .NET 7.0 if you want to use ABP 7.0. + +> You can check the [Migrate from ASP.NET Core 6.0 to 7.0](https://learn.microsoft.com/en-us/aspnet/core/migration/60-70?view=aspnetcore-7.0) documentation. Also, there is an ABP Community article that shows how to upgrade an existing project to .NET 7.0. You can check it from 👉 [here](https://community.abp.io/posts/upgrade-your-existing-projects-to-.net7-nmx6vm9m). + +### Upgraded to OpenIddict 4.0 + +OpenIddict 4.0 preview has been released on June 22. So, we decided to upgrade the OpenIddict packages to 4.0-preview in ABP 7.0. + +Once the final release of OpenIddict 4.0 is published, we will immediately upgrade it to the stable version and we plan to make ABP 7.0 final use the stable version of OpenIddict 4.0. + +> You can read the "[OpenIddict 4.0 preview1 is out](https://kevinchalet.com/2022/06/22/openiddict-4-0-preview1-is-out/)" post to learn what's new with OpenIddict 4.0. + +### Dapr Integration + +[Dapr (Distributed Application Runtime)](https://dapr.io/) provides APIs that simplify microservice connectivity. + +ABP and Dapr have some intersecting features like service-to-service communication, distributed message bus and distributed locking. However, the purposes of ABP and Dapr are different. ABP's goal is to provide an end-to-end developer experience with an opinionated architecture. On the other hand, Dapr's purpose is to provide a runtime to decouple common microservice communication patterns from your application logic. + +ABP 7.0 offers some packages to provide better integration with Dapper. I will cover some important integration notes below but if you want to get a full overview of ABP Dapr Integration please see the [ABP Dapr Integration documentation](https://docs.abp.io/en/abp/7.0/Dapr/Index). + +#### Distributed Event Bus Integration + +ABP's [Distributed Event Bus System](https://docs.abp.io/en/abp/7.0/Distributed-Event-Bus) provides a convenient abstraction to allow applications to communicate asynchronously via events. + +The new [Volo.Abp.EventBus.Dapr](https://www.nuget.org/packages/Volo.Abp.EventBus.Dapr) and [Volo.Abp.AspNetCore.Mvc.Dapr.EventBus](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus) packages make it possible to use the Dapr infrastructure with the ABP's standard distributed event bus abstractions. The **Volo.Abp.EventBus.Dapr** package is used to publish events and the **Volo.Abp.AspNetCore.Mvc.Dapr.EventBus** package is used to subscribe to events. + +> See [the documentation](https://docs.abp.io/en/abp/7.0/Dapr/Index#distributed-event-bus-integration) to learn more. + +#### C# API Client Proxies Integration + +ABP can [dynamically](https://docs.abp.io/en/abp/7.0/API/Dynamic-CSharp-API-Clients) or [statically](https://docs.abp.io/en/abp/7.0/API/Static-CSharp-API-Clients) generate proxy classes to invoke your HTTP APIs from a Dotnet client application. + +The [Volo.Abp.Http.Client.Dapr](https://www.nuget.org/packages/Volo.Abp.Http.Client.Dapr) package configures the client-side proxy system, so it uses Dapr's service invocation building block for the communication between your applications. + +> See [the documentation](https://docs.abp.io/en/abp/7.0/Dapr/Index#c-api-client-proxies-integration) to learn more. + +#### Distributed Lock + +ABP provides a [Distributed Locking](https://docs.abp.io/en/abp/7.0/Distributed-Locking) abstraction to control access to a resource that's shared by multiple applications. Dapr also has a [distributed lock building block](https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/). + +The [Volo.Abp.DistributedLocking.Dapr](https://www.nuget.org/packages/Volo.Abp.DistributedLocking.Dapr) package makes ABP use Dapr's distributed locking system. + +> See [the documentation](https://docs.abp.io/en/abp/7.0/Dapr/Index#distributed-lock) to learn more. + +### Integration Services + +Integration services [was an idea](https://github.com/abpframework/abp/issues/12470) to distinguish the application services that are built for inter-module (or inter-microservice) communication from the application services that are intended to be consumed from a user interface or a client application. + +With ABP 7.0, now it is possible to mark an application service as an integration service using the `[IntegrationService]` attribute (that is defined in the `Volo.Abp.Application.Services` namespace). Example: + +````csharp +[IntegrationService] +public class ProductAppService : ApplicationService, IProductAppService +{ + // ... +} +```` + +If your application service has an interface, like `IProductService`, you can use it on the service interface: + +````csharp +[IntegrationService] +public interface IProductAppService : IApplicationService +{ + // ... +} +```` + +When you do that ABP takes the following actions by conventions: + +* If you use the [Auto API Controllers](https://docs.abp.io/en/abp/latest/API/Auto-API-Controllers) feature, the URL prefix will be `/integration-api/` instead of `/api/`. In this way, for example, you can prevent REST API calls to your integration services out of your API Gateway, in a microservice system, and don't authorize these services. You can also filter integration services (or non-integration services) while creating Auto API Controllers, using the `ApplicationServiceTypes` option of the `ConventionalControllerSetting` object. +* Calls made to integration services are not audit logged by default, because they are intended to be used by other services. You can set `IsEnabledForIntegrationServices` to `true` in `AbpAuditingOptions` [options class](https://docs.abp.io/en/abp/latest/Options) to enable audit logging for the integration services too. + +### Dynamic Permissions and Features + +In ABP Framework, [permissions](https://docs.abp.io/en/abp/latest/Authorization) and [features](https://docs.abp.io/en/abp/latest/Features) are defined in the codebase of your application. Because of that design, it was hard to define permissions (and features) in different microservices and centrally manage all the permissions (and features) in a single admin application. To make that possible, we were adding project references for all the microservices' service contract packages from a single microservice, so it can know all the permissions (and features) and manage them. As a result, that permission manager microservice needs to be re-deployed whenever a microservice's permissions change. + +With ABP 7.0, we've introduced the [dynamic permissions](https://github.com/abpframework/abp/pull/13644) and [dynamic features](https://github.com/abpframework/abp/pull/13881) systems. See the following figure: + +![dynamic-permissions.png](1686b2c9b7c4f24e825d3a07afe68750.png) + +Here, Microservice 1 defines the permissions A and B, Microservice 2 defines the permissions C, D, E. The Permission Management microservice is used by the permission management UI and manages all the permissions of a user in the application. + +Basically, in the solution with ABP 7.0, all microservices serialize their own permission definitions and write them into a shared database on their application startup (with a highly optimized algorithm). On the other hand, the permission management service can dynamically get these permission definitions from the database (it is also highly optimized to reduce database usage) and allow the UI to show and manage them for a user or role. + +We will update the authorization and features documentation in next days to state the configuration, while it mostly works automatically. + +> If you want to know why we made all these decisions and what problems we've solved, you can watch Halil İbrahim Kalkan's "[Authorization in a Distributed / Microservice System](https://www.youtube.com/watch?v=DVqvRZ0w-7g)" talk in .NET Conf 2022. + +### External Localization Infrastructure + +Localization was another problem in a microservice system, when each microservice try to define its own localization texts and you build a unified UI application. + +The PR [#13845](https://github.com/abpframework/abp/pull/13845) described what's done in details. Basically, you need to implement `IExternalLocalizationStore ` to get localizations of other services. However, since the open-source ABP Framework doesn't provide a module for dynamic localization, we haven't implemented that out of the box. We may implement it for open-source if we get a considerable request from the community (you can upvote [#13953](https://github.com/abpframework/abp/issues/13953)). + +We've implemented the external localization system in ABP Commercial's [Language Management module](https://commercial.abp.io/modules/Volo.LanguageManagement) and also applied it in the [microservice startup template](https://commercial.abp.io/startup-templates/microservice). See the ABP Commercial part of this blog post to know more. + +### Distributed Entity Cache Service + +ABP introduces a distributed entity cache service with v7.0. + +Assume that you have a `Product` entity (an [aggregate root](https://docs.abp.io/en/abp/latest/Entities) actually): + +````csharp +public class Product : AggregateRoot +{ + public string Name { get; set; } + public string Description { get; set; } + public float Price { get; set; } + public int StockCount { get; set; } +} +```` + +And you want to use caching for faster access to the products. You first should configure the [dependency injection](https://docs.abp.io/en/abp/latest/Dependency-Injection) to register the `IEntityCache` service, in the `ConfigureServices` method of your [module class](https://docs.abp.io/en/abp/latest/Module-Development-Basics): + +````csharp +context.Services.AddEntityCache(); +```` + +Now, you can inject the `IEntityCache` service whenever you need: + +````csharp +public class ProductAppService : ApplicationService +{ + private readonly IEntityCache _productCache; + + public ProductAppService(IEntityCache productCache) + { + _productCache = productCache; + } + + public async Task GetAsync(Guid id) + { + var product = await _productCache.GetAsync(id); + return ObjectMapper.Map(product); + } +} +```` + +*In this example, I assume that the [object mapping](https://docs.abp.io/en/abp/latest/Object-To-Object-Mapping) is configured to map from `Product` to `ProductDto`.* + +Here, We've directly cached the `Product` objects. In that case, the `Product` class must be serializable (because it is serialized to JSON when saving in the [distributed cache](https://docs.abp.io/en/abp/latest/Caching)). That may not be possible in some scenarios and you may want to use another class to store the cache data. For example, we may want to use the `ProductDto` class instead of the `Product` class for the cache object. In this case, change the dependency injection configuration as below: + +````csharp +context.Services.AddEntityCache(); +```` + +Then inject the `IEntityCache` service instead of the `IEntityCache` service. + +You can configure the cache duration by passing a `DistributedCacheEntryOptions` object to the `AddEntityCache` method: + +````csharp +context.Services.AddEntityCache( + new DistributedCacheEntryOptions + { + SlidingExpiration = TimeSpan.FromMinutes(30) + } +); +```` + +Default cache duration is 2 minutes with the `AbsoluteExpirationRelativeToNow` configuration. + +> Check [this PR](https://github.com/abpframework/abp/pull/14055) to see the implementation and additional notes. + +### Layout Hooks for Blazor UI + +The **Layout Hook System** allows you to add code to some specific parts of the layout and all layouts of the themes provided by the ABP Framework implement these hooks. + +This system was already implemented for MVC UI but not for Blazor UI. We announced in the previous blog post ([ABP 6.0 Release Candidate blog post](https://blog.abp.io/abp/ABP.IO-Platform-6.0-RC-Has-Been-Published)) that we were planning to implement it in version 7.0. And now, we are introducing the Layout Hook System for Blazor UI as planned within this version. + +> You can read the [Blazor UI: Layout Hooks](https://docs.abp.io/en/abp/7.0/UI/Blazor/Layout-Hooks) documentation if you want to use the Layout Hooks in your Blazor application and see the required configurations. + +### Improvements on eShopOnAbp + +The following improvements have been made on the [eShopOnAbp project](https://github.com/abpframework/eShopOnAbp) within this version: + +* We've integrated [Keycloak](https://www.keycloak.org/) (an open-source identity and access management system) as the authentication server instead of the built-in authentication server (that was based on IdentityServer). See [#12021](https://github.com/abpframework/abp/issues/12021) for more information. +* The product detail page now uses CMS Kit's [Rating](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Ratings) and [Comment](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Comments) features. See [#11429](https://github.com/abpframework/abp/issues/11429) for more info. + +### Other News + +* ABP 7.0 introduces the `AbpDistributedLockOptions` for the main options class to configure the distributed locking. You can specify any name as the lock prefix by configuring the `AbpDistributedLockOptions`. See the [documentation](https://docs.abp.io/en/abp/7.0/Distributed-Locking#abpdistributedlockoptions) for more. + +## What's New with ABP Commercial 7.0? + +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.0. + +### Microservice Solution Architectural Improvements + +We've worked on the [microservice startup solution](https://commercial.abp.io/startup-templates/microservice) to make it proper for more advanced scenarios and better service independencies. As a result, all the services are made independently deployable and flexible to define its own permissions, features and localization texts. + +For the permissions and features part, we've applied ABP's new dynamic permission and feature systems that are explained above. For the localization texts, we'd implemented ABP's new external localization infrastructure (that was also explained above) in the [Language Management Module](https://commercial.abp.io/modules/Volo.LanguageManagement). + +If you want to build a new microservice solution with ABP 7.0, all these are pre-configured for you. Just create a new solution and focus on your own business code! You can also migrate your existing microservice solutions to take advantage of these new enhancements. You can follow [this guide](https://docs.abp.io/en/abp/latest/Migration-Guides/Upgrading-Startup-Template) as a good way to see the changes you need to apply in your solutions. + +### Set the Tenant Admin's Password from Host + +![tenant-admin-password.gif](e3241810b6d9885128c03a07afe72f3a.gif) + +ABP Commercial's [SaaS module](https://commercial.abp.io/modules/Volo.Saas) now allows setting the tenant admin's password from the host side. You can set a new password to any tenant admin's password from the Tenants page if you are a host user of the system. + +### WeChat and Alipay Integrations for the Payment Module + +![payment-gateway-1.png](f6372b06f40fa2da9d993a07afe78654.png) + +In this version, WeChat Pay and Alipay gateways have been added to the payment module. You can read the [Payment Module documentation](https://docs.abp.io/en/commercial/7.0/modules/payment#alipayoptions) for configurations and more information. + +### Others + +* [CMS Kit (Pro) Module](https://commercial.abp.io/modules/Volo.CmsKit.Pro): Contact Feature allows multiple (named) contact forms with this version. Now, you can add different contact forms on different pages (with different settings). +* [Saas Module](https://commercial.abp.io/modules/Volo.Saas): Allows host users to test the connection string of a tenant database on the UI. +* [Chat Module](https://commercial.abp.io/modules/Volo.Chat): Introduces permission for searching other users. + + +## Community News + +### New ABP Community Posts + +* [gdlcf88](https://github.com/gdlcf88) has created two new community articles: + * [Use Stepping To Perform Atomic Multi-Step Operations](https://community.abp.io/posts/use-stepping-to-perform-atomic-multistep-operations-4kqu8ewp) + * [Notice and Solve ABP Distributed Events Disordering](https://community.abp.io/posts/notice-and-solve-abp-distributed-events-disordering-yi9vq3p4) +* [GDUnit](https://community.abp.io/members/GDUnit) has created his first ABP community article that shows multi-tenant subdomain resolution in Blazor applications. You can read it 👉 [here](https://community.abp.io/posts/abp-blazor-multitenant-subdomain-resolution-c1x4un8x). +* [EngincanV](https://twitter.com/EngincanVeske) has created two new community articles: + * [Testing in ABP Framework (with examples)](https://community.abp.io/posts/testing-in-abp-framework-with-examples-3w29v6ce) + * [What's new with .NET 7?](https://community.abp.io/posts/whats-new-with-.net-7-tlq2g43w) +* [Alper Ebicoglu](https://twitter.com/alperebicoglu) has created a new community article to show "How to upgrade an existing project to .NET7". You can read it 👉 [here](https://community.abp.io/posts/upgrade-your-existing-projects-to-.net7-nmx6vm9m). +* [Kirti Kulkarni](https://community.abp.io/members/kirtik) has created a new community article to show "How to integrate and enable the Chat Module in an ABP Commercial application". You can read it 👉 [here](https://community.abp.io/posts/integrating-and-enabling-the-chat-module-in-abp-commercial-vsci3ov2). +* [maliming](https://github.com/maliming) has created a new community article to show "how to add custom grant type in OpenIddict". You can read it 👉 [here](https://community.abp.io/posts/how-to-add-a-custom-grant-type-in-openiddict.-6v0df94z). + +We thank you all. We thank all the authors for contributing to the [ABP Community platform](https://community.abp.io/). + +### We were in the .NET Conf 2022 + +![dotnef-conf-2022.jpg](552094437245394af26b3a07afe7c07b.jpg) + +Microsoft has released .NET 7.0 and celebrated it with a 3-days international online conference. Halil İbrahim Kalkan, the lead developer of ABP Framework attended [.NET Conf 2022](https://www.dotnetconf.net/) on November 10, 2022. His topic was "Authorization in a Distributed / Microservice System". In this talk, he talked about permission-based authorization systems and their challenges in a distributed system. Then, gave solutions that are implemented in the open source ABP Framework. + +You can watch his speech from 👉 [here](https://www.youtube.com/watch?v=DVqvRZ0w-7g). + +### Community Talks 2022.9: .NET 7.0 & ABP 7.0 + +![](streamyard.png) + +In this episode of ABP Community Talks, 2022.9; we'll talk about .NET 7.0 and ABP 7.0 with the ABP Core Team. We will dive into the features that came with .NET 7.0, how they are implemented in ABP 7.0, and the highlights in the .NET Conf 2022 with [Halil İbrahim Kalkan](https://github.com/hikalkan), [Alper Ebicoglu](https://github.com/ebicoglu), [Engincan Veske](https://github.com/EngincanV), [Hamza Albreem](https://github.com/braim23) and [Bige Besikci Yaman](https://github.com/bigebesikci). + +> Register to listen and ask your questions now 👉 https://kommunity.com/volosoft/events/abp-community-20229-net-70-abp-70-f9e8fb72 . + +## 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.0/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try the ABP v7.0 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/streamyard.png b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/streamyard.png new file mode 100644 index 0000000000..fe7b5e3e3a Binary files /dev/null and b/docs/en/Community-Articles/2022-11-22-abpio-platform-70-rc-has-been-published/streamyard.png differ diff --git a/docs/en/Community-Articles/2023-01-02-abpio-is-sponsoring-ndc-london-2023/post.md b/docs/en/Community-Articles/2023-01-02-abpio-is-sponsoring-ndc-london-2023/post.md new file mode 100644 index 0000000000..4202855593 --- /dev/null +++ b/docs/en/Community-Articles/2023-01-02-abpio-is-sponsoring-ndc-london-2023/post.md @@ -0,0 +1,13 @@ +ABP.IO is excited to announce that we will be sponsoring [NDC London 2023](https://ndclondon.com/) for the fourth time! It is thrilling to support the software development community in London. + +NDC London is a conference for software developers that covers a wide range of topics in the software development industry and brings together experts from around the world to share their knowledge and insights on the latest technologies and best practices in the industry. It is organized by NDC Conferences, a company that produces a number of software development conferences around the world. + +We are proud to sponsor this event and to support the software development community. We believe that conferences like NDC London are an important opportunity for developers to learn, network, and stay up-to-date on the latest trends in the field. + +As always, we have some special surprises for attendees at our booth on the 3rd floor of the Queen Elizabeth II Centre. Be sure to stop by to pick up one of our exclusive swag kits and enter our raffle for a chance to win Meta Quest 2. + +As [ABP.IO](https://abp.io/) Team, we are looking forward to participating in NDC London 2023 and connecting with other professionals in the software development industry. Stay tuned for more updates on our involvement in the conference. We believe that conferences like NDC London are an important opportunity for developers to learn, network, and stay up-to-date on the latest trends in the field. + +If you're interested in learning more about Volosoft and our software development services, or if you want to find out more about our SaaS product, [ABP Commercial](https://commercial.abp.io/), which is based on our [ABP Framework](https://github.com/abpframework/abp), be sure to visit us at our booth. We would be happy to discuss your software development needs and how we can help. + +We hope to see you at NDC London 2023! \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-01-05-abpio-platform-70-final-has-been-released/post.md b/docs/en/Community-Articles/2023-01-05-abpio-platform-70-final-has-been-released/post.md new file mode 100644 index 0000000000..a3619fdc80 --- /dev/null +++ b/docs/en/Community-Articles/2023-01-05-abpio-platform-70-final-has-been-released/post.md @@ -0,0 +1,73 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 7.0 versions have been released today. + +## What's New With 7.0? + +Since all the new features are already explained in detail in the [7.0 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-7.0-RC-Has-Been-Published), I will not repeat all the details again. See the [RC Blog Post](https://blog.abp.io/abp/ABP.IO-Platform-7.0-RC-Has-Been-Published) for all the features and enhancements. + +## Getting Started with 7.0 + +### Creating New Solutions + +You can create a new solution with the ABP Framework version 7.0 by either using the `abp new` command or generating the CLI command on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to Upgrade an Existing Solution + +#### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed it yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading Existing Solutions with the ABP Update Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guides + +There are breaking changes in this version that may affect your application. Please see the following migration documents, if you are upgrading from v6.x: + +* [ABP Framework 6.x to 7.0 Migration Guide](https://docs.abp.io/en/abp/7.0/Migration-Guides/Abp-7_0) +* [ABP Commercial 6.x to 7.0 Migration Guide](https://docs.abp.io/en/commercial/7.0/migration-guides/v7_0) + +## Community News + +### Highlights from .NET 7.0? + +Our team has closely followed the ASP.NET Core and Entity Framework Core 7.0 releases, read Microsoft's guides and documentation and adapt the changes to our ABP.IO Platform. We are proud to say that we've shipped the ABP 7.0 RC.1 based on .NET 7.0 just after Microsoft's .NET 7.0 release. + +In addition to the ABP's .NET 7.0 upgrade, our team has created 13 great articles to highlight the important features coming with ASP.NET Core 7.0 and Entity Framework Core 7.0. + +> You can read [this post](https://volosoft.com/Blog/Highlights-for-ASP.NET-Entity-Framework-Core-NET-7.0) to see the list of all articles. + +### New ABP Community Posts + +In addition to [the 13 articles to highlight .NET 7.0 features written by our team](https://volosoft.com/Blog/Highlights-for-ASP.NET-Entity-Framework-Core-NET-7.0), here are some of the recent posts added to the [ABP Community](https://community.abp.io/): + +* [liangshiwei](https://github.com/realLiangshiwei) has created a new community article, that shows [How to Use the Weixin Authentication for MVC / Razor Page Applications](https://community.abp.io/posts/how-to-use-the-weixin-authentication-for-mvc-razor-page-applications-a33e0wti). +* [Jasen Fici](https://community.abp.io/posts/deploying-abp.io-to-an-azure-appservice-ma8kukdp) has created a new article: [Deploying abp.io to an Azure AppService](https://community.abp.io/posts/deploying-abp.io-to-an-azure-appservice-ma8kukdp). + +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. + +## About the Next Version + +The next feature version will be 7.1. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). + +Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-01-19-abp-commercial-is-application-development-category-leader-of-2022/post.md b/docs/en/Community-Articles/2023-01-19-abp-commercial-is-application-development-category-leader-of-2022/post.md new file mode 100644 index 0000000000..d139a8fca4 --- /dev/null +++ b/docs/en/Community-Articles/2023-01-19-abp-commercial-is-application-development-category-leader-of-2022/post.md @@ -0,0 +1,33 @@ +

We are excited to announce that ABP Commercial on GetApp has been selected as one of the Application Development Category Leader in 2022!

+ + +

The Category Leaders program is intended to help businesses find the best software products in various categories to meet their needs, by providing an objective and unbiased ranking of products based on user reviews and other data.

+ +

GetApp's Category Leaders program ranks software products based on ratings from users in five key areas: ease of use, value for money, functionality, customer support, and likelihood to recommend.

+ +

For Application Development Category, GetApp evaluated 368 products and ABP Commercial entered to the 2022 GetApp Application Development Category Leaders' list from the 12th order in the first 15 high-scorer products, a.k.a. Category Leaders.

+ +

We are proud that ABP Commercial has been recognized as one of the top-ranked product in Application Development category, thanks to the high ratings it has received from users.

+ +

By being selected as a Category Leader, ABP Commercial has demonstrated a high level of satisfaction among its users and a strong performance in the key areas that matter most to businesses.

+ + + +
    Here are ABP Commercial's user rankings: +
  • Ease of use: 16 out of 20
  • +
  • Value for money: 16 out of 20
  • +
  • Functionality: 17 out of 20
  • +
  • Customer support: 16 out of 20
  • +
  • Likelihood to recommend: 16 out of 20
  • +
  • In total: 82 out of 100
  • +
+ +

If you are in the market for business software, we encourage you to check out the Front Runner list and give ABP Commercial a try. We are confident that you will be satisfied with our product and the support we provide.

+

You could also leave ABP Commercial a review to help us understand your experience.

+ +

We would like to thank all of our customers and users for their support and feedback, which have helped us achieve this recognition.

+ +

We will continue to strive for excellence and provide the best possible products and services to our users.

+ + +

Please see the other recognition we got from Software Advice as 2022 Application Development Category Front Runner.

diff --git a/docs/en/Community-Articles/2023-01-19-abp-commercial-is-application-development-front-runner-of-2022/post.md b/docs/en/Community-Articles/2023-01-19-abp-commercial-is-application-development-front-runner-of-2022/post.md new file mode 100644 index 0000000000..2cf0b1b539 --- /dev/null +++ b/docs/en/Community-Articles/2023-01-19-abp-commercial-is-application-development-front-runner-of-2022/post.md @@ -0,0 +1,21 @@ +

Attention all business software buyers! We are excited to announce that ABP Commercial on Software Advice has been selected as a Front Runner on App Development Software category.

+ +

For those unfamiliar with Software Advice, the company is a leading provider of software reviews that helps organizations find the right software for their needs by providing comparisons according to reviews of various business software products.

+ +

The Front Runner list is a ranking of software products based on their performance in a specific market segment, as determined by Software Advice according to the reviews left for those products.

+ +

To be considered for inclusion on the Front Runner list, a software product must meet certain criteria.

+
    The scores for each software product are divided in 2 main categories: +
  • Usability(x-axis) is calculated according to a weighted average of functionality(50%) and ease of use(50%).
  • +
  • Customer Satisfaction(y-axis) is calculated according to a weighted average of value for money(25%), likelihood to recommend(25%), customer support(50%).
  • +
+

You can see the graph for Software Advice App Development Category Front Runners in 2022 and locate ABP Commercial in there!

+ +

We are thrilled to being selected as one of the App Development Software Category's Front Runner and are proud of the high ratings we have received from users.

+

If you are in the market for business software, we encourage you to check out the Front Runner list and give ABP Commercial a try. We are confident that you will be satisfied with our product and the support we provide.

+

You could also leave ABP Commercial a review to help us understand your experience.

+ +

Thank to all of our users for this recognition. We look forward to continuing to provide top-notch software and support to businesses everywhere.

+ + +

Please see the other recognition we got from GetApp as 2022 Application Development Category Leader.

diff --git a/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/75da2f04db562e7a26de3a0947c1bb92.png b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/75da2f04db562e7a26de3a0947c1bb92.png new file mode 100644 index 0000000000..3dfd62fb94 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/75da2f04db562e7a26de3a0947c1bb92.png differ diff --git a/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/997466650163fa5699e43a0947c1a535.png b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/997466650163fa5699e43a0947c1a535.png new file mode 100644 index 0000000000..30a9d70cea Binary files /dev/null and b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/997466650163fa5699e43a0947c1a535.png differ diff --git a/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/b6f3ecc5835632eb71613a0947c17a0e.png b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/b6f3ecc5835632eb71613a0947c17a0e.png new file mode 100644 index 0000000000..7ea566207b Binary files /dev/null and b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/b6f3ecc5835632eb71613a0947c17a0e.png differ diff --git a/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/e4acbb4e2ecce17e64203a0947c1e78b.png b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/e4acbb4e2ecce17e64203a0947c1e78b.png new file mode 100644 index 0000000000..cddf3d01b8 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/e4acbb4e2ecce17e64203a0947c1e78b.png differ diff --git a/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/linkedin-twitter-new-dat.png b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/linkedin-twitter-new-dat.png new file mode 100644 index 0000000000..b95adaebff Binary files /dev/null and b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/linkedin-twitter-new-dat.png differ diff --git a/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/post.md b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/post.md new file mode 100644 index 0000000000..5b8e73548f --- /dev/null +++ b/docs/en/Community-Articles/2023-02-09-abpio-platform-71-rc-has-been-published/post.md @@ -0,0 +1,211 @@ +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **7.1 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.1! Thanks to all of you. + +## Get Started with the 7.1 RC + +Follow the steps below to try version 7.1.0 RC today: + +1) **Upgrade** the ABP CLI to version `7.1.0-rc.1` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 7.1.0-rc.1 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 7.1.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 Guide + +This version comes with a breaking change, so please see the following migration guide if you are upgrading from v7.0: + +* [ABP Framework 7.0 to 7.1 Migration Guide](https://docs.abp.io/en/abp/7.1/Migration-Guides/Abp-7_1) + +> **Note**: Entity Framework developers may need to add a new code-first database migration to their projects since we made some improvements to the existing entities of some application modules. + +## What's New with ABP Framework 7.1? + +In this section, I will introduce some major features released in this version. In addition to these features, so many enhancements have been made in this version too. + +Here is a brief list of the titles explained in the next sections: + +* Blazor WASM option added to Application Single Layer Startup Template +* Introducing the `IHasEntityVersion` interface and `EntitySynchronizer` base class +* Introducing the `DeleteDirectAsync` method for the `IRepository` interface +* Introducing the `IAbpHostEnvironment` interface +* Improvements on the eShopOnAbp project +* Others + +### Blazor WASM option added to Application Single Layer Startup Template + +We've created the [Application (Single Layer) Startup Template](https://docs.abp.io/en/abp/7.1/Startup-Templates/Application-Single-Layer) in v5.2 with three UI types: Angular, Blazor Server, and MVC. At the moment, we didn't provide a UI option for Blazor, because it required 3 projects at least (server-side, client-side, and shared library between these two projects). + +In this version, we've added the Blazor WASM option to the **Application (Single Layer) Startup Template**. It still contains three projects (`blazor`, `host`, and `contracts`) but hosted by a single `host` project. + +You can use the following CLI command to create an `app-nolayers` template with the Blazor UI as the UI option: + +```bash +abp new TodoApp -t app-nolayers -u blazor --version 7.1.0-rc.1 +``` + +> You can check the [Quick Start documentation](https://docs.abp.io/en/abp/7.1/Tutorials/Todo/Single-Layer/Index?UI=Blazor&DB=EF) for a quick start with this template. + +### Introducing the `IHasEntityVersion` interface and `EntitySynchronizer` base class + +Entity synchronization is an important concept, especially in distributed applications and module development. If we have an entity that is related to other modules, we need to align/sync their data once the entity changes and versioning entity changes can also be good, so we can know whether they're synced or not. + +In this version, [@gdlcf88](https://github.com/gdlcf88) made a great contribution to the ABP Framework and introduced the `IHasEntityVersion` interface which adds **auto-versioning** to entity classes and `EntitySynchronizer` base class to **automatically sync an entity's properties from a source entity**. + +You can check the issue and documentation from the following links for more info: + +- [Issue: Entity synchronizers and a new EntityVersion audit property](https://github.com/abpframework/abp/issues/14196) +- [Versioning Entities](https://docs.abp.io/en/abp/7.1/Entities#versioning-entities) +- [Distributed Event Bus - Entity Synchronizer](https://docs.abp.io/en/abp/7.1/Distributed-Event-Bus#entity-synchronizer) + +> Note: The entities of some modules from the ABP Framework have implemented the `IHasEntityVersion` interface. Therefore, if you are upgrading your application from an earlier version, you need to create a new migration and apply it to your database. + +### Introducing the `DeleteDirectAsync` method for the `IRepository` interface + +EF 7 introduced a new [`ExecuteDeleteAsync`](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/whatsnew#executeupdate-and-executedelete-bulk-updates) method that deletes entities without involving the change tracker into the process. Therefore, it's much faster. + +We've added the `DeleteDirectAsync` method to the `IRepository<>` interface to take the full power of EF 7. It deletes all entities that fit the given predicate. It directly deletes entities from the database, without fetching them. Therefore, some features (like **soft-delete**, **multi-tenancy**, and **audit logging)** won't work, so use this method carefully when you need it. And use the `DeleteAsync` method if you need those features. + +### Introducing the `IAbpHostEnvironment` interface + +Sometimes, while creating an application, we need to get the current hosting environment and take actions according to that. In such cases, we can use some services such as [IWebHostEnvironment](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.iwebhostenvironment?view=aspnetcore-7.0) or [IWebAssemblyHostEnvironment](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.webassembly.hosting.iwebassemblyhostenvironment) provided by .NET, in the final application. + +However, we can not use these services in a class library, which is used by the final application. ABP Framework provides the `IAbpHostEnvironment` service, which allows you to get the current environment name whenever you want. `IAbpHostEnvironment` is used by the ABP Framework in several places to perform specific actions by the environment. For example, ABP Framework reduces the cache duration on the **Development** environment for some services. + +**Usage:** + +```csharp +public class MyService +{ + private readonly IAbpHostEnvironment _abpHostEnvironment; + + public MyService(IAbpHostEnvironment abpHostEnvironment) + { + _abpHostEnvironment = abpHostEnvironment; + } + + public void MyMethod() + { + //getting the current environment name + var environmentName = _abpHostEnvironment.EnvironmentName; + + //check for the current environment + if (_abpHostEnvironment.IsDevelopment()) { /* ... */ } + } +} +``` + +You can inject the `IAbpHostEnvironment` into your service and get the current environment by using its `EnvironmentName` property. You can also check the current environment by using its extension methods such as `IsDevelopment()`. + +> Check the [ABP Application Startup](https://docs.abp.io/en/abp/7.1/Application-Startup) documentation for more information. + +### Improvements on the eShopOnAbp project + +K8s and Docker configurations have been made within this version (Dockerfiles and helm-charts have been added and image build scripts have been updated). See [#14083](https://github.com/abpframework/abp/issues/14083) for more information. + +### Others + +* Referral Links have been added to the CMS Kit Comment Feature (optional). You can specify common referral links (such as "nofollow" and "noreferrer") for links in the comments. See [#15458](https://github.com/abpframework/abp/issues/15458) for more information. +* ReCaptcha verification has been added to the CMS Kit Comment Feature (optional). You can enable ReCaptcha support to enable protection against bots. See the [documentation](https://docs.abp.io/en/abp/7.1/Modules/Cms-Kit/Comments) for more information. +* In the development environment, it is a must to reduce cache durations for some points. We typically don't have to invalidate the cache manually or wait on it for a certain time to be invalidated. For that purpose, we have reduced the cache durations for some points on the development environment. See [#14842](https://github.com/abpframework/abp/pull/14842) for more information. + +## What's New with ABP Commercial 7.1? + +We've also worked on [ABP Commercial](https://commercial.abp.io/) to align the new features and changes made in the ABP Framework. The following sections introduce a few new features coming with ABP Commercial 7.1. + +### Blazor WASM option added to Application Single Layer Pro Startup Template + +The [**Application (Single Layer) Startup Template**](https://docs.abp.io/en/commercial/latest/startup-templates/application-single-layer/index) with Blazor UI is also available for ABP Commercial customers with this version as explained above. + +You can use the following CLI command to create an `app-nolayers-pro` template with Blazor UI as the UI option: + +```bash +abp new TodoApp -t app-nolayers-pro -u blazor --version 7.1.0-rc.1 +``` + +You can also create an `app-nolayers-pro` template with Blazor UI via ABP Suite: + +![suite-blazor-wasm-nolayers.png](b6f3ecc5835632eb71613a0947c17a0e.png) + +### Suite - MAUI Blazor Code Generation + +We provided a new UI option "MAUI Blazor" for the `app-pro` template in the previous version and it's possible to create a `maui-blazor` application with both ABP CLI and ABP Suite. + +You can create an `app-pro` template with the MAUI Blazor as the UI option with the following ABP CLI command: + +```bash +abp new Acme.BookStore -t app-pro -u maui-blazor +``` + +In this version, we implemented the code generation for MAUI Blazor. You can create and generate CRUD pages for this new UI option as you do in other UI types. + +> Note: MAUI Blazor is currently only available with the `app-pro` template. + +### SaaS Module - Allowing entering a username while impersonating the tenant + +In the previous versions, we were able to impersonate a tenant from the [SaaS Module's Tenant Management UI](https://docs.abp.io/en/commercial/7.1/modules/saas#tenant-management). There was a constraint in this approach, which forced us to only impersonate the "admin" user. However, the tenant might change the admin user's username, or we may want to impersonate another user of the tenant. + +Thus, with this version, we decided to allow the impersonation of the tenant by the specified username. + +*You can click on the "Login with this tenant" action button:* + +![saas-impersonation-1.png](997466650163fa5699e43a0947c1a535.png) + +*Then, Specify the admin name of the tenant:* + +![saas-impersonation-2.png](75da2f04db562e7a26de3a0947c1bb92.png) + +## Community News + +### New ABP Community Posts + +* [Sergei Gorlovetsky](https://community.abp.io/members/Sergei.Gorlovetsky) has created two new community articles: + * [Why ABP Framework is one of the best tools for migration from legacy MS Access systems to latest Web app](https://community.abp.io/posts/why-abp-framework-is-one-of-the-best-tools-for-migration-from-legacy-ms-access-systems-to-latest-web-app-7l39eof0) + * [ABP Framework — 5 steps Go No Go Decision Tree](https://community.abp.io/posts/abp-framework-5-steps-go-no-go-decision-tree-2sy6r2st) +* [Onur Pıçakcı](https://github.com/onurpicakci) has created his first ABP community article that explains how to contribute to ABP Framework. You can read it 👉 [here](https://community.abp.io/posts/how-to-contribute-to-abp-framework-46dvzzvj). +* [Maliming](https://github.com/maliming) has created a new community article to show how to convert create/edit modals to a page. You can read it 👉 [here](https://community.abp.io/posts/converting-createedit-modal-to-page-4ps5v60m). + +We thank you all. We thank all the authors for contributing to the [ABP Community platform](https://community.abp.io/). + +### Volosoft Attended NDC London 2023 + +![ndc-london.png](e4acbb4e2ecce17e64203a0947c1e78b.png) + +Core team members of the ABP Framework, [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan) and [Alper Ebicoglu](https://twitter.com/alperebicoglu) attended [NDC London 2023](https://ndclondon.com/) from the 23rd to the 27th of January. + +> You can check [this post](https://volosoft.com/blog/What%E2%80%99s-NEW-in-NDC-London-2023) to see our takeaways from the **NDC London 2023**. + +### Community Talks 2023.1: LeptonX Customization + +![image](linkedin-twitter-new-dat.png) + +In this episode of ABP Community Talks, 2023.1; we'll talk about **LeptonX Customization**. We will dive into the details and show you how to customize the [LeptonX Theme](https://leptontheme.com/) with examples. + +The event will be live on Thursday, February 28, 2023 (17:00 UTC). + +> Register to listen and ask your questions now 👉 https://kommunity.com/volosoft/events/abp-community-talks-20231-leptonx-customization-03f9fd8c. + +## 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.1/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try the ABP v7.1 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096135937d3f2a596c3f0298830a40.JPG b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096135937d3f2a596c3f0298830a40.JPG new file mode 100644 index 0000000000..3f526ab23b Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096135937d3f2a596c3f0298830a40.JPG differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a0961366f44a7136b2fb97bd59d5dfc.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a0961366f44a7136b2fb97bd59d5dfc.jpg new file mode 100644 index 0000000000..7ba3edd466 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a0961366f44a7136b2fb97bd59d5dfc.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a0961369b8e73cbf7212e02194dfe38.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a0961369b8e73cbf7212e02194dfe38.jpg new file mode 100644 index 0000000000..5d85f3f6bd Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a0961369b8e73cbf7212e02194dfe38.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096137121dd1fc027a8a3f049b7545.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096137121dd1fc027a8a3f049b7545.jpg new file mode 100644 index 0000000000..b270012659 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096137121dd1fc027a8a3f049b7545.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096138b4f6513b8233788e96ac8c05.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096138b4f6513b8233788e96ac8c05.jpg new file mode 100644 index 0000000000..98b7c746f2 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096138b4f6513b8233788e96ac8c05.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613b87df4f9cb2dec966008d135f.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613b87df4f9cb2dec966008d135f.jpg new file mode 100644 index 0000000000..6bedc0428d Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613b87df4f9cb2dec966008d135f.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613d3ba8b917e8e4a473a6ff0a7b.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613d3ba8b917e8e4a473a6ff0a7b.jpg new file mode 100644 index 0000000000..5442186f36 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613d3ba8b917e8e4a473a6ff0a7b.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613d87b1034d63a74d5da77b6ceb.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613d87b1034d63a74d5da77b6ceb.jpg new file mode 100644 index 0000000000..acbcf7aee2 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613d87b1034d63a74d5da77b6ceb.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613e6993994a27cb3dd7715ff6d1.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613e6993994a27cb3dd7715ff6d1.jpg new file mode 100644 index 0000000000..5d341a0327 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613e6993994a27cb3dd7715ff6d1.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613f0111d0bf3f477dfc6653d6b6.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613f0111d0bf3f477dfc6653d6b6.jpg new file mode 100644 index 0000000000..7e7a340553 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09613f0111d0bf3f477dfc6653d6b6.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096140602aa2e4345480767ee7ced8.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096140602aa2e4345480767ee7ced8.jpg new file mode 100644 index 0000000000..bfab97a6e6 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096140602aa2e4345480767ee7ced8.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a0961410637bce3c946855d5e559ecd.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a0961410637bce3c946855d5e559ecd.jpg new file mode 100644 index 0000000000..eaad32f215 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a0961410637bce3c946855d5e559ecd.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096143f0266e4c809c33143d42e139.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096143f0266e4c809c33143d42e139.jpg new file mode 100644 index 0000000000..ac0f334d43 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096143f0266e4c809c33143d42e139.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096144b581c4e1a35d85415c8bda44.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096144b581c4e1a35d85415c8bda44.jpg new file mode 100644 index 0000000000..67fcb8d42d Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096144b581c4e1a35d85415c8bda44.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096144eb966eb756f2f381e0dcbb73.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096144eb966eb756f2f381e0dcbb73.jpg new file mode 100644 index 0000000000..1e9f2ce7ec Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096144eb966eb756f2f381e0dcbb73.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09614531ca59eecf978535611a4f76.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09614531ca59eecf978535611a4f76.jpg new file mode 100644 index 0000000000..95d92c792d Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09614531ca59eecf978535611a4f76.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096148452f3112958cee9aed14aa8a.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096148452f3112958cee9aed14aa8a.jpg new file mode 100644 index 0000000000..ce8491e45e Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a096148452f3112958cee9aed14aa8a.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09614ee47c4815fb537306266608c4.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09614ee47c4815fb537306266608c4.jpg new file mode 100644 index 0000000000..895e91fcb0 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09614ee47c4815fb537306266608c4.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09614fca668d23b0cef632d0cd74b8.jpg b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09614fca668d23b0cef632d0cd74b8.jpg new file mode 100644 index 0000000000..f39d9a90c8 Binary files /dev/null and b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/3a09614fca668d23b0cef632d0cd74b8.jpg differ diff --git a/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/post.md b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/post.md new file mode 100644 index 0000000000..06d56d43b5 --- /dev/null +++ b/docs/en/Community-Articles/2023-02-14-ndc-london-2023-sponsored-for-the-4th-time/post.md @@ -0,0 +1,73 @@ +#### **Recap & Impressions🌟** + +Last week, we were just back from [NDC {London} ](https://ndclondon.com)after had a blast at Queen Elizabeth II Centre in the center of Westminster, London, UK, with holding a stand on Level 3 during the 3-day conference (24 Jan. - 27 Jan.) introducing about the [ABP.IO](https://abp.io) platform. + +![IMG\_4535.JPG](3a096135937d3f2a596c3f0298830a40.JPG) + +We were proud and glad to be a presenting partner of the conference for the 4th time in NDC London, and was able to meet up with other global companies, top experts with their specialties, and the impressive count of attendees. + +![IMG\_0017 16.14.45.jpg](3a0961366f44a7136b2fb97bd59d5dfc.jpg) + +![52660341321\_4883550b40\_c.jpg](3a0961369b8e73cbf7212e02194dfe38.jpg) + +![52659842632\_b45bac83cc\_c.jpg](3a096137121dd1fc027a8a3f049b7545.jpg) + +It was a no-brainer that our team would attend again as we had an absolute blast meeting and chatting with a global group of passionate developers and talented speakers. + +![52660786305\_0cd21ea380\_c.jpg](3a096138b4f6513b8233788e96ac8c05.jpg) + +![52660831093\_85a72a64c5\_o.jpg](3a09613b87df4f9cb2dec966008d135f.jpg) + +Our lead developers *[Halil](https://twitter.com/hibrahimkalkan)* and *[Alper](https://twitter.com/alperebicoglu)* presented the ABP.IO platform modules and features were quite busy enjoying their presenting work with latest version of demos. + +We introduced **[ABP Framework](https://abp.io)**, community-driven open-source web application framework, and **[ABP Commercial](https://commercial.abp.io)**, our enterprise-ready web development platform that is built on top of the open-source ABP Framework. + +![52660783985\_aa747395f6\_c.jpg](3a09613d3ba8b917e8e4a473a6ff0a7b.jpg) + +![F98C7DBC-C412-4010-BE0F-AAA3DF87F8FC.jpg](3a09613d87b1034d63a74d5da77b6ceb.jpg) + +We were pleased with the traffic coming by our booth all the time. + +On the conference, we chatted with [@Nick Chapsas](https://twitter.com/nickchapsas) in person. It was great to talk and discuss out of screen with him for ABP.IO this time. Hope to see more chemistry in our collaborations! + +![IMG\_0014.jpg](3a09613e6993994a27cb3dd7715ff6d1.jpg) + +![IMG\_3623.jpg](3a09613f0111d0bf3f477dfc6653d6b6.jpg) + +#### **SWAGGIE👀** + +For this year NDC London conference, we definitely brought really cool swags for the attendees: + +![IMG\_0010.jpg](3a096140602aa2e4345480767ee7ced8.jpg) + +![IMG\_3619.jpg](3a0961410637bce3c946855d5e559ecd.jpg) + +And I have to say, we’ve got lots of loving feedbacks from the folks on the venue! + +#### **NDC Party🍾** + +Another impression we’ve got from NDC London 2023 is the Thursday Night Party including an amazing music show. Check out the pictures below for feeling the dope live atmosphere! + +![52660620029\_f85f93f2b0\_w.jpg](3a096143f0266e4c809c33143d42e139.jpg) + +![52659840962\_849f1af229\_w.jpg](3a096144b581c4e1a35d85415c8bda44.jpg) + +![52660339311\_6c42d016b3\_w.jpg](3a096144eb966eb756f2f381e0dcbb73.jpg) + +![52660339286\_80576d16a5\_w.jpg](3a09614531ca59eecf978535611a4f76.jpg) + +#### **Drawing RAFFLE🎁** + +We ended up our last day of the conference with the exciting Raffle - META QUEST II ! + +![95f0b17d-a817-443b-8780-18ed1f125bb5.jpg](3a096148452f3112958cee9aed14aa8a.jpg) + +Under the eyes of everyone's great expectation, the winner turned out to be a very cute girl-developer from Poland. I bet she was the happiest one departed from the conference. + +![IMG\_3755.jpg](3a09614ee47c4815fb537306266608c4.jpg) + +It was an absolutely amazing week in NDC London. We had so much fun meeting all of you with pressure! Thanks to all enthusiasts developers and organizers who made the conference days shining inspiring! + +![52660784160\_446aecc95b\_c.jpg](3a09614fca668d23b0cef632d0cd74b8.jpg) + +We see you on the next one! Cheers! \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-02-21-abp-year-review-2022-wrap-up/post.md b/docs/en/Community-Articles/2023-02-21-abp-year-review-2022-wrap-up/post.md new file mode 100644 index 0000000000..6abf2f3d12 --- /dev/null +++ b/docs/en/Community-Articles/2023-02-21-abp-year-review-2022-wrap-up/post.md @@ -0,0 +1,100 @@ +

ABP Framework is an open source infrastructure that enables developers to create modern web applications by following the best practices and conventions of software development. In 2022, ABP Framework continued to thrive, achieving significant milestones and making waves in the software development community. With more than 9K GitHub stars and over 10 millions of downloads on NuGet, ABP Framework has become a go-to framework for developers seeking a reliable and efficient way to build web applications.

+ +

As ABP Team, we owe our success to our vibrant community, and we are immensely grateful for the support and contributions of each and every member. With your help, we achieved a lot in 2022. We remained committed to our values of transparency, openness, and collaboration, engaging with our community members as much as possible to ensure that we are creating a framework that meets their needs.

+ +

One of the major highlights of 2022 was the release of .NET Core 7, which provided a powerful platform for ABP Framework to build upon. Additionally, ABP Commercial and our training programs continued to help developers and businesses to leverage the power of the ABP Framework, enabling them to build modern web applications more efficiently and effectively than ever before.

+ +

In this article, we'll take a closer look at the key highlights of 2022 for ABP Framework, from major updates to achivements and the community insights. We are excited to share our progress with you and provide insights into how ABP Framework is continuing to shape the future of software development. So, let's dive in!

+ + + + +

NuGet Downloads

+

NuGet is a package manager designed specifically for the .NET ecosystem. It simplifies the process of creating and consuming packages, thanks to the NuGet client tools. By using these tools, developers can easily manage their project dependencies and improve their workflow.

+

In 2022, ABP Core NuGet package reached more than 10 million of downloads!

+

On the other hand, overall Volosoft NuGet Packages reached more than half a billion downloads!

+

Thank you all for your interest and support towards Volosoft and ABP packages.

+ + +

E-Books

+

Our published e-book amount is reached 3! This year, with our founder Halil İbrahim Kalkan's contributions we now have 3 published e-books.

+ + + +

Tutorial Videos

+

In 2022, we tried to be as much active as we could. To give you more insight and let you understand ABP Framework with short videos according to your interests, we published 48 tutorial videos. Though the videos were created by overall team members of ABP Framework, someone deserves a special mention here. Shout out to our ABP Core Team member Hamza Albreem for his hard work.

+ + +

GitHub Stars

+

ABP Framework GitHub repository reached more than 9K stars. We appreciate your interest and support for ABP Framework GitHub repository. We are working hard to be worthy of your interest and reach out to more people to simplify and streamline their development processes.

+ +

Community Talks

+

ABP Community Talks is our monthly event that brings together members of the ABP Framework community to discuss and exchange ideas. Prior to each event, we collect suggestions from our contributors, monitor trending topics in the industry, and review updates and news related to the ABP Platform to curate the topics for discussion. Once the topics are finalized, we announce them through our social media and community channels to ensure everyone is aware and can join in on the conversation.

+

We did 10 ABP Community Talks Episodes of and 1 ABP Suite webinar. You can take a look at them and check out our videos we have on Volosoft YouTube Channel.

+ +

ABP Community Contributions

+

The ABP Community is a hub that offers resources such as articles, video tutorials, and updates on ABP's development progress and events for ABP Framework, .NET, and software development. Developers can also connect with others, help each other, and share their expertise in ABP Community.

+
    You can check out each source from the list below. +
  • ABP Community Events: You can reach them from here.
  • +
  • ABP Community Posts: You can reach them from here
  • +
  • ABP Community Videos: You can reach them from here.
  • +
  • ABP Community Stackoverflow: You can reach them from here.
  • +
+

In 2022, the community's contribution reached a point where more than 100 resources. Thank you for all your effort! Please keep it going! It is becoming a more and more rich resource thanks to your variety of contributions and help.

+ + +

ABP Community Discord Server

+

To take community interaction to the next level, we created the official ABP Discord server, providing a platform for the ABP Community to connect and communicate instantly through chatting.

+

We were so excited announcing the official ABP Discord Server. In the first week of announcing it, the server quickly attracted over 500 members. We're grateful for your interest and support, which confirms the need for a dedicated platform for community interaction.

+> Join ABP Discord Server Now + + +

ABP Framework GitHub Contributions

+

In 2022, ABP Core Team worked hard to achieve milestones and give the best value with ABP Framework so users can benefit from its features. Additional to our team's work, ABP Framework is perfected in 2022 with ABP Community members' contributions, 3157 commits pushed from 48 different contributors.

+

We appreciate your hard work and effort you put into making ABP Framework better and improved.

+ + +

Events/Summits

+

We try to contribute to the developers community as much as we can since day 1. This year was no different. We tried to give value through sponsorships for developer communities. Especially with us leaving the pandemic behind every day, we try to keep up with the in-person events as well as online events. We plan to do more in next year. So, stay tuned!

+

This year, we sponsored to 4 events. They were, DevNot +Designing Monolith First for Microservice Architecture event, DNF Summit 2022, Developer Summit 2022, and .NET Conference 2022. + + +

ABP Releases

+

ABP Framework released 4 versions from 5.1 to 7.1 in 2022. You can check the release logs from ABP Framework Release Logs.

+

The most important milestone in these releases is that we upgraded ABP Framework to .NET 7.0 in ABP v7.0.

+

Additionally, we switched to OpenIddict for the startup templates in ABP v6.0.

+ + +

ABP Commercial

+

It has been a successful year for ABP Commercial as well as ABP Framework. We have already reached to more than 100 countries over the years of ABP Commercial's release. This year, we continued to be streamline businesses' development processes with ABP Commercial.

+
    +
  • We have served to different sizes of businesses from more than 50 countries and more than 40 industries .
  • +
  • We performed 286 hours of training to simplify users' learning curve of ABP Framework.
  • +
  • 1771 support tickets resolved in the premium support forum in which ABP Commercial users can ask their questions directly to ABP Core Team members via ABP Commercial Support Center in addition to community support we provide for ABP Framework users/developers.
  • +
  • We received 39 new testimonials, all from satisfied customers which led us to the other headline, Gartner Badges.
  • +
+ + +

LeptonX Theme

+

The Lepton Theme is a module that offers a theme for abp.io-based applications, featuring an Admin Dashboard designed by the ABP Platform. We released a version we called LeptonX Theme which is an upgraded version of Lepton Theme. You can view a live preview of the LeptonX Theme. While the LeptonX theme is currently exclusive to ABP Commercial users, ABP Framework users can still access the Lite version. You can see the documentation for ABP LeptonX Theme light from here.

+ + +

Gartner Badges

+

Gartner badges are given as an award to the listed softwares within their software review/suggestion platforms. To be able to get these awards, certain criterias have to be met such as ease of use, likelihood of recommend, functionality, etc. and they are calculated completely according to the users' real reviews.

+

In 2022, ABP Commercial reached to such success thanks to its users' support on Gartner, it has been recognized with 2 badges in Application Development category.

+ +

Thank you all for all these recognition you deemed us worthy of.

diff --git a/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/citext-1.jpg b/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/citext-1.jpg new file mode 100644 index 0000000000..f0005d378d Binary files /dev/null and b/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/citext-1.jpg differ diff --git a/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/citext-2.jpg b/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/citext-2.jpg new file mode 100644 index 0000000000..439e529ee9 Binary files /dev/null and b/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/citext-2.jpg differ diff --git a/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/citext-3.jpg b/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/citext-3.jpg new file mode 100644 index 0000000000..309a7a142f Binary files /dev/null and b/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/citext-3.jpg differ diff --git a/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/db-converter.jpg b/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/db-converter.jpg new file mode 100644 index 0000000000..b2d0a78ee4 Binary files /dev/null and b/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/db-converter.jpg differ diff --git a/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/post.md b/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/post.md new file mode 100644 index 0000000000..d1ce98390c --- /dev/null +++ b/docs/en/Community-Articles/2023-03-20-migrating-from-ms-sql-to-postgresql/post.md @@ -0,0 +1,34 @@ +## Introduction + +Database migration is a common practice for organizations that want to move from one database system to another. This can be for various reasons, including cost, performance, and features. In this article, we will discuss migrating a database from MS-SQL to PostgreSQL, the challenges that may arise during the migration, and how to overcome them. And we recently moved the main database of the https://abp.io platform from MS-SQL to PostgreSQL. + +We switched our database from Microsoft SQL Server (MS-SQL) to PostgreSQL to move our on-premise platform to Azure. We’ve also discovered that the license cost for MS-SQL on Azure was significantly higher than PostgreSQL. After conducting a cost-benefit analysis, we migrated our database to PostgreSQL to save costs. + +Before migrating to Azure, we decided to switch our database from MS-SQL to PostgreSQL on-premise first. This allowed us to test and fine-tune the migration process before making the final switch to Azure. + +## Challenges + +Despite using a third-party tool(DBConvert for MySQL & PostgreSQL) for the migration, we faced three main problems when exporting data to PostgreSQL. Firstly, some tables with plain text had +UTF-8 encoding problems. We overcame this problem by dump-restoring these tables. + +![db-converter](db-converter.jpg) + + +Secondly, our database had to be case-insensitive, but PostgreSQL does not have this as a default configuration. We handled it using `citext` with the ABP migration service. + +![citext-1](citext-1.jpg) +![citext-2](citext-2.jpg) +![citext-3](citext-3.jpg) + + +While everything was proceeding very smoothly, we faced one last problem: importing binary data, such as the content of the NuGet packages. It was hard to understand that the binaries of the NuGet packages were different. Our paid commercial NuGet packages are stored as binary data in the database. Therefore, it was the most compelling part of this migration to transfer the NuGet packages. Fortunately, we overcame the binary error. And we decided to write a custom .NET tool to move only the binary data from MS-SQL to PostgreSQL, thanks to the ABP Core team! + + +## Conclusion + +One of the benefits of using PostgreSQL is the low license costs of the Azure platform. As the main contributors of ABP, we also use ABP Framework under the hood of our abp.io websites; we could easily switch to PostgreSQL. For those who want to switch their ABP project to PostgreSQL, check out [docs.abp.io/en/abp/latest/Entity-Framework-Core-PostgreSQL](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-PostgreSQL). We had not used any MS-SQL specific function, therefore there was no need to make any changes in the repository classes. This means that the applications that were previously using MS-SQL can seamlessly switch to PostgreSQL without any modifications. + +Thanks to the flexibility of ABP, it has [PostgreSQL package](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.PostgreSql), which is 100% compatible with PostgreSQL. This helped us to make this migration very smooth and seamless. + +In conclusion, migrating a database from MS-SQL to PostgreSQL can be challenging, but it can bring significant cost savings in the long run. By testing and fine-tuning the migration process before making the final switch, we overcame the challenges we’d faced during the migration process. Thanks to the flexibility of ABP, we were able to make the transition with minimal code changes. Also, we didn't see any big performance differences between MS-SQL and PostgreSQL. + diff --git a/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/az-infra.png b/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/az-infra.png new file mode 100644 index 0000000000..7602764591 Binary files /dev/null and b/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/az-infra.png differ diff --git a/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/post.md b/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/post.md new file mode 100644 index 0000000000..3069d06b02 --- /dev/null +++ b/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/post.md @@ -0,0 +1,41 @@ + +Migrating a Kubernetes platform with a database from our own dedicated servers to Azure can be a compelling task, but it can be a necessary one to take advantage of the benefits that the cloud service offers. In this post, we will discuss the reasons for migrating from a on-premise platform to Azure, the steps taken to create and configure the [abp.io platform](https://abp.io) on Azure, and the benefits gained from the migration. + +### On-Premise Server: The old platform + +There were several reasons for migrating from the old on-premise platform to Azure. First, the Kubernetes cluster and the database were on the same Windows server. Additionally, the Linux virtual machines in Kubernetes were on the Windows server and had limited resources. Furthermore, the Kubernetes maintenance was quite challenging, which was another reason for the migration. + +### Reasons for Moving to Azure: The new platform + +The decision to move to the cloud was made to eliminate the disadvantages of the old platform. The migration to Azure meant that the resources would be independent of each other but faster in terms of communicating with each other. The platform would also take advantage of cloud security and availability. The managed Kubernetes service that Azure offers comes with autoscaling and loadbalancing, which makes the platform more reliable. Finally, the migration to Azure would provide a better quality service to global customers and the community. + +### Before Moving to Azure + +Before migrating to Azure, we decided to switch our database from MS-SQL to PostgreSQL on-premise first. This gave us the opportunity to test and fine-tune the migration process before making the final switch to Azure.You can check the details of database migration from this article [Migrating from MS-SQL to Postgresql](https://blog.abp.io/abp/Migrating-from-MS-SQL-to-Postgresql). + +The platform was tested in a staging environment created on Azure with the same resources as the production environment. The staging environment was used to test and optimize the migration process, including the migration of data from the old platform to Azure, which was tested multiple times to ensure success. + +### Creating and Configuring the abp.io Platform on Azure + +Several steps were taken to create and configure the abp.io platform on Azure. [Terraform](https://www.terraform.io/) was used to create the infrastructure (VM, Private Network, AKS, Postgresql Flexible Server...), while [Ansible](https://www.ansible.com/) was used to configure the Azure resources like Terraform, Helm, Kubectl, Docker, VPN, Redis, Prometheus, Grafana, ElasticSearch, Kibana and so on.... Azure DevOps pipelines and release were used for AKS deployment. The most time-consuming part in this process was to prepare, test and optimize the terraform and ansible settings files. + +To access our platform, which is configured on a private network in Azure, we require a VPN connection. To enable this, we have installed [Wireguard](https://www.wireguard.com/) - an open source VPN service - by creating a virtual machine using Terraform and configuring it with Ansible in Azure. This approach has made the process efficient and streamlined. + +![terra-wire](terra-wire.png) + +The most important step was to transfer the data in both the database and Kubernetes of the volumes. rsync (remote sync commands) were used to transfer the data from Kubernetes volumes to Azure Files through the VPN machine. Additionally, `pg_dump` and `pg_restore` were used to transfer the PostgreSQL database through the machine with VPN. + +Before the production environment, the data migration was tested many times for the staging environment. We estimated this migration to take max 1.5 hours. The ABP community was informed that there may be interruptions during the hours designated for the transition to Azure. To inform our customers and community, we created a status page before this migration. The new status page is [status.abp.io](https://status.abp.io). From now on we will make all the infrastructural announcements on [status.abp.io](https://status.abp.io). We used [Upptime](https://upptime.js.org) which is an open-source uptime monitor and status page provider. During the migration of the production environment, the websites and databases were still up and running. After the data transfer, the only remaining step was to direct the traffic of the already standing abp.io sites to the Azure Kubernetes service via Cloudflare. + +We would like to happily state that **we were offline for only 4 minutes** during this transition. + +![az-infra](az-infra.png) + + +### Benefits of Moving to Azure + +The migration to Azure resulted in several benefits. The platform is now more reliable, scalable, secure, solid with built-in one-click backup and recovery capabilities for abp.io. Additionally, the critical resources are in a private network, making them more secure than the old environment. When we initially compared the speed of our abp.io sites before and after migrating to Azure, we were pleasantly surprised by the significant improvement in performance. To be honest, we did not expect such a speed increase. + +![speed](speed.png) + +In conclusion, migrating a Kubernetes platform with a database from on-premise to Azure is a complex process that requires careful planning and execution. However, the benefits gained from the migration make the process worthwhile. By moving to Azure, the abp.io platform now has a more reliable and available infrastructure that is more secure than the old environment. The migration also resulted in significant improvements in connection speeds, which ultimately provides a better service to global customers and the community. diff --git a/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/speed.png b/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/speed.png new file mode 100644 index 0000000000..186615468b Binary files /dev/null and b/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/speed.png differ diff --git a/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/terra-wire.png b/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/terra-wire.png new file mode 100644 index 0000000000..a2a032a1de Binary files /dev/null and b/docs/en/Community-Articles/2023-03-20-on-prem-to-azure-migration-of-abpio-platform-to-azure/terra-wire.png differ diff --git a/docs/en/Community-Articles/2023-03-23-abpio-platform-71-final-has-been-released/3a0a20886e5c7ab36bd0475a9674495e.png b/docs/en/Community-Articles/2023-03-23-abpio-platform-71-final-has-been-released/3a0a20886e5c7ab36bd0475a9674495e.png new file mode 100644 index 0000000000..730e48dc0b Binary files /dev/null and b/docs/en/Community-Articles/2023-03-23-abpio-platform-71-final-has-been-released/3a0a20886e5c7ab36bd0475a9674495e.png differ diff --git a/docs/en/Community-Articles/2023-03-23-abpio-platform-71-final-has-been-released/3a0a208890e0a0bd9a8348c07e9ca0d1.png b/docs/en/Community-Articles/2023-03-23-abpio-platform-71-final-has-been-released/3a0a208890e0a0bd9a8348c07e9ca0d1.png new file mode 100644 index 0000000000..b562de6dae Binary files /dev/null and b/docs/en/Community-Articles/2023-03-23-abpio-platform-71-final-has-been-released/3a0a208890e0a0bd9a8348c07e9ca0d1.png differ diff --git a/docs/en/Community-Articles/2023-03-23-abpio-platform-71-final-has-been-released/post.md b/docs/en/Community-Articles/2023-03-23-abpio-platform-71-final-has-been-released/post.md new file mode 100644 index 0000000000..3cc5956cc3 --- /dev/null +++ b/docs/en/Community-Articles/2023-03-23-abpio-platform-71-final-has-been-released/post.md @@ -0,0 +1,80 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 7.1 versions have been released today. + +## What's New With Version 7.1? + +All the new features were already explained in detail in the [7.1 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-7.1-RC-Has-Been-Published), so no need to go over them again. Check it out for more details. + +## Getting Started with 7.1 + +### Creating New Solutions + +You can create a new solution with the ABP Framework version 7.1 by either using the `abp new` command or generating the CLI command on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to Upgrade an Existing Solution + +#### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update the existing CLI: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading Existing Solutions with the ABP Update Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guides + +This version includes a very minor breaking change and it doesn't affect most of the applications. Check [the migration guide](https://docs.abp.io/en/abp/7.1/Migration-Guides/Abp-7_1) for the details. + +## Community News + +## ABP Community Talks 2023.2 + +The next ABP Community Talks will take place on March 30, at 18:00 (UTC). + +![abp-comm-talks-2023-2.png](3a0a20886e5c7ab36bd0475a9674495e.png) + +In this episode, core ABP Framework developers will discuss the benefits of using the ABP Framework as a .NET developer instead of creating your own solution from scratch. They will answer most of the common doubts about using ABP and application frameworks in general. You will better understand how ABP makes a developer’s life easier and more enjoyable while cutting production costs. We will also have a question - answer session after the talk, as always. I think this talk will be useful for every .NET developer whether they use ABP or not. + +**[CLICK HERE to register for the event and join us](https://kommunity.com/volosoft/events/abp-community-talks-20232-why-use-abp-framework-as-a-net-developer-e3254183)**. + +## Introducing the first ABP .NET Conference! + +As the ABP team, we've executed more than 10 [online events](https://community.abp.io/events) and gained a good experience of software talks. In May, we are organizing a full-featured software conference, named **ABP Dotnet Conference 2023**! + +![abp-conf-2023.png](3a0a208890e0a0bd9a8348c07e9ca0d1.png) + +We are still organizing the speakers, talks and schedule. There will be 12 sessions about software development and .NET. These will also include a few ABP-related talks. You can **follow https://abp.io/conference website** and buy early bird tickets from now. + +### New ABP Community Posts + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Creating Dockerfile for ABP Applications](https://community.abp.io/posts/creating-dockerfile-for-abp-applications-caj4fkxa) by [Anto Subash](https://community.abp.io/members/antosubash) +* [IdentityUser Relationship and Extending it](https://community.abp.io/posts/identityuser-relationship-and-extending-it-xtv79mpx) by [Onur Pıçakçı](https://community.abp.io/members/onurpicakci) +* [Streamline Localization in Your ABP Project](https://community.abp.io/posts/streamline-localization-in-your-abp-project-1t12rmjc) by [Salih Özkara](https://community.abp.io/members/salih) +* [.Net Microservice template with ABP](https://community.abp.io/posts/.net-microservice-template-with-abp-53r52ryy) by [Anto Subash](https://community.abp.io/members/antosubash) + +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. + +## About the Next Version + +The next feature version will be 7.2. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. diff --git a/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/discord.png b/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/discord.png new file mode 100644 index 0000000000..0e773729e4 Binary files /dev/null and b/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/discord.png differ diff --git a/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/gh-status.png b/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/gh-status.png new file mode 100644 index 0000000000..0490eeb6f6 Binary files /dev/null and b/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/gh-status.png differ diff --git a/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/issue.png b/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/issue.png new file mode 100644 index 0000000000..7f21404e8f Binary files /dev/null and b/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/issue.png differ diff --git a/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/post.md b/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/post.md new file mode 100644 index 0000000000..33221e869b --- /dev/null +++ b/docs/en/Community-Articles/2023-03-27-creating-a-custom-status-page-for-abpio-with-upptime/post.md @@ -0,0 +1,112 @@ +# Creating a Custom Status Page for abp.io with Upptime + +## Introduction +In today's digital world, providing reliable and transparent information about your platform's availability is essential to maintaining trust among your community and customers. With the growing number of abp.io users, we needed a dedicated status page [status.abp.io](https://status.abp.io/) to keep everyone informed about our platform's health. To achieve this, we utilized the open-source project [Upptime](https://upptime.js.org/) and built a custom status page on [GitHub Pages](https://pages.github.com/). In this article, we'll guide you through the process of creating our own status page and customizing it to suit our needs. + +## Why we chose Upptime +[Upptime](https://github.com/upptime/upptime) is an open-source, easy-to-use, and cost-effective solution for monitoring websites and APIs. It offers essential features, such as downtime alerts, response time monitoring, and status history. We decided to use Upptime because of its compatibility with GitHub Pages, ease of customization, comprehensive [documentation ](https://upptime.js.org/docs/) and discord notifications. + +![gh-status](gh-status.png) + +#### Advantages of Upptime +* Open-source: Allows easy customization and community support. + +* GitHub Pages compatibility: Seamless integration with GitHub Pages for hosting. + +* Cost-effective: Utilizes GitHub Actions, which provides free monitoring within the GitHub Actions usage limits. + +* Comprehensive documentation: Easy-to-follow instructions for setting up and customizing the status page. + +#### Disadvantages of Upptime +* Limited monitoring capabilities: Upptime offers basic monitoring features but lacks advanced capabilities found in dedicated monitoring tools. + +* Dependence on GitHub Actions: Upptime relies on GitHub Actions, which may pose limitations for users unfamiliar with GitHub's ecosystem or those with large-scale projects. + +* No built-in alerting system: Users must rely on third-party integrations or custom solutions for notifications, requiring additional configuration. + +* Limited customization options: Upptime allows for some customization, but options are limited compared to comprehensive monitoring platforms. + +* Self-hosted limitations: As a self-hosted solution, users are responsible for maintaining and managing their own infrastructure, which may not be ideal for those who prefer a fully managed monitoring solution. + + +## How to set up the status page on GitHub Pages +To get started with our custom status page, we followed the instructions in the [Upptime documentation](https://upptime.js.org/docs/). Here's a summary of the steps we took: + +* Fork the Upptime [template repository](https://github.com/upptime/upptime) to our own GitHub account as [abpio-status](https://github.com/abpframework/abpio-status). + +* Configure the GitHub Actions workflow. We configured the GitHub Actions workflow by adding the following lines to the [`.github/workflows/uptime.yml`](https://github.com/abpframework/abpio-status/blob/master/.github/workflows/uptime.yml) + +* Add the monitored endpoints. We added the monitored endpoints (our abp.io websites) to the [.upptimerc.yml](https://github.com/abpframework/abpio-status/blob/master/.upptimerc.yml) file. This file is located in the root of the repository and contains a list of URLs that Upptime monitors. + +```yaml +sites: + - name: abp.io + url: https://abp.io/health-status + - name: community.abp.io + url: https://community.abp.io/health-status + - name: commercial.abp.io + url: https://commercial.abp.io/health-status + - name: nuget.abp.io + url: https://nuget.abp.io/health-status + - name: docs.abp.io + url: https://docs.abp.io/health-status + - name: support.abp.io + url: https://support.abp.io/health-status + - name: blog.abp.io + url: https://blog.abp.io/health-status + - name: commercial-demo.abp.io + url: https://commercial-demo.abp.io/health-status +``` +* Enable GitHub Pages. Finally, we enabled GitHub Pages for our forked repository by going to the repository's settings and selecting the gh-pages branch as the source. This made our status page accessible at [status.abp.io](https://status.abp.io/). + +## Customizing the status page + +After setting up the default Upptime status page, we focused on customizing it to align with our brand and provide a consistent experience for our community and customers. We made the following changes: + +* Updating the logo and favicon. We replaced the default logo and favicon with our own abp.io branded assets. This involved adding the new image files to the repository and updating the references in the `.upptimerc.yml` file: + +* Customizing the color scheme and typography. We customized the color scheme and typography to match our corporate identity by editing the `.upptimerc.yml` file: + +```yaml +status-website: + theme: dark + # Add your custom domain name, or remove the `cname` line if you don't have a domain + # Uncomment the `baseUrl` line if you don't have a custom domain and add your repo name there + cname: status.abp.io + # baseUrl: /abpio-status + logoUrl: https://commercial.abp.io/assets/svg/abp-logo-light.svg + favicon: https://raw.githubusercontent.com/abpframework/abpio-status/master/assets/abp-logo-without-text.svg + faviconSvg: https://raw.githubusercontent.com/abpframework/abpio-status/master/assets/abp-logo-without-text.svg +``` +## Creating GitHub Issues for Maintenance Information on status.abp.io + +To provide maintenance information for your status page, you can create GitHub issues in your repository. This allows you to inform your users about planned downtime or ongoing maintenance work. + +![issue](issue.png) + +## Discord Notifications + +### Create a Discord Webhook + +To set up Discord notifications for your status.abp.io status page using [Upptime documentation](https://upptime.js.org/docs/notifications#discord), follow these steps: + +* In Discord, go to "Server Settings" > "Integrations" > "Create Webhook." +* Customize the Webhook name, choose a channel, and copy the Webhook URL. + +### Configure GitHub Actions +* In your Upptime repository, go to the "Settings" tab. +* Click on "Secrets" and then "New repository secret." +* Add secret: Name it DISCORD_WEBHOOK_URL and paste the Webhook URL as the value. +* Add environment variables NOTIFICATION_DISCORD_WEBHOOK and NOTIFICATION_DISCORD set it to true. + +Your status page will now send notifications to your Discord channel whenever there's a change in your platform's status. + +![discord](discord.png) + + +## Conclusion +If your primary goal is to create a simple, cost-effective status page with basic monitoring features, Upptime is an excellent choice. Its open-source nature, seamless integration with GitHub Pages, and comprehensive documentation make it a user-friendly option. + +If you require advanced monitoring capabilities or prefer a fully managed monitoring solution, you may want to explore dedicated monitoring tools, such as Pingdom, Uptime Robot, or Datadog. These tools typically offer more robust monitoring features, built-in alerting systems, and customizable dashboards. + +Creating a custom status page for abp.io using Upptime and GitHub Pages proved to be an efficient and cost-effective solution. By following the documentation and customizing the template, we were able to provide our community and customers with a reliable source of information about our platform's availability. With this new status page [status.abp.io](https://status.abp.io/), we can continue to build trust and transparency as our platform grows and evolves. diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574d0d129822a1deb4f2f5b3310a.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574d0d129822a1deb4f2f5b3310a.png new file mode 100644 index 0000000000..081376668b Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574d0d129822a1deb4f2f5b3310a.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574d690031cc40f67400922eecfb.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574d690031cc40f67400922eecfb.png new file mode 100644 index 0000000000..cecdd739b4 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574d690031cc40f67400922eecfb.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574dd6214b6de0cf998da277eb4d.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574dd6214b6de0cf998da277eb4d.png new file mode 100644 index 0000000000..2550a9209d Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574dd6214b6de0cf998da277eb4d.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574e38a4fd3d6dda4f9884ecd502.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574e38a4fd3d6dda4f9884ecd502.png new file mode 100644 index 0000000000..45f6261a57 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574e38a4fd3d6dda4f9884ecd502.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574edb1461fcb4a37a2cdd16783e.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574edb1461fcb4a37a2cdd16783e.png new file mode 100644 index 0000000000..e709f00327 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574edb1461fcb4a37a2cdd16783e.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574f237946f9746a99e2ef62fca8.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574f237946f9746a99e2ef62fca8.png new file mode 100644 index 0000000000..dee5928bbd Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574f237946f9746a99e2ef62fca8.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574f7e65be09cff31cdfeacadb66.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574f7e65be09cff31cdfeacadb66.png new file mode 100644 index 0000000000..96943ef81f Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574f7e65be09cff31cdfeacadb66.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a575077ee05f6b67f1d05658457ff.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a575077ee05f6b67f1d05658457ff.png new file mode 100644 index 0000000000..bae6f08238 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a575077ee05f6b67f1d05658457ff.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5ba45243aa36cf8878e3907f96a8.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5ba45243aa36cf8878e3907f96a8.png new file mode 100644 index 0000000000..e4ad6d6014 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5ba45243aa36cf8878e3907f96a8.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5ba4ffbab9c4d502284b08b92b18.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5ba4ffbab9c4d502284b08b92b18.png new file mode 100644 index 0000000000..0d5f5a7e9a Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5ba4ffbab9c4d502284b08b92b18.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5bccb0f41d45e97f2ff4d962d5fd.png b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5bccb0f41d45e97f2ff4d962d5fd.png new file mode 100644 index 0000000000..b1157793bf Binary files /dev/null and b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5bccb0f41d45e97f2ff4d962d5fd.png differ diff --git a/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/post.md b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/post.md new file mode 100644 index 0000000000..b5ac2c7a46 --- /dev/null +++ b/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/post.md @@ -0,0 +1,127 @@ + + +ABP Framework is an open-source web application development framework that provides developers with a set of tools to build modern, scalable, and maintainable web applications. ABP Framework is also a C# web framework that is based on the ASP.NET web framework. It is one of the [most popular repository](https://github.com/abpframework/abp) for open source application framework. + +![ABP Framework is an open source web development framework ](3a0a5bccb0f41d45e97f2ff4d962d5fd.png) + +ABP Framework is a modular and extensible framework that uses clean architecture principles and is built on top of the latest .NET technologies. The framework comes with a set of pre-built modules, including user management, role management, permission management, and content management system (CMS) modules, which makes it easier for developers to create line of business applications. + + + +## Clean Architecture + +When you want to start a new scratch project, you first google Dotnet Framework Architecture. There are some boilerplate dotnet startup templates, but these are only an orchestration of some popular tools. ABP is not a template, but it's a full stack open source application development framework. + +When you say "Clean Architecture ASP.NET Core", the first web development framework that comes to mind is undoubtedly the ABP Framework. It is built using clean architecture principles, which help developers build scalable and maintainable applications. The clean architecture separates the application into distinct layers, each with a clear responsibility. The dotnet architecture layers include the presentation layer, application layer, domain layer, and infrastructure layer. Each layer has a clear responsibility, which helps in separating concerns and keeping the code organized. This makes ABP Framework one of the best asp net frameworks. + +![Clean architecture - ABP Layers](3a0a574d0d129822a1deb4f2f5b3310a.png) + + +## C# Web Framework for Web Development + +ABP Framework is built using C#, which is a modern programming language that is widely used in the development of web applications. C# provides developers with a set of features that make it easy to write clean and maintainable code. ABP Framework is a web framework that is designed to work with C# and provides developers with a set of tools that makes it easy to build modern web applications. If you are looking for an ASP NET Core shared framework download, then go to https://abp.io/get-started and create your project. + +![ABP Framework Essentials](3a0a574f237946f9746a99e2ef62fca8.png) + +## Yet another ASP.NET Web Framework + +There are a few full stack AspNet Core frameworks around. Many of them are one developer projects which can be risky for you to start a long running project. ABP Framework is built on top of the latest ASP NET Core Framework, which provides developers with a set of features that makes it easy to build modern web applications. And most important part is, ABP is backed with a large group of developers and it has almost 10K stars on GitHub. ASP.NET provides developers with a set of tools that makes it easy to build web applications using a model-view-controller (MVC) architecture. + +![ABP.io Platform](3a0a575077ee05f6b67f1d05658457ff.png) + + +## Implementing Domain Driven Design with C# + +ABP Framework provides developers with a set of tools that make it easy to implement domain-driven design principles. The framework comes with a set of pre-built modules, including user management, role management, permission management, and content management system (CMS) modules, which makes it easier for developers to create complex applications. + +![Implementing Domain Driven Design with C#](3a0a574e38a4fd3d6dda4f9884ecd502.png) + + + +## Open Source Web Application + +ABP Framework is an open-source web application development framework that is free to use and distribute. The framework is licensed under the MIT license, meaning developers can use it for commercial and non-commercial purposes without any restrictions. + + + +## .NET Application Framework with Pre-Built Modules + +ABP Framework is built using the latest .NET technologies and provides developers with a set of tools that makes it easy to build modern web applications. ABP contains several important modules of a line of business applications. + +![ABP Pre-built Modules](3a0a5ba4ffbab9c4d502284b08b92b18.png) + + +## C# Microservice Framework + +ABP Framework is a C# microservices framework that is designed to help developers build scalable and maintainable microservices. The framework is also known as .NET .net microservices framework. It provides developers with a set of tools that makes it easy to build microservices using clean architecture principles. + +![C# Microservice Framework](3a0a574dd6214b6de0cf998da277eb4d.png) + + +## CRUD Tool Dotnet + +ABP Framework has a commercial version as well. The paid version comes with premium support, rich themes and there's a very handy tool called [ABP Suite](https://commercial.abp.io/tools/suite) for "CRUD page generation ASP.NET". While ABP is not a low-code or no-code platform, ABP Suite provides ASP NET rapid application development. There are many ASP.NET rapid development tools but only tools without a framework support. If you are looking for web based rapid application development tools (also open-source), ABP is the way to go! + +![ABP Suite](3a0a5ba45243aa36cf8878e3907f96a8.png) + +## Modular Development + +One of the best sides of the ABP Framework is the modular development side. It's born as a modular system. There are several open source web frameworks around but many of them lack of modularity. + +![Modular Development](3a0a574f7e65be09cff31cdfeacadb66.png) + + +Let's see the key features of the ABP Framework: + +- Multi-tenancy support +- Cross-cutting concerns implemented +- Full-stack microservice solution +- SaaS framework +- ASP.NET modular monolith +- Has an ASP.NET user management module +- Distributed events +- Layered architecture +- Free framework for website +- Several framework templates + + + +## The Essential Features of ABP + +ABP Framework is an open source SaaS framework. This crucial feature distinguishes it from other open source web development frameworks. + +![Essential Features](3a0a574edb1461fcb4a37a2cdd16783e.png) + +The following essential ASP.NET features are available in the ABP Framework: + +ASP.NET modularity, ASP.NET modular development, ASP.NET localization, ASP.NET multi-tenancy, ASP.NET SaaS, ASP.NET SaaS framework, ASP.NET distributed events, ASP.NET distributed event bus, ASP.NET cross-cutting concerns, ASP.NET blob storing, ASP.NET audit logging, ASP.NET microservice, ASP.NET microservice solution, ASP.NET microservice example, ASP.NET API gateway, ASP.NET domain driven design, ASP.NET layered architecture, ASP.NET layering, ASP.NET clean architecture, ASP.NET authentication, ASP.NET authorization, ASP.NET identity, ASP.NET identity server, ASP.NET IdentityServer, ASP.NET payment module, ASP.NET best practices, ASP.NET design patterns, ASP.NET background jobs, ASP.NET exception handling, ASP.NET background workers, ASP.NET repository, ASP.NET repository pattern, ASP.NET unit of work, ASP.NET domain services, ASP.NET swagger, ASP.NET content management system, ASP.NET user management, ASP.NET role management, ASP.NET permission management + + + +## Microservice Example: eShopOnAbp + +[eShopOnAbp](https://github.com/abpframework/eShopOnAbp) is a microservice example built on top of ABP. It is a sample net application similar to Microsoft's [eShopOnContainer](https://github.com/dotnet-architecture/eShopOnContainers) project. It is a reference microservice solution built with the ABP Framework and .NET, runs on Kubernetes with Helm configuration and includes API Gateways, Angular and ASP.NET Core MVC applications with PostgreSQL and MongoDB databases. For more information, check out https://github.com/abpframework/eShopOnAbp. + +> ⚠️ **Important Notice** +> This project, "eshoponabp," is outdated. It served as a reference project for microservice architecture using the ABP Framework, but we now recommend using the [ABP Microservice Solution Template](https://abp.io/docs/latest/solution-templates/microservice) for new projects. +> +> The new template offers a modernized and officially supported starting point for building microservices with ABP. Please consider transitioning to the new template for the latest features and improvements. + + +## Conclusion + +In conclusion, ABP Framework is an open-source web development framework that offers many features and benefits for building modern and scalable web applications. Its modular and extensible architecture, implementation of Domain-Driven Design, and compatibility with various platforms make it a popular choice for developers. Whether you're building a web application, microservices, or modular monoliths, ABP Framework has everything you need to get started. + +![conclusion](3a0a574d690031cc40f67400922eecfb.png) + +Whether you're building a dot net website, a web app infrastructure, or a webpage framework, open source web application frameworks are a cost-effective and flexible option for web development. If you are looking for an open source web application builder which contains a project framework template with web application development tools (open source), [ABP Framework](https://abp.io/) is the right choice. + +--- + +> I'm Alper Ebicoglu 🧑🏽‍💻\ +> ABP Framework Core Team Member\ +> Follow me for the latest news about .NET and software development:\ +> 📌 [twitter.com/alperebicoglu](https://twitter.com/alperebicoglu)\ +> 📌 [github.com/ebicoglu](https://github.com/ebicoglu)\ +> 📌 [linkedin.com/in/ebicoglu](https://www.linkedin.com/in/ebicoglu)\ +> 📌 [medium.com/@alperonline](https://medium.com/@alperonline) diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3c7807c882c1889c1f431b86b7.png b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3c7807c882c1889c1f431b86b7.png new file mode 100644 index 0000000000..0bd8d212b8 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3c7807c882c1889c1f431b86b7.png differ diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3d69a4f5b2b15674fc70e97ba2.png b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3d69a4f5b2b15674fc70e97ba2.png new file mode 100644 index 0000000000..2f68e23137 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3d69a4f5b2b15674fc70e97ba2.png differ diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3dbc9eb0ada4effa3d06208fb4.png b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3dbc9eb0ada4effa3d06208fb4.png new file mode 100644 index 0000000000..c3a5ffdaec Binary files /dev/null and b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3dbc9eb0ada4effa3d06208fb4.png differ diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b43a8bea7e8df7d2ff6b7f1aa8f.png b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b43a8bea7e8df7d2ff6b7f1aa8f.png new file mode 100644 index 0000000000..6c166ac7eb Binary files /dev/null and b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b43a8bea7e8df7d2ff6b7f1aa8f.png differ diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b44fb2a208a89d3c9a56916d653.png b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b44fb2a208a89d3c9a56916d653.png new file mode 100644 index 0000000000..4c4b714694 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b44fb2a208a89d3c9a56916d653.png differ diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b45f7f68832d7a7f72262f3c216.png b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b45f7f68832d7a7f72262f3c216.png new file mode 100644 index 0000000000..5889357a42 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b45f7f68832d7a7f72262f3c216.png differ diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b4812b27aa05c1159478175fa02.png b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b4812b27aa05c1159478175fa02.png new file mode 100644 index 0000000000..50d8d09f9b Binary files /dev/null and b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b4812b27aa05c1159478175fa02.png differ diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b492ee3cbf9482090fcc8473653.png b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b492ee3cbf9482090fcc8473653.png new file mode 100644 index 0000000000..b18c3b716a Binary files /dev/null and b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b492ee3cbf9482090fcc8473653.png differ diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b4b7f00461297fbe88d4c34b831.png b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b4b7f00461297fbe88d4c34b831.png new file mode 100644 index 0000000000..287d130cb8 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b4b7f00461297fbe88d4c34b831.png differ diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b58d26f47970f6edd6f6fbee851.png b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b58d26f47970f6edd6f6fbee851.png new file mode 100644 index 0000000000..7c07800cac Binary files /dev/null and b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b58d26f47970f6edd6f6fbee851.png differ diff --git a/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/post.md b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/post.md new file mode 100644 index 0000000000..35624d8c32 --- /dev/null +++ b/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/post.md @@ -0,0 +1,99 @@ +Building robust web applications has become more important than ever as the world is becoming more web-focused. Choosing the right web development framework can be challenging with the rise of new tools and frameworks. Especially if you are a .NET developer, there are not so many popular ASPNET Framework around. However, the ABP Framework has become popular for many developers due to its flexibility, scalability, feature set and performance. Let's mention what's ABP Framework and what it promises to .NET developers. + +## ASP.NET Core Architecture Best Practices + +![ABP Key Features](3a0a6b44fb2a208a89d3c9a56916d653.png) + +ABP Framework is an application design framework that provides developers with a powerful set of tools to build web applications quickly and efficiently. It is an open-source, cross-platform framework supporting monolithic and microservices architectures. ABP Framework is built on top of the ASP.NET Core architecture and incorporates best practices for developing web applications. + +## ASP.NET Platform + +The framework includes a wide range of features, such as an angular code generator with the help of [ABP Suite](https://commercial.abp.io/tools/suite), project templates, and web application themes. These features enable developers to create web applications that are both functional and visually appealing without spending much time on coding. Moreover, ABP Framework provides a common application framework that can be used for different applications, including SaaS, e-commerce, and social media platforms. + +ABP Framework also supports the domain-driven design, which means that the framework is designed to be flexible and adaptable to different business requirements. This approach allows developers to build applications aligned with business needs, ensuring they are efficient and effective. + +## Open Source Dot Net Framework + +One of the major advantages of ABP Framework is its open-source nature. Many developers continuously improve and update the framework, making it more reliable and secure. Moreover, the ABP Framework is compatible with multiple .NET frameworks, including ASP.NET and .NET Core. When starting your project on top of a solid Microsoft web framework, the ABP Framework is one of the best choices. + +![ABP is cross platform](3a0a6b45f7f68832d7a7f72262f3c216.png) + +Another advantage of ABP Framework is that it provides rapid web application development tools that are easy to use. The framework includes project templates that developers can use as a starting point for their web applications, which can significantly reduce the development time. ABP Framework also provides a web app builder that developers can use to create web applications quickly and efficiently. + +## ASPNET Core Architecture + +ABP Framework is also compatible with Microsoft's Clean Architecture, a software design pattern that promotes separation of concerns and maintainability. This integration ensures that the applications developed using ABP Framework are well-structured, easy to maintain, and scalable. Many application marketplace reviewers commented about ABP as the best web application framework. While ABP supports multiple UI choices like MVC, Angular, Blazor Web Assembly, and Blazor Server, the most downloaded one is MVC microservice architecture. If you are here to find a NET application framework for your next NET Core application, you are in the right place! + +![ABP Framework Project Hierarchy](3a0a6b4812b27aa05c1159478175fa02.png) + +Clean Architecture is a design pattern emphasizing the separation of concerns, ensuring that the code is organized in independent layers. This helps developers to write code that is easy to maintain, test and refactor. ABP Framework uses this pattern to structure its application code and ensure it is easy to manage. + +## Open Source Web Framework + +ABP Framework is an open-source web framework that is free to use and distribute. The framework is licensed under the MIT license, meaning developers can use it for commercial and non-commercial purposes without any restrictions. + +ABP Framework provides different templates, which are ASPNET Core web app compatible with various platforms, including Windows, Linux, and macOS. + +## Domain Driven Design DotNet + +The ABP Framework also implements Domain-Driven Design (DDD), a software design methodology that emphasizes the importance of the domain model. The framework provides a guide for implementing DDD through an implementing domain-driven design. It helps developers to create a domain model that is easy to understand, test, and maintain. As ABP is a C# framework, it supports most of the common application framework features for a core framework. + +![ABP Framework - Domain Driven Design e-book](3a0a6b492ee3cbf9482090fcc8473653.png) + +There is also a free PDF e-book for Dotnet developers that explains the Domain Driven Design principle with real-world examples. The book is written by the ABP Core Team. You can download this e-book at [abp.io/books/implementing-domain-driven-design](https://abp.io/books/implementing-domain-driven-design) + +![The official book of ABP Framework: Mastering ABP Framework](3a0a6b58d26f47970f6edd6f6fbee851.png) + +You can also purchase the official Mastering ABP Framework book from Amazon. Check out [amazon.com/Mastering-ABP-Framework-maintainable-implementing/dp/1801079242](https://www.amazon.com/Mastering-ABP-Framework-maintainable-implementing/dp/1801079242) + +## It's a Dotnet Web Framework + +ABP Framework is a dotnet web framework that is designed with C# and provides developers with a set of tools that makes it easy to build modern web applications. Whether you want to start a new dotnet monolithic solution or dotnet microservice solution, you can start with ABP. Creating your own dotnet framework architecture may be hard if you don't have many years of experience. The brain team of the ABP Framework specializes in ASP.NET framework architecture and ASP.NET application frameworks. + +![ABP Framework is developer focused](3a0a6b3c7807c882c1889c1f431b86b7.png) + +## Essential Features of the ABP Framework: + +ASP.NET Core modularity, ASP.NET Core modular development, ASP.NET Core localization, ASP.NET Core SaaS framework, ASP.NET Core distributed, event, bus, ASP.NET Core cross-cutting concerns, ASP.NET Core blob storing, ASP.NET Core audit logging, ASP.NET Core microservice, ASP.NET Core microservice solution, ASP.NET Core microservice example, ASP.NET Core API gateway, ASP.NET Core domain, driven, design, ASP.NET Core layered architecture, ASP.NET Core layering, ASP.NET Core clean architecture, ASP.NET Core authentication, ASP.NET Core authorization, ASP.NET Core UI theme, ASP.NET Core tag helpers, ASP.NET Core identity, ASP.NET Core, identity, server, ASP.NET Core IdentityServer, ASP.NET Core payment module, ASP.NET Core best practices, ASP.NET Core design patterns, ASP.NET Core background jobs, ASP.NET Core exception handling, ASP.NET Core, background, workers, ASP.NET Core repository, ASP.NET Core repository pattern, ASP.NET Core unit of work, ASP.NET Core domain services, ASP.NET Core Swagger, ASP.NET Core content management system, ASP.NET Core CMS module, ASP.NET Core user management, ASP.NET Core Role management, ASP.NET Core permission management + +![ABP Essential Features](3a0a6b4b7f00461297fbe88d4c34b831.png) + +## Open Source Web Application Framework + +ABP Framework is an open-source web application development framework that is free to use and distribute. The framework is licensed under the MIT license, meaning developers can use it for commercial and non-commercial purposes without any restrictions. + +![ABP Framework is open-source](3a0a6b43a8bea7e8df7d2ff6b7f1aa8f.png) + +## C# Web Application Framework + +ABP Framework is built using C#, which is a modern programming language that is widely used in the development of web applications. C# provides developers with features that make it easy to write clean and maintainable code. ABP Framework is a web framework designed to work with C# and provides developers with tools that make it easy to build modern web applications. + +## Key Features + +The following .NET features are available in the ABP Framework: + +.NET modular development, .NET localization, .NET multi-tenancy, .NET SaaS framework, .NET distributed event bus, .NET cross-cutting concerns, .NET, microservice, .NET microservice solution, .NET microservice example, .NET Domain Driven Design, .NET clean architecture, .NET authentication, .NET authorization, .NET best practices, .NET design patterns, .NET exception handling, .NET background workers, .NET unit of work, .NET domain services, .NET user management, .NET role management, .NET permission management + +![ABP Framework Features](3a0a6b3d69a4f5b2b15674fc70e97ba2.png) + +The following keywords best describe the ABP Framework; + +Open source backend framework, open source development framework, open source web app builder, open source web applications, open source web development, web application development framework, web application framework, web application framework software, web application infrastructure, web application open source, asp net framework, asp net open source, ASP.NET application, ASP.NET software, ASP.NET web app, ASP.NET web development, web app builder open source, web app framework, Dotnet framework, Dotnet UI framework, Dotnet web application themes. + + + +## Conclusion + +ABP Framework is a powerful and flexible web application framework that provides developers with the tools to build high-quality web applications quickly and efficiently. It is an open-source, cross-platform framework that supports multiple .NET frameworks, including ASP.NET and .NET Core. ABP Framework provides rapid web application development tools, project templates, and web application themes that enable developers to create visually appealing and functional applications in no time. + +![Try ABP Framework Now to be hero in the first day](3a0a6b3dbc9eb0ada4effa3d06208fb4.png) + +--- + +> I'm Alper Ebicoglu 🧑🏽‍💻\ +> ABP Framework Core Team Member\ +> Follow me for the latest news about .NET and software development:\ +> 📌 [twitter.com/alperebicoglu](https://twitter.com/alperebicoglu)\ +> 📌 [github.com/ebicoglu](https://github.com/ebicoglu)\ +> 📌 [linkedin.com/in/ebicoglu](https://www.linkedin.com/in/ebicoglu)\ +> 📌 [medium.com/@alperonline](https://medium.com/@alperonline) diff --git a/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/3a0a80478f1cfd26d5802eff5361ba70.png b/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/3a0a80478f1cfd26d5802eff5361ba70.png new file mode 100644 index 0000000000..e986bb5719 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/3a0a80478f1cfd26d5802eff5361ba70.png differ diff --git a/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/3a0a87d836c4e1b10a280fbab982d55f.png b/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/3a0a87d836c4e1b10a280fbab982d55f.png new file mode 100644 index 0000000000..574dd90088 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/3a0a87d836c4e1b10a280fbab982d55f.png differ diff --git a/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/post.md b/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/post.md new file mode 100644 index 0000000000..9862081f39 --- /dev/null +++ b/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/post.md @@ -0,0 +1,81 @@ +> *Brief Summary*: +> +> This article is intended for .NET Core developers who wish to create a robust and useful.NET core application. It is a list of the most popular and widely used .NET Core libraries that have been carefully vetted. Go up the GitHub reference link for the DotNet libraries and see how many stars the .NET community has rewarded. + + + +## Best .NET libraries — Top useful libraries every .NET developers use + +.NET Core has become one of the most popular frameworks for developing modern applications. One of the reasons for its popularity is the wide range of libraries available to developers. .NET Core got new updates in its features with lesser coding, deploying high-accomplishment, and extremely scalable applications. Making the underlying architecture functions more effective and efficient without having to reinvent the wheel will free up your time to focus on more crucial tasks, including making your application stand out from the competition. + +In this article, we'll take a closer look at **The Most Popular .NET Libraries Every Developer Should Know**. As a software developer, you're likely familiar with the .NET framework and the many libraries it offers. With so many options available, it can be overwhelming to know which ones to choose for your project. This is the main reason I have compiled a list of the **Top 10 .NET Libraries That Developers Should Use** to make their development process more efficient and effective. A list of Top 10 .NET Core Libraries will let developers understand these so that they can pick appropriate libraries for their projects. + +If you're a .NET Core developer, there are **10 important .NET Core libraries** that you should be familiar with. While creating these **Essential 10 .NET Libraries Every Developer Must Know**, I used NuGet and GitHub.com popular repositories. And all the libraries listed here are also open-source. The list is filtered with only to .NET Core related libraries. Also I excluded the Microsoft .NET Core Framework libraries from this **Top 10 Unique .NET Core Libraries Developers Must Utilize**. So, without further ado, let’s get right into it: + + +![Best .NET libraries with GitHub stars and download counts](3a0a87d836c4e1b10a280fbab982d55f.png) + +## Top 10 best libraries for .NET developers + + +Here's the list of the most popular open-source .NET tools: + +1. **Newtonsoft.Json:** This library is widely used for working with JSON data in .NET applications. It provides high performance and ease of use, making it a go-to solution for serialization and deserialization of JSON data. +2. **Dapper:** It is a simple and efficient ORM that offers high performance and flexibility when working with relational databases. It is easy to use and offers a fast and efficient way to interact with databases. +3. **Polly:** Polly is a library that helps handle transient errors and faults in .NET applications. It offers an easy-to-use policy-based approach to handling retries, timeouts, and circuit breakers, making it a valuable tool for building reliable applications. +4. **AutoMapper**: This .NET Core library simplifies object-to-object mapping by automatically mapping properties from one object to another. This library is especially useful in larger projects where mapping can become time-consuming and tedious. +5. **FluentValidation:** It is a library that provides a fluent API for building validation rules. It makes it easy to create complex validation logic and supports a wide range of validation scenarios, making it a valuable tool for ensuring data integrity in your applications. +6. **Serilog**: This library is a structured logging library that makes it easy to collect and analyze logs from your application. It offers flexibility and extensibility, and supports a variety of sinks for storing logs, including Elasticsearch, SQL Server, and more. +7. **Swashbuckle.AspNetCore.Swagger:** This library generates OpenAPI documentation for your ASP.NET Core Web API. It makes it easy to understand the functionality of your API and allows you to easily generate client code for your API. +8. **NLog**: It is is a free logging platform for .NET with rich log routing and management capabilities. It makes it easy to produce and manage high-quality logs for your application regardless of its size or complexity. +9. **Moq4**: It is is a popular mocking framework for .NET applications. It makes it easy to create mock objects for unit testing, reducing the need for expensive and time-consuming integration testing. +10. **StackExchange.Redis**: This is a library for working with Redis databases in .NET applications. It provides a simple and efficient way to interact with Redis, and offers high performance and scalability. + +------ + + +![10 important .NET Core Libraries](3a0a80478f1cfd26d5802eff5361ba70.png) + + +## Top 10 .NET Core Libraries List That Every Developer Must Know + +Here you can see them in the table with the GitHub stars, GitHub release counts, recent release frequency, NuGet download counts and per day NuGet download counts: + +| GitHub URL | NuGet URL | Stars | Releases | Last release | Downloads | Download Per Day | +| ------------------------------------------------------------ | ------------------------------------------------------------ | ----- | -------- | ------------ | --------- | ---------------- | +| [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) | [Newtonsoft.Json](https://www.nuget.org/packages/Newtonsoft.Json) | 10K | 65 | 1 month ago | 3B | 680K | +| [Dapper](https://github.com/DapperLib/Dapper) | [Dapper](https://www.nuget.org/packages/Dapper) | 16K | 70 | 2 years ago | 216M | 50K | +| [Polly](https://github.com/App-vNext/Polly) | [Polly](https://www.nuget.org/packages/polly) | 12K | 26 | 1 year ago | 335M | 92K | +| [AutoMapper](https://github.com/AutoMapper/AutoMapper) | [AutoMapper](https://www.nuget.org/packages/AutoMapper) | 9K | 41 | 6 months ago | 400M | 90K | +| [FluentValidation](https://github.com/FluentValidation/FluentValidation) | [FluentValidation](https://www.nuget.org/packages/FluentValidation) | 8K | 68 | 3 days ago | 250M | 56K | +| [Serilog](https://github.com/serilog/serilog) | [Serilog](https://www.nuget.org/packages/Serilog) | 6K | 15 | 1 month ago | 722M | 197K | +| [Swashbuckle.AspNetCore.Swagger](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) | [Swashbuckle.AspNetCore.Swagger](https://www.nuget.org/packages/Swashbuckle.AspNetCore.Swagger) | 5K | 28 | 4 months ago | 386M | 168K | +| [NLog](https://github.com/NLog/NLog) | [NLog](https://www.nuget.org/packages/Nlog) | 6K | 125 | 1 week ago | 217M | 48K | +| [Moq](https://github.com/moq/moq4) | [Moq](https://www.nuget.org/packages/Moq) | 5K | 33 | 4 months ago | 418M | 93K | +| [StackExchange.Redis](https://github.com/StackExchange/StackExchange.Redis) | [StackExchange.Redis](https://www.nuget.org/packages/StackExchange.Redis) | 5K | 34 | 11 days ago | 244M | 74K | + + + +In conclusion, these 10 .NET Core libraries are essential tools for any .NET Core developer. They offer a wide range of functionality, from handling errors to mocking for unit testing and simplifying object mapping. Whether you're working on a large-scale enterprise application or a small project, these libraries can help you build more reliable, efficient, and effective applications. + +There's also a cool GitHub page that gathers all kinds of popular .NET tools. Check out https://github.com/quozd/awesome-dotnet + + +### What is ABP Framework? +ABP Framework offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET and the ASP.NET Core platforms. It provides the fundamental infrastructure, production-ready startup templates, modules, themes, tooling, guides and documentation to implement that architecture properly and automate the details and repetitive work as much as possible. + +If you are starting a new ASP.NET Core project, try [abp.io](https://abp.io) now... + + **IT IS FREE AND OPEN-SOURCE!** + +--- + +> I'm Alper Ebicoglu 🧑🏽‍💻 \ +> ABP Framework Core Team Member\ +> Follow me for the latest news about .NET and software development:\ +> 📌 [twitter.com/alperebicoglu](https://twitter.com/alperebicoglu)\ +> 📌 [github.com/ebicoglu](https://github.com/ebicoglu)\ +> 📌 [linkedin.com/in/ebicoglu](https://www.linkedin.com/in/ebicoglu)\ +> 📌 [medium.com/@alperonline](https://medium.com/@alperonline) + + diff --git a/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c6fb57718ff5547cff4fa27c10a.png b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c6fb57718ff5547cff4fa27c10a.png new file mode 100644 index 0000000000..dec11bc1c9 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c6fb57718ff5547cff4fa27c10a.png differ diff --git a/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c6fd580494a5edc64b664497aa0.png b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c6fd580494a5edc64b664497aa0.png new file mode 100644 index 0000000000..783225e175 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c6fd580494a5edc64b664497aa0.png differ diff --git a/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c6ff161f75a4d0fdb68bc77fa88.png b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c6ff161f75a4d0fdb68bc77fa88.png new file mode 100644 index 0000000000..8ed43ac2a7 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c6ff161f75a4d0fdb68bc77fa88.png differ diff --git a/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c70346ae7f3a9b397bbb4c00cb3.png b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c70346ae7f3a9b397bbb4c00cb3.png new file mode 100644 index 0000000000..5a02c2596f Binary files /dev/null and b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c70346ae7f3a9b397bbb4c00cb3.png differ diff --git a/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c70509eaa4595d157033a743a56.png b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c70509eaa4595d157033a743a56.png new file mode 100644 index 0000000000..aa14b424a2 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c70509eaa4595d157033a743a56.png differ diff --git a/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c7070216a981e155eadf3e3cda7.png b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c7070216a981e155eadf3e3cda7.png new file mode 100644 index 0000000000..b562de6dae Binary files /dev/null and b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/3a0a8c7070216a981e155eadf3e3cda7.png differ diff --git a/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/authority-delegation.gif b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/authority-delegation.gif new file mode 100644 index 0000000000..c09f428798 Binary files /dev/null and b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/authority-delegation.gif differ diff --git a/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/post.md b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/post.md new file mode 100644 index 0000000000..9245f99afe --- /dev/null +++ b/docs/en/Community-Articles/2023-04-13-abpio-platform-72-rc-has-been-published/post.md @@ -0,0 +1,211 @@ +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **7.2 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.2! Thanks to all of you. + +## Get Started with the 7.2 RC + +Follow the steps below to try version 7.2.0 RC today: + +1) **Upgrade** the ABP CLI to version `7.2.0-rc.1` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 7.2.0-rc.1 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 7.2.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 breaking changes in this version that may affect your application. +Please see the following migration documents, if you are upgrading from v7.1: + +* [ABP Framework 7.1 to 7.2 Migration Guide](https://docs.abp.io/en/abp/7.2/Migration-Guides/Abp-7_2) +* [ABP Commercial 7.1 to 7.2 Migration Guide](https://docs.abp.io/en/commercial/7.2/migration-guides/v7_2) + + +## What's New with ABP Framework 7.2? + +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: + +* Grouping of Navigation Menu Items +* Introducing the `BlazorWebAssemblyCurrentApplicationConfigurationCacheResetService` +* CMS Kit Comments: Don't Allow External URLs +* Angular UI New Components +* Others + +### Grouping of Navigation Menu Items + +Some applications may need to group their main menus to tidy up their menu structure. For example, you may want to group ABP's menu items, which came from modules in a group named *Admin*. + +In this version, you can allow to define groups and associate menu items with a group. Then your theme can render your menu items within the specified groups. + +**Example:** + +```csharp +private async Task ConfigureMainMenuAsync(MenuConfigurationContext context) +{ + //Creating a new group + context.Menu.AddGroup("Dashboards", l["Dashboards"]); + + //Setting the group name for menu items + context.Menu + .AddItem(new ApplicationMenuItem("Home", l["Menu:Home"], groupName: "Dashboards") + .AddItem(new ApplicationMenuItem("Home", l["Menu:Dashboard"], groupName: "Dashboards"); +} +``` + +> **Note**: Currently, only the [LeptonX Theme](https://leptontheme.com/) renders groups for menu items. See the "LeptonX - Render Groups for Menu Items" section below for a demonstration. + +### Introducing the `BlazorWebAssemblyCurrentApplicationConfigurationCacheResetService` + +In this version, we have introduced the `BlazorWebAssemblyCurrentApplicationConfigurationCacheResetService` service to re-initialize application configurations. This service can be helpful, if you want to reset the application configurations after changing some configurations through your code. For example, you might have changed the values of some settings and might want to be able to get the new settings without the need to refresh the page. For this purpose, the `BlazorWebAssemblyCurrentApplicationConfigurationCacheResetService.ResetAsync()` method can be used to re-initialize the application configurations and cache the updated configurations for further usages. + +> For more information, please see [https://github.com/abpframework/abp/issues/15887](https://github.com/abpframework/abp/issues/15887). + +### CMS Kit Comments: Disallowing External URLs + +CMS Kit provides a [comment system](https://docs.abp.io/en/abp/7.2/Modules/Cms-Kit/Comments) to add the comment feature to any kind of resource, like blog posts for an example. The CMS Kit comment section is good for visitor comments and can improve your interaction with your application users. + +Sometimes, malicious users (or bots) can submit advertisement links into the comment sections. With this version, you can specify *allowed external URLs* for a specific comment section and disallow any other external URLs. You just need to configure the `CmsKitCommentOptions` as follows: + +```csharp +Configure(options => +{ + options.AllowedExternalUrls = new Dictionary> + { + { + "Product", + new List + { + "https://abp.io/" + } + } + }; +}); +``` + +If you don't specify any allowed external URLs for a specific comment section, all external URLs are allowed to be used in comments. For more information, please refer to the [CMS Kit: Comments documentation](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Comments). + +### New Components for Angular UI + +In this version, we have created some useful UI components for Angular UI, which are `abp-checkbox`, `abp-form-input`, and `abp-card`. Instead of using the related HTML elements and specifying bootstrap classes, from this version on, you can use these components. + +You can see the following examples for the usage of the `abp-card` component: + +```html + + +
...
+
+
+``` + +> See the [Card Component documentation](https://docs.abp.io/en/abp/7.2/UI/Angular/Card-Component) for more information. + +### Others + +* OpenIddict registered custom scopes have been added to the openid-configuration endpoint (`/.well-known/openid-configuration`) automatically. See [#16141](https://github.com/abpframework/abp/issues/16141) for more information. +* Two new tag-helpers have been added to MVC UI, which are `abp-date-picker` and `abp-date-range-picker`. See [#15806](https://github.com/abpframework/abp/pull/15806) for more information. +* Filtering/searching has been improved in the Docs Module and unified under a single *Search* section. See [#15787](https://github.com/abpframework/abp/issues/15787) for more information. + +## What's New with ABP Commercial 7.2? + +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.2. + +### Authority Delegation + +Authority Delegation is a way of delegating the responsibility of the current user to a different user(s) for a limited time. Thus, a user can be switched to the delegated users' account and perform actions on their behalf. + +This version introduces support for the **Authority Delegation** in the [Account Module](https://docs.abp.io/en/commercial/latest/modules/account). You can check the following gif for a demonstration: + +![authority delegation](authority-delegation.gif) + +> You can check the [Authority Delegation in ABP Commercial](https://community.abp.io/posts/authority-delegation-in-abp-commereical-3wtljpp0) post for an overview of this feature. + +### Force Password Change at Next Logon + +It's a typical need to force users to change their password after their first successful login. Especially, if you as admin create a new user (*from the Users page of the Identity Pro module*, for example) with an easy initial password or a randomly generated password. The user should change his/her password with a more secure password that only they know. + +In this version, the "Forcing Password Change at Next Logon" feature has been added for this kind of purpose. Now, it's possible to force a user to change their password on the next login. + +The admin only needs to check the *Should change password on next login* option, while creating a new user: + +![force-password-change.png](3a0a8c6fb57718ff5547cff4fa27c10a.png) + +After the first successful login, a password change page will open and force the user to change their password: + +![password-change-form.png](3a0a8c6fd580494a5edc64b664497aa0.png) + +Then, the user starts using their account with a secure password that only they know. + +### Periodic Password Changes (Password Aging) + +**Password aging** is a mechanism to force users to periodically change their passwords. It allows you to specify a max number of days that a password can be used before it has to be changed. + +![password-aging.png](3a0a8c6ff161f75a4d0fdb68bc77fa88.png) + +You can force this behavior in the "Password renewing settings" section of the Settings page as can be seen in the image above. Then, after the specified time has passed, users will have to renew their passwords. + +### LeptonX - Render Groups for Menu Items + +As mentioned in the *Grouping of Navigation Menu Items* section above, the [LeptonX Theme](https://leptontheme.com/) renders groups for menu items: + +![leptonx-group-render.png](3a0a8c70346ae7f3a9b397bbb4c00cb3.png) + +### Suite: Show Properties on Create/Update/List Pages + +In this version, ABP Suite allows you to choose whether a property is visible/invisible on the create/update modals and list page. It also allows you to set specific properties to *readonly* on the update modals. + +![suite-property.png](3a0a8c70509eaa4595d157033a743a56.png) + +## Community News + +### ABP - DOTNET CONF'23 + +![abp-conf.png](3a0a8c7070216a981e155eadf3e3cda7.png) + +As the ABP team, we've organized 10+ [online events](https://community.abp.io/events) and gained a good experience with software talks. We are organizing ABP Dotnet Conference 2023, a full-featured software conference, in May. You can visit [https://abp.io/conference](https://abp.io/conference) to see speakers, talks, schedules, and other details. + +**Less than a month left until the event**! Don't forget to take your seat and buy an early bird ticket from [https://kommunity.com/volosoft/events/1st-abp-conference-96db1a54](https://kommunity.com/volosoft/events/1st-abp-conference-96db1a54)! + +### New ABP Community Posts + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [What’s New in .NET 8 🧐 ? Discover ALL .NET 8 Features](https://community.abp.io/posts/whats-new-in-.net-8-discover-all-.net-8-features-llcmrdre) by [Alper Ebicoglu](https://twitter.com/alperebicoglu). +* [Converting Create/Edit Modal to Page - Blazor](https://community.abp.io/posts/converting-createedit-modal-to-page-blazor-eexdex8y) by [Enis Necipoglu](https://twitter.com/EnisNecipoglu). +* [Using Dapper with the ABP Framework](https://community.abp.io/posts/using-dapper-with-the-abp-framework-shp74p2l) by [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan). +* [ABP React Template](https://community.abp.io/posts/abp-react-template-33pjmran) by [Anto Subash](https://twitter.com/antosubash). +* [How to Export Data to Excel Files with ASP.NET Core Minimal API](https://community.abp.io/posts/how-to-export-data-to-excel-files-with-asp.net-core-minimal-api-79o45u3s) by [Berkan Sasmaz](https://twitter.com/berkansasmazz). + +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 Framework: Open Source Web Application Development Framework](https://blog.abp.io/abp/open-source-web-application-development-framework) by [Alper Ebicoglu](https://twitter.com/alperebicoglu). +* [ABP Framework: The Ultimate .NET Web Framework for Rapid Application Development](https://blog.abp.io/abp/ultimate-net-web-framework-for-rapid-application-development) by [Alper Ebicoglu](https://twitter.com/alperebicoglu). +* [Top 10 .NET Core Libraries Every Developer Should Know 🔥](https://blog.abp.io/abp/Top-10-.NET-Core-Libraries-Every-Developer-Should-Know) by [Alper Ebicoglu](https://twitter.com/alperebicoglu) + +## 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.2/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v7.2 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! diff --git a/docs/en/Community-Articles/2023-04-14-you-are-invited-to-abp-net-conf23-/post.md b/docs/en/Community-Articles/2023-04-14-you-are-invited-to-abp-net-conf23-/post.md new file mode 100644 index 0000000000..6f01e73a3f --- /dev/null +++ b/docs/en/Community-Articles/2023-04-14-you-are-invited-to-abp-net-conf23-/post.md @@ -0,0 +1,65 @@ +Hey .NET developers! + +🎉 We are thrilled to share with you that we are hosting a .NET online event: [ABP .NET Conference](https://abp.io/conference) which will take place on **May 10th, 2023**. + +[ABP .NET Conf’23](https://abp.io/conference) is a unique opportunity for .NET developers to: +* Gain insight into the latest trends and developments in the .NET world from industry experts, +* Network with like-minded individuals, +* Discover new technologies and solutions, +* And open many more opportunities! +The conference is expected to attract hundreds of global professionals and experts from all around the globe. + +We aim to inspire and motivate the [ABP .NET Conference](https://abp.io/conference)’s attendees from different angles to embrace new perspectives, improve their skills, and advance their careers in the .NET world. + +Regardless of the location, our claim is to make you feel like you are actually in an in-person conference area in [ABP .NET Conf’23](https://abp.io/conference)! We specifically picked the live streaming platform to let attendees of the [ABP .NET Conference](https://abp.io/conference) engage with each other, speakers and sponsors. + +🧐 **Usual stuff will exist:** +* A common area with chat box to let attendees talk with each other +* Sponsors will have rooms, just like a booth, for you to visit (we know not being able to take promotional items is a bummer but we have a solution, trust me) +* Q&A box to ask your questions to the speakers during the session + +🕺 **Fun parts will also exist:** +* A special engagement feature named “90SN” for you to randomly match with another attendee and talk, exchange socials and simply videochat for 90 seconds. –This is an especially great addition to remove the obstacles of virtual events against networking. +* You will have a photo booth to take a picture of yourself and share on your social media with a specifically-designed ABP .NET Conf’23 photo frame. +* Raffles will take place at the end of the conference for giveaways. They will be given to the ones who actually participated in the ABP .NET Conference. + +Our main purpose of organizing the [ABP .NET Conference](https://abp.io/conference) is to provide valuable insights and practical knowledge to the [ABP .NET Conf’23](https://abp.io/conference) attendees and make our contribution towards the community of ABP and overall .NET. You will have the chance to expand your understanding of the .NET and its ecosystem by taking the best practices through keynote speech by [Taswar Bhatti](https://abp.io/conference/speakers/taswar-bhatti) from Microsoft, and the expert-led sessions from a talented line of speakers. + +With [ABP .NET Conference](https://abp.io/conference) being our first actual conference beside our regular [ABP Community Talks](https://community.abp.io/events), it is quite special for us. Therefore, we poured tears and sweat to create a great experience out of it for you. This is why, we picked a line of pretty talented speakers in the .NET world: +* 🎙️[Halil Ibrahim Kalkan, Co-Founder at Volosoft / Lead Architect and Developer of ABP Framework](https://abp.io/conference/speakers/halil-ibrahim-kalkan), +* 🎙️[Cecil Phillip, Developer Advocate at Stripe](https://abp.io/conference/speakers/cecil-phillip), +* 🎙️[Daniel Marbach, Software Engineer at Particular Software](https://abp.io/conference/speakers/daniel-marbach), +* 🎙️[Gleidson Nascimento, SRE/Cloud Advisor at Urvin Finance](https://abp.io/conference/speakers/gleidson-nascimento), +* 🎙️[Isaac Levin, .NET Developer Advocate at Amazon Web Services](https://abp.io/conference/speakers/isaac-levin), +* 🎙️[Jimmy Engström, Microsoft MVP / Developer at Erik Penser Bank / Azm dev](https://abp.io/conference/speakers/jimmy-engstrom), +* 🎙️[Joseph Guadagno, JosephGuadahno.NET, LLC](https://abp.io/conference/speakers/joseph-guadagno), +* 🎙️[Melissa Houghton, Lead Software Engineer and Developer Relations at Azenix](https://abp.io/conference/speakers/melissa-houghton), +* 🎙️[Nicolas Frankel, Head of Developer Advocacy at Apache APISIX](https://abp.io/conference/speakers/nicolas-frankel), +* 🎙️[Shaun Walker, CTO and Professional Services at Cognizant](https://abp.io/conference/speakers/shaun-walker), +* 🎙️[Simon Painter, Senior Software Developer at Mueller Dairies](https://abp.io/conference/speakers/simon-painter), +* 🎙️[Taswar Bhatti, Azure GTM Manager for CEMA at Microsoft EMEA](https://abp.io/conference/speakers/taswar-bhatti), +* 🎙️[Todd Gardner, CEO at Request Metrics](https://abp.io/conference/speakers/todd-gardner) + +We invite everyone that is related within the .NET ecosystem and want to stay up-to-date on the latest advancements and trends in the .NET world. + +Most exciting of all, there will be raffles from our sponsors for you to look forward to! 🎁 + +What are you waiting for! Come and join us for the [ABP .NET Conference’23](http://conf.abp.io/)!⏳ +
+ +> 👉 **[REGISTER TO ABP .NET CONF'23 NOW](https://kommunity.com/volosoft/events/1st-abp-conference-96db1a54)** 👈 +
+ +🚨 **Last Date to Catch The Early-Bird Tickets:** 🚨 +
April 21, 2023 + +🗓️ **Live Date:** 🗓️ +
Wednesday, May 10, 2023 + +🕘 **Live Times:** 🕔 +
09:00 AM UTC +
17:00 PM UTC + +
+ +Special thanks to our sponsors [ApiX-Drive](https://apix-drive.com/), [Decision Tree](https://decisiontree.tech/), [DM Consulting](https://www.dmconsulting.it/), [.NET Foundation](https://dotnetfoundation.org/), [Microsoft](https://www.microsoft.com/), [Packt Publishing](https://www.packtpub.com/), [WAi Technology](https://waiin.com/). \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-04-18--speed-up-your-aspnet-application-/post.md b/docs/en/Community-Articles/2023-04-18--speed-up-your-aspnet-application-/post.md new file mode 100644 index 0000000000..6f36474400 --- /dev/null +++ b/docs/en/Community-Articles/2023-04-18--speed-up-your-aspnet-application-/post.md @@ -0,0 +1,119 @@ +## How to Optimize Your ASP.NET Application for Improved Performance + +If you want your ASP.NET application to perform well, you need to optimize it for speed, responsiveness, and user experience. Performance optimization is critical for factors like fast page load times, improved response efficiency, and happy users. In this article, I'll provide several tips and tricks to help you optimize performance in ASP.NET Core. + +### Use Response Compression in Your ASP.NET Application +You can use ASP.NET Core's built-in response compression middleware to compress the response data and reduce the amount of data that needs to be transferred over the network. To use response compression, add the following code to your application's Startup.cs file: + +```csharp +services.AddResponseCompression(options => +{ + options.EnableForHttps = true; +}); + +app.UseResponseCompression(); +``` + +### 🖼️ Optimize Images in Your ASP.NET Application: + +Images can be a major contributor to page bloat and slow load times. Here are some tips to optimize images: + +🖌️ Use a tool like ImageOptim or Kraken.io to compress and optimize images. + +🖼️ Specify the width and height of images in HTML so the browser can allocate space for them before they load. + +📝 Use alt attributes to provide descriptive text for images, which can improve accessibility and also help with SEO. + +📜 Use lazy loading for images that are below the fold, meaning they're not visible on the initial screen view. You can use libraries like Vanilla LazyLoad to implement lazy loading. + +📱 Use responsive images to serve different image sizes to different devices. This can improve page load times by reducing the size of images that are displayed on smaller devices. + +💻 Example: + +```html + + + + Image + +``` + +```javascript +var lazyLoadInstance = new LazyLoad(); +``` + +### 🧱 Optimize HTML in Your ASP.NET Application: + +The structure and organization of HTML can affect the page speed. Here are some tips to optimize HTML: + +📝 Use the heading tags (h1, h2, h3, etc.) in a logical and sequential order. + +🔩 Use the "defer" attribute for script tags that don't need to be executed immediately. This can improve the page load times by delaying the execution of scripts until after the page has rendered. + +🔩 Use the "async" attribute for script tags that can be executed asynchronously. This can further improve the page load times by allowing scripts to be downloaded and executed simultaneously. + +🧱 Use semantic HTML elements (like nav, section, and article) to provide additional structure and meaning to the page. + +### 🎨 Optimize CSS and JavaScript in Your ASP.NET Application: + +CSS and JavaScript files can be a major contributor to the page load times. Here are some tips to optimize CSS and JavaScript in your ASP.NET application: + +🔨 Minify and concatenate CSS and JavaScript files to reduce their size. + +🔩 Use the "defer" or "async" attributes for script tags to delay or asynchronously load scripts. + +### 🔡 Use system fonts in Your ASP.NET Application: + +Loading custom fonts can be slow and increase page load times. Using system fonts can improve page speed by allowing the browser to use fonts that are already installed on the user's device. + +### 🖼️ Use Placeholders and Progress Indicators in Your ASP.NET Application: + +To improve the perceived performance of your website, you can use placeholders and progress indicators for slow-loading sections of your page. You can use JavaScript to load these sections after the initial page load. + +💻 Example: + +```html + +
+

Loading...

+
+``` + +```javascript +const placeholder = document.querySelector('#placeholder'); + fetch(placeholder.dataset.url) + .then(response => response.text()) + .then(html => placeholder.innerHTML = html); +``` + +### 🔗 Use the Appropriate Link Text and ARIA Labels: + +When using links, use appropriate link texts that accurately describe the content of the linked page. This can improve the accessibility and also help with SEO. + +ARIA labels should also be used to provide additional context for links. This can also improve the accessibility and help with SEO. + +💻 Example: + +```html +Example +Another Example +``` + +### 🌐 Optimize the Third-party Resources in Your ASP.NET Application: + +Third-party resources like social media widgets and advertising scripts can slow down the page load times. Here are some tips to optimize third-party resources: + +🔩 Use asynchronous scripts when possible. + +🔍 Only load third-party resources that are necessary for the page. + +By following these optimization techniques, you can significantly improve the page speed of your ASP.NET Core web application. + +## Optimized Web Applications with ABP Framework? + +ABP Framework offers an opinionated architecture to build enterprise software solutions with ASP.NET Core best practices on top of the .NET and the ASP.NET Core platforms. It is also a powerful infrastructure to help you develop low-effort web-optimized applications. +It provides the fundamental web application infrastructure, production-ready dotnet startup templates, modules, asp.net core ui themes, tooling, guides and documentation to implement that ASP.NET core architecture properly and automate the details and repetitive work as much as possible. + +If you are starting a new ASP.NET Core project and want a fast website [abp.io](https://abp.io/) now... + +**IT IS FREE AND OPEN-SOURCE!** \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-05-02-c-12--discover-the-exciting-new-features--improvements-/post.md b/docs/en/Community-Articles/2023-05-02-c-12--discover-the-exciting-new-features--improvements-/post.md new file mode 100644 index 0000000000..dc51ac2b5d --- /dev/null +++ b/docs/en/Community-Articles/2023-05-02-c-12--discover-the-exciting-new-features--improvements-/post.md @@ -0,0 +1,113 @@ +Several exciting new features come with C# 12 and the.NET 8 preview. C# is easier to use and more effective than **previous** versions thanks to changes made by the Microsoft development team. **In** **this** **post,** **we'll** **take** **a** **quick** **look** **at** some of the **major** changes in C# **12.** + + + +## 1. Improved Support for Interpolated Strings 🧩 + +With the release of C# 12, you now have the option to incorporate expressions inside interpolated strings. With the help of this functionality, You can now create dynamic values for strings using complicated expressions and techniques. + +For instance, you can use code like this: + +``` +int x = 10; +string message = $"The value of x is {x}, and its square is {x*x}."; +``` + +This will result in a string value of "*The value of x is 10, and its square is 100.*" + +## 2. Primary Constructors 📝 + + +You can now create primary constructors in any class and struct. With primary constructors, developers can add parameters to the class declaration and use these values inside the class body. + +Primary constructors were introduced in C# 9 as part of the record positional syntax. C# 12 extends these to all structs and classes. + +```csharp + public class Book(int pageSize, string authorName, IEnumerable prices) + { + public Book(int pageSize, string authorName) : this(pageSize, authorName, Enumerable.Empty()) { } + public int pageSize => pageSize; + public string authorName { get; set; } = authorName; + public float totalPrice => prices.Sum(); + } +``` + +The good part is that you can avoid the pain of declaring private fields and, you know, binding parameter values to those fields in those tedious constructor bodies by using primary constructors instead. + +## 3. Improved Lambda Expressions 🐑 + +Many of us are using Lambda expressions in our daily development to gain the code better readability. +With this version we see that many enhancements came to lambda expressions make them more effective. +For example, you can now create more complex expressions within lambda functions using the new `and` , `or` operators. +Besides, lambda expressions can now be transformed into expression trees, simplifying the construction of complex queries and optimizing performance. + +## 4. Async Streams 🌐 + +You may iterate through asynchronous data sources thanks to the new `async` streams feature in C# 12. +This new iterator `await foreach` gains us to iterate over a set of async data. +See the following code snippet: + +```csharp +await foreach (var record in FetchRecordsAsyncData()) +{ + Console.WriteLine(record.text); +} +``` + +This will iterate over the asynchronous data returned by the `GetAsyncData()` method and writes each item's text to the console. + +## 5. Target-typed New Expressions 🎯 + +Target-typed new expressions, a new feature in C# 12, make it simpler to construct new objects. +You can now declare new objects using the `var` keyword. +The object's type is inferred from the context. +Especially when dealing with complex types, it gives us better code readability. + +An alternative to writing: + +```csharp +AcmeClass thatObject = new AcmeClass(); +``` + +You can now write: + +```csharp +var thatObject = new AcmeClass(); +``` + + + +## Conclusion 🎬 + +As always Microsoft makes developers' life easier with every release of .NET and C#. +C# 12 comes with many features and improvements. +You now have new tools at your disposal to create more effective, concise, and durable code. +You may now design more potent and reliable applications with C# thanks to the increased support for interpolated strings, records, lambda expressions, target-typed new expressions, and async streams. + + + +## Start C# 12 with the ABP Framework 📚 + +ABP Framework offers an opinionated architecture to build enterprise software solutions with ASP.NET Core best practices on top of the .NET and the ASP.NET Core platforms. It is also a powerful infrastructure to help you develop low-effort web-optimized applications. It provides the fundamental web application infrastructure, production-ready dotnet startup templates, modules, asp.net core ui themes, tooling, guides and documentation to implement that ASP.NET core architecture properly and automate the details and repetitive work as much as possible. + +If you are starting a new ASP.NET Core project and want a fast website [abp.io](https://abp.io/) now... + +🆓 **It's FREE & OPEN-SOURCE!** 🔓 + + +Happy coding 🍿✨ + + +--- + + + +> I'm Alper Ebicoglu 🧑🏽‍💻\ +> ABP Framework Core Team Member\ +> Follow me for the latest news about .NET and software development:\ +> 📌 [twitter.com/alperebicoglu](https://twitter.com/alperebicoglu)\ +> 📌 [github.com/ebicoglu](https://github.com/ebicoglu)\ +> 📌 [linkedin.com/in/ebicoglu](https://www.linkedin.com/in/ebicoglu)\ +> 📌 [medium.com/@alperonline](https://medium.com/@alperonline) + + diff --git a/docs/en/Community-Articles/2023-05-04--abpio-platform-72-final-has-been-released/3a0af7a8a3b472b85ab9c7c030934121.png b/docs/en/Community-Articles/2023-05-04--abpio-platform-72-final-has-been-released/3a0af7a8a3b472b85ab9c7c030934121.png new file mode 100644 index 0000000000..b562de6dae Binary files /dev/null and b/docs/en/Community-Articles/2023-05-04--abpio-platform-72-final-has-been-released/3a0af7a8a3b472b85ab9c7c030934121.png differ diff --git a/docs/en/Community-Articles/2023-05-04--abpio-platform-72-final-has-been-released/post.md b/docs/en/Community-Articles/2023-05-04--abpio-platform-72-final-has-been-released/post.md new file mode 100644 index 0000000000..7dd574196c --- /dev/null +++ b/docs/en/Community-Articles/2023-05-04--abpio-platform-72-final-has-been-released/post.md @@ -0,0 +1,85 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 7.2 versions have been released today. + +## What's New With Version 7.2? + +All the new features were already explained in detail in the [7.2 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-7.2-RC-Has-Been-Published), so there is no need to go over them again. Check it out for more details. + +## Getting Started with 7.2 + +### Creating New Solutions + +You can create a new solution with the ABP Framework version 7.2 by either using the `abp new` command or generating the CLI command on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to Upgrade an Existing Solution + +#### Install/Update the ABP CLI + +First, install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update the existing CLI: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading Existing Solutions with the ABP Update Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP-related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guides + +There are breaking changes in this version that may affect your application. +Please see the following migration documents if you are upgrading from v7.1: + +* [ABP Framework 7.1 to 7.2 Migration Guide](https://docs.abp.io/en/abp/7.2/Migration-Guides/Abp-7_2) +* [ABP Commercial 7.1 to 7.2 Migration Guide](https://docs.abp.io/en/commercial/7.2/migration-guides/v7_2) + +## Community News + +### ABP - DOTNET CONF'23 + +![abp-conf.png](3a0af7a8a3b472b85ab9c7c030934121.png) + +As the ABP team, we've organized 10+ [online events](https://community.abp.io/events) and gained a good experience with software talks. We are organizing ABP Dotnet Conference 2023, a full-featured software conference, on May 10. You can visit [https://abp.io/conference](https://abp.io/conference) to see the speakers, talks, schedules, and other details. + +Don't forget to take your seat and buy a ticket from [https://kommunity.com/volosoft/events/1st-abp-conference-96db1a54](https://kommunity.com/volosoft/events/1st-abp-conference-96db1a54)! + +### New ABP Community Posts + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Converting Create/Edit Modal to Page AngularUI](https://community.abp.io/posts/converting-createedit-modal-to-page-angularui-doadhgil) by [Masum Ulu](https://twitter.com/masumulu) +* [How to Export Data to Excel Files with ASP.NET Core Minimal API](https://community.abp.io/posts/how-to-export-data-to-excel-files-with-asp.net-core-minimal-api-79o45u3s) by [Berkan Sasmaz](https://twitter.com/berkansasmazz) +* [ABP React Template](https://community.abp.io/posts/abp-react-template-33pjmran) by [Anto Subash](https://twitter.com/antosubash) +* [Using Dapper with the ABP Framework](https://community.abp.io/posts/using-dapper-with-the-abp-framework-shp74p2l) by [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan) +* [Converting Create/Edit Modal to Page - Blazor](https://community.abp.io/posts/converting-createedit-modal-to-page-blazor-eexdex8y) by [Enis Necipoglu](https://twitter.com/EnisNecipoglu) +* [What’s New in .NET 8 🧐 ? Discover ALL .NET 8 Features](https://community.abp.io/posts/whats-new-in-.net-8-discover-all-.net-8-features-llcmrdre) by [Alper Ebicoglu](https://twitter.com/alperebicoglu) +* [Authority Delegation in ABP Commercial](https://community.abp.io/posts/Authority%20Delegation%20In%20ABP%20Commereical-3wtljpp0) by [Liang Shiwei](https://github.com/realLiangshiwei) + +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: + +* [You Are Invited to ABP .NET Conf’23! 📣](https://blog.abp.io/abp/You-Are-Invited-to-ABP-dotNET-Conf23) by [Bige Beşikçi](https://twitter.com/bigedediki) +* [💻 Speed Up Your ASP.NET Application 🚀](https://blog.abp.io/abp/Speed-Up-Your-ASP.NET-Application) by [Salih Özkara](https://twitter.com/salihozkara_) +* [C# 12 🔍 Discover the Exciting New Features & Improvements 🆕🚀](https://blog.abp.io/abp/CSharp-12-Discover-the-Exciting-New-Features-and-Improvements) by [Alper Ebiçoğlu](https://twitter.com/alperebicoglu) + +## About the Next Version + +The next feature version will be 7.3. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. diff --git a/docs/en/Community-Articles/2023-05-18-abp-net-conference-2023-wrap-up/3a0b4156603fad07000254bf7ec80ab0.png b/docs/en/Community-Articles/2023-05-18-abp-net-conference-2023-wrap-up/3a0b4156603fad07000254bf7ec80ab0.png new file mode 100644 index 0000000000..4e78e8982b Binary files /dev/null and b/docs/en/Community-Articles/2023-05-18-abp-net-conference-2023-wrap-up/3a0b4156603fad07000254bf7ec80ab0.png differ diff --git a/docs/en/Community-Articles/2023-05-18-abp-net-conference-2023-wrap-up/3a0bac0a6ffa3cbcea65d8806d938aea.png b/docs/en/Community-Articles/2023-05-18-abp-net-conference-2023-wrap-up/3a0bac0a6ffa3cbcea65d8806d938aea.png new file mode 100644 index 0000000000..65ad8c14d1 Binary files /dev/null and b/docs/en/Community-Articles/2023-05-18-abp-net-conference-2023-wrap-up/3a0bac0a6ffa3cbcea65d8806d938aea.png differ diff --git a/docs/en/Community-Articles/2023-05-18-abp-net-conference-2023-wrap-up/post.md b/docs/en/Community-Articles/2023-05-18-abp-net-conference-2023-wrap-up/post.md new file mode 100644 index 0000000000..093c1f42ac --- /dev/null +++ b/docs/en/Community-Articles/2023-05-18-abp-net-conference-2023-wrap-up/post.md @@ -0,0 +1,50 @@ +Hello and gratitudes, ABP.IO Community! + +We are happy to share the success of the ABP.NET Conference 2023, which captivated overwhelmingly interested live viewers from all over the world. ABP .NET Conference 2023, besides being the first full-day ABP Community event experience, it was also a remarkable one. The intense engagement and attention shown by the community towards the amazing line up of 13 talented speakers was worth mentioning. Join me as we give thanks for the outstanding support and explore the fascinating conversations that took place during this truly global .NET event. + +The virtual nature of our conference allowed us to transcend geographical boundaries, bringing together individuals from diverse cultures and up to 59 different countries. The map below showcases the countries of the live viewers, with darker shades indicating higher minutes viewed. It is an incredible feeling for us to reach this amount of global audience and see the impact of our conference. + +![Screenshot 2023-05-18 at 15.13.25.png](3a0b4156603fad07000254bf7ec80ab0.png) + +The success of ABP .NET Conference 2023 would not have been possible without the invaluable contributions of our talented speakers. These 13 great line up of speakers which include .NET experts and Microsoft MVPs delivered captivating talks that resonated with the audiences. Each of the talk attracted great amount interest and a lot of questions, sparking curiosity in the attendees. We extend our deepest appreciation to each speaker for their valuable insights and for igniting the curiosity throughout the ABP .NET Conference 2023. Let’s remember them and their talk titles: +* 🎙️[Halil Ibrahim Kalkan, Co-Founder at Volosoft / Lead Architect and Developer of ABP Framework](https://twitter.com/hibrahimkalkan), +* 🎙️[Cecil Phillip, Developer Advocate at Stripe](https://twitter.com/cecilphillip), +* 🎙️[Daniel Marbach, Software Engineer at Particular Software](https://twitter.com/danielmarbach), +* 🎙️[Gleidson Nascimento, SRE/Cloud Advisor at Urvin Finance](https://twitter.com/slaterx), +* 🎙️[Isaac Levin, .NET Developer Advocate at Amazon Web Services](https://twitter.com/isaacrlevin), +* 🎙️[Jimmy Engström, Microsoft MVP / Developer at Erik Penser Bank / Azm dev](https://twitter.com/EngstromJimmy), +* 🎙️[Joseph Guadagno, JosephGuadahno.NET, LLC](https://twitter.com/jguadagno), +* 🎙️[Melissa Houghton, Lead Software Engineer and Developer Relations at Azenix](https://twitter.com/meliss_houghton), +* 🎙️[Nicolas Frankel, Head of Developer Advocacy at Apache APISIX](https://twitter.com/nicolas_frankel), +* 🎙️[Shaun Walker, CTO and Professional Services at Cognizant](https://twitter.com/sbwalker), +* 🎙️[Simon Painter, Senior Software Developer at Mueller Dairies](https://twitter.com/madSimonJ), +* 🎙️[Taswar Bhatti, Azure GTM Manager for CEMA at Microsoft EMEA](https://twitter.com/taswarbhatti), +* 🎙️[Todd Gardner, CEO at Request Metrics](https://twitter.com/toddhgardner) + +We are grateful to the each live viewers who dedicated their time and actively participated in ABP .NET Conference 2023. Your presence and engagement made ABP .NET Conference the success it achieved. The image representing your countries serves as a vivid reminder of the collective enthusiasm and passion that raised from each corner of the world. We are humbled by your support and inspired by the connections forged through shared knowledge. + +The interactive nature of ABP .NET Conference 2023 provided an ideal platform for attendees to engage with the speakers. The depth of the subjects presented and the multitude of questions asked during the Q&A sessions showed the intellectuality of the audience. Each question provided a base for engaging discussions and enriched the experience for everyone. The exchange of ideas and the diverse perspectives brought the beauty of the inclusiveness of the ABP .NET Conference 2023. + +For a special thank to our not only a sponsor but also a great partner of ABP Commercial - [Wai Technologies](https://waiin.com/). Besides the impactful contribution of Wai Technologies to the success of our event, we would like to highlight their solid service to the customers. One of their remarkable achievements was assisting a large enterprise-grade logistics company in completely revamping their legacy sales and order management platform. + +Wai Technologies played a crucial role in enabling the logistics company to achieve over 50% acceleration in taking their product to market. They implemented practical solutions that significantly improved application usability, management, and scaling for the company. + +How Wai Technologies refactored the monolithic application to the Micro- +services Architecture: + +![Screenshot 2023-06-08 at 10.16.40.png](3a0bac0a6ffa3cbcea65d8806d938aea.png) + +The technology stack utilized by Wai Technologies included the following: +-ABP Commercial Micro-services +-Angular Frontend +-SQL/Mongo DB +-Azure BLOB Storage +-Azure App Insights +-Docker, Azure Kubernetes Service (AKS) +-Elsa.Net for Workflows +-Elsa Visual workflow Designer + +We are grateful to our partner, Wai Technologies, for their invaluable contributions and expertise. It’s been always a great partnership between ABP Commercial & Wai Technologies. + + +Special thanks to our other sponsors [ApiX-Drive](https://apix-drive.com/), [Decision Tree](https://decisiontree.tech/), [DM Consulting](https://www.dmconsulting.it/), [.NET Foundation](https://dotnetfoundation.org/), [Microsoft](https://www.microsoft.com/), [Packt Publishing](https://www.packtpub.com/). \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac23c58b6d34e665030b4f089e9e.png b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac23c58b6d34e665030b4f089e9e.png new file mode 100644 index 0000000000..b248970b47 Binary files /dev/null and b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac23c58b6d34e665030b4f089e9e.png differ diff --git a/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac23df9ab9c68f361acd9c9fa79b.png b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac23df9ab9c68f361acd9c9fa79b.png new file mode 100644 index 0000000000..4ad00ddd5f Binary files /dev/null and b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac23df9ab9c68f361acd9c9fa79b.png differ diff --git a/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac23fd1a5e7625d1fa11b27684ce.png b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac23fd1a5e7625d1fa11b27684ce.png new file mode 100644 index 0000000000..407d8bc6d3 Binary files /dev/null and b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac23fd1a5e7625d1fa11b27684ce.png differ diff --git a/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac241d501c2727fd77b885edbfe9.png b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac241d501c2727fd77b885edbfe9.png new file mode 100644 index 0000000000..d627f5c783 Binary files /dev/null and b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac241d501c2727fd77b885edbfe9.png differ diff --git a/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac2466ce529b36ae8e6c38603f80.png b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac2466ce529b36ae8e6c38603f80.png new file mode 100644 index 0000000000..90ae483bec Binary files /dev/null and b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac2466ce529b36ae8e6c38603f80.png differ diff --git a/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac24d1635475ef24d00707bbc67b.png b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac24d1635475ef24d00707bbc67b.png new file mode 100644 index 0000000000..b3add3ebc0 Binary files /dev/null and b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac24d1635475ef24d00707bbc67b.png differ diff --git a/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac250d28086e119cd60b671240ad.png b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac250d28086e119cd60b671240ad.png new file mode 100644 index 0000000000..9175452037 Binary files /dev/null and b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac250d28086e119cd60b671240ad.png differ diff --git a/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac252686a27b707f6686f6ba5fab.png b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac252686a27b707f6686f6ba5fab.png new file mode 100644 index 0000000000..896663ae28 Binary files /dev/null and b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/3a0bac252686a27b707f6686f6ba5fab.png differ diff --git a/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/abp-community-talk-4.png b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/abp-community-talk-4.png new file mode 100644 index 0000000000..36171a8c7b Binary files /dev/null and b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/abp-community-talk-4.png differ diff --git a/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/post.md b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/post.md new file mode 100644 index 0000000000..29a8c2c78d --- /dev/null +++ b/docs/en/Community-Articles/2023-06-08-abpio-platform-73-rc-has-been-published/post.md @@ -0,0 +1,266 @@ +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, ITransientDependency +{ + public async Task HandleEventAsync(DistributedEventSent eventData) + { + // TODO: IMPLEMENT YOUR LOGIC... + } +} +``` + +> See the documentation to learn more: [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, + 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: [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(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/7.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](3a0bac23c58b6d34e665030b4f089e9e.png) + +**Step 2 - Verify the QR Code with an authenticator app:** + +![two-factor-auth-2.png](3a0bac23df9ab9c68f361acd9c9fa79b.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](3a0bac23fd1a5e7625d1fa11b27684ce.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](3a0bac241d501c2727fd77b885edbfe9.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( + "", + 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](3a0bac2466ce529b36ae8e6c38603f80.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](abp-community-talk-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](3a0bac24d1635475ef24d00707bbc67b.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](3a0bac250d28086e119cd60b671240ad.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](3a0bac252686a27b707f6686f6ba5fab.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) +* [Reflecting on Devnot Dotnet Conference 2023](https://volosoft.com/blog/Reflecting-on-Devnot-Dotnet-Conference-2023) 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! diff --git a/docs/en/Community-Articles/2023-07-14-abpio-platform-73-final-has-been-released/3a0c651a881f2c3554ccf785699d205f.png b/docs/en/Community-Articles/2023-07-14-abpio-platform-73-final-has-been-released/3a0c651a881f2c3554ccf785699d205f.png new file mode 100644 index 0000000000..23371576ed Binary files /dev/null and b/docs/en/Community-Articles/2023-07-14-abpio-platform-73-final-has-been-released/3a0c651a881f2c3554ccf785699d205f.png differ diff --git a/docs/en/Community-Articles/2023-07-14-abpio-platform-73-final-has-been-released/post.md b/docs/en/Community-Articles/2023-07-14-abpio-platform-73-final-has-been-released/post.md new file mode 100644 index 0000000000..4ae23d2fbf --- /dev/null +++ b/docs/en/Community-Articles/2023-07-14-abpio-platform-73-final-has-been-released/post.md @@ -0,0 +1,74 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 7.3 versions have been released today. + +## What's New With Version 7.3? + +All the new features were already explained in detail in the [7.3 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-7-3-RC-Has-Been-Published), so no need to go over them again. Check it out for more details. + +## Getting Started with 7.3 + +### Creating New Solutions + +You can create a new solution with the ABP Framework version 7.3 by either using the `abp new` command or generating the CLI command on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to Upgrade an Existing Solution + +#### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update the existing CLI: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading Existing Solutions with the ABP Update Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guides + +There are 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) + +## Community News + +### ABP Community Talks 2023.5: Mobile Development with the ABP Framework + +![abp-community-talk-4-1920.png](3a0c651a881f2c3554ccf785699d205f.png) + +In this episode, we'll talk about Exploring Options for Mobile Development with the ABP Framework. + +> Join us to explore the options for Mobile Development in ABP Framework on July 27, 2023, at 17:00 UTC. You can register from [here](https://kommunity.com/volosoft/events/abp-community-talks-20235-mobile-development-with-the-abp-framework-68e64e59). + +### New ABP Community Posts + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Video: ABP Framework Entity Framework Core](https://community.abp.io/videos/abp-framework-entity-framework-core-z0eyf1yy) by [Hamza Albreem](https://twitter.com/st_braim) +* [Image Compression and Resize with ABP Framework](https://community.abp.io/posts/image-compression-and-resize-with-abp-framework-4v2gpb7g) by [Engincan Veske](https://twitter.com/EngincanVeske) +* [Manage Quartz with SilkierQuartz](https://community.abp.io/posts/manage-quartz-with-silkierquartz-xb4ovbj9) by [Jadyn](https://community.abp.io/members/Jadyn) +* [ABP Helper Methods](https://community.abp.io/posts/abp-helper-methods-04dk74cq) by [Engincan Veske](https://twitter.com/EngincanVeske) +* [How to replace SwaggerUI with RapiDoc](https://community.abp.io/posts/how-to-replace-swaggerui-with-rapidoc-hw7pktmz) by [Jadyn](https://community.abp.io/members/Jadyn) + +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. + +## About the Next Version + +The next feature version will be 7.4. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d5f9cef5d3b21450039a0d60c4.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d5f9cef5d3b21450039a0d60c4.png new file mode 100644 index 0000000000..b059320b9d Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d5f9cef5d3b21450039a0d60c4.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d64851246bb2cf6a71d9c59109.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d64851246bb2cf6a71d9c59109.png new file mode 100644 index 0000000000..9715f7ff52 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d64851246bb2cf6a71d9c59109.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d67e161ba5d8cec75510aee73e.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d67e161ba5d8cec75510aee73e.png new file mode 100644 index 0000000000..5efd677bb4 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d67e161ba5d8cec75510aee73e.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d72e81c83a96ecd5c3ea477b91.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d72e81c83a96ecd5c3ea477b91.png new file mode 100644 index 0000000000..82f09d6247 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d72e81c83a96ecd5c3ea477b91.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d747b1e8af45ed3266d54157bf.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d747b1e8af45ed3266d54157bf.png new file mode 100644 index 0000000000..ddbae4a841 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d747b1e8af45ed3266d54157bf.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d77b35c85754842b0e738fb6e0.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d77b35c85754842b0e738fb6e0.png new file mode 100644 index 0000000000..9d4e95c191 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d77b35c85754842b0e738fb6e0.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d7d95884d0ebc118ffa1208ef3.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d7d95884d0ebc118ffa1208ef3.png new file mode 100644 index 0000000000..eb322626e3 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d7d95884d0ebc118ffa1208ef3.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d805049381a723f9d66af6c553.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d805049381a723f9d66af6c553.png new file mode 100644 index 0000000000..5f8c7cf24f Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d805049381a723f9d66af6c553.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d832074ca544cc93be80c3a476.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d832074ca544cc93be80c3a476.png new file mode 100644 index 0000000000..3eff13e504 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d832074ca544cc93be80c3a476.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d858aa0277a94f9383d38be6e1.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d858aa0277a94f9383d38be6e1.png new file mode 100644 index 0000000000..ea96907e56 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d858aa0277a94f9383d38be6e1.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d89e809905d8ace81340fd63a8.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d89e809905d8ace81340fd63a8.png new file mode 100644 index 0000000000..d850245181 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d89e809905d8ace81340fd63a8.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d8c4ea4107b9c3c18a3117defb.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d8c4ea4107b9c3c18a3117defb.png new file mode 100644 index 0000000000..8801b5fb0b Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d8c4ea4107b9c3c18a3117defb.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d90b8305953bb3099f18506d8b.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d90b8305953bb3099f18506d8b.png new file mode 100644 index 0000000000..d5afe74f10 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d90b8305953bb3099f18506d8b.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d939347073b53288be8286eb41.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d939347073b53288be8286eb41.png new file mode 100644 index 0000000000..8934a9404e Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d939347073b53288be8286eb41.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d96302be92961ed920f55b7865.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d96302be92961ed920f55b7865.png new file mode 100644 index 0000000000..d3b8555be1 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d96302be92961ed920f55b7865.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d99b0db5650b0400f2f338b522.jpg b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d99b0db5650b0400f2f338b522.jpg new file mode 100644 index 0000000000..65bae90315 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d14d99b0db5650b0400f2f338b522.jpg differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d15cd0485c48ab849c6e27d174b74.png b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d15cd0485c48ab849c6e27d174b74.png new file mode 100644 index 0000000000..00c17acccd Binary files /dev/null and b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/3a0d15cd0485c48ab849c6e27d174b74.png differ diff --git a/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/post.md b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/post.md new file mode 100644 index 0000000000..8fd1e7ae9f --- /dev/null +++ b/docs/en/Community-Articles/2023-08-17-abpio-platform-74-rc-has-been-published/post.md @@ -0,0 +1,300 @@ +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **7.4 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.4! Thanks to all of you. + +## Get Started with the 7.4 RC + +Follow the steps below to try version 7.4.0 RC today: + +1) **Upgrade** the ABP CLI to version `7.4.0-rc.5` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 7.4.0-rc.5 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 7.4.0-rc.5 +```` + +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.3 or earlier: + +* [ABP Framework 7.3 to 7.4 Migration Guide](https://docs.abp.io/en/abp/7.4/Migration-Guides/Abp-7_4) +* [ABP Commercial 7.3 to 7.4 Migration Guide](https://docs.abp.io/en/commercial/7.4/migration-guides/v7_4) + +## What's New with ABP Framework 7.4? + +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: + +* Dynamic Setting Store +* Introducing the `AdditionalAssemblyAttribute` +* `CorrelationId` Support on Distributed Events +* Database Migration System for EF Core +* Other News + +### Dynamic Setting Store + +Prior to this version, it was hard to define settings in different microservices and centrally manage all setting definitions in a single admin application. To make that possible, we used to add project references for all the microservices' service contract packages from a single microservice, so it can know all the setting definitions and manage them. + +In this version, ABP Framework introduces the Dynamic Setting Store, which is an important feature that allows you to collect and get all setting definitions from a single point and overcome the setting management problems on microservices. + +> *Note*: If you are upgrading from an earlier version and using the Setting Management module, you need to create a new migration and apply it to your database because a new database table has been added for this feature. + +### Introducing the `AdditionalAssemblyAttribute` + +In this version, we have introduced the `AdditionalAssemblyAttribute` to define additional assemblies to be part of a module. ABP Framework automatically registers all the services of your module to the [Dependency Injection System](https://docs.abp.io/en/abp/latest/Dependency-Injection). It finds the service types by scanning types in the assembly that define your module class. Typically, every assembly contains a separate module class definition and modules depend on each other using the `DependsOn` attribute. + +In some rare cases, your module may consist of multiple assemblies and only one of them defines a module class, and you want to make the other assemblies parts of your module. This is especially useful if you can't define a module class in the target assembly or you don't want to depend on that module's dependencies. + +In that case, you can use the `AdditionalAssembly` attribute as shown below: + +```csharp +[DependsOn(...)] // Your module dependencies as you normally would do +[AdditionalAssembly(typeof(IdentityServiceModule))] // A type in the target assembly (in another assembly) +public class IdentityServiceTestModule : AbpModule +{ + ... +} +``` + +With the `AdditionalAssembly` attribute definition, ABP loads the assembly containing the `IdentityServiceModule` class as a part of the identity service module. Notice that in this case, none of the module dependencies of the `IdentityServiceModule` are loaded. Because we are not depending on the `IdentityServiceModule`, instead we are just adding its assembly as a part of the `IdentityServiceTestModule`. + +> You can check the [Module Development Basics](https://docs.abp.io/en/abp/7.4/Module-Development-Basics) documentation to learn more. + +### `CorrelationId` Support on Distributed Events + +In this version, `CorrelationId` (a unique key that is used in distributed applications to trace requests across multiple services/operations) is attached to the distributed events, so you can relate events with HTTP requests and can trace all the related activities. + +ABP Framework generates a `correlationId` for the first time when an operation is started and then attaches the current `correlationId` to distributed events as an additional property. For example, if you are using the [transactional outbox or inbox pattern provided by ABP Framework](https://docs.abp.io/en/abp/latest/Distributed-Event-Bus#outbox-inbox-for-transactional-events), you can see the `correlationId` in the extra properties of the `IncomingEventInfo` or `OutgoingEventInfo` classes with the standard `X-Correlation-Id` key. + +> You can check [this issue](https://github.com/abpframework/abp/issues/16773) for more information. + +### Database Migration System for EF Core + +In this version, ABP Framework provides base classes and events to migrate the database schema and seed the database on application startup. This system works compatibly with multi-tenancy and whenever a new tenant is created or a tenant's database connection string has been updated, it checks and applies database migrations for the new tenant state. + +This system is especially useful to migrate databases for microservices. In this way, when you deploy a new version of a microservice, you don't need to manually migrate its database. + +You need to take the following actions to use the database migration system: + +* Create a class that derives from `EfCoreRuntimeDatabaseMigratorBase` class, override and implement its `SeedAsync` method. And lastly, execute the `CheckAndApplyDatabaseMigrationsAsync` method of your class in the `OnPostApplicationInitializationAsync` method of your module class. +* Create a class that derives from `DatabaseMigrationEventHandlerBase` class, override and implement its `SeedAsync` method. Then, whenever a new tenant is created or a tenant's connection string is changed then the `SeedAsync` method will be executed. + +### Other News + +* [OpenIddict](https://github.com/openiddict/openiddict-core/tree/4.7.0) library has been upgraded to **v4.7.0**. See [#17334](https://github.com/abpframework/abp/pull/17334) for more info. +* ABP v7.4 introduces the `Volo.Abp.Maui.Client` package, which is used by the MAUI mobile application in ABP Commercial. See [#17201](https://github.com/abpframework/abp/pull/17201) for more info. +* In this version, the `AbpAspNetCoreIntegratedTestBase` class gets a generic type parameter, which expects either a startup class or an ABP module class. This allows us to use configurations from an ABP module or old-style ASP.NET Core Startup class in a test application class and this simplifies the test application project. See [#17039](https://github.com/abpframework/abp/pull/17039) for more info. + +## What's New with ABP Commercial 7.4? + +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 new features coming with ABP Commercial 7.4. + +### Dynamic Text Template Store + +Prior to this version, it was hard to create text templates in different microservices and centrally manage them in a single admin application. For example, if you would define a text template in your ordering microservice, then those text templates could not be seen on the administration microservice because the administration microservice would not have any knowledge about that text template (because it's hard-coded in the ordering microservice). + +For this reason, in this version, the Dynamic Text Template Store has been introduced to make the [Text Template Management module](https://docs.abp.io/en/commercial/latest/modules/text-template-management) compatible with microservices and distributed systems. It allows you to store and get all text templates from a single point. Thanks to that, you can centrally manage the text templates in your admin application. + +> *Note*: If you are upgrading from an earlier version and are using the Text Template Management module, you need to create a new migration and apply it to your database. + +To enable the dynamic template store, you just need to configure the `TextTemplateManagementOptions` and set the `IsDynamicTemplateStoreEnabled` as true in your module class: + +```csharp +Configure(options => +{ + options.IsDynamicTemplateStoreEnabled = true; +}); +``` + +Notice this is only needed in the microservice where you centrally manage your text template contents. So, typically you would use the configuration above in your administration microservice. Other microservices automatically save their text template contents to the central database. + +### Suite: Custom Code Support + +In this version, we have implemented the custom code support in Suite. This allows you to customize the generated code-blocks and preserve your custom code changes in the next CRUD Page Generation in Suite. ABP Suite specifies hook-points to allow adding custom code blocks. Then, the code that you wrote to these hook points will be respected and will not be overridden in the next entity generation. + +![suite-custom-code.png](3a0d14d5f9cef5d3b21450039a0d60c4.png) + +To enable custom code support, you should check the *Customizable code* option in the crud page generation page. When you enable the custom code support, you will be seeing some hook-points in your application. + +For example, on the C# side, you'll be seeing some abstract classes and classes that derive from them (for entities, application services, interfaces, domain services, and so on...). You can write your custom code in those classes (`*.Extended.cs`) and the next time when you need to re-generate the entity, your custom code will not be overridden (only the base abstract classes will be re-generated and your changes on Suite will be respected): + +Folder structure | Book.Extended.cs +:-------------------------:|:-------------------------: +![suite-custom-code-backend.png](3a0d14d64851246bb2cf6a71d9c59109.png) | ![book-extended-cs.png](3a0d14d67e161ba5d8cec75510aee73e.png) + +> *Note*: If you want to override the entity and add custom code, please do not touch the code between `...` placeholders, because the constructor of the entity should be always re-generated in case of a new property added. + +On the UI side, you can see the *comment placeholders* on the pages for MVC & Blazor applications. These are hook-points provided by ABP Suite and you can write your custom code between these comment sections: + +Folder structure | Books/Index.cshtml +:-------------------------:|:-------------------------: +![suite-custom-code-ui.png](3a0d14d72e81c83a96ecd5c3ea477b91.png) | ![book-extended-cshtml.png](3a0d14d747b1e8af45ed3266d54157bf.png) + +### MAUI & React Native UI Revisions + +In this version, we have revised MAUI & React Native mobile applications and added new pages, functionalities and made improvements on the UI side. + +![maui.png](3a0d14d77b35c85754842b0e738fb6e0.png) + +For example, in the MAUI application, we have implemented the following functionalities and changed the UI completely: + +* **User Management Page**: Management page for your application users. You can search, add, update, or delete users of your application. +* **Tenants**: Management page for your tenants. +* **Settings**: Management page for your application settings. On this page, you can change **the current language**, **the profile picture**, **the current password**, or/and **the current theme**. + +Also, we have aligned the features on both of these mobile options (MAUI & React Native) and showed them in the ["ABP Community Talks 2023.5: Exploring the Options for Mobile Development with the ABP Framework"](https://community.abp.io/events/mobile-development-with-the-abp-framework-ogtwaz5l). + +> If you have missed the event, you can watch from 👉 [here](https://www.youtube.com/watch?v=-wrdngeKgZw). + +### New LeptonX Theme Features + +In the new version of LeptonX Theme, which is v2.4.0-rc.1, there are some new features that we want to mention. + +#### Mobile Toolbars + +The [Toolbar System](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Toolbars) is used to define *toolbars* on the user interface. Modules (or your application) can add items to a toolbar, then the UI themes can render the toolbar on the layout. + +LeptonX Theme extends this system even further and introduces mobile toolbars with this version. You can create a component and add it as a mobile toolbar as below: + +```csharp +public class MyToolbarContributor : IToolbarContributor +{ + public Task ConfigureToolbarAsync(IToolbarConfigurationContext context) + { + if (context.Toolbar.Name == LeptonXToolbars.MainMobile) + { + context.Toolbar.Items.Add(new ToolbarItem(typeof(ShoppingCardToolbarComponent))); + + //other mobile toolbars... + } + + return Task.CompletedTask; + } +} +``` + +Then, the LeptonX Theme will render these mobile toolbars like in the figure below: + +![mobile-toolbars.png](3a0d14d7d95884d0ebc118ffa1208ef3.png) + +> **Note**: The Angular UI hasn't been completed yet. We aim to complete it as soon as possible and include it in the next release. + +#### New Error Page Designs + +In this version, we have implemented new error pages. Encounter a fresh look during error situations with the 'New Error Page Designs,' providing informative and visually appealing error displays that enhance user experience: + +![error-page.png](3a0d14d805049381a723f9d66af6c553.png) + +#### Fluid Layout + +In this version, LeptonX Theme introduces the fresh-looking **Fluid Layout**, which is a layout that lets you align elements so that they automatically adjust their alignment and proportions for different page sizes and orientations. + +![fluid-layout.png](3a0d14d832074ca544cc93be80c3a476.png) + +> You can visit [the live demo of LeptonX Theme](https://x.leptontheme.com/side-menu) and try the Fluid Layout now! + +### Check & Move Related Entities on Deletion/Demand + +In application modules, there are some entities that have complete relationships with each other such as role-user relations. In such cases, it's a typical requirement to check & move related entities that have a relation with the other entity that is about to be deleted. + +For example, if you need to delete an edition from your system, you would typically want to move the tenant that is associated with that edition. For this purpose, in this version, ABP Commercial allows you to move related entities on deletion/demand. + +![editions.png](3a0d14d858aa0277a94f9383d38be6e1.png) + +Currently, this feature is implemented for SaaS and Identity Pro modules and for the following relations: + +* Edition - Tenant +* Role - User +* Organization Unit - User + +Also, it's possible to move the related associated-records before deleting the record. For example, you can move all tenants from an edition as shown in the figure below: + +"Move all tenants" action | "Move all tenants" modal +:-------------------------:|:-------------------------: +![move-all-tenants.png](3a0d14d89e809905d8ace81340fd63a8.png) | ![move-tenants.png](3a0d14d8c4ea4107b9c3c18a3117defb.png) + +### CMS Kit Pro: Page Feedback + +In this version, the **Page Feedback** feature has been added to the [CMS Kit Pro](https://docs.abp.io/en/commercial/latest/modules/cms-kit/index) module. This feature allows you to get feedback from a page in your application. + +This is especially useful if you have content that needs feedback from users. For example, if you have documentation or a blog website, it's a common requirement to assess the quality of the articles and get feedback from users. In that case, you can use this feature: + +![page-feedback.png](3a0d14d90b8305953bb3099f18506d8b.png) + +### Chat Module: Deleting Messages & Conversations + +In this version, the [Chat Module](https://docs.abp.io/en/commercial/latest/modules/chat) allows you to delete individual messages or a complete conversation. + +You can enable or disable the message/conversation deletion globally on your application: + +![settings.png](3a0d14d939347073b53288be8286eb41.png) + +> **Note**: The Angular UI hasn't been completed yet. We aim to complete it as soon as possible and include it in the next release. + +### Password Complexity Indicators + +In this version, ABP Framework introduces an innovative ["Password Complexity Indicator"](https://docs.abp.io/en/commercial/7.4/ui/angular/password-complexity-indicator-component) feature, designed to enhance security and user experience. This feature dynamically evaluates and rates the strength of user-generated passwords, providing real-time feedback to users as they create or update their passwords. By visually indicating the complexity level, users are guided toward crafting stronger passwords that meet modern security standards. + +![password-complexity.png](3a0d14d96302be92961ed920f55b7865.png) + +You can check the [Password Complexity Indicator Angular documentation](https://docs.abp.io/en/commercial/7.4/ui/angular/password-complexity-indicator-component) to learn more. + +> **Note**: Currently, this feature is only available for the Angular UI, but we will be implemented for other UIs in the next version. + +## Community News + +### ABP Community Talks 2023.6: Live Community Questions Session + +![streamyard.png](3a0d15cd0485c48ab849c6e27d174b74.png) + +In this episode, the core ABP team will do a Live Q&A session **on August 31, 2023, at 17:00 UTC**. This is your chance to ask the team anything about ABP. Whether it's about features, best practices, or upcoming releases... We want to hear from you! + +You can do either of the following things to send your questions: + +* Reply to this tweet: [https://twitter.com/abpframework/status/1692157154692595817](https://twitter.com/abpframework/status/1692157154692595817) +* Send us an email at [marketing@volosoft.com](mailto:marketing@volosoft) with **"ABP Community Talks Live Q&A"** in the subject line +* Or simply, be there at the live session in the chat. + +> Register to listen and ask your questions now 👉 [https://kommunity.com/volosoft/events/abp-community-talks-20236-live-community-questions-session-1a545496](https://kommunity.com/volosoft/events/abp-community-talks-20236-live-community-questions-session-1a545496). + +### DevNot Developer Summit 2023 + +![developersummit.jpg](3a0d14d99b0db5650b0400f2f338b522.jpg) + +We are thrilled to announce that the co-founder of [Volosoft](https://volosoft.com/) and Lead Developer of the ABP Framework, Halil Ibrahim Kalkan will give a speech about "Building a Kubernetes Integrated Local Development Environment" in the [Developer Summit 2023 event](https://summit.devnot.com/) on the 7th of October. + +### New ABP Community Posts + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [ABP Commercial - GDPR Module Overview](https://community.abp.io/posts/abp-commercial-gdpr-module-overview-kvmsm3ku) by [Engincan Veske](https://twitter.com/EngincanVeske) +* [Video: ABP Framework Data Transfer Objects](https://community.abp.io/videos/abp-framework-data-transfer-objects-qwebfqz5) by [Hamza Albreem](https://github.com/braim23) +* [Video: ABP Framework Essentials: MongoDB](https://community.abp.io/videos/abp-framework-essentials-mongodb-gwlblh5x) by [Hamza Albreem](https://github.com/braim23) +* [ABP Modules and Entity Dependencies](https://community.abp.io/posts/abp-modules-and-entity-dependencies-hn7wr093) by [Jack Fistelmann](https://github.com/nebula2) +* [How to add dark mode support to the Basic Theme in 3 steps?](https://community.abp.io/posts/how-to-add-dark-mode-support-to-the-basic-theme-in-3-steps-ge9c0f85) by [Enis Necipoğlu](https://twitter.com/EnisNecipoglu) +* [Deploying docker image to Azure with yml and bicep through Github Actions](https://community.abp.io/posts/deploying-docker-image-to-azure-with-yml-and-bicep-through-github-actions-cjiuh55m) by [Sturla](https://community.abp.io/members/Sturla) + +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. + +## 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.4/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v7.4 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! diff --git a/docs/en/Community-Articles/2023-08-30-celebrating-abps-ddd-a-decade-dedicated-to-development/post.md b/docs/en/Community-Articles/2023-08-30-celebrating-abps-ddd-a-decade-dedicated-to-development/post.md new file mode 100644 index 0000000000..6831e7eb1d --- /dev/null +++ b/docs/en/Community-Articles/2023-08-30-celebrating-abps-ddd-a-decade-dedicated-to-development/post.md @@ -0,0 +1,44 @@ +Today isn't just another day. Today, we celebrate a decade of dedication, innovation, and collaboration. A day that reminds us of the late nights, the brainstorming sessions, the challenges faced, and the solutions found. A decade ago, we started with a simple idea: to make web application development for .NET developers easier and more efficient. This idea wasn't just a fleeting thought; it was a commitment to every .NET developer out there. That commitment was shaped in the form of [open-source ASP.NET Boilerplate project](https://github.com/aspnetboilerplate/aspnetboilerplate). +As we stand at this 10-year mark, it's not just about looking back but also realizing how every step, every feedback, and every update has shaped ABP journey for today. + +##### Milestones From a Commit to a Community + +* August 2013: The journey began with the **first commit** to the [open-source ASP.NET Boilerplate project](https://github.com/aspnetboilerplate/aspnetboilerplate). +* February 2014: We celebrated the **first official release** of [ASP.NET Boilerplate](https://aspnetboilerplate.com/), marking its readiness for the .NET developer community. +* May 2015: The **launch of [ASP.NET Zero](https://aspnetzero.com/)** provided a startup solution based on the foundational [ASP.NET Boilerplate](https://aspnetboilerplate.com/). +* December 2016: A new chapter unfolded with the **first commit** to the [open-source ABP Framework project](https://github.com/abpframework/abp), ensuring the legacy of [ASP.NET Boilerplate](https://aspnetboilerplate.com/) continued to flourish. +* June 2018: The **first release of the [ABP Framework](https://github.com/abpframework/abp)** showcased its capabilities and features. +* September 2018: We publicly **announced the [open-source ABP Framework project](https://github.com/abpframework/abp)**, inviting developers worldwide to be a part of this journey. +* January 2020: The **introduction of [ABP Commercial](https://commercial.abp.io/)** added a layer of commercial benefits and features on top of the robust ABP Framework. +* August 2023: Here we are, **celebrating 10 years of ABP**! + + +##### A Heartfelt Ode to the ABP Community + +Our journey over the past decade wouldn't have been possible without you. Your relentless feedback, unwavering support, and enduring trust that have not only shaped ABP but also redefined what community-driven development means. Every line of code, every feature, and every update was inspired by you; every milestone we achieved was a testament to the collaborative spirit of the ABP community. Every challenge we overcame was because of the collective wisdom and passion of this vibrant ecosystem. + +You have been the wind beneath our wings - dedicated community of developers, contributors, partners, and users. We appreciate all of it and look forward to the upcoming decades with you! + + +##### Looking Ahead + +While we cherish our achievements over the past decade, we're even more excited about what the future holds. The world of web development is ever-evolving, and so are we. Our commitment remains unwavering: to ensure ABP not only keeps up with the times but sets new benchmarks. With emerging technologies, changing user needs, and the ever-growing expectations of developers, we're committed to pushing the boundaries, innovating, and ensuring that ABP remains the gold standard for .NET developers across the globe. + +With ABP Community's continued support, we are super excited about the future, our eyes are set on the horizon. + + +##### Engage, Enrich, and Evolve with Us + +* **Join ABP Community Events:** We try to make ABP Community Talks on a monthly basis. You can join to [Volosoft Kommunity](https://kommunity.com/volosoft/about) to be the first to hear about every new episode of ABP Community Talks when it is announced. You can watch the previous ABP Community Talks episodes from [here](https://www.youtube.com/playlist?list=PLsNclT2aHJcOsPustEkzG6DywiO8eh0lB). +* **ABP Conference:** Did you catch the [ABP .NET Conference 2023](https://abp.io/Conference/2023)? If not, no worries! We're making it an annual affair. Also, you can watch any session you want from the [ABP DOTNET Conf'23 Playlist](https://www.youtube.com/playlist?list=PLsNclT2aHJcPTA3D4fIF10fsbhbckEbBC). You can follow [ABP Framework Twitter](https://twitter.com/abpframework) for ABP .NET Conf'24 and many more announcements. +* **Chat with Us:** Got questions or ideas? Join to the official [ABP Discord Server](https://community.abp.io/discord) and chat with fellow community members. +* **Watch and Learn:** We're active on [Volosoft YouTube Channel](https://www.youtube.com/@Volosoft). Subscribe to stay ahead of the curve with informative videos, live shows, and much more. + + +##### Wrapping Up + +A decade in the tech world is an eternity, and to have thrived, evolved, and led for ten years is no small feat. It's been ten years of breaking barriers with coding, continuous learning, and growing together as one big family. But this is just the beginning. The future awaits with new challenges, new technologies, and new milestones. And as we gear up to embrace what's next, we want you ABP Community right there with us, scripting the next chapters of this incredible journey. + +From the bottom of our hearts, a big thank you for being an integral part of our story. Together, let's continue to create, innovate, and set new standards. + +Here's to countless more decades dedicated to development, innovation and excellence together with ABP! diff --git a/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/1a06907364a779fb8bad39f3e6890219.jpg b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/1a06907364a779fb8bad39f3e6890219.jpg new file mode 100644 index 0000000000..6e756f8072 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/1a06907364a779fb8bad39f3e6890219.jpg differ diff --git a/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7a636a849847e69dec153c7e07.jpg b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7a636a849847e69dec153c7e07.jpg new file mode 100644 index 0000000000..7a6a0c86e9 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7a636a849847e69dec153c7e07.jpg differ diff --git a/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7aaa5d774528cc6afeeae8e88b.jpg b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7aaa5d774528cc6afeeae8e88b.jpg new file mode 100644 index 0000000000..35494d6935 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7aaa5d774528cc6afeeae8e88b.jpg differ diff --git a/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7bf6d6942ff236ff2ac5a8f092.jpeg b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7bf6d6942ff236ff2ac5a8f092.jpeg new file mode 100644 index 0000000000..7e77436157 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7bf6d6942ff236ff2ac5a8f092.jpeg differ diff --git a/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7c5833ae0ab6f3395339b17dd8.jpg b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7c5833ae0ab6f3395339b17dd8.jpg new file mode 100644 index 0000000000..56286ddec1 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7c5833ae0ab6f3395339b17dd8.jpg differ diff --git a/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7e6fba0856fb5444f7c63256af.jpg b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7e6fba0856fb5444f7c63256af.jpg new file mode 100644 index 0000000000..d6d1e8d37d Binary files /dev/null and b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e7e6fba0856fb5444f7c63256af.jpg differ diff --git a/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e889ae94471a3dd396494be5519.jpeg b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e889ae94471a3dd396494be5519.jpeg new file mode 100644 index 0000000000..06b9513423 Binary files /dev/null and b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/3a0d5e889ae94471a3dd396494be5519.jpeg differ diff --git a/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/post.md b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/post.md new file mode 100644 index 0000000000..1330516ed4 --- /dev/null +++ b/docs/en/Community-Articles/2023-08-31-abpio-is-sponsoring-basta-mainz-2023/post.md @@ -0,0 +1,31 @@ +We are thrilled to announce that ABP.IO will be sponsoring [BASTA! Mainz 2023](https://basta.net/mainz-en/)! We are always eager to support the software development community, and this time, it's in Mainz, Germany. + +BASTA! is a renowned conference for software developers that delves into a plethora of topics in the software development realm. It gathers experts from all corners of the globe to disseminate their knowledge and insights on cutting-edge technologies and industry best practices. This year, the event will take place from September 25 to 29, 2023, at the Rheingoldhalle Mainz. + +We take immense pride in sponsoring such pivotal events and supporting the software development community. Conferences like BASTA! Mainz are perfect for developers to learn, network, and keep up with the evolving trends in the domain. + +Here are some previews from the events we sponsored before, so you know what to expect in BASTA! Mainz 2023: +### DevNot Summit 2022: +![20221015\_113630.jpg](3a0d5e7e6fba0856fb5444f7c63256af.jpg) + +### NDC London 2020: +![00f93d44fcdeb12edd6039f3e6787472.jpg](3a0d5e7a636a849847e69dec153c7e07.jpg) + +![image](1a06907364a779fb8bad39f3e6890219.jpg) + +### NDC London 2023: +![IMG\_0014.jpg](3a0d5e7c5833ae0ab6f3395339b17dd8.jpg) + +![20230125\_084840.jpg](3a0d5e7aaa5d774528cc6afeeae8e88b.jpg) + +### DevNot DotNet 2023: +![Devnot dotnet.jpeg](3a0d5e7bf6d6942ff236ff2ac5a8f092.jpeg) + +As is customary, we have some delightful surprises in store for attendees at our booth. Swing by to grab one of our exclusive swag kits and join our raffles for a chance to win exciting prizes. And, delicious hand-made chocolates all the way from Turkey. here is a sneak peak at what they look like: +![FnZ8qOxWAAA4fDD.jpeg](3a0d5e889ae94471a3dd396494be5519.jpeg) + +The [ABP.IO](https://abp.io/) Team is eagerly anticipating our participation in BASTA! Mainz 2023. We are keen on forging connections with other professionals in the software development industry. Keep an eye out for more updates on our engagement in the conference from [ABP Framework Twitter account](https://twitter.com/abpframework). + +For those keen on learning more about Volosoft and our software development offerings, or if you're curious about our SaaS product, [ABP Commercial](https://commercial.abp.io/), which is built on our [ABP Framework](https://abp.io/), do visit us at our booth. We're always up for a chat about your software development requirements and how we can assist. + +Meet us at BASTA! Mainz 2023! \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee356bf503f43f8ceb6dca73c9f0.png b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee356bf503f43f8ceb6dca73c9f0.png new file mode 100644 index 0000000000..33c0a61b6b Binary files /dev/null and b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee356bf503f43f8ceb6dca73c9f0.png differ diff --git a/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee35853c7f829442023af6553f66.jpg b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee35853c7f829442023af6553f66.jpg new file mode 100644 index 0000000000..3a6366eb7b Binary files /dev/null and b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee35853c7f829442023af6553f66.jpg differ diff --git a/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee35afc7099825d6dca031412a29.jpg b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee35afc7099825d6dca031412a29.jpg new file mode 100644 index 0000000000..56d1b43a01 Binary files /dev/null and b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee35afc7099825d6dca031412a29.jpg differ diff --git a/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee35ea587cfd54dbe7f25b08f1ba.jpg b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee35ea587cfd54dbe7f25b08f1ba.jpg new file mode 100644 index 0000000000..4179451e34 Binary files /dev/null and b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee35ea587cfd54dbe7f25b08f1ba.jpg differ diff --git a/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee361959cf15deace2c962b45824.jpg b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee361959cf15deace2c962b45824.jpg new file mode 100644 index 0000000000..8e0d71909b Binary files /dev/null and b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee361959cf15deace2c962b45824.jpg differ diff --git a/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee3661356610a7c0d806dd40ef97.jpg b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee3661356610a7c0d806dd40ef97.jpg new file mode 100644 index 0000000000..8ebe63afa7 Binary files /dev/null and b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee3661356610a7c0d806dd40ef97.jpg differ diff --git a/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee3697640ce7b9a095a99940cec9.png b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee3697640ce7b9a095a99940cec9.png new file mode 100644 index 0000000000..08d456b9b3 Binary files /dev/null and b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee3697640ce7b9a095a99940cec9.png differ diff --git a/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee36b334fb642cc43560a493fc5a.jpg b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee36b334fb642cc43560a493fc5a.jpg new file mode 100644 index 0000000000..9a2594c3b9 Binary files /dev/null and b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee36b334fb642cc43560a493fc5a.jpg differ diff --git a/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee36e64265b465069593419fb9d6.png b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee36e64265b465069593419fb9d6.png new file mode 100644 index 0000000000..991b764ce6 Binary files /dev/null and b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/3a0dee36e64265b465069593419fb9d6.png differ diff --git a/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/post.md b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/post.md new file mode 100644 index 0000000000..be659ec86f --- /dev/null +++ b/docs/en/Community-Articles/2023-09-28-unleash-the-power-of-abp-cms-kit-a-dynamic-content-showcase/post.md @@ -0,0 +1,105 @@ +We're excited to introduce to you [ABP](https://abp.io/)'s [CMS Kit Module](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Index) – a versatile module that empowers you to build your own dynamic content website with ease. In this introductory blog post, we'll first take a look at the **CMS Kit Module** and then we'll take you on a journey through our **CMS Kit Demo Application**, showcasing the incredible capabilities of this feature-rich module. + +## ABP Community Talks 2023.7: Build Your Content Management System with .NET + +We as the ABP team organized the [**ABP Community Talks 2023.7: Build Your Content Management System with .NET**](https://community.abp.io/events/build-your-own-cms-with-.net-a-first-look-at-abps-content-management-system-kit-3nfvm9ix) event to explore the depths of the CMS Kit Module and its real-world applications. The talk delved into the intricacies of the CMS Kit Module, providing valuable insights into its features and functionalities. Attendees had the opportunity to witness the module in action through live demonstrations and interactive Q&A sessions. + +For those who missed the live session, you can catch up on all the enriching discussions and demonstrations by watching the record below 👇: + + + +## Overview of the CMS Kit Module + +At the heart of ABP's CMS Kit Module is a robust Content Management System (CMS) designed to simplify content creation and management. With the CMS Kit, you have the tools to build your own dynamic content website, complete with a range of features tailored to your specific needs. It provides core **building blocks** and fully working sub-systems to create your own website with the CMS features or use the building blocks in your websites for any purpose. + +### CMS Kit: The Building Blocks (a.k.a Features) + +The following features are currently available and ready to use: + +* **Blogging**: Create your blog and publish posts (with markdown / HTML support) +* **Dynamic Pages**: Create pages with dynamic URLs (with markdown / HTML support) +* **Dynamic Menu**: Manage your application’s main menu on the fly +* **Tagging**: Tag any kind of content, like a blog post +* **Comments**: Allow users to comment and discuss in your application +* **Reactions**: Allow users to react to your content using simple smileys +* **Rating**: Reusable component to rate other contents +* **Global Resources**: Dynamically add CSS / JavaScript to your pages or blog posts +* **Dynamic Widgets**: Build widgets and use them in dynamic content, like blog posts + +> For more information, please check the [CMS Kit Module documentation](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Index). In the documentation, you can see descriptions for each feature, learn how to install & configure the module, and much more... + +### CMS Kit Pro: The Building Blocks (a.k.a Features) + +CMS Kit Pro is a part of [ABP Commercial](https://commercial.abp.io/) and provides additional features. The following features are provided by the CMS Kit Pro Module: + +* **Contact Form**: Easily add a «contact us» form to your website +* **Newsletter**: Allow users to subscribe to your newsletter (with multiple categories) +* **URL Forwarding**: Create short URLs or redirect users to other pages (for example: [abp.io/dapr](https://abp.io/dapr)) +* **Poll**: Create quick polls for your users +* **Page Feedback**: Collect feedbacks from users for your content + +> For more information, check the [CMS Kit Pro Module documentation](https://docs.abp.io/en/commercial/latest/modules/cms-kit/index). + +## Explore the CMS Kit Demo Application + +As the core ABP development team, we've created a sample application to showcase the incredible capabilities of the ABP's CMS Kit Module. You can explore the source code of the application on our [GitHub repository](https://github.com/abpframework/cms-kit-demo) to get a deeper understanding of how the CMS Kit works under the hood. While developing the application, we aimed to build a real-world application and use almost all of the CMS Kit Features. + +In the next sections, we will provide a detailed walkthrough of the application and highlight each CMS Kit feature that has been incorporated into it. + +### Dynamic Menu Creation with CMS Kit's Menu System + +One of the standing out features of the CMS Kit is its [Menu System](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Menus), which allows for the creation and dynamic ordering of application menu items. Say goodbye to static menus; with CMS Kit, you have the power to tailor your menu structure according to your evolving content needs. + +You can see the homepage of the application in the following figure: + +![homepage.png](3a0dee356bf503f43f8ceb6dca73c9f0.png) + +The application menu items in the navbar are **created & ordered dynamically** with the [CMS Kit's Menu System](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Menus): + +![menu-admin-side.jpg](3a0dee35853c7f829442023af6553f66.jpg) + +### Custom Implementations with Comment & Reaction Features + +Our demo application goes a step further by demonstrating custom implementations, such as an **image gallery**, seamlessly integrated with CMS Kit's [Comment](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Comments) & [Reaction](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Reactions) Features: + +| Gallery | Detail Page | +|------------------------ |-----------------------| +| ![image-gallery.jpg](3a0dee35afc7099825d6dca031412a29.jpg) | ![image-gallery-detail.jpg](3a0dee35ea587cfd54dbe7f25b08f1ba.jpg) | + +It's pretty easy to integrate CMS Kit Features such as Comments & Reactions into your existing pages. You can check the [source code of the application](https://github.com/abpframework/cms-kit-demo/blob/main/src/CmsKitDemo/Pages/Gallery/Detail.cshtml) and see how to integrate the features. + +### Robust Blogging Capabilities + +Blogging has never been easier! With the CMS Kit's [Blogging Feature](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Blogging), you can effortlessly manage your blog content, complete with [Ratings](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Ratings), [Comments](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Comments), [Tags](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Tags), and [Reactions](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Reactions) features as enabled: + +| Blog | Blog Post | +|------------------------ |-----------------------| +| ![blogs.jpg](3a0dee361959cf15deace2c962b45824.jpg) | ![blog-detail.jpg](3a0dee3661356610a7c0d806dd40ef97.jpg) | + +You can enable/disable CMS Kit Features per blog on the admin side easily: + +![cmskit-module-features.png](3a0dee3697640ce7b9a095a99940cec9.png) + +### Dynamic Pages with Style and Script Integration + +*Products* pages showcase the flexibility of the CMS Kit's [Pages Feature](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Pages), allowing for dynamic content creation, style customization, and script integration. Your website can now truly reflect your unique brand and content style. + +You can create pages with dynamic URLs on the admin side: + +![pages-admin-side.jpg](3a0dee36b334fb642cc43560a493fc5a.jpg) + +After you have created the page, you can access it via `/{slug}` URL on the public-web side: + +![products-abp-commercial.png](3a0dee36e64265b465069593419fb9d6.png) + +## What's Next? + +Please try the CMS Kit Module now and provide [feedback](https://github.com/abpframework/abp) to help us build a more effective content management kit! + +## Resources + +* [CMS Kit Demo: Source Code](https://github.com/abpframework/cms-kit-demo) +* [cms-kit-demo.abp.io](https://cms-kit-demo.abp.io/) (will be live soon) +* [CMS Kit Module documentation](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Index) +* [CMS Kit Pro Module documentation](https://docs.abp.io/en/commercial/latest/modules/cms-kit/index) +* [ABP Community Talks 2023.7: Build Your Content Management System with .NET](https://www.youtube.com/watch?v=S9__Hnu29tI) \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074506bcc60cad473655b6fd5da6.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074506bcc60cad473655b6fd5da6.jpg new file mode 100644 index 0000000000..0017e817ba Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074506bcc60cad473655b6fd5da6.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074555e8d6f62bc3d47c00f86762.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074555e8d6f62bc3d47c00f86762.jpg new file mode 100644 index 0000000000..a9b3649dd2 Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074555e8d6f62bc3d47c00f86762.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0745b6418472a66d905053d492e6.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0745b6418472a66d905053d492e6.jpg new file mode 100644 index 0000000000..929c3753fe Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0745b6418472a66d905053d492e6.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074625fddc3097efdc1bef3058d8.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074625fddc3097efdc1bef3058d8.jpg new file mode 100644 index 0000000000..b04382a27b Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074625fddc3097efdc1bef3058d8.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074675731c4a59167a878d4cd04e.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074675731c4a59167a878d4cd04e.jpg new file mode 100644 index 0000000000..3452104d4a Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074675731c4a59167a878d4cd04e.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074703a63129e5713ff51653aaac.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074703a63129e5713ff51653aaac.jpg new file mode 100644 index 0000000000..d51c0fb0df Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074703a63129e5713ff51653aaac.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e07477e980a4c2104300557e8f7fb.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e07477e980a4c2104300557e8f7fb.jpg new file mode 100644 index 0000000000..4b0af90172 Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e07477e980a4c2104300557e8f7fb.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0747c283919bbc5edfdc289db1d8.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0747c283919bbc5edfdc289db1d8.jpg new file mode 100644 index 0000000000..3ba57d015b Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0747c283919bbc5edfdc289db1d8.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0748c8752dfdc2bcb5b9b2ce5908.png b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0748c8752dfdc2bcb5b9b2ce5908.png new file mode 100644 index 0000000000..e9799d9420 Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0748c8752dfdc2bcb5b9b2ce5908.png differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e07495efa58bb9f1e523d982dbc65.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e07495efa58bb9f1e523d982dbc65.jpg new file mode 100644 index 0000000000..f7f5d1431f Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e07495efa58bb9f1e523d982dbc65.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0749c23a9e3b06d66ed54bed0c7a.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0749c23a9e3b06d66ed54bed0c7a.jpg new file mode 100644 index 0000000000..35de7b572d Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e0749c23a9e3b06d66ed54bed0c7a.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074a268272e630d8422ace32b4c8.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074a268272e630d8422ace32b4c8.jpg new file mode 100644 index 0000000000..02bdc29a17 Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074a268272e630d8422ace32b4c8.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074aa3857a696cb941edc46dcb52.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074aa3857a696cb941edc46dcb52.jpg new file mode 100644 index 0000000000..166c058bba Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074aa3857a696cb941edc46dcb52.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074b0a46662cf39a6796d0f23086.jpg b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074b0a46662cf39a6796d0f23086.jpg new file mode 100644 index 0000000000..a84abea379 Binary files /dev/null and b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/3a0e074b0a46662cf39a6796d0f23086.jpg differ diff --git a/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/post.md b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/post.md new file mode 100644 index 0000000000..dd7cafc13f --- /dev/null +++ b/docs/en/Community-Articles/2023-10-03-basta-mainz-2023-what-a-blast-in-germany/post.md @@ -0,0 +1,118 @@ +BASTA! Mainz 2023 has wrapped up, and what an extraordinary journey it has been! We can’t wait to share our impressions, highlights, and the incredible impact it had on the tech community in Germany and beyond. + + + +### A Glance Back at BASTA! Mainz 2023 + + + + + +We just came back from the[ BASTA! Conference 2023](https://basta.net/), which is an incredible .NET event with over 600 in-person attendees and an additional 200+ tuning in virtually from across the globe. The buzz of excitement and anticipation in the air was undeniable, setting the stage for an unforgettable event for [ABP.IO](https://abp.io/). + + + +![53227564247\_b7acafea68\_c.jpg](3a0e074506bcc60cad473655b6fd5da6.jpg) + + + +![53227631612\_eb38958391\_c.jpg](3a0e074555e8d6f62bc3d47c00f86762.jpg) + + + +![53227631792\_a6d87b4abf\_k.jpg](3a0e0745b6418472a66d905053d492e6.jpg) + + + +As one of the proud sponsors, we set up our booth, engaged with attendees, and delved into a wide range of sessions, workshops, and keynotes to absorb the latest software development trends. + + + +### Engaging with Enthusiastic Minds + + + + + +As the lead developers of ABP Core Team, *[Alper](https://twitter.com/alperebicoglu)* and *[Ismail](https://twitter.com/ismcagdas)* presented the ABP.IO platform modules and features were quite busy enjoying their presenting work with latest version of demos. Alper also gave a great speech on “Building Multi-tenant ASP.NET Core Application & the ABP Framework” at the BASTA! Mainz conference. + + + +![53229004005\_3312b6bfa2\_k.jpg](3a0e074625fddc3097efdc1bef3058d8.jpg) + + + +![20230926\_170335.jpg](3a0e074675731c4a59167a878d4cd04e.jpg) + + + +We introduced **[ABP Framework](https://abp.io/)**, community-driven open-source web application framework, and **[ABP Commercial](https://commercial.abp.io/)**, our enterprise-ready web development platform that is built on top of the open-source ABP Framework to the crowds. + + + +![53227632222\_0a5af1fcc1\_k.jpg](3a0e074703a63129e5713ff51653aaac.jpg) + + + +![53228506206\_24e22498fa\_o.jpg](3a0e07477e980a4c2104300557e8f7fb.jpg) + + + +![53228505931\_b2aea761f9\_k.jpg](3a0e0747c283919bbc5edfdc289db1d8.jpg) + + + +Apart from that, we were thrilled to give away the **[ABP Commercial Licenses](https://commercial.abp.io/pricing)** to the eager attendees on the venue, including the Raffle prize, **Meta Quest 2**, on our last day in BASTA! Conference. + + + +![截屏2023-10-03 11.06.01.png](3a0e0748c8752dfdc2bcb5b9b2ce5908.png) + + + +We are profoundly satisfied with the huge interest and engagement shown by the attendees. The sense of community, collaboration, and shared passion for .NET solutions was palpable throughout the event. + + + +![20230927\_171046.jpg](3a0e07495efa58bb9f1e523d982dbc65.jpg) + + + +![20230928\_150135.jpg](3a0e0749c23a9e3b06d66ed54bed0c7a.jpg) + + + +![20230928\_150533 20.57.50.jpg](3a0e074a268272e630d8422ace32b4c8.jpg) + + + +### A Great Partnership with LIS GmbH + + + + + +![3a0e074aa3857a696cb941edc46dcb52](https://github.com/user-attachments/assets/ea0f6d32-e49b-4573-997f-9751ef16b303) + + + + +At BASTA! Mainz 2023, we were particularly thrilled to celebrate our collaboration with ***LIS GmbH***, a leading software solutions provider. This partnership added a unique dimension to the conference, brought us a fresh perspective to the conference, fostering innovation and opening up new avenues for attendees. + + + +### A Big Thank-You from ABP Team + + + + + +![53228503821\_27860119d9\_k.jpg](3a0e074b0a46662cf39a6796d0f23086.jpg) + + + +Now, a shout-out to BASTA! Mainz 2023. We want to thank to everyone who contributed to the success of this event – attendees, speakers, sponsors, and partners.The conference may have ended, but the knowledge gained, connections formed, and inspiration ignited will continue to shape the tech landscape for years to come. + + + +Until next time! diff --git a/docs/en/Community-Articles/2023-10-11-abpio-platform-74-final-has-been-released/3a0e2f9e8d77cf9c6d53415c46dba4a2.png b/docs/en/Community-Articles/2023-10-11-abpio-platform-74-final-has-been-released/3a0e2f9e8d77cf9c6d53415c46dba4a2.png new file mode 100644 index 0000000000..a84abea379 Binary files /dev/null and b/docs/en/Community-Articles/2023-10-11-abpio-platform-74-final-has-been-released/3a0e2f9e8d77cf9c6d53415c46dba4a2.png differ diff --git a/docs/en/Community-Articles/2023-10-11-abpio-platform-74-final-has-been-released/post.md b/docs/en/Community-Articles/2023-10-11-abpio-platform-74-final-has-been-released/post.md new file mode 100644 index 0000000000..90f89200fb --- /dev/null +++ b/docs/en/Community-Articles/2023-10-11-abpio-platform-74-final-has-been-released/post.md @@ -0,0 +1,79 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 7.4 versions have been released today. + +## What's New With Version 7.4? + +All the new features were already explained in detail in the [7.4 RC Announcement Post](https://blog.abp.io/abp/ABP.IO-Platform-7-4-RC-Has-Been-Published), so no need to go over them again. Check it out for more details. + +## Getting Started with 7.4 + +### Creating New Solutions + +You can create a new solution with the ABP Framework version 7.4 by either using the `abp new` command or generating the CLI command on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to Upgrade an Existing Solution + +#### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update the existing CLI: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading Existing Solutions with the ABP Update Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guides + +There are breaking changes in this version that may affect your application. +Please see the following migration documents, if you are upgrading from v7.3: + +* [ABP Framework 7.3 to 7.4 Migration Guide](https://docs.abp.io/en/abp/7.4/Migration-Guides/Abp-7_4) +* [ABP Commercial 7.3 to 7.4 Migration Guide](https://docs.abp.io/en/commercial/7.4/migration-guides/v7_4) + +## Community News + +### ABP Community Talks 2023.7: Build Your Content Management System with .NET + +We as the ABP team organized the [**ABP Community Talks 2023.7: Build Your Content Management System with .NET**](https://community.abp.io/events/build-your-own-cms-with-.net-a-first-look-at-abps-content-management-system-kit-3nfvm9ix) event to explore the depths of the CMS Kit Module and its real-world applications. The talk delved into the intricacies of the CMS Kit Module, providing valuable insights into its features and functionalities. Attendees had the opportunity to witness the module in action through live demonstrations and interactive Q&A sessions. + +For those who missed the live session, you can catch up on all the enriching discussions and demonstrations by watching the record below 👇: + + + +### BASTA! Mainz 2023 + +![basta-mainz.png](3a0e2f9e8d77cf9c6d53415c46dba4a2.png) + +BASTA! Mainz 2023 has wrapped up, and what an extraordinary journey it has been! We have shared our impressions, highlights, and the incredible impact it had on the tech community in Germany and beyond in a blog post, which you can find at [https://blog.abp.io/abp/BASTA-Mainz-2023-What-a-Blast-in-Germany](https://blog.abp.io/abp/BASTA-Mainz-2023-What-a-Blast-in-Germany). + +### New ABP Community Posts + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Moving Background Job Execution To A Separate Application](https://community.abp.io/posts/moving-background-job-execution-to-a-separate-application-my9cgo9a) by [liangshiwei](https://github.com/realLiangshiwei). +* [Cascading Option Loading with Extensions System in ABP Angular](https://community.abp.io/posts/cascading-option-loading-with-extensions-system-in-abp-angular-gcxgp0v9) by [Masum Ulu](https://twitter.com/masumulu). +* [How to use domain-based tenant resolver in ABP with Angular and OpenIddict](https://community.abp.io/posts/how-to-use-domainbased-tenant-resolver-in-abp-with-angular-and-openiddict-v9y8da7v) by [Mahmut Gündoğdu](https://twitter.com/MahmutGundogdu). + +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. + +## About the Next Version + +The next feature version will be 8.0. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. diff --git a/docs/en/Community-Articles/2023-11-06-Blazor-Fullstack-Web-Ui/Post.md b/docs/en/Community-Articles/2023-11-06-Blazor-Fullstack-Web-Ui/Post.md index c1c38d7818..5c1b03701e 100644 --- a/docs/en/Community-Articles/2023-11-06-Blazor-Fullstack-Web-Ui/Post.md +++ b/docs/en/Community-Articles/2023-11-06-Blazor-Fullstack-Web-Ui/Post.md @@ -1,8 +1,5 @@ # Blazor's History and Full-stack Web UI -![Cover Image](cover-image.png) - - Blazor is a web framework that allows developers to build interactive web applications using .NET instead of JavaScript. The first version of Blazor was released on May 14, 2020. Since its initial release, Blazor has evolved with the new versions. Until now, six different versions have been declared. Sometimes, it can be not very clear to see the differences between these approaches. First, let's try to understand these. * **Blazor-Server**: >> *Loads fast at first* >> In this version, heavy things are done in the server. Browsers are thin clients and download a small page for the first load. The page updates are done via SignalR connection. This was released with .NET Core 3. diff --git a/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e83be956add9b4719eed77e22e4.png b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e83be956add9b4719eed77e22e4.png new file mode 100644 index 0000000000..d58c0c52a9 Binary files /dev/null and b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e83be956add9b4719eed77e22e4.png differ diff --git a/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e83e5fafb8221fae02a69433781.png b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e83e5fafb8221fae02a69433781.png new file mode 100644 index 0000000000..c774e78671 Binary files /dev/null and b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e83e5fafb8221fae02a69433781.png differ diff --git a/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e841f0e8a850191acdbb32b54eb.png b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e841f0e8a850191acdbb32b54eb.png new file mode 100644 index 0000000000..ba1d5f5a97 Binary files /dev/null and b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e841f0e8a850191acdbb32b54eb.png differ diff --git a/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e85960459e2e5d4f60737eabfe6.png b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e85960459e2e5d4f60737eabfe6.png new file mode 100644 index 0000000000..d5c3b4d68a Binary files /dev/null and b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e85960459e2e5d4f60737eabfe6.png differ diff --git a/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e8a3e0bb1981553fa4ae2698d56.png b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e8a3e0bb1981553fa4ae2698d56.png new file mode 100644 index 0000000000..e8e44f42bb Binary files /dev/null and b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f0e8a3e0bb1981553fa4ae2698d56.png differ diff --git a/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f2c0ca1a84f21abe964e9f4e0fbac.png b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f2c0ca1a84f21abe964e9f4e0fbac.png new file mode 100644 index 0000000000..d64eb052fa Binary files /dev/null and b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/3a0f2c0ca1a84f21abe964e9f4e0fbac.png differ diff --git a/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/identity-users.gif b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/identity-users.gif new file mode 100644 index 0000000000..92dad96550 Binary files /dev/null and b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/identity-users.gif differ diff --git a/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/post.md b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/post.md new file mode 100644 index 0000000000..2e6bfe8202 --- /dev/null +++ b/docs/en/Community-Articles/2023-11-23-abpio-platform-80-rc-has-been-published/post.md @@ -0,0 +1,224 @@ +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **8.0 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 v8.0! Thanks to all of you. + +## Get Started with the 8.0 RC + +Follow the steps below to try version 8.0.0 RC today: + +1) **Upgrade** the ABP CLI to version `8.0.0-rc.3` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 8.0.0-rc.3 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 8.0.0-rc.3 +```` + +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 8.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.x or earlier: + +* [ABP Framework 7.x to 8.0 Migration Guide](https://docs.abp.io/en/abp/8.0/Migration-Guides/Abp-8_0) +* [ABP Commercial 7.x to 8.0 Migration Guide](https://docs.abp.io/en/commercial/8.0/migration-guides/v8_0) + +## What's New with ABP Framework 8.0? + +In this section, I will introduce some major features released in this version. +Here is a brief list of titles explained in the next sections: + +* Upgraded to .NET 8.0 +* Upgraded to Angular 17 +* Dynamic Claims +* CDN Support for Bundling & Minification System +* Read-Only Repositories +* Account Module: Set Username After Social/External Login +* Other News... + +### Upgraded to .NET 8.0 + +We've upgraded the ABP Framework to .NET 8.0, so you need to move your solutions to .NET 8.0 if you want to use ABP 8.0. You can check [Microsoft’s Migrate from ASP.NET Core 7.0 to 8.0 documentation](https://learn.microsoft.com/en-us/aspnet/core/migration/70-80), to see how to update an existing ASP.NET Core 7.0 project to ASP.NET Core 8.0. + +### Upgraded to Angular 17 + +Angular 17 [was released on November 8](https://blog.angular.io/introducing-angular-v17-4d7033312e4b) and ABP Framework & ABP Commercial startup templates were immediately migrated to **Angular 17**! + +So, when you create a new solution with the Angular UI, you will take advantage of the new Angular with the new cutting-edge features and enhancements right from the start! + +### Dynamic Claims + +The **Dynamic Claims** feature is used to dynamically generate claims for the user in each request. It's used to automatically and dynamically override the configured claim values in the client's authentication token/cookie by the latest user claims. + +In the prior versions, whenever a user changed their email address or confirmed their own email address, or any other information related to the user (and if it's in the claims), he/she would need to logout and then login to refresh its claims. The new **Dynamic Claims** feature overcomes this problem and allows to **always get the latest user claims**. + +This feature is disabled by default and you can enable it easily for your existing MVC applications by following the [Dynamic Claims documentation](https://docs.abp.io/en/abp/8.0/Dynamic-Claims). For the other UI options (Angular & Blazor UIs), you don't need to enable this feature, since they obtain claims ftom a configuration endpoint. + +> **Note**: Beginning from the v8.0, all the startup templates are pre-configured and the **Dynamic Claims** feature is enabled by default. + +### CDN Support for Bundling & Minification System + +In this version, ABP Framework's [Bundling & Minification System](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Bundling-Minification) provides CDN support for MVC / Razor Pages UI. The bundling system automatically recognizes the external/CDN files and places them as link/script tags on the page along with the bundled CSS/JSS files. + +> Read the documentation for more info: https://docs.abp.io/en/abp/8.0/UI/AspNetCore/Bundling-Minification + +### Read-Only Repositories + +ABP Framework provides read-only repository interfaces (`IReadOnlyRepository<>` or `IReadOnlyBasicRepository<>`) to explicitly indicate that your purpose is to query data, but not change it. It uses [EF Core's No-Tracking Feature](https://learn.microsoft.com/en-us/ef/core/querying/tracking#no-tracking-queries) behind the scenes, which means the entities returned from the repository will not be tracked by the EF Core's [change tracker](https://learn.microsoft.com/en-us/ef/core/change-tracking/) and thanks to that you get significant performance gains. + +```csharp +public class MyService +{ + private readonly IReadOnlyRepository _bookRepository; + + public async Task MyMethod() + { + var books = await _bookRepository.GetListAsync(); //change tracking not involved + + //... + } +} +``` + +> In addition to the read-only repository interfaces, ABP Framework introduces the `IRepository.DisableTracking()` and `IRepository.EnableTracking()` extension methods to allow developers to disable/enable entity tracking by these methods manually. If you don't want to use the read-only repositories, you can use these methods to enable or disable the change tracker controlled. Read the documentation to learn more: [https://docs.abp.io/en/abp/8.0/Repositories#enabling-disabling-the-change-tracking](https://docs.abp.io/en/abp/8.0/Repositories#enabling-disabling-the-change-tracking) + +### Account Module: Set Username After Social/External Login + +Prior to this version, when you registered with your social accounts for the first time, your email address was becoming your username and it was shown everywhere in the application. Therefore, you would need to update your username later on and this is not a good user experience. + +Thus, in this version, we have enhanced this flow, and now, when you register as an external user for the first time, a username and email address are shown you in a form for you to revise and update if you want, before logging into the application. Thanks to that, after the social registration you would not need to update your username and email address. This is also good at the point of GDPR regulations because your email address will not be shown as a username and will not exposed. + +![account-module-register.png](3a0f0e83be956add9b4719eed77e22e4.png) + +### Other News + +* LDAP over SSL (LDAPS) setting has been added and recommended to establish a secure connection. See [#17865](https://github.com/abpframework/abp/pull/17865) for more information. +* Object Mapping Enhancements (supports mapping collection of objects for custom object mappers). +* Email Sending Improvements (sending attachments with `IEmailSender.QueueAsync()` method). +* Made improvements on NuGet.Config files (by using [packageSourceMapping](https://learn.microsoft.com/en-us/nuget/consume-packages/package-source-mapping)) that came with startup templates and this reduced the restore time of the projects in your solution: + +![nuget.png](3a0f2c0ca1a84f21abe964e9f4e0fbac.png) + +## What's New with ABP Commercial 8.0? + +We've also worked on ABP Commercial to align the features and changes made in the ABP Framework. The following sections introduce a few new features coming with ABP Commercial 8.0. + +### Suite: Generating Master/Detail Relationship + +In this version, we have introduced the **Master/Detail Relationship** support in Suite. The Master-Detail (or Master-Child) relationship refers to a hierarchical connection between two entities, where one entity (the master or parent entity) influences or controls the behavior or properties of another element (the child entity) relationship. The relationship between **Order - Order Lines** can be considered as an example of a master-detail relationship. + +![suite-master-child-datagrid.png](3a0f0e83e5fafb8221fae02a69433781.png) + +ABP Suite allows you to create a master-detail relationship with a few clicks. It generates the necessary code for the master and detail tables, including the foreign key relationship between the two tables. + +To establish a master-detail relationship, you need to apply the following two steps: + +1. Create the master entity, +2. Create a child entity and associate it with a master entity. + +That's it! ABP Suite will be generating the entities, making the related configurations, establishing database relations (including the foreign key relationship), generating the UI for the master entity (with child-grids for child entities), and so on... + +It’s already documented and you can read the documentation at [https://docs.abp.io/en/commercial/8.0/abp-suite/creating-master-detail-relationship](https://docs.abp.io/en/commercial/8.0/abp-suite/creating-master-detail-relationship). + +#### Known Issues + +* (For v8.0-rc.1 and v8.0.rc.2, it's fixed with v8.0-rc.3) After you generate CRUD pages via Suite for the Angular UI, you should start the backend project and run the `abp generate-proxy -t ng` command in the root directory of the Angular application manually. It will be automatically done with the next version, so you will not need to run the command manually in further versions. + +### Get Profile Picture From Social/External Logins + +A user's profile picture would be blank when they first register for an application using a social account through an external authentication provider like Google or Facebook because it hasn't been configured yet. The user must update their profile photo after logging into the application. + + +In order to save the user from having to change their profile picture after logging in for the first time, we have improved this behavior in this version and are now attempting to retrieve the user's profile picture from external authentication providers (like Google) and set it as their profile picture. Later on, if desired, he or she might modify the profile image. + +### Switch Ocelot to YARP for the API Gateway + +Until this version, ABP Commercial was using the [Ocelot](https://github.com/ThreeMammals/Ocelot) for the API Gateway, in the [Microservice Startup Template](https://docs.abp.io/en/commercial/latest/startup-templates/microservice/index). Since the **Ocelot** library is not actively maintained, we have searched for an alternative and decided to switch from Ocelot to [YARP](https://github.com/microsoft/reverse-proxy) for the API Gateway. YARP is maintained by Microsoft and is actively being developed and seems a better alternative than Ocelot and provides the same feature stack and even more. + +You can read the [Migrating to YARP](https://docs.abp.io/en/commercial/8.0/migration-guides/migrating-to-yarp) documentation for migrating your existing microservice application's API Gateway from [Ocelot](https://github.com/ThreeMammals/Ocelot) to [YARP](https://github.com/microsoft/reverse-proxy). + +> We have made the all related changes in the Microservice Startup Template, and also updated the documentation, which you can read [here](https://docs.abp.io/en/commercial/8.0/startup-templates/microservice/gateways). + +### Password Complexity Indicators (MVC & Blazor UIs) + +In v7.4, we have introduced the [Password Complexity Indicators for Angular UI](https://docs.abp.io/en/commercial/7.4/ui/angular/password-complexity-indicator-component) and with this version, we have implemented it for the MVC & Blazor UIs as well. You can use this feature to dynamically evaluate and rate the strength of user-generated passwords, providing real-time feedback to users as they create or update their passwords. + +![password-complexity-indicators.png](3a0f0e841f0e8a850191acdbb32b54eb.png) + +### Read-Only View for Users Page + +In your application, you may want to grant permission to a specific group or people to read-only view the users of your application to be able to do some actions. For example, you may want to marketing team to see the users to organize campaigns for the customers, or make controls. In this case, you can grant default permissions for these groups, however, they could not see the details of a user, because in the current design, if the edit permission is not granted you can't see the detailed info for a user. + +![](identity-users.gif) + +In this version, we have added the read-only view action to the user's page. This allows you to only grant the default view permission to the specific users and allow them to view user information as read-only and not allow them to change or modify it. + +### Export & Import Users as Excel / CSV + +With v8.0, now it's possible to import and export user records in Excel and CSV formats. You can import external users, or import users from Excel or CSV files and also you can export users to Excel or CSV files: + +![users-page.png](3a0f0e85960459e2e5d4f60737eabfe6.png) + +## Community News + +### Highlights from .NET 8.0 + +Our team has closely followed the ASP.NET Core and Entity Framework Core 8.0 releases, read Microsoft's guides and documentation, and adapted the changes to our ABP.IO Platform. We are proud to say that we've shipped the ABP 8.0 RC.1 based on .NET 8.0 just after Microsoft's .NET 8.0 release. + +In addition to the ABP's .NET 8.0 upgrade, our team has created 13 great articles to highlight the important features coming with ASP.NET Core 8.0 and Entity Framework Core 8.0. + +> You can read [this post](https://volosoft.com/blog/Highlights-for-ASP-NET-Entity-Framework-Core-NET-8-0) to see the list of all articles. + +### New ABP Community Articles + +In addition to [the 13 articles to highlight .NET 8.0 features written by our team](https://volosoft.com/blog/Highlights-for-ASP-NET-Entity-Framework-Core-NET-8-0), here are some of the recent posts added to the [ABP Community](https://community.abp.io/): + +* [Upgrade Your Existing Projects to .NET 8 & ABP 8.0](https://community.abp.io/posts/upgrade-your-existing-projects-to-.net-8-abp-8.0-x0n7hiqr) by [Engincan Veske](https://github.com/EngincanV) +* [How to Upload and Download Files in the ABP Framework using Angular](https://community.abp.io/posts/how-to-upload-and-download-files-in-the-abp-framework-using-angular-que8cdr8) by [Mahmut Gündoğdu](https://github.com/mahmut-gundogdu) +* New **ABP Framework Essentials** Videos by [Hamza Albreem](https://github.com/braim23): + * [ABP Essentials - Interception](https://community.abp.io/videos/abp-essentials-interception-ath78xhw) + * [ABP Essentials - Virtual File System](https://community.abp.io/videos/abp-essentials-virtual-file-system-hpgr2j72) + * [ABP Framework Essentials - Localization](https://community.abp.io/videos/abp-framework-essentials-localization-7taieh68) + * [ABP Framework Essentials - Dependency Injection](https://community.abp.io/videos/abp-framework-essentials-dependency-injection-q241mfrf) + * See the playlist for other videos of this series: https://www.youtube.com/playlist?list=PLsNclT2aHJcNupH2wz83y7htugpLoUZ_B + +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. + +### We were in the .NET Conf 2023 + +Microsoft has released .NET 8.0 and celebrated it with a 3-day international online conference. The core team members of ABP Framework, [Alper Ebiçoğlu](https://twitter.com/alperebicoglu) and [Enis Necipoğlu](https://twitter.com/EnisNecipoglu) gave speeches at the .NET Conf 2023. + +[Alper Ebiçoğlu](https://twitter.com/alperebicoglu)'s topic was "Building Multi-Tenant ASP.NET Core Applications and ABP Framework" and in this talk, he talked about what's SaaS development, what are its pros and challenges and multi-tenant development with the open-source ABP Framework: + + + +On the other hand, [Enis Necipoğlu](https://twitter.com/EnisNecipoglu)'s topic was "Reactive programming with .NET MAUI" and he talked about applying reactive programming in .NET MAUI with MVVM and ReactiveUI: + + + +### ABP Community Talks 2023.8: What’s coming with .NET 8.0 & ABP v8.0 + +![community-talk-2023-8.png](3a0f0e8a3e0bb1981553fa4ae2698d56.png) + +In this episode of ABP Community Talks, 2023.8; [Steve Sanderson](https://twitter.com/stevensanderson) will be our guest speaker and we'll talk about .NET 8.0 and ABP 8.0 with the ABP Core Team. We will dive into the features that came with .NET 8.0, how they are implemented in ABP 8.0, and the highlights in the .NET Conf 2023 with [Halil İbrahim Kalkan](https://github.com/hikalkan), [Alper Ebicoglu](https://github.com/ebicoglu), [Engincan Veske](https://github.com/EngincanV), [Berkan Sasmaz](https://github.com/berkansasmaz) and [Bige Besikci Yaman](https://github.com/bigebesikci). + +## 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/8.0/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v8.0 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e08dc3131b22f8e8cdb714f2ef4.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e08dc3131b22f8e8cdb714f2ef4.jpeg new file mode 100644 index 0000000000..9a417e288e Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e08dc3131b22f8e8cdb714f2ef4.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e08f5f98360ad38c8dc2b96c5a9.jpg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e08f5f98360ad38c8dc2b96c5a9.jpg new file mode 100644 index 0000000000..8dd2d3d6d6 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e08f5f98360ad38c8dc2b96c5a9.jpg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e090fd29b0f78520367930777fa.jpg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e090fd29b0f78520367930777fa.jpg new file mode 100644 index 0000000000..88ac4647f7 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e090fd29b0f78520367930777fa.jpg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0923b0f7d003a0ff46e6ad9da4.jpg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0923b0f7d003a0ff46e6ad9da4.jpg new file mode 100644 index 0000000000..3255703956 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0923b0f7d003a0ff46e6ad9da4.jpg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e097cb0a3425b5268f32c730ff5.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e097cb0a3425b5268f32c730ff5.jpeg new file mode 100644 index 0000000000..a24bf3cfd5 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e097cb0a3425b5268f32c730ff5.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e098c741838d700e4fd5982d9af.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e098c741838d700e4fd5982d9af.jpeg new file mode 100644 index 0000000000..71e266bbca Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e098c741838d700e4fd5982d9af.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09ab67925b359e1ef210f37742.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09ab67925b359e1ef210f37742.jpeg new file mode 100644 index 0000000000..81fd1c716b Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09ab67925b359e1ef210f37742.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09b9a1b5380afcafec58f75df2.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09b9a1b5380afcafec58f75df2.jpeg new file mode 100644 index 0000000000..1394d57bb1 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09b9a1b5380afcafec58f75df2.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09def79c37f4280478fe3b870a.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09def79c37f4280478fe3b870a.jpeg new file mode 100644 index 0000000000..dcab0bdb92 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09def79c37f4280478fe3b870a.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09f09cf1d44f136068714a71fa.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09f09cf1d44f136068714a71fa.jpeg new file mode 100644 index 0000000000..7e6b6d5b3c Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e09f09cf1d44f136068714a71fa.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a19860cefa46476eb171b5e08.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a19860cefa46476eb171b5e08.jpeg new file mode 100644 index 0000000000..711a117c9d Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a19860cefa46476eb171b5e08.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a2e23f7395ab84f7ca206b4ee.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a2e23f7395ab84f7ca206b4ee.jpeg new file mode 100644 index 0000000000..e29ed6de89 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a2e23f7395ab84f7ca206b4ee.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a3c8271fa658eb4fd1e3d2fd0.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a3c8271fa658eb4fd1e3d2fd0.jpeg new file mode 100644 index 0000000000..76305b4579 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a3c8271fa658eb4fd1e3d2fd0.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a49bb67213ac3bfc49a23e355.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a49bb67213ac3bfc49a23e355.jpeg new file mode 100644 index 0000000000..c704702d13 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0a49bb67213ac3bfc49a23e355.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0ac3b558e62dd95cd5c9e9ec80.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0ac3b558e62dd95cd5c9e9ec80.jpeg new file mode 100644 index 0000000000..37e5686783 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0ac3b558e62dd95cd5c9e9ec80.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0ad416925db11783b31331826c.jpeg b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0ad416925db11783b31331826c.jpeg new file mode 100644 index 0000000000..e656b59362 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/3a0f8e0ad416925db11783b31331826c.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/post.md b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/post.md new file mode 100644 index 0000000000..def5bcc18d --- /dev/null +++ b/docs/en/Community-Articles/2023-12-18-abp-at-china-net-conf-2023/post.md @@ -0,0 +1,41 @@ +### .NET Conf China 2023 + +China's most influential .NET event officially kicked off on December 16, 2023. Although a heavy snowfall a few days ago impacted traffic, It did not stop the enthusiastic developers. + + The conference has invited 30+ technical experts from various fields to share the new features of .NET 8, full-stack Blazor, AI and .NET MAUI and other trend-setting technology highlights, focusing on the theme of Intelligent · Open Source · Security. In-depth discussion of artificial Intelligence, web development, front-end & security and other hot technical topics, and more .NET technical experts shared their valuable practical experience over the past year. + +![1.jpeg](3a0f8e08dc3131b22f8e8cdb714f2ef4.jpeg) +![2.jpg](3a0f8e08f5f98360ad38c8dc2b96c5a9.jpg) +![3.jpg](3a0f8e090fd29b0f78520367930777fa.jpg) +![4.jpg](3a0f8e0923b0f7d003a0ff46e6ad9da4.jpg) + +### As one of the community partners of .NET Conf China 2023 + +Our ABP.IO China team arrived at the venue much earlier than it started and was carefully prepared to welcome the developers. + +At the event, we showed developers the latest news and related updates on ABP.IO. We also held face-to-face interactive conversations with multiple developers, including senior ABP developers, framework fans and ABP Commercial customers. We listened to everyone's feedback and discussed how to make ABP.IO better serve developers. + +![10.jpeg](3a0f8e097cb0a3425b5268f32c730ff5.jpeg) +![11.jpeg](3a0f8e098c741838d700e4fd5982d9af.jpeg) +![12.jpeg](3a0f8e09ab67925b359e1ef210f37742.jpeg) +![13.jpeg](3a0f8e09b9a1b5380afcafec58f75df2.jpeg) +![14.jpeg](3a0f8e09def79c37f4280478fe3b870a.jpeg) +![15.jpeg](3a0f8e09f09cf1d44f136068714a71fa.jpeg) + +### As always, we have a raffle. + +Including ABP Commercial's TEAM and PERSONAL licenses, [Halil İbrahim Kalkan](https://halilibrahimkalkan.com/)'s latest book **Mastering ABP Framework**, the ABP community's popular **Implementing Domain Driven Design** book, Bluetooth headset and other ABP peripheral brochures, stickers... + +![19.jpeg](3a0f8e0a19860cefa46476eb171b5e08.jpeg) +![16.jpeg](3a0f8e0a2e23f7395ab84f7ca206b4ee.jpeg) +![17.jpeg](3a0f8e0a3c8271fa658eb4fd1e3d2fd0.jpeg) +![18.jpeg](3a0f8e0a49bb67213ac3bfc49a23e355.jpeg) + +### Through this event, + +We gained a lot and felt the enthusiasm and support of the developers community for ABP.IO. We will continue to work hard to provide better services for developers and contribute to the development of ABP.IO. + +### See you at the next community event! + +![20.jpeg](3a0f8e0ad416925db11783b31331826c.jpeg) +![21.jpeg](3a0f8e0ac3b558e62dd95cd5c9e9ec80.jpeg) \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-12-20-abp-commercial-won-5-recognitions-from-gartner-in-2023/post.md b/docs/en/Community-Articles/2023-12-20-abp-commercial-won-5-recognitions-from-gartner-in-2023/post.md new file mode 100644 index 0000000000..6b8042d376 --- /dev/null +++ b/docs/en/Community-Articles/2023-12-20-abp-commercial-won-5-recognitions-from-gartner-in-2023/post.md @@ -0,0 +1,90 @@ +2023 was the year for ABP.IO to strive with the community. First of all, we'd like to express our appreciation for all your interest and say we are genuinely thankful to you for being with us this year. +As an important part of the community, ABP.IO Core Team worked hard to give the ABP Community the best possible service and it was delivered and appreciated by the users which got us to receive these awards. +On top of last years' [Software Advice's Front Runner of Application Development in 2022](https://blog.abp.io/abp/abpcommercial-2022-front-runner-in-app-development-category) and [GetApp's Application Development Category Leader in 2022](https://blog.abp.io/abp/abpcommercial-2022-category-leader-in-app-development-category), we won **5 awards** this year from Gartner! + +For those of you don't know what [Gartner](https://www.gartner.com/en) is, it is a research and consultant company for IT industry, one of the biggest companies in their area. You might have heard Magic Quadrant, Capterra, GetApp, etc. Those are all Gartner's works. + +In 2023, according to their benchmarking criterias on Capterra, GetApp and Software Advice; ABP Commercial won 5 awards in both Application Development and App Building categories! You can find the whole list divided by the titles below. +These awards are given to those product that are most likely to help businesses the best products for their enhancement needs according to users' objective rankings in different areas like customer satisfaction, ease of use, functionality, etc. That's why we are thankful for our team members' hard work and ABP Community's support! + +To show our appreciation, we generated a set of links that rewards your review for ABP Commercial product in your local Amazon Store! + +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/07a1ac5a-4658-4552-a87d-5f4e1089fee9?lang=en)**[get $10 gift card](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/07a1ac5a-4658-4552-a87d-5f4e1089fee9?lang=en)** +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/30b5d7f2-d0c5-4b38-b968-2dc5601aa196?lang=en)**[get £10 gift card](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/30b5d7f2-d0c5-4b38-b968-2dc5601aa196?lang=en)** +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/8fd7b0e8-e4e1-487a-96d6-88f70c14128c?lang=en)**[get €10 gift card](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/8fd7b0e8-e4e1-487a-96d6-88f70c14128c?lang=en)** +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/f6ee291b-f48f-4821-ac3a-606b7e6af005?lang=en)**[get 1500.0¥](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/f6ee291b-f48f-4821-ac3a-606b7e6af005?lang=en)** + +# GetApp Category Leader + +GetApp's Category Leader ranks top software products based on end-user ratings in five key areas(ease of use, value for money, functionality, customer support, and likelihood to recommend). The scores are derived from user reviews, public data, and vendor information, normalized for recency and volume, and then scaled to a maximum of 20 points per dimension, culminating in a total maximum score of 100. + +[ABP Commercial on GetApp](https://www.getapp.com/development-tools-software/a/abp-commercial/reviews/) is in 2 categories, App Building and Application Development; and was the 2023 Category Leader in both of them! + +## ABP Commercial as 2023 App Building Category Leader + +This year was the first time of ABP Commercial on GetApp to win this award in App Building Category. In App Building Category, GetApp examined 199 products and selected ABP Commercial as one of the [2023 Category Leaders of App Building](https://www.getapp.com/development-tools-software/application-builder/category-leaders/) and selected in the 8th row out of 15 top-ranking products. + +Here is how ABP Commercial ranked in the 5 categories of GetApp when selecting the App Building Category's Leaders: + +* Ease of Use: **16 out of 20** +* Value for Money: **16 out of 20** +* Functionality: **17 out of 20** +* Customer Support: **17 out of 20** +* Likelihood to Recommend: **16 out of 20** + In total: **83 out of 100** + +## ABP Commercial as 2023 Application Development Category Leader + +This year, it was the second year in a row [ABP Commercial won the Category Leader of Application Development](https://www.getapp.com/development-tools-software/application-development/category-leaders/). In Application Development Category, in 2023, the number of products GetApp examined went up to 436 whereas it was 368 in 2022. ABP Commercial's row in these products went down to 14th row in the 15 top-ranking products whereas it was 8th the previous year. + +Here is how ABP Commercial ranked in the 5 categories of GetApp when selecting the Application Development Category's Leaders: + +* Ease of Use: **16 out of 20** +* Value for Money: **15 out of 20** +* Functionality: **16 out of 20** +* Customer Support: **16 out of 20** +* Likelihood to Recommend: **15 out of 20** + In total: **82 out of 100** + +# Software Advice Front Runners + +Software Advice's FrontRunners are selected by evaluating the software products using objective user reviews to score them on Usability and Customer Satisfaction. These scores are based on data from user reviews, public sources, and vendor information. The Usability score combines user ratings on functionality(50%) and ease-of-use(50%). Customer Satisfaction is assessed through value for money(25%), likelihood to recommend(25%), and customer support ratings(50%). All ratings are converted to a standard 5-point scale, normalized for recency and volume, and then scaled up to 100. Products that meet a minimum score threshold on both axes, with a cap on the number of FrontRunners to ensure only the top 10 to 25 products per category are included, and no product scoring below 60 in either dimension is featured. The final FrontRunners graphic positions products based on their scores in these two key dimensions. + +In 2023, ABP Commercial won 2 awards in both categories it exists; App Building and Application Development Categories' Front Runners according to the evaluation criterias mentioned above. Let's have a look at where ABP Commercial is located in the graphic of per categories. + +## ABP Commercial as 2023 Front Runner in App Building + +[ABP Commercial on Software Advice in App Building Category](https://www.softwareadvice.com/app-building/abp-commercial-profile/) is one of the Front Runners in App Building Category among 186 products evaluated in this category of Software Advice. +You can check out the full [App Building Category's Front Runners](https://www.softwareadvice.com/app-building/#frontrunners)' graphic below and locate ABP Commercial in it. + + + +## ABP Commercial as 2023 Front Runner in App Development Software + +[ABP Commercial on Software Advice in App Development Category](https://www.softwareadvice.com/app-development/abp-commercial-profile/) is one of the Front Runners in App Development Category among 390 products evaluated in this category of Software Advice. + +You can check out the full [App Development Category's Front Runners](https://www.softwareadvice.com/app-development/#frontrunners)' graphic below and locate ABP Commercial in it. + + + +# Capterra Shortlist + +Capterra evaluates top software products using a blend of user ratings and popularity including up to 25 products per category for their Shortlists. Those products are selected based on the user reviews and a proprietary scoring system that rates products on a scale of 1 to 50 in User Ratings and Popularity. The Shortlist is intended to offer a comprehensive view of products' recent popularity and ratings, aiding buyers in making informed decisions. + +2023 was the first year for ABP Commercial to win an award in Capterra and it was in App Building Software Category. + +## ABP Commercial as 2023 App Building Software Shortlist Products. + +[ABP Commercial on Capterra](https://www.capterra.com/app-building-software/shortlist/) is one of the App Building Software Shortlist in between 17 other highest-ranking products. Capterra's methodology for the 2023 App Building Software Shortlist involved analyzing 332 products, filtering out those lacking in functionality and user reviews, and then ranking the remaining software based on popularity and user ratings. +ABP Commercial got 49 out of 50, indicating exceptional user satisfaction, and a respectable popularity score of 19 out of 50, reflecting its solid web presence and search trend interest. + +You can access the full grid from [here](https://www.capterra.com/app-building-software/shortlist/). + +Thank you all ABP Community members for this recognition we got this year. We look forward to continuing to provide top-notch software and support to businesses everywhere! + +Don't forget to leave your review and redeem your code from Gartner to help us further, if you like to! + +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/07a1ac5a-4658-4552-a87d-5f4e1089fee9?lang=en)**[get $10 gift card](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/07a1ac5a-4658-4552-a87d-5f4e1089fee9?lang=en)** +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/30b5d7f2-d0c5-4b38-b968-2dc5601aa196?lang=en)**[get £10 gift card](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/30b5d7f2-d0c5-4b38-b968-2dc5601aa196?lang=en)** +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/8fd7b0e8-e4e1-487a-96d6-88f70c14128c?lang=en)**[get €10 gift card](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/8fd7b0e8-e4e1-487a-96d6-88f70c14128c?lang=en)** +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/f6ee291b-f48f-4821-ac3a-606b7e6af005?lang=en)**[get 1500.0¥](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/f6ee291b-f48f-4821-ac3a-606b7e6af005?lang=en)** \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-12-21-abpio-platform-80-has-been-released-based-on-net-80/3a0f9f142d036581db5a7873c9daf529.jpeg b/docs/en/Community-Articles/2023-12-21-abpio-platform-80-has-been-released-based-on-net-80/3a0f9f142d036581db5a7873c9daf529.jpeg new file mode 100644 index 0000000000..a24bf3cfd5 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-21-abpio-platform-80-has-been-released-based-on-net-80/3a0f9f142d036581db5a7873c9daf529.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-21-abpio-platform-80-has-been-released-based-on-net-80/3a0f9f144d6126f5709ecb668aa69465.jpeg b/docs/en/Community-Articles/2023-12-21-abpio-platform-80-has-been-released-based-on-net-80/3a0f9f144d6126f5709ecb668aa69465.jpeg new file mode 100644 index 0000000000..42dc55846f Binary files /dev/null and b/docs/en/Community-Articles/2023-12-21-abpio-platform-80-has-been-released-based-on-net-80/3a0f9f144d6126f5709ecb668aa69465.jpeg differ diff --git a/docs/en/Community-Articles/2023-12-21-abpio-platform-80-has-been-released-based-on-net-80/post.md b/docs/en/Community-Articles/2023-12-21-abpio-platform-80-has-been-released-based-on-net-80/post.md new file mode 100644 index 0000000000..6711c43a21 --- /dev/null +++ b/docs/en/Community-Articles/2023-12-21-abpio-platform-80-has-been-released-based-on-net-80/post.md @@ -0,0 +1,82 @@ +Today, [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 8.0 versions have been released based on [.NET 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0). + +## What's New With Version 8.0? + +All the new features were explained in detail in the [8.0 RC Announcement Post](https://blog.abp.io/abp/announcing-abp-8-0-release-candidate), so there is no need to review them again. You can check it out for more details. + +## Getting Started with 8.0 + +### Creating New Solutions + +You can create a new solution with the ABP Framework version 8.0 by either using the `abp new` command or generating the CLI command on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to Upgrade an Existing Solution + +#### Install/Update the ABP CLI + +First, install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update the existing CLI: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading Existing Solutions with the ABP Update Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guides + +There are breaking changes in this version that may affect your application. +Please see the following migration documents if you are upgrading from v7.x or earlier: + +* [ABP Framework 7.x to 8.0 Migration Guide](https://docs.abp.io/en/abp/8.0/Migration-Guides/Abp-8_0) +* [ABP Commercial 7.x to 8.0 Migration Guide](https://docs.abp.io/en/commercial/8.0/migration-guides/v8_0) + +## Community News + +### We were at China .NET Conf 2023 + +China's most influential .NET event officially kicked off on December 16, 2023. The conference has invited 30+ technical experts from various fields to share the new features of .NET 8, full-stack Blazor, AI, .NET MAUI, and more... + +![abp-china-team.jpeg](3a0f9f142d036581db5a7873c9daf529.jpeg) + +As one of the community partners of .NET Conf China 2023, our ABP.IO China team was at the event. At the event, we showed developers the latest news and related updates on ABP.IO. + +Through this event, we gained a lot and felt the enthusiasm and support of the developers community for ABP.IO. If you want to learn more, we have shared our impressions and takeaways in a blog post, which you can find at [https://blog.abp.io/abp/ABP-at-China-NET-Conf-2023](https://blog.abp.io/abp/ABP-at-China-NET-Conf-2023). + +### ABP Commercial Won 5 Recognitions from Gartner + +![awards.jpeg](3a0f9f144d6126f5709ecb668aa69465.jpeg) + +2023 was the year for ABP.IO to strive with the community. On top of last year's [Software Advice's Front Runner of Application Development in 2022](https://blog.abp.io/abp/abpcommercial-2022-front-runner-in-app-development-category) and [GetApp's Application Development Category Leader in 2022](https://blog.abp.io/abp/abpcommercial-2022-category-leader-in-app-development-category), we won **5 awards** this year from **Gartner**! + +> If you are interested in these awards and want to learn more, you can check out our [blog post](https://blog.abp.io/abp/ABP-Commercial-Won-5-Recognitions-from-Gartner-in-2023)! + +### New ABP Community Posts + +There are exciting articles contributed by the ABP community, as always. I will highlight some of them here: + +* [Performance Optimization of .NET-based application](https://community.abp.io/posts/performance-optimization-of-.netbased-and-also-abpbased-application-pmdwhwxc) by [Leon Košak](https://github.com/leonkosak) +* [Video: ABP Framework Consuming HTTP APIs from a .NET Client](https://community.abp.io/videos/abp-framework-consuming-http-apis-from-a-.net-client-uzul9og4) by [Hamza Albreem](https://github.com/braim23) + +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. + +## About the Next Version + +The next feature version will be 8.1. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. diff --git a/docs/en/Community-Articles/2023-12-27-abpio-platform-2023-wrap-up/3a0fbeb0fa89d75154155e2c537e5ca9.png b/docs/en/Community-Articles/2023-12-27-abpio-platform-2023-wrap-up/3a0fbeb0fa89d75154155e2c537e5ca9.png new file mode 100644 index 0000000000..9b25b24617 Binary files /dev/null and b/docs/en/Community-Articles/2023-12-27-abpio-platform-2023-wrap-up/3a0fbeb0fa89d75154155e2c537e5ca9.png differ diff --git a/docs/en/Community-Articles/2023-12-27-abpio-platform-2023-wrap-up/post.md b/docs/en/Community-Articles/2023-12-27-abpio-platform-2023-wrap-up/post.md new file mode 100644 index 0000000000..1842cf2fe3 --- /dev/null +++ b/docs/en/Community-Articles/2023-12-27-abpio-platform-2023-wrap-up/post.md @@ -0,0 +1,104 @@ +ABP.IO is a comprehensive platform that includes the open-source ABP Framework based on ASP.NET Core and its commercial solution designed on the .NET ecosystem. ABP.IO's purpose is to provide a robust infrastructure for developers to create modern web applications efficiently. As ABP.IO Core Team, we came to this day and are excited for the upcoming days thanks to the ever expanding ABP Community members. + +We are grateful for ABP Community including the team members who put effort into making ABP what it is today and the community members for all their amazing support. On top of the achievements in 2022 we summed up in [ABP Year Review 2022 Wrap Up](https://blog.abp.io/abp/ABP-Year-Review-2022-Wrap-Up) blog post for 2022, we, as ABP, achieved even more great successes in 2023 with and thanks to all of you ABP Community members. This year, we remained transparent and committed to our values for trying to help the developers build their web applications efficiently with ABP Framework based on ASP.NET Core. + +We will look into ABP.IO Platform 2023 milestones and wrap the year up in this blog post. Before we hop on to the ABP's recap, we'd like to mention the major highlights in .NET ecosystem which is the **release of .NET 8**. In ABP, it's worth mentioning before all that 2023 was the year we celebrated the **10th Year of ABP** and the first year ever we organized a full conference-**ABP .NET Conf'23**! Let's have a look at them and more. + +![ABP.IO 2023 Wrap Up & Recap.png](3a0fbeb0fa89d75154155e2c537e5ca9.png) + +### Anniversary + +This year was a special year in which we celebrated the **10th Birthday of the ABP**! Looking back, a decade passed till the very first day of the ABP journey. Words are simply not nearly enough to describe our excitement and how surprised we are since it now feels like a blink aside from all the bitter and sweet moments of our journey. Take a look at the milestones we overcame with you and how the last decade went in [Celebrating ABP's DDD: A Decade Dedicated to Development](https://blog.abp.io/abp/Celebrating-ABP%2527s-DDD%253A-A-Decade-Dedicated-to-Development). We dedicated a full 3-day weekend to celebrate the 10th birthday of ABP with our team. [Take a peak at the 1-minute-video from that weekend](https://youtube.com/embed/LxMqIVNHKOk). +In addition to our celebration, we created ABP Framework swag shop that includes a limited-time swag items that have ABP's special 10th Year logo on them. +If you would like to get your Limited-time ABP 10th Year Swag from + +* European Union Store, [visit ABP Framework EU Store](https://abpframework-eu.myspreadshop.net) +* United States Store, [visit ABP Framework US Store](https://abpframework-us.myspreadshop.com) + +It was the **7th birthday of Volosoft**, the company behind the ABP platform. We are proud and excited for the many years to come with the amazing team and many more valuable people to come and join to our team! + +### Events + +We give significant importance to giving back .NET and the overall software development industry. This year was our most active year in the events part of it, because, we not only sponsored to events this year but also **organized** one. + +* **[ABP .NET Conf'23](https://abp.io/conference/2023)** ABP .NET Conference 2023 took place online on May 10, 2023 and each talk is published in [ABP DOTNET Conf'23 Playlist](https://www.youtube.com/playlist?list=PLsNclT2aHJcPTA3D4fIF10fsbhbckEbBC) publicly available on YouTube. Anyone was invited to the event as we mentioned in our [You Are Invited to ABP .NET Conf'23!](https://blog.abp.io/abp/You-Are-Invited-to-ABP-dotNET-Conf23) along with our excitement. It was a truly remarkable experience we got to taste for the first time and got a significant interest. You can read all the statistics in [ABP .NET Conference 2023 Wrap Up](https://blog.abp.io/abp/ABP-.NET-Conference-2023-Wrap-Up) along with our gratitude. Here is a known secret: we plan to do it on a yearly basis! + +In addition to organizing our own .NET event, we, of course, also sponsored 5 events in 2023. Here is the list of the events we sponsored: + +* **[NDC London](https://ndclondon.com/)** is an event we have sponsored almost every year they have organized since 2018. This year, we announced we will sponsor NDC London again in [this announcement blog post](https://blog.abp.io/abp/ABP.IO-is-sponsoring-NDC-London-2023) and a [Recap of the NDC London 2023 here](https://blog.abp.io/abp/What%E2%80%99s-NEW-in-NDC-London-2023). +* **[Devnot Dotnet 2023](https://dotnet.devnot.com/)** is an event we sponsored as Volosoft Company, you can find how it went in [this blog post](https://volosoft.com/Blog/Reflecting-on-Devnot-Dotnet-Conference-2023). +* **[BASTA! Mainz 2023](https://basta.net/mainz-en/)** is the event we sponsored for the first time this year. We were so excited and published a blog post announcing [ABP.IO is sponsoring BASTA! Mainz](https://blog.abp.io/abp/ABP.IO-is-sponsoring-BASTA!-Mainz-2023) and a [Recap of BASTA! Mainz](https://volosoft.com/blog/BASTA-Mainz-2023-What-a-Blast-in-Germany) from our perspective of this amazing event. +* **[.NET Conf 2023](https://www.dotnetconf.net/)** was another online blast we experienced this year to be a sponsor of. We were happy to give ABP Commercial gifts as a form of our thanks to the biggest virtual .NET Conference audience. +* **[DOTNET Conf China 2023](https://chinaevent.microsoft.com/events/details/5f625a2b-206c-4838-b2af-079b3ea27270)** in another part of the usual .NET Conferences but is offering an in-person, therefore, as much amazing platform as the virtual one as a conference. This year, we sponsored .NET Conference China and had a great time there. You can read about the Recap of [ABP at China .NET Conf 2023](https://blog.abp.io/abp/ABP-at-China-NET-Conf-2023). + +### Community Talks + +[ABP Community Talks](https://community.abp.io/events#abp-community-talks) is the monthly live event where we gather to talk and share ideas about the latest news about ABP Framework and overall .NET-related topics in an hour with ABP Community members and a spontaneous appearance of famous .NET names such as Jon Galloway, Joseph Guadagno, Steve Sanderson, etc. This year, we organized **8 ABP Community Talks episodes** about several topics and shared some insights while being interactive with the ABP Community. [Watch ABP Community Talks from its YouTube Playlist](https://www.youtube.com/playlist?list=PLsNclT2aHJcOsPustEkzG6DywiO8eh0lB) and don't forget to [subscribe to our YouTube Channel](https://www.youtube.com/@volosoft) and open the alerts to learn about the upcoming episodes. While you are at it, you are more than welcome to take a look at the resourceful videos we published, as well. 🙂 + +### NuGet Downloads + +NuGet is a package manager designed specifically for the .NET ecosystem. It simplifies the process of creating and consuming packages, thanks to the NuGet client tools. By using these tools, developers can easily manage their project dependencies and improve their workflow. +In 2023, [ABP Core NuGet package](https://www.nuget.org/packages/Volo.Abp.Core/6.0.2) reached more than **22.3 million** of downloads! +On the other hand, overall [Volosoft NuGet Profile](https://www.nuget.org/profiles/volosoft) reached **almost a billion** downloads! + +Thank you all for your interest and support towards ABP and overall Volosoft Packages. + +### ABP Community Posts + +[ABP Community](https://community.abp.io/) is a hub for ABP Framework, .NET and software development. There are articles, videos, events and many more within ABP Community resources. In 2023, only the articles reached up to **almost 200 posts** on top of the videos and events. You can find each resources from the given links below. + +* [ABP Community Events](https://community.abp.io/events) +* [ABP Community Articles](https://community.abp.io/posts) +* [ABP Community Videos](https://community.abp.io/videos) +* [ABP Community Raffles](https://community.abp.io/raffles) + +### ABP Framework on GitHub + +This year was yet another year we shine with [ABP Framework GitHub Repository](https://github.com/abpframework/abp)'s **11.8k stars**! +We appreciate **precisely 100 different [ABP contributors](https://github.com/abpframework/abp/graphs/contributors)** dedicated their valuable time to contribute to make ABP Framework better. In 2023, ABP Framework got **[more than 2850 commits](https://github.com/abpframework/abp/graphs/commit-activity) from 37 different contributors**. Your hard work and effort worth a million thanks, if nothing! We are grateful for each and every one of you and embrace more ten thousands of stars we will gain together with more hundreds of ABP Framework Contributors in the near future. + +### ABP.IO Platform Version Releases + +ABP Framework released 5 versions from 7.1 to 8.0 in 2023. You can check the release logs from [ABP Framework Release Logs](https://github.com/abpframework/abp/releases). + +The most important milestone in these releases is that we upgraded ABP Framework to .NET 8 in [ABP v8.0](https://blog.abp.io/abp/abp-8-0-stable-release-with-dotnet-8-0). + +### Video Tutorials + +In 2023, we published **29 tutorial videos** on top of the 48 videos from last year. We gathered them in [ABP.IO Video Courses](https://abp.io/video-courses) for you to watch free on ABP.IO to learn more about the ABP Framework Essentials and simplify your ABP Platform Journey according to your interests. You can find more videos on [Volosoft's YouTube Channel](https://www.youtube.com/c/@volosoft). + +### ABP Commercial + +2023 was the year for ABP Commercial to shine along with ABP Framework in which more than **80 countries** in the world bought a license which cumulated the customer base of ABP Commercial up to **more than 120 countries**! With this math, it's now safe to say that ABP Commercial is helping streamline the application development processes of businesses from **more than half of the world**! + +* This year, businesses that are active in **more than 95 different industries from more than from 80 countries** accelarated their app development with ABP Commercial +* We performed **293 hours** of [Live ABP Training](https://commercial.abp.io/trainings) to help ABP Framework and ABP Commercial users to perfect their development skills +* Our talented support team solved **more than 1920 support tickets** in 2023. + +#### New launch: ABP Studio + +We were preparing [ABP Studio](https://commercial.abp.io/studio) as a whole new launch for more than a year. 2023 was the year we matured it enough to finally share it with you and share our excitement with all of you! It was a thrill for our Co-Founder [Halil İbrahim Kalkan](https://github.com/hikalkan) to mention about it for the first time in [ABP .NET Conf'23](https://abp.io/conference/2023) with his talk on [Kubernetes Integrated Microservice Development with ABP Studio](https://youtu.be/XiPRcIHJ3NE?si=3FlfJRbbi5D15s9U). Then, we prepared [ABP Studio's dedicated page](https://commercial.abp.io/studio) and shared its details for you to check out and test it out in the Beta version which is AVAILABLE NOW. You can [visit ABP Studio page and request a Beta Access from there](https://commercial.abp.io/studio). Here are some key resources for ABP Studio aside from its page: + +* [ABP Studio Documentation](https://docs.abp.io/en/commercial/latest/studio/index) +* [ABP Community Talks 2023.8: What's Coming with ABP 8 & .NET 8 - ABP Studio Part](https://www.youtube.com/watch?v=yo2L1xGa2pM&t=3250s) +* [Demo: Running and Developing Microservice Applications with ABP Studio Kubernetes Integration](https://www.youtube.com/watch?v=CeUq2ysz-mQ) +* [Demo: Running and Developing Microservice Applications with ABP Studio Solution Runner](https://www.youtube.com/watch?v=sSCxyccoHqE) +* [Kubernetes Integrated Microservice Development with ABP Studio \| ABP \.NET Conference 2023](https://youtu.be/XiPRcIHJ3NE?si=3FlfJRbbi5D15s9U) + +## Gartner Badges + +[Gartner](https://www.gartner.com/en) is a research and consultant company for IT industry, one of the biggest companies in their area. You might have heard Magic Quadrant, Capterra, GetApp, etc. Those are all Gartner's works. This year, we earned **5 Gartner badges** for ABP Commercial which makes us more successful than 2022 in which we earned 2 badges([Application Development Front Runner of Software Advice](https://blog.abp.io/abp/abpcommercial-2022-front-runner-in-app-development-category) and [Application Develompent Category Leader of GetApp](https://blog.abp.io/abp/abpcommercial-2022-category-leader-in-app-development-category)) from Gartner. + +* Capterra Shortlist 2023 in App Building Category +* GetApp Category Leader 2023 in App Building Category +* GetApp Category Leader 2023 in Application Development Category +* Software Advice Front Runner 2023 in App Building Category +* Software Advice Front Runner 2023 in App Development Category + You can learn more about the each Gartner Badges in our recently published blog post, [ABP Commercial Won 5 Recognitions from Gartner in 2023](https://blog.abp.io/abp/ABP-Commercial-Won-5-Recognitions-from-Gartner-in-2023). + +To show our appreciation, we generated a set of links that rewards your review for ABP Commercial product in your local Amazon Store! + +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/07a1ac5a-4658-4552-a87d-5f4e1089fee9?lang=en)**[get $10 gift card](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/07a1ac5a-4658-4552-a87d-5f4e1089fee9?lang=en)** +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/30b5d7f2-d0c5-4b38-b968-2dc5601aa196?lang=en)**[get £10 gift card](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/30b5d7f2-d0c5-4b38-b968-2dc5601aa196?lang=en)** +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/8fd7b0e8-e4e1-487a-96d6-88f70c14128c?lang=en)**[get €10 gift card](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/8fd7b0e8-e4e1-487a-96d6-88f70c14128c?lang=en)** +* [Leave a review for ABP Commercial & ](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/f6ee291b-f48f-4821-ac3a-606b7e6af005?lang=en)**[get 1500.0¥](https://reviews.capterra.com/products/new/8b6f9777-574b-42c6-9902-c045b585ab7c/f6ee291b-f48f-4821-ac3a-606b7e6af005?lang=en)** \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-01-02-meet-abpio-at-ndc-london-2024/post.md b/docs/en/Community-Articles/2024-01-02-meet-abpio-at-ndc-london-2024/post.md new file mode 100644 index 0000000000..aa2fa568c4 --- /dev/null +++ b/docs/en/Community-Articles/2024-01-02-meet-abpio-at-ndc-london-2024/post.md @@ -0,0 +1,18 @@ +Hey there, are you ready to start 2024 journey with [ABP.IO](https://abp.io/)? + +We're absolutely thrilled to announce that ABP.IO is proudly sponsoring [NDC London 2024](https://ndclondon.com) for the fifth consecutive year! With 110+ speakers and 115+ conference sessions, the conference will be held in the heart of the City of London at the QEII. As a dedicated supporter of the software development community, especially in .NET community, we’re excited to once again be part of this phenomenal gathering. + +For those new to the scene, NDC London is a conference where software developers come together to explore a wide range of topics in the industry. It actively brings experts from around the world share their knowledge on the latest technologies and best practices. Organized by NDC Conferences, known for hosting similar events worldwide, it's a great opportunity to learn and connect in the software development community. + +The ABP.IO team is just ready up for NDC London 2024. We're eager to connect with fellow developers and dive deep into the conference insights. Stay tuned for more updates as we gear up for this fantastic event. Join us at our booth on the 3rd floor of the Queen Elizabeth II Centre for exciting surprises! We've prepared exclusive swag kits and the raffle you won't want to miss. + +As [Volosoft Company](https://volosoft.com/), supporting events like NDC London reflects our dedication to empowering the software development community. These gatherings are essential—a chance to learn, connect, and stay updated in our dynamic field. Catch insights from past NDC events and more conference experiences on our previous [blogs](https://blog.abp.io/abp). + +Interested in Volosoft and our contributions to software development? Drop by our booth to discuss [ABP Commercial](https://commercial.abp.io/), our SaaS product based on the robust open source [ABP Framework](https://github.com/abpframework/abp). Let's chat about your software needs and how we can assist you. + +Mark your calendars because NDC London 2024 is going to be off the charts, and we can't wait to see you there! Let's dive into the future of software development together. + +
+See you at NDC London 2024! + +
diff --git a/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59366a9beb61202ddf67a48af0.jpg b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59366a9beb61202ddf67a48af0.jpg new file mode 100644 index 0000000000..dbdf7c96b0 Binary files /dev/null and b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59366a9beb61202ddf67a48af0.jpg differ diff --git a/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5964f409df4857352a7750144f.jpg b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5964f409df4857352a7750144f.jpg new file mode 100644 index 0000000000..a25fabcc98 Binary files /dev/null and b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5964f409df4857352a7750144f.jpg differ diff --git a/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e598d63941f1b4eb0bbb9c1a7bf.jpg b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e598d63941f1b4eb0bbb9c1a7bf.jpg new file mode 100644 index 0000000000..660d086cbc Binary files /dev/null and b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e598d63941f1b4eb0bbb9c1a7bf.jpg differ diff --git a/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59b2bc78fcdb2805b6b2c2e0d8.jpg b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59b2bc78fcdb2805b6b2c2e0d8.jpg new file mode 100644 index 0000000000..7babc9ab5b Binary files /dev/null and b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59b2bc78fcdb2805b6b2c2e0d8.jpg differ diff --git a/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59d73b779a17a42733619a5082.jpg b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59d73b779a17a42733619a5082.jpg new file mode 100644 index 0000000000..b1ab47d590 Binary files /dev/null and b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59d73b779a17a42733619a5082.jpg differ diff --git a/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59fc9f52bfdd52a5b2a6fd629b.jpg b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59fc9f52bfdd52a5b2a6fd629b.jpg new file mode 100644 index 0000000000..27aad1a716 Binary files /dev/null and b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e59fc9f52bfdd52a5b2a6fd629b.jpg differ diff --git a/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5a3c4d33948a14f739566c3e91.jpg b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5a3c4d33948a14f739566c3e91.jpg new file mode 100644 index 0000000000..eda7ac4735 Binary files /dev/null and b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5a3c4d33948a14f739566c3e91.jpg differ diff --git a/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5a65ed0e44544fba86d71ba538.jpg b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5a65ed0e44544fba86d71ba538.jpg new file mode 100644 index 0000000000..76842cf0fa Binary files /dev/null and b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5a65ed0e44544fba86d71ba538.jpg differ diff --git a/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5a8d62fe81356f87616a4c00bc.jpg b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5a8d62fe81356f87616a4c00bc.jpg new file mode 100644 index 0000000000..5be2c5d6dc Binary files /dev/null and b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/3a101e5a8d62fe81356f87616a4c00bc.jpg differ diff --git a/docs/en/Community-Articles/2024-01-15-2024-first-community-event/post.md b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/post.md new file mode 100644 index 0000000000..9f338522b9 --- /dev/null +++ b/docs/en/Community-Articles/2024-01-15-2024-first-community-event/post.md @@ -0,0 +1,21 @@ + ## 2024 First Community Event. + +The first .NET community event in 2024 was successfully held in Shenzhen on January 14, 2024. + +This event is co-organized by **Microsoft MVP China Team**, **Microsoft Reactor**, **China .NET Community** and **Shenzhen .NET Club**. + +**ABP.IO** continues to strongly support the community, and we have prepared exquisite gifts for participants. + +The event includes four wonderful technical lectures to reveal big data and AI's potential opportunities and innovations. It is a transfer of knowledge and a platform for communication and cooperation among technology enthusiasts. + +![1.jpg](3a101e59366a9beb61202ddf67a48af0.jpg) +![2.jpg](3a101e5964f409df4857352a7750144f.jpg) +![3.jpg](3a101e598d63941f1b4eb0bbb9c1a7bf.jpg) +![4.jpg](3a101e59b2bc78fcdb2805b6b2c2e0d8.jpg) +![51.jpg](3a101e59fc9f52bfdd52a5b2a6fd629b.jpg) +![5.jpg](3a101e59d73b779a17a42733619a5082.jpg) +![6.jpg](3a101e5a3c4d33948a14f739566c3e91.jpg) +![8.jpg](3a101e5a65ed0e44544fba86d71ba538.jpg) +![9.jpg](3a101e5a8d62fe81356f87616a4c00bc.jpg) + +**See you at the next community event!** \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-01-15-Abp-Supports-NET8/Post.md b/docs/en/Community-Articles/2024-01-15-Abp-Supports-NET8/Post.md index a45f893b16..c6a37d85cd 100644 --- a/docs/en/Community-Articles/2024-01-15-Abp-Supports-NET8/Post.md +++ b/docs/en/Community-Articles/2024-01-15-Abp-Supports-NET8/Post.md @@ -1,5 +1,3 @@ -![cover](cover.png) - # ABP Now Supports .NET 8 Recently we have published ABP v8.0. With this version [the ABP Framework](https://github.com/abpframework/abp/blob/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj#L6) and ABP Commercial both supports for .NET 8, aligning itself with the latest enhancements and new features of the ASP.NET's new version 8. @@ -170,4 +168,4 @@ Starting in .NET 8, C# Hot Reload [supports modifying generic types and generic *References:* -* https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8 \ No newline at end of file +* https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8 diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c22c9c7b27c9d007bc5817adaee.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c22c9c7b27c9d007bc5817adaee.png new file mode 100644 index 0000000000..2935b780b5 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c22c9c7b27c9d007bc5817adaee.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c28bb8b56956ba1e9486162c9fb.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c28bb8b56956ba1e9486162c9fb.png new file mode 100644 index 0000000000..cb03ca7462 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c28bb8b56956ba1e9486162c9fb.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c291c1653e33f4b475ed8543b39.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c291c1653e33f4b475ed8543b39.png new file mode 100644 index 0000000000..afbb6bd078 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c291c1653e33f4b475ed8543b39.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c297595810b3386fbb639eb1ed9.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c297595810b3386fbb639eb1ed9.png new file mode 100644 index 0000000000..872c190993 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c297595810b3386fbb639eb1ed9.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c29c57e24188931b73d4c13bcff.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c29c57e24188931b73d4c13bcff.png new file mode 100644 index 0000000000..1a249f2fc7 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c29c57e24188931b73d4c13bcff.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c2ef17a8549b7bdb49926421e64.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c2ef17a8549b7bdb49926421e64.png new file mode 100644 index 0000000000..bff98168a4 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c2ef17a8549b7bdb49926421e64.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c2f49f707344bf790f8a7b8f248.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c2f49f707344bf790f8a7b8f248.png new file mode 100644 index 0000000000..70354be8b9 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c2f49f707344bf790f8a7b8f248.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c2f94607809e9ea4da93c4b58fb.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c2f94607809e9ea4da93c4b58fb.png new file mode 100644 index 0000000000..d388ed6aa4 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c2f94607809e9ea4da93c4b58fb.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c3322a8172d22fdceb1c931bfb7.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c3322a8172d22fdceb1c931bfb7.png new file mode 100644 index 0000000000..02706c7981 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c3322a8172d22fdceb1c931bfb7.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c3d26924d5ccd093c79e351e2cf.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c3d26924d5ccd093c79e351e2cf.png new file mode 100644 index 0000000000..c7ce9a56ae Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108c3d26924d5ccd093c79e351e2cf.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108f97f94047a43a52511f8b4c1802.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108f97f94047a43a52511f8b4c1802.png new file mode 100644 index 0000000000..73ef0ae7c7 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108f97f94047a43a52511f8b4c1802.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108fa3b8c97de8532fba8646e48f0b.png b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108fa3b8c97de8532fba8646e48f0b.png new file mode 100644 index 0000000000..e34e403d90 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/3a108fa3b8c97de8532fba8646e48f0b.png differ diff --git a/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/post.md b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/post.md new file mode 100644 index 0000000000..a7a397498f --- /dev/null +++ b/docs/en/Community-Articles/2024-02-05-ndc-london-2024-abpios-key-highlights/post.md @@ -0,0 +1,83 @@ +As ABP.IO team, we just got back from our amazing trip with [NDC London](https://ndclondon.com/) and would love to share a recap of this amazing conference. It was the 5th time in a row we were a proud sponsor of NDC London. It, now, basically feels like home spending 3 days in Queen Elizabeth Centre II with NDC London for the [ABP.IO](https://abp.io/) team to be there. + +![booth.png](3a108c22c9c7b27c9d007bc5817adaee.png) + +This year, we were there with Lead Developers of ABP.IO Platform [Halil Ibrahim Kalkan](https://community.abp.io/members/hikalkan) and [Alper Ebicoglu](https://community.abp.io/members/alper) -as usual- and also ABP.IO Core team members, [Engincan Veske](https://community.abp.io/Members/EngincanV) and [Bige Besikci Yaman](https://community.abp.io/Members/bigebesikci). + +![team.png](3a108c28bb8b56956ba1e9486162c9fb.png) + +These 3 days with the team was all about chatting and having fun with amazing attendees and speakers. We met with talented and passionate software developers and introduced the [open source ABP Framework](https://github.com/abpframework/abp) - web application framework built on ASP.NET Core and [ABP Commercial](https://commercial.abp.io/) - the complete web application development platform built on open source ABP Framework to them. We also had a chance to reunite with some of the regulars as us and talked about the latest updates on .NET and ABP.IO Platform. + +![attendees1.png](3a108c291c1653e33f4b475ed8543b39.png) + +![attendees2.png](3a108c297595810b3386fbb639eb1ed9.png) + +![attendees3.png](3a108c29c57e24188931b73d4c13bcff.png) + +It wasn't all about learning but always fun and games with all the attendees. We love to show our hospitality with hand-made chocolates; enjoy the small-but-useful gadgets as well as the beneficial items such as books and of course the funny stickers. This year was no different. +We had delicious hand-made chocolates we brought all the way to London as always and didn't forget to enjoy them as we go through the days! +Attendees got to test their .NET knowledge with an easy quiz and left our booth with their TWS earphones. +As for the benefits and efficiency, we gave [Implementing DDD e-book](https://abp.io/books/implementing-domain-driven-design)'s paperback written by the Lead Architecture of ABP Framework - Halil Ibrahim Kalkan to the .NET developers. Because, what better gift than a book? + +![booth2.png](3a108c3322a8172d22fdceb1c931bfb7.png) + +As usual, we draw a raffle on the last day for Meta Quest 2 prize. Congratulations to our winner, Christian Wattengard. + +![raffle winner.png](3a108fa3b8c97de8532fba8646e48f0b.png) +
+ +NDC London was - once again - full of insightful talks with 110 sessions and 100+ speakers. You can find some highlights from those talks below. + +## First Day of NDC London +#### "Keynote: Debug your thinking" by [Laila Bougria](https://twitter.com/noctovis) +She showed how crucial it is to make good decisions in software development, more than just picking the right tech. She set an example of how she improved her way of thinking, pushing for a methodical way to make decisions that result in better, more well-rounded solutions. She encouraged everyone to think deeply and improve their problem-solving skills to come up with better software solutions. + +#### "Real-Time Connected Apps with .NET MAUI, Blazor, and SignalR" by [Gerald Versluis](https://twitter.com/jfversluis) +He kicked off one of the first sessions by talking on how to build apps that update instantly using SignalR, .NET MAUI, and Blazor. He broke down the basics of SignalR and showed off its capabilities with some cool demos, showing how apps on phones and the web can work together in real time. His talk was all about making apps that work together smoothly and keep users engaged. + +#### "You are doing logging in .NET wrong. Let’s fix it" by [Nick Chapsas](https://twitter.com/nickchapsas) +He talked about how important logging is for finding and fixing problems in apps that are already out there. He pointed out the usual mistakes people make when logging in .NET and showed how to fix them. His advice aimed to make logging more effective. + +#### "Architecture Modernization: Aligning Software, Strategy, and Structure" by [Nick Tune](https://twitter.com/ntcoding) +He warned about the dangers of sticking with old software architectures, which can stop a business from growing. He argued for updating software architectures to stay competitive, helping businesses move faster and grow bigger. + +## Second Day of NDC London +#### "Distribu-ready with the Modular Monolith" by [Layla Porter](https://twitter.com/laylacodesit) +She tackled the excitement and problems with distributed systems and microservices. She introduced the Modular Monolith as a smarter way to prepare for growth without making things too complicated. She explained how this approach keeps things simpler but still ready for the future. + +#### "How to effectively spy on your systems" by [Laila Bougria](https://twitter.com/noctovis) +In her second talk of NDC London after the Keynote on the first day, she explained how to keep an eye on complex systems using OpenTelemetry. She talked about the hurdles of making sure you can watch over your systems effectively and shared tips on picking the right tools, keeping costs down, and setting up your system for the best oversight. Her talk aimed to give a full picture of how to monitor systems well. + +#### "Tales from the .NET 8 Migration Trenches" by [Jimmy Bogard](https://twitter.com/jbogard) +He shared his experience with updating a .NET 4.8 app to .NET 8, without starting from scratch. He gave advice on how to move parts of an app to newer versions bit by bit, while still keeping everything running. His focus was on how to update common parts of apps, like databases and messaging, with practical tips from real projects. + +#### "CS Fundamentals: Why SSL and SSH are Secure" by [Jon Skeet](https://twitter.com/jonskeet) and [Rob Conery](https://twitter.com/robconery) +They took a close look at the RSA algorithm, a key piece of technology that keeps online communication secure and talked about why it's so important as well as its history, and even showed how it works, all while sharing interesting stories. + +## Third and the Last Day of NDC London +#### "How GitHub delivers GitHub using GitHub" by [April Edwards](https://twitter.com/TheAprilEdwards) +She shared how Microsoft's engineering teams have become more agile, going from releasing new versions every three years to every three weeks. She also explained how GitHub uses its own tools to build and improve itself. In her talk, she compared the agile journeys of Microsoft and GitHub, showing how they deliver software quickly and efficiently. + +![talks1.png](3a108c2ef17a8549b7bdb49926421e64.png) + +![talks2.png](3a108c2f49f707344bf790f8a7b8f248.png) + +![talks3.png](3a108c2f94607809e9ea4da93c4b58fb.png) + +## The fun part of the NDC London +The expo area on the third floor of Queen Elizabeth II Centre was also full of fun in all aspects. There were a variety of delicious food and the place hosted a yet another great party with delicious cocktails. We didn't forget to have fun and had our bellies full at all times! + +![food.png](3a108c3d26924d5ccd093c79e351e2cf.png) +![cocktail.png](3a108f97f94047a43a52511f8b4c1802.png) + +Last but not least, let's take a look around in Queen Elizabeth II Centre and re-live the expo area of NDC London atmosphere. +
+ +Thank you all for visiting our booth and the amazing chat you cherished our 3 days with. +We will see you all on the next one! :) + +To see how the past 4 NDC London sponsorships went, check out: +* [NDC London 2023 - Sponsored for the 4th time](https://volosoft.com/blog/NDC-London-2018-Impressions) +* [Recap: NDC {London} 2020 Software Developers Conference](https://volosoft.com/blog/Recap-NDC-London-2020-Software-Developers-Conference) +* [Impressions of NDC London 2019](https://volosoft.com/blog/Impressions-of-NDC-London-2019) +* [NDC London 2018 Impressions](https://volosoft.com/blog/NDC-London-2018-Impressions) \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2b6804e27641c3a54a31b17af.png b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2b6804e27641c3a54a31b17af.png new file mode 100644 index 0000000000..8281ecb8d6 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2b6804e27641c3a54a31b17af.png differ diff --git a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2ccca44199565fef1d235b2cc.png b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2ccca44199565fef1d235b2cc.png new file mode 100644 index 0000000000..92b767515a Binary files /dev/null and b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2ccca44199565fef1d235b2cc.png differ diff --git a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2ea684ad6afba3caab97b4425.png b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2ea684ad6afba3caab97b4425.png new file mode 100644 index 0000000000..6c45f9cb71 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2ea684ad6afba3caab97b4425.png differ diff --git a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2fff3262dc03a5acaa50ffb00.png b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2fff3262dc03a5acaa50ffb00.png new file mode 100644 index 0000000000..23b1dc8513 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a2fff3262dc03a5acaa50ffb00.png differ diff --git a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a31f35c6183ddc89755c791bff.png b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a31f35c6183ddc89755c791bff.png new file mode 100644 index 0000000000..6bb0920800 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a31f35c6183ddc89755c791bff.png differ diff --git a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a33d9bacfe3632188944e5ed02.png b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a33d9bacfe3632188944e5ed02.png new file mode 100644 index 0000000000..c1c8e6ca8d Binary files /dev/null and b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a33d9bacfe3632188944e5ed02.png differ diff --git a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a35dec6b8ff82063cf4422efd7.jpg b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a35dec6b8ff82063cf4422efd7.jpg new file mode 100644 index 0000000000..c8a78a0f93 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a35dec6b8ff82063cf4422efd7.jpg differ diff --git a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a3779ccb1908d67691ec3f1ba4.png b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a3779ccb1908d67691ec3f1ba4.png new file mode 100644 index 0000000000..cb03ca7462 Binary files /dev/null and b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/3a10d2a3779ccb1908d67691ec3f1ba4.png differ diff --git a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/post.md b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/post.md new file mode 100644 index 0000000000..569e566af7 --- /dev/null +++ b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/post.md @@ -0,0 +1,237 @@ +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **8.1 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 v8.1! Thanks to all of you. + +## Get Started with the 8.1 RC + +Follow the steps below to try version 8.1.0 RC today: + +1) **Upgrade** the ABP CLI to version `8.1.0-rc.1` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 8.1.0-rc.1 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 8.1.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 8.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 v8.x or earlier: + +* [ABP Framework 8.0 to 8.1 Migration Guide](https://docs.abp.io/en/abp/8.1/Migration-Guides/Abp-8_1) +* [ABP Commercial 8.0 to 8.1 Migration Guide](https://docs.abp.io/en/commercial/8.1/migration-guides/v8_1) + +## What's New with ABP Framework 8.1? + +In this section, I will introduce some major features released in this version. +Here is a brief list of titles explained in the next sections: + +* Introducing the `ExposeKeyedServiceAttribute` +* Custom Menu Component Support for MVC UI +* Introducing the `DisableAbpFeaturesAttribute` + +### Introducing the `ExposeKeyedServiceAttribute` + +[Keyed dependency injection (DI) services](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-8.0#keyed-services) were added to the built-in DI container as a new feature with .NET 8.0. This is an important feature, which allows for registering and retrieving DI services using keys/names. + +In this version, we have introduced the `ExposeKeyedServiceAttribute` to allow you to automatically register keyed services by conventions: + +```csharp +[ExposeKeyedService("taxCalculator")] +[ExposeKeyedService("calculator")] +public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency +{ +} +``` + +In the example above, the `TaxCalculator` class exposes the `ITaxCalculator` interface with the key `taxCalculator` and the `ICalculator` interface with the key `calculator`. + +Thanks to that, then you can use the [`FromKeyedServicesAttribute`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.fromkeyedservicesattribute?view=dotnet-plat-ext-8.0) to resolve a certain keyed service in the constructor: + +```csharp +public class MyClass +{ + //... + public MyClass([FromKeyedServices("taxCalculator")] ITaxCalculator taxCalculator) + { + TaxCalculator = taxCalculator; + } +} +``` + +> Notice that the `ExposeKeyedServiceAttribute` only exposes the keyed services. So, you can not inject the `ITaxCalculator` or `ICalculator` interfaces in your application without using the `FromKeyedServicesAttribute` as shown in the example above. + +> If you want to learn more about the keyed dependency injection services, please refer to [Microsoft's documentation](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-8.0#keyed-services) and [ABP Framework's Dependency Injection document](https://docs.abp.io/en/abp/8.1/Dependency-Injection#exposekeyedservice-attribute). + +### Custom Menu Component Support for MVC UI + +In this version, we have introduced the **custom menu component support**, which allows you to use a custom component for a certain menu item. + +You can use the `UseComponent` extension method while defining menu items to use your custom component for the related menu item: + +```csharp +context.Menu.Items.Add( + new ApplicationMenuItem("Custom.1", "My Custom Menu", "#") + .UseComponent(typeof(MyMenuComponent))); +``` + +Then, for the related menu item, your custom component will be rendered on the UI. + +### Introducing the `DisableAbpFeaturesAttribute` + +In this version, we have introduced the `DisableAbpFeaturesAttribute` to allow you to disable interceptors, middlewares, and MVC filters for a specific controller. + +For example, you may want to disable interceptors for a certain controller, but you may also don't want to disable middlewares and mvc filters, in that case, you can use the `DisableAbpFeaturesAttribute` as follows: + +```csharp +[Route("api/my-endpoint")] +[DisableAbpFeatures(DisableInterceptors = true, DisableMiddleware = false, DisableMvcFilters = false)] +public class MyController : AbpController +{ + +} +``` + +This can be useful if you have some APIs that are used frequently but you don't need all the features of ABP Framework. + +> **Note:** If you want to disable all interceptors, middlewares, and filters for a certain controller, then you can use the `[DisableAbpFeatures]` without the need to specify the parameters, they are disabled by default. + +## What's New with ABP Commercial 8.1? + +We've also worked on ABP Commercial to align the features and changes made in the ABP Framework. The following sections introduce a few new features coming with ABP Commercial 8.1. + +### Suite: New Features + +In this version, we mostly worked on ABP Suite and implemented some wanted features, such as *bulk delete*, *filterable properties*, *customizable page title*, *allowing establishing relationships with installed ABP modules' entities* and *supporting the `BasicAggregateRoot` as the base class*. + +#### Bulk Delete + +From this version on, ABP Suite allows you to perform bulk deletion of records based on specified criteria. + +![bulk-delete.png](3a10d2a2b6804e27641c3a54a31b17af.png) + +To enable *bulk delete support*, you should enable the *Bulk delete* option in the CRUD page generation page, along with the *Create user interface* option (they are enabled by default). When you enable the *bulk delete support*, you will see the checkboxes for each line in the datatable: + +![bulk-delete-datatable.png](3a10d2a2ccca44199565fef1d235b2cc.png) + +By selecting these checkboxes, you can delete all records in the current datatable (10 records by default), or delete all records in the database (by selecting *select all xx items* selection), or delete any records you want by selecting them one by one. + +> **Note:** This feature has already been implemented for MVC & Blazor UIs, but not implemented for Angular UI yet. We aim to implement it for Angular UI with *v8.1.0-rc.2*. + +#### Filterable Properties + +ABP Suite has been generating advanced filters for entities for a while and before this version, if you enabled the *create user interface* option, then all of the properties that you specified were included in the advanced filter section automatically. + +In this version, we have introduced the **filterable properties** feature to allow you to select which properties should be filterable and which are not: + +![filterable-properties.png](3a10d2a2ea684ad6afba3caab97b4425.png) + +Now, you have full control to select which properties should be included as filter inputs and shown on the advanced filters section on your generated pages. + +In other words, once, you select a property as *not filterable*, then the property will not be included in the filter inputs and in the advanced filter section. Also, if there are not any filterable properties for an entity, then the advanced filters section will not be generated. + +#### Customizable Page Title + +In this version on, ABP Suite allows you to specify the page title for the current entity. + +![page-title.png](3a10d2a2fff3262dc03a5acaa50ffb00.png) + +You just need to specify the *page title* on the CRUD page generation page for a specific entity and then it will be used as a localization key in the application (and also will be localized - for example, if you specify it as 'MyPageTitle', then it will be localized in English as 'My Page Title'), so you can localize it for different languages later on. + +#### Allowing Establishing Relationships with Installed ABP Modules' Entities + +In this version, ABP Suite allows you to establish one-to-many relationship with pre-installed ABP Modules. You can add any entity from pre-installed ABP modules as a navigation property, by checking the **Include entities from ABP modules** checkbox in the navigation property model and choosing the related module entity as in the following figure: + +![suite-include-entities-from-abp-modules.png](3a10d2a31f35c6183ddc89755c791bff.png) + +In the example above, the `IdentityUser` entity is selected as the navigation property but you can also choose any entity from the installed ABP modules in the navigation property model. + +> **Note:** Ensure that your solution is built properly before establishing relationship between your own entity and a module entity because ABP Suite scans assemblies and finds which ABP modules you are using and lists their entities in the navigation property model if you have checked the **Include entities from ABP modules** checkbox. + +#### Support `BasicAggregateRoot` Base Class + +In this version on, ABP Suite allows you to choose the `BasicAggregateRoot` as the base class while generating an entity: + +![basic-aggregate-root.png](3a10d2a33d9bacfe3632188944e5ed02.png) + +> You can choose the [BasicAggregateRoot](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/BasicAggregateRoot.cs) if you want to create an aggregate root without the `IHasExtraProperties` and `IHasConcurrencyStamp` interfaces implemented (extra properties & concurrency check). + +### ABP Studio v0.6.5 Has Been Released! + +We have just released v0.6.5 for ABP Studio and with this version, we fixed many minor bugs reported by you, started supporting running multiple ABP Studio instances, and added important features, such as adding a public website to the new microservice template, and so on... + +In addition to all of this, we continue to enrich ABP Studio's documentation as always and you can read them at [https://docs.abp.io/en/commercial/latest/studio/overview](https://docs.abp.io/en/commercial/latest/studio/overview). + +Please try ABP Studio v0.6.5 and [provide feedback](https://support.abp.io/QA/Questions/6416/ABP-Studio-Bugs--Issues) to help us release more stable versions. Thanks in advance! + +## Community News + +### .NET Conf China 2023 Watch Party + +![dotnet-conf-china-2023-watch-party.jpg](3a10d2a35dec6b8ff82063cf4422efd7.jpg) + +ABP.IO was thrilled to sponsor the first .NET Community event in 2024 held in Shenzen on January 14, 2024. + +The event included four wonderful technical lectures to reveal big data and AI's potential opportunities and innovations. It was a transfer of knowledge and a platform for communication and cooperation among technology enthusiasts and we are happy to be attended. + +> If you want to learn more about the .NET Conf China 2023 Watch Party event, please check [the blog post](https://blog.abp.io/abp/2024-First-Community-Event). + +### Volosoft Attended NDC London 2024 + +![ndc-london-2024.png](3a10d2a3779ccb1908d67691ec3f1ba4.png) + +Core team members of the ABP Framework, [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan), [Alper Ebicoglu](https://twitter.com/alperebicoglu), [Engincan Veske](https://twitter.com/EngincanVeske), and [Bige Beşikci Yaman](https://twitter.com/bigedediki) attended [NDC London 2024](https://ndclondon.com/) from the 31st of January to the 2nd of February. + +It was the 5th time in a row we were a proud sponsor of NDC London. It, now, basically feels like home spending 3 days in Queen Elizabeth Centre II with NDC London for the [ABP.IO](https://abp.io/) team to be there. + +These 3 days with the team were all about chatting and having fun with amazing attendees and speakers. We met with talented and passionate software developers and introduced the [open source ABP Framework](https://github.com/abpframework/abp) - web application framework built on ASP.NET Core and [ABP Commercial](https://commercial.abp.io/) - the complete web application development platform built on open source ABP Framework - to them. + +> We shared our insights and key highlights from the NDC London 2024 event, which you can find at [https://blog.abp.io/abp/NDC-London-2024-ABP.IO-Key-Highlights](https://blog.abp.io/abp/NDC-London-2024-ABP.IO-Key-Highlights). + +### New ABP Community Articles + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Every Programmer Should Know #2: Optimistic Concurrency Control](https://community.abp.io/posts/every-programmer-should-know-2-optimistic-concurrency-control-sms9xs9n) by [Berkan Sasmaz](https://github.com/berkansasmaz) +* [Global Error Handling in Angular](https://community.abp.io/posts/global-error-handling-in-angular-gjcb2f1e) by [Sinan Öztürk](https://github.com/Sinan997) +* [ABP Framework goes Azure](https://community.abp.io/posts/abp-framework-goes-azure-ub4u5ax5) by [Bart Van Hoey](https://github.com/bartvanhoey) +* [ABP Supports .NET8](https://community.abp.io/posts/abp-supports-.net8-e4gve6ih) by [Alper Ebicoglu](https://community.abp.io/members/alper) +* [Engincan Veske](https://github.com/EngincanV) has created **three** new community articles: + * [ABP Now Supports Keyed Services!](https://community.abp.io/posts/abp-now-supports-keyed-services-6k92wz7h) + * [Mutation Testing in C# with Stryker](https://community.abp.io/posts/mutation-testing-in-c-with-stryker-tp6u599h) + * [ABP Suite: Best CRUD Page Generation Tool for .NET](https://community.abp.io/posts/abp-suite-best-crud-page-generation-tool-for-.net-cmm9xs3n) +* [Ahmed Tarek](https://github.com/AhmedTarekHasan) has created **nine** new community articles: + * [📑 Cover IO Based Apps With Unit Tests in .NET C# 🧪](https://community.abp.io/posts/-cover-io-based-apps-with-unit-tests-in-.net-c--zp6kip2r) + * [Better Enhanced Repository Pattern Implementation in .NET C#](https://community.abp.io/posts/better-enhanced-repository-pattern-implementation-in-.net-c-hpkbxr3l) + * [When Not To Use DI, IoC, and IoC Containers in .NET C#](https://community.abp.io/posts/when-not-to-use-di-ioc-and-ioc-containers-in-.net-c-n769hq8u) + * [⏰ Best Practice for Using Timers in .NET C# ⏳](https://community.abp.io/posts/-best-practice-for-using-timers-in-.net-c--3cqvew5o) + * [How to Fully Cover .NET C# Console Application With Unit Tests](https://community.abp.io/posts/how-to-fully-cover-.net-c-console-application-with-unit-tests-3h248yhe) + * [Web Scraping in .NET C#](https://community.abp.io/posts/web-scraping-in-.net-c-6pkp1abi) + * [Step by step guide to develop a Fluent API from scratch in .NET C# using the Builder Design Pattern](https://community.abp.io/posts/step-by-step-guide-to-develop-a-fluent-api-from-scratch-in-.net-c-using-the-builder-design-pattern-sbww0vky) + * [A Best Practice for Designing Interfaces in .NET C#](https://community.abp.io/posts/a-best-practice-for-designing-interfaces-in-.net-c-9xqc4h8d) + * [Invariance, Covariance, and Contravariance in .NET C#](https://community.abp.io/posts/invariance-covariance-and-contravariance-in-.net-c-9blmuhme) + +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/posts/submit) to the ABP Community. + +## 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/8.1/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v8.1 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/Post.md b/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/Post.md new file mode 100644 index 0000000000..a73fd2507a --- /dev/null +++ b/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/Post.md @@ -0,0 +1,134 @@ +# URL-Based Localization + +In this article I'll show you how to optimize your ABP website localization with a URL parameter. URL Paths are commonly being used to change the current UI culture. This method makes our website SEO-Friendly as you structuring the URLs for multiple languages. And you can also share the link of your website with a specific language. Let's see implementing multi-language support with URL parameters in an ABP project. + +![Turkish and English Localization within URL](scrshot1.jpg) + + + +## Mastering Website Localization: Language Codes in URLs Explained + +Enhancing UX with URL-Based website localization is mainly done with ASP.NET Core's routing system. Also we need to automatically redirect the links without language code parameter. Our URL structures for the localization will be as following: + +- https://mywebsite.com/en/dashboard (English) +- https://mywebsite.com/tr/dashboard (Turkish) + + + +## Routing + +Before starting to explain how to do this, you can see [this commit](https://github.com/salihozkara/MultiLangRoute/commit/09e40cfd751562dec0dab890e54e0c5ca9ee256c) which implements this functionality. The routing module consists of these fundamental classes: + +### 1. **MultiLanguageSupportMetaData.cs** + +This class is used to add a language parameter to route templates. For example, it changes the `/about` route to `/language/about`. + +### 2. **MultiLanguageRedirectRequiredMetaData.cs** + +This class is used to redirect users to the correct language version. If a user visits the `/about` page and the current culture is `"tr-TR"`, this class will redirect them to `/tr-TR/about`. + +### 3. **UrlNormalizer.cs** + +This static class is used to normalize URLs by adding language information and improving performance using caching. + +```csharp +public static string NormalizeUrl(EndpointDataSource endpointDataSource, HttpContext httpContext, string url) +{ + // Normalize the URL and cache it + return Cache.GetOrAdd(url, (key) => + { + var absoluteUrl = GetAbsoluteUrl(key); + var multiLanguageRedirectRequiredMetaData = + GetMultiLanguageRedirectRequiredMetaData(endpointDataSource, absoluteUrl); + return multiLanguageRedirectRequiredMetaData?.ReBuildUrl(httpContext, key) ?? key; + }); +} +``` + +### 4. **MyLinkGenerator.cs** + +This class extends ASP.NET Core’s `LinkGenerator` class to automatically add language information to all generated links. + +### 5. **MyRouteDataRequestCultureProvider.cs** + +This class determines the current culture using the language parameter in the URL. For example, it extracts the `"tr-TR"` culture from the `/tr-TR/about` URL. + +### 6. **RoutingMiddleware.cs** + +This middleware processes HTTP requests and redirects users to the correct language version when necessary. + +```csharp +public override Task InvokeAsync(HttpContext context, RequestDelegate next) +{ + var endpoint = context.GetEndpoint(); + if(endpoint is not RouteEndpoint) + { + return next(context); + } + + // Redirect if necessary + var redirectMetaData = endpoint.Metadata.GetMetadata(); + if (redirectMetaData is not null) + { + redirectMetaData.Redirect(context); + return Task.CompletedTask; + } + + // ... +} +``` + + + +## CultureAnchorTagHelper.cs + +This **Tag Helper** processes `` tags in a Razor page and automatically adds language information to URLs if it's missing. + +```csharp +[HtmlTargetElement("a", Attributes = "href", TagStructure = TagStructure.NormalOrSelfClosing)] +public class CultureAnchorTagHelper(EndpointDataSource endpointDataSource, IHttpContextAccessor contextAccessor) + : TagHelper, ITransientDependency +{ + public override void Process(TagHelperContext context, TagHelperOutput output) + { + var href = output.Attributes["href"].Value.ToString(); + if (href != null) + { + output.Attributes.SetAttribute("href", + UrlNormalizer.NormalizeUrl(endpointDataSource, contextAccessor.HttpContext!, href)); + } + } +} +``` + +**How This Tag Helper Works:** + +- Finds all `` tags within your Razor pages. +- Retrieves the `href` attribute of each link. +- Uses the `UrlNormalizer.NormalizeUrl()` method to normalize the URL with the current culture information. +- Replaces the original URL with the normalized one. + +For example, if the current culture is `"tr"` and a page contains ``, this Tag Helper will transform it into ``. + + + +## Sample Project + +Salih Özkara from ABP team created a sample working project which implements URL localization. He used ABP free tier MVC template and MongoDB. You can check out the related commit which implements URL localization: + +https://github.com/salihozkara/MultiLangRoute/commit/09e40cfd751562dec0dab890e54e0c5ca9ee256c + +And full working demo is available at: + +https://github.com/salihozkara/MultiLangRoute + +You can download the demo project at: + +[UrlLocalizationSampleProject.zip](https://github.com/abpframework/abp/blob/634ff52fb07d0b1281640695dbeffccdc943ca53/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/UrlLocalizationSampleProject.zip) + + + +## Summary + +This implementation extends ASP.NET Core’s routing mechanism and utilizes caching for improved performance. It ensures multilingual support by normalizing URLs, redirecting users to the appropriate language version, and automatically handling language-specific links. + diff --git a/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/UrlLocalizationSampleProject.zip b/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/UrlLocalizationSampleProject.zip new file mode 100644 index 0000000000..a9079c5f6e Binary files /dev/null and b/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/UrlLocalizationSampleProject.zip differ diff --git a/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/cover.png b/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/cover.png new file mode 100644 index 0000000000..b0f06080af Binary files /dev/null and b/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/cover.png differ diff --git a/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/scrshot1.jpg b/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/scrshot1.jpg new file mode 100644 index 0000000000..0d35786717 Binary files /dev/null and b/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/scrshot1.jpg differ diff --git a/docs/en/Community-Articles/2024-03-19-join-abpio-at-modern-net-web-day/3a11773a4db7b592ecf271fd1fe58e93.png b/docs/en/Community-Articles/2024-03-19-join-abpio-at-modern-net-web-day/3a11773a4db7b592ecf271fd1fe58e93.png new file mode 100644 index 0000000000..06945f9cda Binary files /dev/null and b/docs/en/Community-Articles/2024-03-19-join-abpio-at-modern-net-web-day/3a11773a4db7b592ecf271fd1fe58e93.png differ diff --git a/docs/en/Community-Articles/2024-03-19-join-abpio-at-modern-net-web-day/post.md b/docs/en/Community-Articles/2024-03-19-join-abpio-at-modern-net-web-day/post.md new file mode 100644 index 0000000000..df8844f18a --- /dev/null +++ b/docs/en/Community-Articles/2024-03-19-join-abpio-at-modern-net-web-day/post.md @@ -0,0 +1,31 @@ +**[ABP.IO](https://www.abp.io/)** is proud to announce our sponsorship of the upcoming **"Modern .NET Day"** event hosted by **[Jeff Fritz](https://twitter.com/csharpfritz)** and Friends, set to take place on Twitch. As one of the sponsors, we are excited to contribute to this enriching experience for .NET fellows worldwide. + +### Exclusive Offer + +As a swag bag sponsor, ABP.IO is delighted to give away 15 FREE tickets to the highly anticipated **[ABP Dotnet Conf’24](https://abp.io/conference/2024)**, scheduled on ***May 8-9***. Sign up for "Modern .NET Web Day" and enter for a chance to win this valuable ticket, paving the way for your next fun journey in the world of dotnet. + +![modern dotnet web day (1).png](3a11773a4db7b592ecf271fd1fe58e93.png) +### Topics to be Discussed + +Join us dive into the magic of .NET 8 at the community live stream event, "Modern .NET Web Day." Prepare to immerse yourself in the latest advancements, from the new Blazor features to revolutionary AI-driven productivity boosts in web development projects.  +Topics that will be covered include: + +* *ASP.NET Core*: Crafting Maintainable Microservices +* *Cloud Native development with .NET Aspire* +* *Developer Productivity with Visual Studio and .NET* +* *GitHub Copilot configuration, extension, tips and tricks* +* *User Experience and Front-End Development*: Delve into responsive design, accessibility, and performance optimization. Discuss modern front-end frameworks (Blazor, React, Angular, etc.) in the .NET ecosystem. Share strategies for creating delightful user interfaces. + +Don't miss out on this opportunity to gain invaluable insights and strategies for creating exceptional user interfaces. Mark your calendars for "Modern .NET Web Day" and join us for an unforgettable experience! + +*** + +📌 **Date:** March 22nd + +⏰ **Time:** 11 AM - 4 PM ET ( 3 - 8 PM UTC ) + +📺 **Where:** [Twitch (twitch.tv/csharpfritz)](https://www.twitch.tv/csharpfritz) + +*** + +[Register now ](https://www.mobilize.net/modern-dotnet-web-day)to join us. We look forward to seeing you there! \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-03-31-announcement-our-new-abpio-unified-platform/post.md b/docs/en/Community-Articles/2024-03-31-announcement-our-new-abpio-unified-platform/post.md new file mode 100644 index 0000000000..9df19e7437 --- /dev/null +++ b/docs/en/Community-Articles/2024-03-31-announcement-our-new-abpio-unified-platform/post.md @@ -0,0 +1,63 @@ +Hi ABP Community, + +📢 We're excited to announce an improvement to your ABP.IO experience! In our ongoing effort to simplify and improve your interaction with our platform, we are working on a new design for ABP.IO and its subdomains. This update isn't just about aesthetics; it's a comprehensive enhancement aimed at unifying all our services under a single platform address: https://abp.io. + + + +## Why are we making this change? + +Whether you're developing with our open-source framework or using our commercial product, or looking for support; our goal is always to deliver the best experience possible. The new design will improve several aspects: + +🔹**Simplifying Navigation**: As the ABP.IO platform has grown rapidly, navigating through numerous subdomains has become challenging. We're transitioning to a well-structured mega menu system that will make navigation tidier and more straightforward. With everything under the ABP.IO domain, finding what you need will be easier. + +🎨 **Enhancing User Experience**: We're introducing a fresh, modern design that not only looks better but also enhances functionality and ease of use. + +🔎 **Better SEO**: A unified domain improves our platform's discoverability, making it easier for new users to find us and for you to share resources with your peers. + + + +## Which services are being unified? + +✅ The following websites will now be unified under ABP.IO: + +- blog.abp.io 👉 abp.io/blog +- docs.abp.io 👉 abp.io/docs +- support.abp.io 👉 abp.io/support +- community.abp.io 👉 abp.io/community +- commercial.abp.io 👉 abp.io + + +> ⛔ The following websites will not be unified during this transition: admin.abp.io, account.abp.io, nuget.abp.io + + +## What can you expect? + +The new ABP.IO platform is designed with you in mind. Here’s what to look forward to: + +- **Seamless Integration**: Transitioning from multiple subdomains to a single address without losing track of your favorite resources. We will keep many pages the same as before. Page-based transitions will be made over a longer period of time. + +- **Improved Support and Documentation**: We will merge commercial and open-source docs into a single address so it'll be easier to access our documentation. + + + +## Your journey with us during this transition + +We know that change is overwhelming, but we are trying to provide a smooth transition. Here's how we're making it seamless for you: + +🚩 **No Immediate Action Required**: Your existing bookmarks and links will continue to work, automatically redirecting you to the new unified platform. + +🎗 **Stay Informed**: We will keep you updated with guides and support during the transition. + +📧 **We’re Here to Help**: Our support team is ready to assist you with any questions or concerns. If you have any issues, you can contact us at our Discord channel or send an email to info@abp.io. + + + +## Looking Ahead + +This upgrade is another milestone in our journey together. Thank you for your support and feedback, which have been instrumental in making this transition possible. Stay tuned for more updates, and here's to a new chapter together at ABP.IO! + + + +Happy coding 🫡 + +ABP.IO Team \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-04-08-abpio-platform-81-final-has-been-released/post.md b/docs/en/Community-Articles/2024-04-08-abpio-platform-81-final-has-been-released/post.md new file mode 100644 index 0000000000..3a2bc44731 --- /dev/null +++ b/docs/en/Community-Articles/2024-04-08-abpio-platform-81-final-has-been-released/post.md @@ -0,0 +1,78 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 8.1 versions have been released today. + +## What's New With Version 8.1? + +All the new features were explained in detail in the [8.1 RC Announcement Post](https://blog.abp.io/abp/announcing-abp-8-1-release-candidate), so there is no need to review them again. You can check it out for more details. + +## Getting Started with 8.1 + +### Creating New Solutions + +You can create a new solution with the ABP Framework version 8.1 by either using the `abp new` command or generating the CLI command on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to Upgrade an Existing Solution + +#### Install/Update the ABP CLI + +First, install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update the existing CLI: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading Existing Solutions with the ABP Update Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## 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 v8.x or earlier: + +* [ABP Framework 8.0 to 8.1 Migration Guide](https://docs.abp.io/en/abp/8.1/Migration-Guides/Abp-8_1) +* [ABP Commercial 8.0 to 8.1 Migration Guide](https://docs.abp.io/en/commercial/8.1/migration-guides/v8_1) + +## Community News + +### New ABP Community Posts + +As always, exciting articles have been contributed by the ABP community. I will highlight some of them here: + +* [Adding a Module to an ABP project made simple](https://community.abp.io/posts/adding-a-module-to-an-abp-project-made-simple-a8zw0j2m) by [Bart Van Hoey](https://twitter.com/@bartvanhoey) +* [Getting started with Abp Vue UI](https://community.abp.io/posts/getting-started-with-abp-vue-ui-4vfiv5io) by [Sajankumar Vijayan](https://community.abp.io/members/Sajan) +* [Liming Ma](https://github.com/maliming) has created **two** new community articles: + * [How to share the cookies between subdomains](https://community.abp.io/posts/how-to-share-the-cookies-between-subdomains-jfrzggc2) + * [Using Testcontainers in ABP Unit Test](https://community.abp.io/posts/using-testcontainers-in-abp-unit-test-b67gzpxg) +* [Ahmed Tarek](https://github.com/AhmedTarekHasan) has created **three** new community articles: + * [Strategy Design Pattern In .NET C#](https://community.abp.io/posts/strategy-design-pattern-in-.net-c-vcgv11h5) + * [Mediator Design Pattern In .NET C#](https://community.abp.io/posts/mediator-design-pattern-in-.net-c-pdsjp93n) + * [SOLID: Liskov Substitution Principle Explained In .NET C#](https://community.abp.io/posts/solid-liskov-substitution-principle-explained-in-.net-c-hx2z8vo9) + +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: + +* [Announcement: Our New ABP.IO Unified Platform](https://blog.abp.io/abp/our-new-abp.io-unified-platform) by [Alper Ebicoglu](https://twitter.com/alperebicoglu) +* [Join ABP.IO at Modern .NET Web Day](https://blog.abp.io/abp/Join-ABP.IO-at-Modern-.NET-Web-Day) by [Roo Xu](https://github.com/Roo1227) + +## About the Next Version + +The next feature version will be 8.2. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-04-16-welcome-to-abp-dotnet-conf24-a-decade-of-net-innovation/3a11fced7109d5f4d3c23920ecb5eec2.png b/docs/en/Community-Articles/2024-04-16-welcome-to-abp-dotnet-conf24-a-decade-of-net-innovation/3a11fced7109d5f4d3c23920ecb5eec2.png new file mode 100644 index 0000000000..ac776fa613 Binary files /dev/null and b/docs/en/Community-Articles/2024-04-16-welcome-to-abp-dotnet-conf24-a-decade-of-net-innovation/3a11fced7109d5f4d3c23920ecb5eec2.png differ diff --git a/docs/en/Community-Articles/2024-04-16-welcome-to-abp-dotnet-conf24-a-decade-of-net-innovation/post.md b/docs/en/Community-Articles/2024-04-16-welcome-to-abp-dotnet-conf24-a-decade-of-net-innovation/post.md new file mode 100644 index 0000000000..92635c6f7e --- /dev/null +++ b/docs/en/Community-Articles/2024-04-16-welcome-to-abp-dotnet-conf24-a-decade-of-net-innovation/post.md @@ -0,0 +1,107 @@ +🌟Hey .NET community! + +We are excited to invite you to join us for the **[ABP Dotnet Conference 2024](https://abp.io/conference/2024)**, taking place online on **May 8-9, 2024**! As we celebrate the 10th anniversary of the **[ABP.IO](https://www.abp.io/)**, sign up for an expanded two-day event packed with even more engaging workshops & talks that promises to deepen your expertise and expand your connections within the .NET ecosystem. + +Building on the success of last year’s event [ABP Dotnet Conf'23](https://abp.io/conference/2023), we are more than excited to bring together passionate developers, renowned speakers, and industry leaders from across the globe once again, for industrial knowledge, inspiration, and networking opportunities. + + + +## Why Attend? + +**[ABP Dotnet Conf'24](https://abp.io/conference/2024)** offers a unique blend of learning and networking opportunities tailored for the .NET community. + +**Industry-Leading Speakers:** Gain insights from pioneers and innovators in the .NET landscape. Expect practical advice, forward-thinking strategies, and inspiring stories that can move your projects and career forward. + +   +**Engaging Formats:** From engaging workshops to enlightening keynote & insightful talks, experience a variety of session formats designed to fit in all levels of expertise. Special highlights include workshops on modern .NET technologies and a keynote that explores career growth through creative practices. + +**Interactive Networking:** Embrace the full conference experience online with features designed to reach the most aspects of in-person events. Engage with experts and peers through live Q&As, virtual meet-ups, and interactive chat rooms. + + + + +## Speakers & Agenda + +As we always be careful with topics we choose on our regular **[ABP Community Talks](https://community.abp.io/events)**, to ensure a great experience for our audience, the same effort behind, for our **[ABP Dotnet Conf’24](https://abp.io/conference/2024)**, we have thoughtfully selected topics and expert speakers to deliver sessions filled with deep insights and inspiration. Our speakers for the **[ABP Dotnet Conference 2024](https://abp.io/conference/2024)**, chosen for their deep expertise, are set to deliver sessions that promise both inspiration and in-depth knowledge to all our attendees. See the crafted **Workshops & Talks** agenda overview: + + +📌 **Day 1 Workshops - May 8th** 📌 + +* 🎙️[Johan Smarius](https://abp.io/conference/2024/speakers/johan-smarius), Building a GraphQL Server in .NET 8 +* 🎙️[Wojciech Krasa](https://abp.io/conference/2024/speakers/wojciech-krasa), Testing framework with PostgreSQL and Testcontainers for .NET +* 🎙️[Ahmet Faruk Ulu](https://abp.io/conference/2024/speakers/ahmet-faruk-ulu), ABP Framework Essentials: Crafting Your SaaS Success Story  +* 🎙️[Alberto Acerbis](https://abp.io/conference/2024/speakers/alberto-acerbis) &  [Ferdinando Santacroce](https://abp.io/conference/2024/speakers/ferdinando-santacroce), Tackling Chaos, Resilience & Metrics in the heart of your Application +* 🎙️[Omkar Choudhari](https://abp.io/conference/2024/speakers/omkar-choudhari) & [Aman Sharma](https://abp.io/conference/2024/speakers/aman-sharma), Building your own copilot with ABP chat module +* 🎙️[Stefan Pölz](https://abp.io/conference/2024/speakers/stefan-polz), Let's Build an incremental source generator with Roslyn +* 🎙️[Ryan Niño Dizon](https://abp.io/conference/2024/speakers/ryan-nino-dizon), Building a Serverless Backend API with Azure Functions +* 🎙️[Kaushik Gokhale](https://abp.io/conference/2024/speakers/kaushik-gokhale) & Omkar Choudhari, React ♥ ABP: Next-Level Frontend Workshop for 3x Acceleration +* 🎙️[Rebai Hamida](https://abp.io/conference/2024/speakers/rebai-hamida), Build containerized application using Docker and Azure + + + +📌 **Day 2 Talks - May 9th** 📌 + +* 🎙️[Hannes Lowette](https://abp.io/conference/2024/speakers/hannes-lowette), Keynote: Manage your career, the Mario Kart way +* 🎙️[Engincan Veske](https://abp.io/conference/2024/speakers/engincan-veske), Sentiment Analysis in .NET +* 🎙️[Jessica Engström](https://abp.io/conference/2024/speakers/jessica-engstrom), Practical tips to improve your UX and accessibility +* 🎙️[Irina Scurtu](https://abp.io/conference/2024/speakers/irina-scurtu), .NET gRPC - deep dive +* 🎙️[Dino Esposito](https://abp.io/conference/2024/speakers/dino-esposito), In Defense of ASP.NET and Server-side Web +* 🎙️[Alexej Sommer](https://abp.io/conference/2024/speakers/alexej-sommer), Security for ASP.NET developers +* 🎙️[Adora Nwodo](https://abp.io/conference/2024/speakers/adora-nwodo), Designing Secure Cloud Native Apps with .NET and Azure +* 🎙️[Nicola Iarocci](https://abp.io/conference/2024/speakers/nicola-iarocci), C# 12 What's new and interesting +* 🎙️[Jimmy Engström](https://abp.io/conference/2024/speakers/jimmy-engstrom), Connecting gadgets to Blazor +* 🎙️[Juergen Gutsch](https://abp.io/conference/2024/speakers/juergen-gutsch), Building cloud native applications with .NET Aspire +* 🎙️[Halil Ibrahim Kalkan](https://abp.io/conference/2024/speakers/halil-ibrahim-kalkan), Designing Modular Monolith for Microservice Architecture +* 🎙️[Shaun Lawrence](https://abp.io/conference/2024/speakers/shaun-lawrance), Building games in .NET MAUI +* 🎙️[Jamie Taylor](https://abp.io/conference/2024/speakers/jamie-taylor), Empathy, Sympathy and Compassion +* 🎙️[Cecil Phillip](https://abp.io/conference/2024/speakers/cecil-phillip), Building Microservices with Dapr and .NET +* 🎙️[Rebai Hamida](https://abp.io/conference/2024/speakers/rebai-hamida), Embracing .NET 8.0: Leveraging New Features for Modern Application Development +* 🎙️[Sergei Gorlovetsky](https://abp.io/conference/2024/speakers/sergei-gorlovetsky), Optimizing ABP Deployments: Strategies and Best Practices with Helm and Kubernetes +* 🎙️[Todd Gardner,](https://abp.io/conference/2024/speakers/todd-gardner) Success On Your Own Terms +* 🎙️[Brian Gorman](https://abp.io/conference/2024/speakers/brian-gorman), Protecting Your Secrets using Azure Key Vault, Azure App Configuration, GitHub and C# MVC +* 🎙️[Mitchel Sellers](https://abp.io/conference/2024/speakers/mitchel-sellers), Architecting ASP.NET Core for Geo-Distributed Deployment + + + + +## What's New This Year? + +* **Enhanced Community Interaction:** An open attendee hub to join a chat with others at the event, or meet in video discussion groups. + +* **Instant Networking:** Meet other people one-on-one at the event in 5-minute video calls from the comfort of where you are during the whole live event, Wednesday 8 May - Thursday 9 May. + +* **Raffles & Giveaways & Gifts:** Stay connected with us, participate actively and stand a chance to win surprising prizes from us & our sponsors. + + + + + + + + +**[ABP Dotnet Conf'24](https://abp.io/conference/2024)** goes beyond just-a-conference. It’s a fun meet-up for the .NET community, fostering collaboration and growth. It's absolutely great for anyone passionate about .NET. Don't miss out on this landmark conference that celebrates a decade of ABP and the vibrant growth of the .NET community.  + + +**🚨 Registration Ends:** May 9, 2024 at 5:00 PM (UTC +0) + +**🗓 Event Dates:** May 8-9, 2024 + +**⏰ Event Times:** Sessions will run from 09:00 AM to 5:00 PM (UTC +0) + + +### > **[REGISTER NOW](https://web-eur.cvent.com/event/181460e1-5a3e-4dd6-9bbd-2b900050e01d/regProcessStep1?environment=production-eu)** +###
+### + + + + + +![1920_1080-1.png](3a11fced7109d5f4d3c23920ecb5eec2.png) + + +Special thanks to our sponsors [WAi Technologies](https://waiin.com/),[ Decision Tree](https://decisiontree.tech/), [DM Consulting](https://www.dmconsulting.it/en/), [HeadChannel](https://headchannel.co.uk/), [3S Studio](https://3sstudio.com/), [Kuem](https://www.kuem.si/en/), [Mailtrap](https://mailtrap.io/), and event partners [Microsoft](https://www.microsoft.com/), [.NET Foundation](https://dotnetfoundation.org/), [JetBrains](https://www.jetbrains.com/), [Packt Publishing](https://www.packtpub.com/), [dotnetdays](https://dotnetdays.ro/),[ International Conference Alerts](https://internationalconferencealerts.com/) who make this event possible and more impactful. + + + +See you there at #abpconf24 and celebrate a decade of ABP with the global .NET community! \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc1039888d362b74f377ad5d7a8.png b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc1039888d362b74f377ad5d7a8.png new file mode 100644 index 0000000000..75c21a9693 Binary files /dev/null and b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc1039888d362b74f377ad5d7a8.png differ diff --git a/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc13e410e85f86a8cada595c4ba.png b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc13e410e85f86a8cada595c4ba.png new file mode 100644 index 0000000000..ed1483f343 Binary files /dev/null and b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc13e410e85f86a8cada595c4ba.png differ diff --git a/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc16be482de862d5cdef1ff74a3.png b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc16be482de862d5cdef1ff74a3.png new file mode 100644 index 0000000000..4d299da6ee Binary files /dev/null and b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc16be482de862d5cdef1ff74a3.png differ diff --git a/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc196f7f658dad6eded9fb78ad0.png b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc196f7f658dad6eded9fb78ad0.png new file mode 100644 index 0000000000..2e4dadafc6 Binary files /dev/null and b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc196f7f658dad6eded9fb78ad0.png differ diff --git a/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc1b7ca559908f2d1b149d2a6c8.png b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc1b7ca559908f2d1b149d2a6c8.png new file mode 100644 index 0000000000..ba1f421339 Binary files /dev/null and b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc1b7ca559908f2d1b149d2a6c8.png differ diff --git a/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc1f4879a000ebb2a81da3cf8b8.png b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc1f4879a000ebb2a81da3cf8b8.png new file mode 100644 index 0000000000..2b5bc20678 Binary files /dev/null and b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/3a122bc1f4879a000ebb2a81da3cf8b8.png differ diff --git a/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/post.md b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/post.md new file mode 100644 index 0000000000..728fdf4f31 --- /dev/null +++ b/docs/en/Community-Articles/2024-04-26-unifying-the-abp-platform/post.md @@ -0,0 +1,108 @@ +I am very excited to announce that some big changes and improvements are coming to the ABP.IO Platform soon. In this post, I will explain the changes we are currently working on. Here, a brief list of these changes: + +* We are merging the subdomains of the ABP.IO Platform websites: Community.abp.io, commercial.abp.io, blog.abp.io, docs.abp.io websites and their contents are being merged into the main domain, abp.io. +* ABP (open source) and ABP Commercial documents are being merged into a single documentation. +* Introducing ABP Studio Community Edition. + +These changes won't effect the license conditions. The open source part will remain the same and the commercial license contents will also be the same. The aim of the changes is to make the platform more consistent, holistic, understandable and easy to start. + +Let's dive deep... + +## Merging the ABP.IO Websites + +ABP.IO website has many subdomains currently: + +* **abp.io**: Home page of the open source ABP Framework project. +* **community.abp.io**: A website that community can share contents and we organize events. +* **commercial.abp.io**: A website to promote and sell commercial ABP licenses which have pre-built modules, themes, tooling and support on top of the ABP Framework. +* **docs.abp.io**: The technical documentation of the ABP Framework and ABP Commercial. +* **blog.abp.io**: A blog website to announce the news on the platform. +* **support.abp.io**: Premium support for the ABP Commercial customers. + +All these subdomains (except the support website for now) are being merged to the abp.io domain. All their contents and UI designs are being revised and enriched. + +Some fundamental purposes of that change are; + +* Making content more coherent and holistic, +* Making the design more harmonious, +* Making the contents of the old subdomains more visible and reachable, +* Allow you to navigate through the web pages much easier, +* Reducing duplications between different websites, + +I will highlight a few important changes in the next sections. + +### The New Mega Menu + +As I said above, the abp.io UI design is also being revised. One of the big revisions is the main menu. We are replacing the current main navigation by a mega menu as shown in the following figure: + +![new-mega-menu.png](3a122bc1039888d362b74f377ad5d7a8.png) + +We believe that new mega menu will allow you to navigate through the web pages much easier. + +### The New Get Started Page + +We are constantly working to improve ABP's onboarding experience. With the new platform changes, we now offer ABP Studio as the starting point for the ABP Platform. You can still use the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) to created new ABP solutions, but the new ABP Studio makes it much easier and understandable. It also provides features to easily run and monitor your applications, even in the Community edition. + +![new-get-started.png](3a122bc13e410e85f86a8cada595c4ba.png) + +You can easily download and install ABP Studio, login with your abp.io account and create your first ABP solution. + +### The New Pricing Page + +Since the [ABP Commercial website](https://commercial.abp.io/) has merged with the main website, you will see the *Pricing* page located on the main menu of the abp.io website. We have completely revised the design and content of this page to better reflect which features are open source and free, and what is included in the paid licenses. + +![new-pricing.png](3a122bc16be482de862d5cdef1ff74a3.png) + +As mentioned above, all the free & open source features are still free & open source. In addition, we included the ABP Studio Community edition (will be explained below) to the free license. + +## Merging the ABP Platform Documentation + +Currently, ABP Framework (open source) and ABP Commercial [documents](https://docs.abp.io/) are completely separated. You can switch between them on the left side: + +![docs-project-selection.png](3a122bc196f7f658dad6eded9fb78ad0.png) + +Based on our and customers' experiences, there are some problems with that approach: + +* Getting started, development tutorials, release notes, road map and some other documents are duplicated (or very similar) among ABP Framework and ABP Commercial documents. +* For ABP Commercial users, it is not clear if they also need to read the ABP Framework (open source) documentation or not. Also, when they read the framework document, some parts are different for ABP Commercial users, and it is also not clear in some cases. + +We are currently working to completely merge the ABP Framework (open source) and ABP Commercial documentation, remove duplications and revisit the contents. We will clearly indicate if a part of a document requires a paid license. + +The left navigation panel tree is also completely revisited and simplified: + +![docs-new-navigation.png](3a122bc1b7ca559908f2d1b149d2a6c8.png) + +## The ABP Studio Community Edition + +[ABP Studio](https://docs.abp.io/en/commercial/latest/studio/index) is a cross-platform desktop application designed for ABP and .NET developers. It aims to provide a comfortable development environment by automating tasks, providing insights about your solution, and simplifying the processes of creation, development, execution, browsing, monitoring, tracing, and deploying your solutions. + +Here, a screenshot from the *Solution Runner* screen of ABP Studio: + +![abp-studio-solution-runner.png](3a122bc1f4879a000ebb2a81da3cf8b8.png) + +ABP Studio has been started as a commercial product, as a part of [ABP Commercial](https://commercial.abp.io/). We are very excited to announce that the *Community Edition* will be available soon for free. It will have some missing features and limitations compared to the full edition, but will be enough to create, explore and run ABP solutions easily. + +We will be offering ABP Studio as a starting point to the ABP platform. The [Getting Started](https://docs.abp.io/en/abp/latest/Getting-Started-Overall) and other documents will use ABP Studio to create new solutions and perform ABP-related operations. + +## Other News + +We are also working on some other topics related to these changes. Some of them are; + +* Completely renewing the [startup templates](https://docs.abp.io/en/abp/latest/Startup-Templates/Index) (with ABP Studio), so they will be more flexible and will provide more options. +* Providing a tool to automatically convert ABP solutions created with open source startup templates into ABP commercial. + +## Questions + +I tried to explain all the important changes in this post. However, you may have some questions in your mind. + +### What should open source users expect? + +Since the [ABP Commercial](https://commercial.abp.io/) website content is merged with the main [abp.io](https://abp.io/) website, you will see paid features being introduced on the main website. The pricing page will also be available on the same website. This may lead you to wonder whether the ABP Platform is a fully paid product. The simple answer to this question is "No". Actually, nothing has changed on the open source side. Everything will be the same. Additionally, open source users will now have ABP Studio Community Edition for free. So open source has more for its users than before. + +### What should ABP Commercial customers expect? + +ABP Commercial license holders may wonder if any license change happens. The answer is "No". All the license types, rules, restrictions and features are the same. With the changes explained in this post, you will follow the documentation easier (since you won't need to go to another website for the framework documentation) and you will better understand what special features are available to you. + +## Last Words + +With this post, we wanted to announce the changes to be made on the ABP platform to the ABP community, so don't be surprised or curious about what happened. If you have any questions or suggestions, feel free to write a comment for this blog post or send an email to info@abp.io. \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-05-06-join-us-at-abp-dotnet-conf-2024-in-just-3-days/post.md b/docs/en/Community-Articles/2024-05-06-join-us-at-abp-dotnet-conf-2024-in-just-3-days/post.md new file mode 100644 index 0000000000..5f8deaceda --- /dev/null +++ b/docs/en/Community-Articles/2024-05-06-join-us-at-abp-dotnet-conf-2024-in-just-3-days/post.md @@ -0,0 +1,11 @@ +We're only three days away from the **[ABP Dotnet Conference 2024](https://abp.io/conference/2024)**. As we prepare to celebrate a decade of innovation in .NET, we want to make sure that no one misses out on the opportunity to be part of this exciting event. + +### Special Offer for Students +We are pleased to provide free tickets for students who are passionate about learning and growing in their careers. Don’t miss this chance to connect with industry leaders and peers at no cost.  If you are a student passionate about dotnet technologies, do not miss your chance to register for a **Free Ticket** on **Day 2, May 9th**. Secure your spot now by filling out the **[👉Student Registration Form👈](https://docs.google.com/forms/u/1/d/e/1FAIpQLSeExnaZ5KKO4D-AtuxBVm3qon7kqyAT8fPuxzrOFuoaEQEVcA/viewform?usp=send_form)** + + +### What to Expect +As highlighted in our [Previous Welcome Blog](https://blog.abp.io/abp/Welcome-to-ABP-Dotnet-Conf%252724%253A-A-Decade-of-.NET-Innovation), **[ABP Dotnet Conf 2024](https://abp.io/conference/2024)** promises to be a remarkable 2-day virtual event with 29 expert speakers, hands-on workshops & talks sessions, and networking opportunities designed to inspire and engage. Whether you're a seasoned developer or a student just starting your career, this conference is the perfect place to deepen your knowledge and connect with other professionals. + + +We look forward to welcoming you to what promises to be an unforgettable event. Let's celebrate the innovations and progress of the .NET ecosystem together at #abpconf24! \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-05-16-abp-dotnet-conference-2024-wrap-up/Screenshot-2024-05-13-at-20-18-36.png b/docs/en/Community-Articles/2024-05-16-abp-dotnet-conference-2024-wrap-up/Screenshot-2024-05-13-at-20-18-36.png new file mode 100644 index 0000000000..6f0a1dee1b Binary files /dev/null and b/docs/en/Community-Articles/2024-05-16-abp-dotnet-conference-2024-wrap-up/Screenshot-2024-05-13-at-20-18-36.png differ diff --git a/docs/en/Community-Articles/2024-05-16-abp-dotnet-conference-2024-wrap-up/post.md b/docs/en/Community-Articles/2024-05-16-abp-dotnet-conference-2024-wrap-up/post.md new file mode 100644 index 0000000000..426b01639c --- /dev/null +++ b/docs/en/Community-Articles/2024-05-16-abp-dotnet-conference-2024-wrap-up/post.md @@ -0,0 +1,57 @@ +Hello and gratitude, ABP.IO Community! + +It was an absolute blast to upgrade ABP Dotnet Conference with a 1-day of workshops and an additional parallel session of talks! With ABP Dotnet Conference 2024, we marked a decade of innovation and community engagement. This year's event, besides being our second full-day(for both days!) ABP Community event, it has another special significance as we celebrated the 10th anniversary of ABP this year. The overwhelming interest and participation of live viewers and speakers from all around the world made this milestone truly memorable. + +From the nature of virtual conference, once again we were able to transcend geographical boundaries, uniting .NET developers from diverse cultures and 52 different countries. The map below showcases the countries of our live viewers, with darker shades indicating higher minutes viewed. Witnessing the global reach and impact of our conference fills us with immense pride and joy. We are grateful to each live viewer who dedicated their time and actively participated in the ABP Dotnet Conference 2024. Your presence and engagement played a crucial role in the success of the event. + +![Live Viewers Map](Screenshot-2024-05-13-at-20-18-36.png) + +The success of ABP Dotnet Conference 2024 would not have been possible without the contributions of our talented speakers. This year, we featured an impressive lineup of 29 speakers from all over the world, including .NET experts and Microsoft MVPs, who delivered captivating talks that resonated with our audience. Each session sparked curiosity and generated numerous questions, leading to enriching discussions. We extend our deepest appreciation to each speaker for their valuable insights and for sharing their knowledges with the attendees. Here’s a reminder of our speakers and their talk titles: + +📌 **Day 1 Workshops - May 8th, 2024** 📌 + +* 🎙️[Johan Smarius](https://abp.io/conference/2024/speakers/johan-smarius), Building a GraphQL Server in .NET 8 +* 🎙️[Wojciech Krasa](https://abp.io/conference/2024/speakers/wojciech-krasa), Testing framework with PostgreSQL and Testcontainers for .NET +* 🎙️[Ahmet Faruk Ulu](https://abp.io/conference/2024/speakers/ahmet-faruk-ulu), ABP Framework Essentials: Crafting Your SaaS Success Story  +* 🎙️[Alberto Acerbis](https://abp.io/conference/2024/speakers/alberto-acerbis) &  [Ferdinando Santacroce](https://abp.io/conference/2024/speakers/ferdinando-santacroce), Tackling Chaos, Resilience & Metrics in the heart of your Application +* 🎙️[Omkar Choudhari](https://abp.io/conference/2024/speakers/omkar-choudhari) & [Aman Sharma](https://abp.io/conference/2024/speakers/aman-sharma), Building your own copilot with ABP chat module +* 🎙️[Stefan Pölz](https://abp.io/conference/2024/speakers/stefan-polz), Let's Build an incremental source generator with Roslyn +* 🎙️[Ryan Niño Dizon](https://abp.io/conference/2024/speakers/ryan-nino-dizon), Building a Serverless Backend API with Azure Functions +* 🎙️[Kaushik Gokhale](https://abp.io/conference/2024/speakers/kaushik-gokhale) & [Omkar Choudhari](https://abp.io/conference/2024/speakers/omkar-choudhari), React ♥ ABP: Next-Level Frontend Workshop for 3x Acceleration +* 🎙️[Rebai Hamida](https://abp.io/conference/2024/speakers/rebai-hamida), Build containerized application using Docker and Azure + + + +📌 **Day 2 Talks - May 9th, 2024** 📌 + +* 🎙️[Hannes Lowette](https://abp.io/conference/2024/speakers/hannes-lowette), Keynote: Manage your career, the Mario Kart way +* 🎙️[Engincan Veske](https://abp.io/conference/2024/speakers/engincan-veske), Sentiment Analysis in .NET +* 🎙️[Jessica Engström](https://abp.io/conference/2024/speakers/jessica-engstrom), Practical tips to improve your UX and accessibility +* 🎙️[Irina Scurtu](https://abp.io/conference/2024/speakers/irina-scurtu), .NET gRPC - deep dive +* 🎙️[Dino Esposito](https://abp.io/conference/2024/speakers/dino-esposito), In Defense of ASP.NET and Server-side Web +* 🎙️[Alexej Sommer](https://abp.io/conference/2024/speakers/alexej-sommer), Security for ASP.NET developers +* 🎙️[Adora Nwodo](https://abp.io/conference/2024/speakers/adora-nwodo), Designing Secure Cloud Native Apps with .NET and Azure +* 🎙️[Nicola Iarocci](https://abp.io/conference/2024/speakers/nicola-iarocci), C# 12 What's new and interesting +* 🎙️[Jimmy Engström](https://abp.io/conference/2024/speakers/jimmy-engstrom), Connecting gadgets to Blazor +* 🎙️[Juergen Gutsch](https://abp.io/conference/2024/speakers/juergen-gutsch), Building cloud native applications with .NET Aspire +* 🎙️[Halil Ibrahim Kalkan](https://abp.io/conference/2024/speakers/halil-ibrahim-kalkan), Designing Modular Monolith for Microservice Architecture +* 🎙️[Shaun Lawrence](https://abp.io/conference/2024/speakers/shaun-lawrance), Building games in .NET MAUI +* 🎙️[Jamie Taylor](https://abp.io/conference/2024/speakers/jamie-taylor), Empathy, Sympathy and Compassion +* 🎙️[Cecil Phillip](https://abp.io/conference/2024/speakers/cecil-phillip), Building Microservices with Dapr and .NET +* 🎙️[Rebai Hamida](https://abp.io/conference/2024/speakers/rebai-hamida), Embracing .NET 8.0: Leveraging New Features for Modern Application Development +* 🎙️[Sergei Gorlovetsky](https://abp.io/conference/2024/speakers/sergei-gorlovetsky), Optimizing ABP Deployments: Strategies and Best Practices with Helm and Kubernetes +* 🎙️[Todd Gardner,](https://abp.io/conference/2024/speakers/todd-gardner) Success On Your Own Terms +* 🎙️[Brian Gorman](https://abp.io/conference/2024/speakers/brian-gorman), Protecting Your Secrets using Azure Key Vault, Azure App Configuration, GitHub and C# MVC +* 🎙️[Mitchel Sellers](https://abp.io/conference/2024/speakers/mitchel-sellers), Architecting ASP.NET Core for Geo-Distributed Deployment + + We are humbled by all ABP Community Members', conference attendees', speakers' and sponsors' support and inspired by the connections forged through shared knowledge. + +The ABP Dotnet Conference 2024 platform's interactive strucutre provided an ideal environment for attendees to engage with the speakers as well as with themselves. The depth of the talks and workshops presented and the multitude of questions asked during the Q&A sessions highlighted the intellectual curiosity of our audience. Each question laid the foundation for engaging discussions, enriching the experience for everyone involved. The exchange of ideas and diverse perspectives showcased the beauty of inclusiveness at the ABP Dotnet Conference 2024. + +Of course, our valuable sponsors deserves a huge special thanks to encourage us to make ABP Dotnet Conference 2024 happen again! Thanks to our sponsors [WAi Technologies](https://waiin.com/), [Decision Tree](https://decisiontree.tech/), [DM Consulting](https://www.dmconsulting.it/en/), [HeadChannel](https://headchannel.co.uk/blog/community-abp.10-posts-submit/), [3S Studio](https://3sstudio.com/), [Kuem](https://www.kuem.si/en/), [Mailtrap](https://mailtrap.io/), and event partners [Microsoft](https://www.microsoft.com/), [.NET Foundation](https://dotnetfoundation.org/), [JetBrains](https://www.jetbrains.com/), [Packt Publishing](https://www.packtpub.com/), [dotnetdays](https://dotnetdays.ro/),[ International Conference Alerts](https://internationalconferencealerts.com/) who make this event possible and more impactful. + +Thank you all for making the ABP Dotnet Conference 2024 great again! We look forward to many more years of innovation and community collaboration. Here’s to another decade of growth and learning together! + +Hope to see you all and more on the next one! + +[Visit ABP Dotnet Conference 2024's website for more information](https://abp.io/conference/2024) \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc3a52aac05d08a0fe3ca28bd69.gif b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc3a52aac05d08a0fe3ca28bd69.gif new file mode 100644 index 0000000000..ecd9819d53 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc3a52aac05d08a0fe3ca28bd69.gif differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc3e2227b31914fbc8227a39369.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc3e2227b31914fbc8227a39369.png new file mode 100644 index 0000000000..2b2aa17308 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc3e2227b31914fbc8227a39369.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc4025ef90a3c26cbecd1b2483c.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc4025ef90a3c26cbecd1b2483c.png new file mode 100644 index 0000000000..82856c45b2 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc4025ef90a3c26cbecd1b2483c.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc413b69c663fb44dd26d593dea.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc413b69c663fb44dd26d593dea.png new file mode 100644 index 0000000000..d2dcfddc5c Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc413b69c663fb44dd26d593dea.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc43db80882c4d63aa228c8784f.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc43db80882c4d63aa228c8784f.png new file mode 100644 index 0000000000..a6b64ee986 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc43db80882c4d63aa228c8784f.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc44f7b46307c446e2072c0e64c.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc44f7b46307c446e2072c0e64c.png new file mode 100644 index 0000000000..2b6d2fdf95 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc44f7b46307c446e2072c0e64c.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc802ce68a2f11bbb3655581faa.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc802ce68a2f11bbb3655581faa.png new file mode 100644 index 0000000000..5a6f8d1186 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc802ce68a2f11bbb3655581faa.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc81a41e7f2141587ed6bea6838.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc81a41e7f2141587ed6bea6838.png new file mode 100644 index 0000000000..5871984876 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc81a41e7f2141587ed6bea6838.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc83546d342d1228c9009b0d42a.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc83546d342d1228c9009b0d42a.png new file mode 100644 index 0000000000..5a6373be10 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc83546d342d1228c9009b0d42a.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc849a78f7cea57557bb834e3a4.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc849a78f7cea57557bb834e3a4.png new file mode 100644 index 0000000000..ed774fd4fd Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc849a78f7cea57557bb834e3a4.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8642a002d1a4e879130667553.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8642a002d1a4e879130667553.png new file mode 100644 index 0000000000..4c20ced391 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8642a002d1a4e879130667553.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8817dc1f3e8c351ca458a6d23.jpg b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8817dc1f3e8c351ca458a6d23.jpg new file mode 100644 index 0000000000..48a71dc881 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8817dc1f3e8c351ca458a6d23.jpg differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc898d5155cc068b1fa85da469a.jpg b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc898d5155cc068b1fa85da469a.jpg new file mode 100644 index 0000000000..639d49176a Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc898d5155cc068b1fa85da469a.jpg differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8b7c12bc3ce1b904e74792a6f.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8b7c12bc3ce1b904e74792a6f.png new file mode 100644 index 0000000000..f37435dc0e Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8b7c12bc3ce1b904e74792a6f.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8cda3abdfcb3556b6390258a7.png b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8cda3abdfcb3556b6390258a7.png new file mode 100644 index 0000000000..a14a47a5a0 Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/3a12bcc8cda3abdfcb3556b6390258a7.png differ diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/post.md b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/post.md new file mode 100644 index 0000000000..6574012f24 --- /dev/null +++ b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/post.md @@ -0,0 +1,268 @@ +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **8.2 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 v8.2! Thanks to all of you. + +## Get Started with the 8.2 RC + +Follow the steps below to try version 8.2.0 RC today: + +1) **Upgrade** the ABP CLI to version `8.2.0-rc.3` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 8.2.0-rc.3 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 8.2.0-rc.3 +```` + +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 8.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 v8.x or earlier: + +* [ABP Framework 8.x to 8.2 Migration Guide](https://docs.abp.io/en/abp/8.2/Migration-Guides/Abp-8_2) +* [ABP Commercial 8.x to 8.2 Migration Guide](https://docs.abp.io/en/commercial/8.2/migration-guides/v8_2) + +## What's New with ABP Framework 8.2? + +In this section, I will introduce some major features released in this version. +Here is a brief list of titles explained in the next sections: + +* Blazor Full-Stack Web App UI +* Introducing the `IBlockUiService` for Blazor UI +* Allowing Case-Insensitive Indexes for MongoDB +* Other News... + +### Blazor Full-Stack Web App UI + +ASP.NET Blazor in .NET 8 allows you to use a single powerful component model to handle all of your web UI needs, including server-side rendering, client-side rendering, streaming rendering, progressive enhancement, and much more! + +ABP v8.2.x supports the new Blazor Web App template, which you can directly create with the following command: + +```bash +abp new BookStore -t app -u blazor-webapp +``` + +When you create the project, you will typically see two main projects for Blazor UI, besides other projects: + +* **MyCompanyName.MyProjectName.Blazor.WebApp** (startup project of your application, and contains `App.razor` component, which is the root component of your application) +* **MyCompanyName.MyProjectName.Blazor.WebApp.Client** + +This new template overcomes the disadvantages of both Blazor WASM and Blazor Server applications and allows you to decide which approaches to use for a specific page or component. Therefore, you can imagine this new web UI as a combination of both Blazor Server and Blazor WASM. + +> This approach mainly overcomes the **large binary downloads of Blazor WASM**, and it resolves the Blazor Server's problem, which **always needs to be connected to the server via SignalR**. + +> If you are considering migrating your existing Blazor project to Blazor WebApp or want to learn more about this new template, please read the [Migrating to Blazor Web App](https://docs.abp.io/en/abp/8.2/Migration-Guides/Abp-8-2-Blazor-Web-App) guide. + +### Introducing the `IBlockUiService` for Blazor UI + +In this version, ABP Framework introduces the [`IBlockUiService`](https://docs.abp.io/en/abp/8.2/UI/Blazor/Block-Busy) for Blazor UI. This service uses UI Block API to disable/block the page or a part of the page. + +You just need to simply inject the `IBlockUiService` to your page or component and call the `Block` or `UnBlock` method to block/unblock the specified element: + +```csharp +namespace MyProject.Blazor.Pages +{ + public partial class Index + { + private readonly IBlockUiService _blockUiService; + + public Index(IBlockUiService _blockUiService) + { + _blockUiService = blockUiService; + } + + public async Task BlockForm() + { + /* + Parameters of Block method: + selectors: A string containing one or more selectors to match. https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector#selectors + busy : Set to true to show a progress indicator on the blocked area. + */ + await _blockUiService.Block(selectors: "#MySelectors", busy: true); + + //Unblocking the element + await _blockUiService.UnBlock(selectors: "#MySelectors"); + } + } +} + +``` + +Here is the resulting UI with all possible options (**block**, **block busy**, and **unblock**): + +![block-ui-service-blazor.gif](3a12bcc3a52aac05d08a0fe3ca28bd69.gif) + +### Allowing Case-Insensitive Indexes for MongoDB + +MongoDB allows case-insensitive string comparisons by using case-insensitive indexes. You can create a case-insensitive index by specifying a **collation**. + +To do that, you should override the `CreateModal` method, configure the `CreateCollectionOptions`, and specify the **collation** as below: + +```csharp +protected override void CreateModel(IMongoModelBuilder modelBuilder) +{ + base.CreateModel(modelBuilder); + + modelBuilder.Entity(b => + { + b.CreateCollectionOptions.Collation = new Collation(locale:"en_US", strength: CollationStrength.Secondary); + + b.ConfigureIndexes(indexes => + { + indexes.CreateOne( + new CreateIndexModel( + Builders.IndexKeys.Ascending("MyProperty"), + new CreateIndexOptions { Unique = true } + ) + ); + } + ); + }); +} +``` + +After this configuration, a unique index will be created for the `MyProperty` property and then you can perform case-insensitive string comparisons without the need to worry. See [#19073](https://github.com/abpframework/abp/pull/19073) for more information. + +### Other News + +* Angular package version has been updated to v17.3.0. See [#19915](https://github.com/abpframework/abp/pull/19915) for more info. +* OpenIddict [5.4.0 has been released on March 26](https://github.com/openiddict/openiddict-core/releases/tag/5.4.0). Therefore, we decided to upgrade the OpenIddict packages to v5.4.0. See [#19427](https://github.com/abpframework/abp/issues/19427). +* AutoMapper [13.0.1 was released on February 8](https://github.com/AutoMapper/AutoMapper/releases/tag/v13.0.1) and in this version, we upgraded AutoMapper packages to v13.0.1. See [#19564](https://github.com/abpframework/abp/pull/19564/). +* See other completed tasks in this version: [https://github.com/abpframework/abp/releases?q=8.2.0-rc](https://github.com/abpframework/abp/releases?q=8.2.0-rc&expanded=true) + +## What's New with ABP Commercial 8.2? + +We've also worked on ABP Commercial to align the features and changes made in the ABP Framework. The following sections introduce a few new features coming with ABP Commercial 8.2. + +### Session Management + +The [Session Management](https://docs.abp.io/en/commercial/8.2/modules/identity/session-management) feature allows you to prevent concurrent login and manage user sessions. You can allow concurrent login, allow only one session of the same device type, or logout from all other devices when a new session is created, by specifying in the settings page: + +![concurrent-login-settings.png](3a12bcc3e2227b31914fbc8227a39369.png) + +Also, you can view and manage users sessions on the `Users` page of the [Identity Module](https://docs.abp.io/en/commercial/8.2/modules/identity): + +![manage-user-sessions-1.png](3a12bcc4025ef90a3c26cbecd1b2483c.png) + +![manage-user-sessions-2.png](3a12bcc413b69c663fb44dd26d593dea.png) + +### Suite: File/Image Property + +In this version, ABP Suite allows you to add a file/image property for an entity. You can select "File" as the property type for your properties as in the following figure: + +![suite-file-property.png](3a12bcc43db80882c4d63aa228c8784f.png) + +Then, when you generate your entity and try to insert a record, you will see the file upload component on the create/update models: + +![suite-file-property-create.png](3a12bcc44f7b46307c446e2072c0e64c.png) + +You can upload a file with any supported extensions and under 10MB (this can be increased in the generated code, if you wish) and after that, you can download, delete and update the existing file any time you want: + +![](suite-file-upload-in-action.gif) + +> **Note:** This feature has already been implemented for MVC & Blazor UIs, but not implemented for Angular UI yet. We aim to implement it for Angular UI with v8.2.0. + +### Suite: DateOnly & TimeOnly Types + +In this version on, ABP Suite provides `DateOnly` and `TimeOnly` types as property types. You can select these types when you create an entity: + +![suite-dateonly-timeonly-properties.png](3a12bcc802ce68a2f11bbb3655581faa.png) + +Then, all related configurations (including db configurations) will be made by ABP Suite, and you will be able to see the fields in the UI: + +![suite-dateonly-timeonly-ui.png](3a12bcc81a41e7f2141587ed6bea6838.png) + +> **Note**: The `DateOnly` and `TimeOnly` types were introduced with .NET 6. Therefore, please make sure that all of your projects' target frameworks are .NET8+. With ABP v8.2, all startup templates target a single target framework, which is .NET8, so if you created your project with version 8.2+, you don't need to make any changes. + +### Periodic Log Deletion for Audit Logs + +In this version, the [Audit Logging Module](https://docs.abp.io/en/commercial/8.2/modules/audit-logging) provides a built-in periodic log deletion system. You can enable/disable the clean-up service system wide, in this way, you can turn off the clean up service for all tenants and their hosts: + +![audit-logging-module-global-settings.png](3a12bcc83546d342d1228c9009b0d42a.png) + +> If the system wide clean up service is enabled, you can configure the global *Expired Item Deletion Period* for all tenants and hosts. + +When configuring the global settings for the audit log module from the host side in this manner, ensure that each tenant and host uses the global values. If you want to set tenant/host-specific values, you can do so under *Settings* -> *Audit Log* -> *General*. This way, you can disable the clean up service for specific tenants or host. It overrides the global settings: + +![audit-logging-module-general-settings.png](3a12bcc849a78f7cea57557bb834e3a4.png) + +> **Note**: To view the audit log settings, you need to enable the feature. For the host side, navigate to *Settings* -> *Feature Management* -> *Manage Host Features* -> *Audit Logging* -> *Enable audit log setting management*. + +## Community News + +### ABP Dotnet Conf 2024 Wrap Up + +![abp-dotnet-conf-2024.png](3a12bcc8642a002d1a4e879130667553.png) + +We organized [ABP Dotnet Conference 2024](https://abp.io/conference/2024) on May 2024 and we are happy to share the success of the conference, which captivated overwhelmingly interested live viewers from all over the world. 29 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-Dotnet-Conference-2024-Wrap-Up](https://blog.abp.io/abp/ABP-Dotnet-Conference-2024-Wrap-Up). + +### DevDays Europe 2024 + +![devdays-europe.jpg](3a12bcc8817dc1f3e8c351ca458a6d23.jpg) + +Co-founder of [Volosoft](https://volosoft.com/), [Alper Ebiçoğlu](https://twitter.com/alperebicoglu) gave a speech about "How to Build a Multi-Tenant ASP.NET Core Application" at the [DevDays Europe 2024](https://devdays.lt/) on the 20th of May. + +### DevOps Pro Europe 2024 + +![devops-pro-europe.jpg](3a12bcc898d5155cc068b1fa85da469a.jpg) + +We are thrilled to announce that the co-founder of [Volosoft](https://volosoft.com/) and Lead Developer of the [ABP Framework](https://abp.io/), [Halil Ibrahim Kalkan](https://x.com/hibrahimkalkan) gave a speech about "Building a Kubernetes Integrated Local Development Environment" in the [DevOps Pro Europe](https://devopspro.lt/) on the 24th of May. + +### Devnot Dotnet Conference 2024 + +We are happy to announce that core team members of the [ABP Framework](https://abp.io/), [Alper Ebiçoğlu](https://twitter.com/alperebicoglu) and [Enis Necipoğlu](https://twitter.com/EnisNecipoglu) will give speeches at the [Devnot Dotnet Conference 2024](https://dotnet.devnot.com/) on 25th of May. + +[Alper Ebiçoğlu](https://twitter.com/alperebicoglu) will talk about **"AspNet Core & Multitenancy"**: + +![devnot-dotnet-conference-alper-ebicoglu.png](3a12bcc8b7c12bc3ce1b904e74792a6f.png) + +On the other hand, [Enis Necipoğlu](https://twitter.com/EnisNecipoglu) will talk about **"Reactive Programming with .NET MAUI"**: + +![devnot-dotnet-conference-enis-necipoglu.png](3a12bcc8cda3abdfcb3556b6390258a7.png) + +### New ABP Community Articles + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Ahmed Tarek](https://twitter.com/AhmedTarekHasa1) has created **four** new community articles: + * [🤔 When Implementations Affect Abstractions ⁉️](https://community.abp.io/posts/-when-implementations-affect-abstractions--ekx1o5xn) + * [👍 Design Best Practices In .NET C# 👀](https://community.abp.io/posts/design-best-practices-in-.net-c--eg8q8xh0) + * [👍 Chain of Responsibility Design Pattern In .NET C# 👀](https://community.abp.io/posts/chain-of-responsibility-design-pattern-in-.net-c--djmvkug1) + * [Flagged Enumerations: How To Represent Features Combinations Into One Field](https://community.abp.io/posts/flagged-enumerations-how-to-represent-features-combinations-into-one-field-9gj4l670) +* [Engincan Veske](https://github.com/EngincanV) has created **three** new community articles: + * [Performing Case-Insensitive Search in ABP Based-PostgreSQL Application: Using citext and Collation](https://community.abp.io/posts/caseinsensitive-search-in-abp-basedpostgresql-application-c9kb05dc) + * [Sentiment Analysis Within ABP-Based Application](https://community.abp.io/posts/sentiment-analysis-within-abpbased-application-lbsfkoxq) + * [Reusing and Optimizing Machine Learning Models in .NET](https://community.abp.io/posts/reusing-and-optimizing-machine-learning-models-in-.net-qj4ycnwu) +* [Unlocking Modularity in ABP.io A Closer Look at the Contributor Pattern](https://community.abp.io/posts/unlocking-modularity-in-abp.io-a-closer-look-at-the-contributor-pattern-ixf6wgbw) by [Qais Al khateeb](https://community.abp.io/members/qais.alkhateeb@devnas-jo.com) +* [Deploy Your ABP Framework MVC Project to Azure Container Apps](https://community.abp.io/posts/deploy-your-abp-framework-mvc-project-to-azure-container-apps-r93u9c6d) by [Selman Koç](https://community.abp.io/members/selmankoc) +* [How claim type works in ASP NET Core and ABP Framework](https://community.abp.io/posts/how-claim-type-works-in-asp-net-core-and-abp-framework-km5dw6g1) by [Liming Ma](https://github.com/maliming) +* [Using FluentValidation with ABP Framework](https://community.abp.io/posts/using-fluentvalidation-with-abp-framework-2cxuwl70) by [Enes Döner](https://community.abp.io/members/Enes) +* [Using Blob Storage with ABP](https://community.abp.io/posts/using-blob-storage-with-abp-framework-jygtmhn4) by [Emre Kendirli](https://community.abp.io/members/emrekenderli) + +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/posts/submit) to the ABP Community. + +## 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/8.2/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v8.2 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/suite-file-upload-in-action.gif b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/suite-file-upload-in-action.gif new file mode 100644 index 0000000000..0b51b1472e Binary files /dev/null and b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/suite-file-upload-in-action.gif differ diff --git a/docs/en/Community-Articles/2024-06-27-abpio-platform-82-final-has-been-released/post.md b/docs/en/Community-Articles/2024-06-27-abpio-platform-82-final-has-been-released/post.md new file mode 100644 index 0000000000..06bacd109a --- /dev/null +++ b/docs/en/Community-Articles/2024-06-27-abpio-platform-82-final-has-been-released/post.md @@ -0,0 +1,65 @@ +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 8.2 versions have been released today. + +## What's New With Version 8.2? + +All the new features were explained in detail in the [8.2 RC Announcement Post](https://blog.abp.io/abp/announcing-abp-8-2-release-candidate), so there is no need to review them again. You can check it out for more details. + +## Getting Started with 8.2 + +### Creating New Solutions + +You can create a new solution with the ABP Framework version 8.2 by either using the `abp new` command or generating the CLI command on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to Upgrade an Existing Solution + +#### Install/Update the ABP CLI + +First, install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update the existing CLI: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading Existing Solutions with the ABP Update Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## 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 v8.x or earlier: + +* [ABP Framework 8.x to 8.2 Migration Guide](https://docs.abp.io/en/abp/8.2/Migration-Guides/Abp-8_2) +* [ABP Commercial 8.x to 8.2 Migration Guide](https://docs.abp.io/en/commercial/8.2/migration-guides/v8_2) + +## Community News + +### New ABP Community Posts + +As always, exciting articles have been contributed by the ABP community. I will highlight some of them here: + +* [How to use Angular Material with Form Validation on ABP](https://community.abp.io/posts/how-to-use-angular-material-with-form-validation-on-abp-jtheajj3) by [Mahmut Gündoğdu](https://x.com/mahmutgundogdu) +* [Tunnel your local host address to a public URL with ngrok](https://community.abp.io/posts/tunnel-your-local-host-address-to-a-public-url-with-ngrok-4cywnocj) by [Bart Van Hoey](https://github.com/bartvanhoey) +* [Antiforgery Token Validation When Angular and HTTP API Runs on the Same Server](https://community.abp.io/posts/antiforgery-token-validation-when-angular-and-http-api-runs-on-the-same-server-mzf5ppdq) by [dignite](https://x.com/dignite_adu) + +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. + +## About the Next Version + +The next feature version will be 8.3. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-07-24-the-new-abp-platform-is-live/post.md b/docs/en/Community-Articles/2024-07-24-the-new-abp-platform-is-live/post.md new file mode 100644 index 0000000000..83e7ab5b74 --- /dev/null +++ b/docs/en/Community-Articles/2024-07-24-the-new-abp-platform-is-live/post.md @@ -0,0 +1,80 @@ +We're thrilled to announce that the **new ABP.IO Platform is now live!** Our team has been hard at unifying and enhancing the entire platform to deliver a seamless, user-friendly experience. Here's what's new: + + +### Unified domain and enhanced navigation 🌍 + +All our services are now consolidated under a single domain; [abp.io](https://abp.io). This means you no longer need to navigate through multiple subdomains. The new mega menu makes finding what you need easier and faster. + + +### Modern design and improved UX 🎨 + +The platform boasts a fresh, modern design aimed at improving both aesthetics and functionality. This redesign enhances usability, making your interaction with ABP.IO more intuitive. + + + +### Documentation in one place 📃 + +We’ve combined the ABP (open-source) and ABP Commercial (paid) documents into a single, comprehensive resource. This unified documentation will help you find what you're looking for more efficiently. The new documentation address is [abp.io/docs](https://abp.io/docs). When you switch to old ABP versions before v8.3, you will see the old documents are still available. + + + +### Introducing "ABP Studio Community Edition" 🪄 + +We're excited to introduce the **ABP Studio Community Edition**, which is now **available for free**. This edition provides powerful tools to streamline your development process. You can easily create a new project with a configuration wizard in ABP Studio. It also provides module management, which means you can add/remove an ABP Module easily. You can also debug your microservice project and track the HTTP requests easily. Connecting your local development environment to a local or remote Kubernetes cluster is another cool feature of ABP Studio. We aim for ABP Studio to be the primary tool for ABP developers to manage their projects. + +> Download ABP Studio 👉 [abp.io/studio](https://abp.io/studio). + + +### Enhanced "ABP CLI" 🚀 + +ABP CLI is also renewed. The new CLI is compatible with ABP Studio. It adds new commands. The new CLI is now available on NuGet at [nuget.org/packages/Volo.Abp.Studio.Cli](https://www.nuget.org/packages/Volo.Abp.Studio.Cli). It's a dotnet global tool. When you install ABP Studio, the new ABP CLI is automatically installed. You can still use the old ABP CLI commands. To use the legacy ABP CLI commands just add `--old` parameter to your commands. + +> The docs of the new ABP CLI 👉 [abp.io/docs/latest/cli](https://abp.io/docs/latest/cli). + + + +### 20% Celebration discount 💰 + +To celebrate the launch of the new platform, we're offering a **20% discount** for a limited time. This discount is valid for all new purchases, renewing existing licenses and buying additional developer seats. + +> Discounted prices 👉 [abp.io/pricing](https://abp.io/pricing). + + +### Existing customers 🛂 + +In terms of licensing rules, existing customers will not be affected by this change. You can manage your license just like before at [abp.io/my-organizations](https://abp.io/my-organizations). + +> The new support website address 👉 [abp.io/support](https://abp.io/support). + + +--- + + +### Community Talk on the new ABP Platform + +We made a community talk on YouTube on August 1st, 2024, and we explained these topics. You can watch it from the below link: + + + + + +--- + +### Why choose the ABP Platform? 🙄 + +ABP Platform simplifies modern software development with well-architected startup templates, modular design infrastructure, multi-tenancy support, comprehensive security features, and a vibrant community. If you are starting a new web project or transforming your legacy application, ABP is the perfect solution! If you still wonder why you need such a solution, see [abp.io/why-choose-abp](https://abp.io/why-choose-abp). + +There are several startup ASP.NET Core templates for your requirements. Read [abp.io/how-it-works](https://abp.io/how-it-works) page to understand ABP's approach. We have a FAQ page where you can find answers to many of your questions [abp.io/faq](https://abp.io/faq). + +> Start your new ABP project -for free- 👉[abp.io/get-started](https://abp.io/get-started)! + + +### Join our community 👨‍👨‍👦 + +We invite developers, IT professionals, and businesses to join the ABP Community. Our community website is now [abp.io/community](https://abp.io/community). On this website, you can read ABP-related posts, watch live community shows and core team's fundamental video courses... + +------ + +For more information, visit our newly unified platform at [abp.io](https://abp.io). We look forward to your feedback and continued support as we grow together! + +> Found a bug in the new platform? Or if you have an idea, write to us 👉 [abp.io/contact](https://abp.io/contact). \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-07-26-introducing-the-new-abp-cli/post.md b/docs/en/Community-Articles/2024-07-26-introducing-the-new-abp-cli/post.md new file mode 100644 index 0000000000..d9c49c1960 --- /dev/null +++ b/docs/en/Community-Articles/2024-07-26-introducing-the-new-abp-cli/post.md @@ -0,0 +1,77 @@ +📢 We're excited to introduce the [new ABP CLI](https://abp.io/docs/latest/cli/index) after the announcement of [the new unified ABP Platform](https://abp.io/blog/new-abp-platform-is-live). + +As you know, we recently unified the ABP platform in a single domain ([abp.io](https://abp.io/)) and made some changes in our templating system to simplify your development. Also, we released more stable ABP Studio versions, which can dramatically improve and speed up your development time. Besides all of these changes, we have also introduced a new ABP CLI to bring you a more streamlined and efficient experience, which also extends the current commands. + +Here is a brief overview of what's new, what's changed, and why this change is happening... + +## The New ABP CLI + +ABP CLI is a command line tool to perform some common operations for ABP based solutions or [ABP Studio](https://abp.io/docs/latest/studio) features. With v8.2+, the old/legacy ABP CLI has been replaced with a new CLI system to align with the new templating system and ABP Studio. + +The new ABP CLI extends the old ABP CLI, adds more features that are used by ABP Studio behind the scenes, and is also fully compatible with the new templating system. Also, it allows you to use the old ABP CLI if you need, it by passing a single parameter. + +To be able to use the new ABP CLI, you should first delete the existing/old CLI with the following command if you installed it before: + +```bash +dotnet tool uninstall -g Volo.Abp.Cli +``` + +Then, to install the new ABP CLI, you can just simply execute the following command in your terminal: + +```bash +dotnet tool install -g Volo.Abp.Studio.Cli +``` + +> Both old and new ABP CLI binary names use the same `abp` command as the executing command. Therefore, you should uninstall the old CLI first, if you installed it before. + +> **Note**: Since the new ABP CLI uses the same `abp` command, you can use the same commands as you did before. + +## Reason for the Change + +ABP introduces a new templating system, which is fully compatible with the ABP Studio from v8.2+. Since, ABP Studio offers more and better features (such as tracking, monitoring, and deploying your applications from a single point), and the new templating system has a different versioning structure, we wanted to introduce a new ABP CLI by extending the current features and adding even more features that are compatible with the new templating system and ABP Studio. + +This change allows you to create your application with the new templating system either by running the cross-platform ABP Studio application or ABP CLI and allows you to create automated pipelines with the power of the new ABP CLI. + +## Using the Old ABP CLI + +If you have an older version of ABP solutions and need to use the old ABP CLI for any reason, you can do it easily with the new ABP CLI. + +You just need to put the `--old` command at the end of your command and execute the related CLI command as you would before. This allows you to use the old CLI commands with the new CLI without the need to uninstall the new CLI. + +For example, if you want to create a new ABP v8.2.0 solution, you can execute the following command: + +```bash +abp new Acme.BookStore --version 8.2.0 --old +``` + +When you run this command, the new ABP CLI installs the old CLI with `abp-old` name as the executing command within the latest version of ABP under the **%UserProfile%\\.abp\studio\cli\old** directory and allows you to use the old commands. + +If you want to use a specific version of the old ABP CLI, it's also possible with the new ABP CLI. You can use the `install-old-cli` command of the new CLI to either install or update an old CLI, then you can directly execute any old ABP CLI command by simply passing the `--old` parameter to the end of your command: + +```bash +# installing the old ABP CLI with v8.0 +abp install-old-cli --version 8.0.0 + +abp new Acme.BookStore --version 8.0 --old # alternatively, you can use the `abp-old` command without need to pass the "--old" parameter +``` + +## New Commands + +New ABP CLI extends the existing features of old ABP CLI and introduces new commands. Here are some of the new commands: + +* `kube-connect`: Connects to Kubernetes environment. (Available for **Business or higher licenses**) +* `kube-intercept`: Intercepts a service running in Kubernetes environment. (Available for **Business or higher licenses**) +* `list-module-sources`: Lists the remote module sources. +* and more... + +You can check the CLI documentation for all available commands and their usage. + +## Conclusion + +In this blog post, we briefly explained the new ABP CLI, what's the reason for this change, and how to use the old ABP CLI with the new ABP CLI. + +If you have any further questions related to the new ABP CLI, you can always refer to the [CLI](https://abp.io/docs/latest/cli/index) and [Old ABP CLI vs New ABP CLI](https://abp.io/docs/latest/cli/differences-between-old-and-new-cli) documentation. Also, we listed some of the questions that you may have, which you can [check from here](https://abp.io/docs/latest/cli/differences-between-old-and-new-cli#common-questions). + +Please try out the new ABP CLI, and provide feedback to help us release more stable versions, with additional features. + +Thanks for being a part of the ABP Community! \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e81208c50f7a7c2c5f2463ee95.png b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e81208c50f7a7c2c5f2463ee95.png new file mode 100644 index 0000000000..35e53cd3dc Binary files /dev/null and b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e81208c50f7a7c2c5f2463ee95.png differ diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e82f626e06b4022b7fe077d68b.png b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e82f626e06b4022b7fe077d68b.png new file mode 100644 index 0000000000..051451d512 Binary files /dev/null and b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e82f626e06b4022b7fe077d68b.png differ diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8580fc750ee048c9a14f7c064.png b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8580fc750ee048c9a14f7c064.png new file mode 100644 index 0000000000..2d97e6067c Binary files /dev/null and b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8580fc750ee048c9a14f7c064.png differ diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e87779052078513905ac904886.png b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e87779052078513905ac904886.png new file mode 100644 index 0000000000..02a2ba1076 Binary files /dev/null and b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e87779052078513905ac904886.png differ diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8936010694a2402ab1e771296.png b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8936010694a2402ab1e771296.png new file mode 100644 index 0000000000..87dbb07a41 Binary files /dev/null and b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8936010694a2402ab1e771296.png differ diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8bcfc8e9ce9dfdcb779fe7d74.png b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8bcfc8e9ce9dfdcb779fe7d74.png new file mode 100644 index 0000000000..edc9118d9c Binary files /dev/null and b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8bcfc8e9ce9dfdcb779fe7d74.png differ diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8eee5a21b45744cedf6e688f3.png b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8eee5a21b45744cedf6e688f3.png new file mode 100644 index 0000000000..e09cfb2ddd Binary files /dev/null and b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e8eee5a21b45744cedf6e688f3.png differ diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e908e6740ea8f1a74a72a8a7e6.png b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e908e6740ea8f1a74a72a8a7e6.png new file mode 100644 index 0000000000..572cf40956 Binary files /dev/null and b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e908e6740ea8f1a74a72a8a7e6.png differ diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e927e9ce87f76be80eb2946060.png b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e927e9ce87f76be80eb2946060.png new file mode 100644 index 0000000000..2f3342d573 Binary files /dev/null and b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e927e9ce87f76be80eb2946060.png differ diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e947cec9e65339c4faf917a656.png b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e947cec9e65339c4faf917a656.png new file mode 100644 index 0000000000..f0ca19268e Binary files /dev/null and b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/3a1414e947cec9e65339c4faf917a656.png differ diff --git a/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/post.md b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/post.md new file mode 100644 index 0000000000..d2bd8c2481 --- /dev/null +++ b/docs/en/Community-Articles/2024-07-30-announcing-abp-studio-beta-general-availability/post.md @@ -0,0 +1,109 @@ +ABP Framework makes your daily coding activities much easier, more convenient, and even more enjoyable. However, building a software product is not just about coding. We know that you need to build, run, test, debug and deploy your software, and trace errors on a failure. You also should to design architecture of your overall solution and perform many common operations on your solutions in addition to the coding activity. + +We'd already provided tools like [ABP CLI](https://abp.io/cli) and [ABP Suite](https://abp.io/suite) for these kind of purposes before. [ABP Studio](https://abp.io/studio) takes this one long step further and offers a tool that you can use continuously throughout your coding activities, help you for non-coding activities to make you focus on your software development. + +I am very excited to announce that the ABP Studio (beta) is generally available to everyone. It is now downloadable on the [get started page](https://abp.io/get-started) of the [new ABP Platform website](https://abp.io/blog/new-abp-platform-is-live). + +## What is ABP Studio? + +[ABP Studio](https://abp.io/docs/latest/studio) is a cross-platform desktop application for ABP and .NET developers. It aims to provide a comfortable development environment for you by automating things, providing insights about your solution, making develop, run, browse, monitor, trace and deploy your solutions much easier. + +**From now on, ABP Studio is the default way to start with the ABP Platform**; + +* The [get started page](https://abp.io/get-started) has updated so it offers to download ABP Studio to create a new ABP based solution. +* The ABP CLI ([Volo.Abp.Cli](https://nuget.org/packages/Volo.Abp.Cli)) is replaced by the ABP Studio CLI ([Volo.Abp.Studio.Cli](https://www.nuget.org/packages/Volo.Abp.Studio.Cli)). [The new ABP Studio CLI](https://abp.io/docs/latest/cli) is compatible with the old one, and extends it by introducing new commands. +* [Startup solution templates](https://abp.io/docs/latest/solution-templates) are completely renewed. The solution structures are similar to the old ones, but they are totally new templates built with the new templating engine. +* All the documentation and tutorials now uses ABP Studio and ABP Studio CLI. + +> **ABP Studio is in beta stage now.** It is also in rapid development and release cycle. We frequently release new feature and patch versions. Please [file an issue](https://github.com/abpframework/abp/issues/new/choose) if you have any problem. +> +> If you want to continue to use the old CLI and old startup templates, please [refer that document](https://abp.io/docs/latest/cli/differences-between-old-and-new-cli). + +## The Easiest Way to Start with ABP + +As mentioned before, the [startup solution templates](https://abp.io/docs/latest/solution-templates) are completely renewed with ABP Studio. They provide much more options compared to the old startup templates. The following screenshot is taken from the New Solution wizard of ABP Studio, which provides an comfortable and easy way to create new solutions: + +![abp-studio-new-layered-solution-template-wizard.png](3a1414e81208c50f7a7c2c5f2463ee95.png) + +For example, you can now select most of the non-fundamental modules as optional while creating a new solution: + +![abp-studio-new-layered-solution-template-wizard-options.png](3a1414e82f626e06b4022b7fe077d68b.png) + +### Developing Microservices Solutions is Now Much Easier + +The most important change is made on the [microservice startup template](https://abp.io/docs/latest/solution-templates/microservice) (which is available only for Business or higher license holders). We've designed the solution structure, integrations, Kubernetes/Helm configuration, database migrations and all others from scratch and well documented all the decisions we've applied. Developing microservice solutions with ABP is now easier and more understandable than ever. + +## Architecting Your Complex Solutions + +One of the main purposes to build ABP Studio was to simplify to create multi-modular and distributed systems. Either you create a modular monolith application or a microservice solution, [ABP Studio's solution explorer](https://abp.io/docs/latest/studio/solution-explorer) provides a convenient way to design your high-level solution structure. + +You see a microservice solution in the following screenshot: + +![solution-explorer.png](3a1414e8580fc750ee048c9a14f7c064.png) + +That ABP Studio solution contains multiple separate .NET solutions (`.sln`) each has multiple .NET projects (`.csproj`). ABP Studio allows you to easily manage such a multi-solution system on a single view. You can create new packages and modules, import existing packages and modules, manage their dependencies and so on. + +## Run and Test Your Multi-Application Solutions with a Single Click + +One of the biggest shortcomings we face when developing distributed or complex solutions is being able to easily run all components of the solutions so that we can test and debug a single service or application without caring about all the runtime dependencies. + +Here a screenshot from the ABP Studio's [Solution Runner](https://abp.io/docs/latest/studio/running-applications) view: + +![abp-studio-solution-runner-overall.png](3a1414e87779052078513905ac904886.png) + +When you use ABP Studio, it is dramatically easier to run, monitor, test, debug and develop your applications and services. You can browse your web UI applications, monitor all the HTTP requests, distributed events, exceptions and logs in real time on a single screen. In this way, you can easily run all the systems and trace the problems when you have. + +All you need to click the *Play* button or right-click and select the *Run* -> *Start All* command: + +![abp-studio-solution-runner-start-apps.png](3a1414e8936010694a2402ab1e771296.png) + +The nice thing is that you can create multiple profiles for each of your teams so that they can run only the applications they need to develop the application they are working on. + +## Seamlessly Develop Your Service as Integrated to Kubernetes + +Kubernetes is the de-facto tool to deploy, run and scale complex systems. However, it can also be a great tool to develop such solutions in a local environment. + +With ABP Studio's [Kubernetes Integration](https://abp.io/docs/latest/studio/kubernetes) system, it is now possible to deploy and run a complex system in a Kubernetes cluster. Then you can establish a bridge between your local development environment and the Kubernetes cluster. In this way, you can develop, run, test and debug an application or service in your local development environment as it is running in the Kubernetes cluster. All incoming and outgoing traffic is properly routed and managed by ABP Studio. You just focus on the service you are responsible to develop and let the Kubernetes run rest of the system for you. + +You can see all the Helm charts in a solution in the Kubernetes panel of ABP Studio: + +![abp-studio-helm-charts.png](3a1414e8bcfc8e9ce9dfdcb779fe7d74.png) + +Here, you can easily build, install and uninstall the Helm charts to your Kubernetes cluster. In the Kubernetes tab, you can connect to the Kubernetes cluster and intercept a service to develop it locally. See [the documentation](https://abp.io/docs/latest/studio/kubernetes) for more information. + +The good news is that all the monitoring data (HTTP Requests, Events, Exceptions, Logs,...) is still visible in real time with the Kubernetes integration too. + +## Use the ABP Suite as Integrated to ABP Studio + +[ABP Suite](https://abp.io/suite) is a tool that is basically used to generate code for ABP Solutions. It has started by creating simple CRUD pages, and now it does much more. It can establish relations with existing entities, create complex user interfaces like parent/child tables and so on... + +ABP Suite can be used directly inside ABP Studio by clicking the *ABP Suite* -> *Open* command: + +![abp-suite-open-in-abp-studio.png](3a1414e8eee5a21b45744cedf6e688f3.png) + +This will open ABP Suite in a new tab for the current solution and focus on the CRUD page generation: + +![abp-suite-in-abp-studio.png](3a1414e908e6740ea8f1a74a72a8a7e6.png) + +The new ABP Studio solution templates and ABP Suite code generation are compatible with each other. Here a screenshot from the generated CRUD UI for a very simple Book entity: + +![suite-generated-entity.png](3a1414e927e9ce87f76be80eb2946060.png) + +## The Community Edition vs Commercial Licenses + +ABP Studio has a Community Edition which is completely free and available to everyone. As you can guess, there are come differences between the community edition and commercial editions. ABP Platform has 4 fundamental license types; + +* Open source (free) +* Team +* Business +* Enterprise + +Here, the comparison table for ABP Studio features for these license types: + +![abp-studio-license-comparison-table.png](3a1414e947cec9e65339c4faf917a656.png) + +Microservice startup template and Kubernetes integration features are available only for commercial licenses since these are considered more enterprise requirements. Also, the solution size is limited with the ABP Community edition. If you are building a large or distributed solution, consider to [purchase a commercial license](https://abp.io/pricing). + +## Conclusion + +I've introduced the ABP Studio General Availability with this post. It is still in the beta stage. You can expect frequent releases during the beta phase. We will add new features and fix issues quickly. Please [download](https://abp.io/studio) and use it now. If you find any problem, do not hesitate to open an [issue on GitHub](https://github.com/abpframework/abp/issues/new/choose). \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff619cb6c8f327d8674864fe158.png b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff619cb6c8f327d8674864fe158.png new file mode 100644 index 0000000000..52eb61f285 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff619cb6c8f327d8674864fe158.png differ diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff64a2f24ce591a64262fe6ee84.png b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff64a2f24ce591a64262fe6ee84.png new file mode 100644 index 0000000000..c0b1a4fe48 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff64a2f24ce591a64262fe6ee84.png differ diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff676c58a374c2b3ec7fd8ebced.png b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff676c58a374c2b3ec7fd8ebced.png new file mode 100644 index 0000000000..9398fa1070 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff676c58a374c2b3ec7fd8ebced.png differ diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6887bf4a58ef4536168c3ba0a.png b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6887bf4a58ef4536168c3ba0a.png new file mode 100644 index 0000000000..082c567f8c Binary files /dev/null and b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6887bf4a58ef4536168c3ba0a.png differ diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6aa7c451b9a2bfc67041a6939.png b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6aa7c451b9a2bfc67041a6939.png new file mode 100644 index 0000000000..be73de4d8f Binary files /dev/null and b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6aa7c451b9a2bfc67041a6939.png differ diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6be3fe8da7d5b3e67142d2a5a.png b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6be3fe8da7d5b3e67142d2a5a.png new file mode 100644 index 0000000000..2f45635782 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6be3fe8da7d5b3e67142d2a5a.png differ diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6dbebdf8dd69c114127b7aa71.png b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6dbebdf8dd69c114127b7aa71.png new file mode 100644 index 0000000000..95265fea29 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6dbebdf8dd69c114127b7aa71.png differ diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6f9de25f4020d8ce7b2c3dd82.png b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6f9de25f4020d8ce7b2c3dd82.png new file mode 100644 index 0000000000..cc468d4bf3 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff6f9de25f4020d8ce7b2c3dd82.png differ diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff70d3a8a6018dde07c5d56b595.png b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff70d3a8a6018dde07c5d56b595.png new file mode 100644 index 0000000000..d92621f403 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a141ff70d3a8a6018dde07c5d56b595.png differ diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a1462b93192e9ffc0c15a5db4ded692.png b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a1462b93192e9ffc0c15a5db4ded692.png new file mode 100644 index 0000000000..32f6d01edb Binary files /dev/null and b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/3a1462b93192e9ffc0c15a5db4ded692.png differ diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/post.md b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/post.md new file mode 100644 index 0000000000..05c18fde03 --- /dev/null +++ b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/post.md @@ -0,0 +1,174 @@ +Today, we are happy to release [ABP](https://abp.io) version **8.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 v8.3! Thanks to you in advance. + +## Get Started with the 8.3 RC + +You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli). + +By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI: + +![switch-to-preview.png](3a1462b93192e9ffc0c15a5db4ded692.png) + +## Migration Guide + +There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v8.2 or earlier: [ABP Version 8.3 Migration Guide](https://abp.io/docs/8.3/release-info/migration-guides/abp-8-3) + +## What's New with ABP v8.3? + +In this section, I will introduce some major features released in this version. +Here is a brief list of titles explained in the next sections: + +* CMS Kit: Marked Items/Favorites +* CMS Kit: Approvement System for Comments +* Docs: Added Google Translation Support & Introducing the Single Project Mode +* Using DBFunction for Global Query Filters +* CMS Kit (PRO): FAQ +* Package Updates (NuGet & NPM) + +### CMS Kit: Marked Items/Favorites + +CMS Kit provides a marking system to mark any kind of resource, like a blog post or a product, as a favorite, starred, flagged, or bookmarked. + +![cmskit-module-markedItems.png](3a141ff619cb6c8f327d8674864fe158.png) + +This system is especially useful if you need to highlight some resources and differentiate them from other items. To use the marking system, you need to define an entity type with the icon name, by configuring the `CmsKitMarkedItemOptions`: + +```csharp +Configure(options => +{ + options.EntityTypes.Add( + new MarkedItemEntityTypeDefinition( + entityType: "product", + icon: StandardMarkedItems.Favorite + ) + ); +}); +``` + +You can select any of the standard marked item icons (as used in the example above) or easily customize the icons shown in the toggling components. + +> Read the [CMS Kit: Marked Item System](https://abp.io/docs/8.3/modules/cms-kit/marked-items) documentation to learn more. + +### CMS Kit: Approvement System for Comments + +CMS Kit Module has been provided a [Commenting System](https://abp.io/docs/8.3/modules/cms-kit/comments) for a while. This system allows you to add the comment feature to any kind of resource, like blog posts, or products. However, this system wasn't providing an approvement system, that allows system administrations to review the comments before publishing them in their application. + +In this version, we have introduced the [Approvement System](https://abp.io/docs/8.3/modules/cms-kit/comments#settings), which allows you to _require approval for comments to be published_. It's disabled by default, but you can make it enabled by simply checking the related setting on the settings page: + +![cmskit-module-comments-settings.png](3a141ff64a2f24ce591a64262fe6ee84.png) + +When you enable it, whenever a user submits a comment, it can be directly seen on the back-office application (in the _cms/comments_ page), and you can determine if the comment should be approved or rejected. If you approve the comment, then it will be shown in the comment section for the related resource. + +> Read the [CMS Kit: Comments](https://abp.io/docs/8.3/modules/cms-kit/comments) documentation to learn more. + +### Docs: Added Google Translation Support & Introducing the Single Project Mode + +In this version, we made some improvements in the [Docs Module](https://abp.io/docs/8.3/modules/docs), added Google Translation support for better findings in the documentation, and introduced a single project mode to align our needs in the documentation system with [the unification of the ABP Platform](https://abp.io/blog/new-abp-platform-is-live). + +The single project mode allows you to use a single name as a project name in your application. If you are not considering supporting multiple projects with their multiple docs and instead if you have a single project and want to have documentation for it, it's especially useful for you. You just need to configure the `DocsUiOptions`, set the single project mode as **enabled** and also define a constant project name: + +```csharp +Configure(options => +{ + options.SingleProjectMode.Enable = true; + options.SingleProjectMode.ProjectName = "abp"; +}); +``` + +In addition to this feature, we also introduced Google Translation support for the documentation system and even integrated it into our [abp.io/docs](https://abp.io/docs/) website: + +![docs-google-search.png](3a141ff676c58a374c2b3ec7fd8ebced.png) + +![google-search-results.png](3a141ff6887bf4a58ef4536168c3ba0a.png) + +Thanks to this system, you can either translate your documentation into your own language by Google Translation System or search specific keywords to easily find the related topic in the documentation. + +### Using DBFunction for Global Query Filters + +In this version, ABP has started using [User-defined function mapping](https://learn.microsoft.com/en-us/ef/core/querying/user-defined-function-mapping) for global filters to gain performance improvements and let EF Core generate more precise SQL commands under the hook. + +> See the documentation for more info: [Using User-defined function mapping for global filters](https://abp.io/docs/8.3/framework/infrastructure/data-filtering#using-user-defined-function-mapping-for-global-filters) + +### CMS Kit: FAQ + +CMS Kit provides a [FAQ System](https://abp.io/docs/8.3/modules/cms-kit-pro/faq) to allow users to create, edit, and delete FAQs. Here is an example screenshot from the FAQ page on the admin side: + +![cms-kit-faq.png](3a141ff6aa7c451b9a2bfc67041a6939.png) + +You can list, create, update, and delete sections and their questions on the admin side of your solution. Then, by using the `FaqViewComponent` in your public-web application, you can display FAQs, section by section: + +![faq-section-public-web.png](3a141ff6be3fe8da7d5b3e67142d2a5a.png) + +> Read the [CMS Kit: FAQ System](https://abp.io/docs/8.3/modules/cms-kit-pro/faq) documentation to learn more. + +### Package Updates + +In this version, we also updated some of the core NuGet and NPM package versions. All of the removed or deprecated methods have already been updated at the framework level. However, if you used any methods from these packages, you should be aware of the change and update it in your code accordingly. + +You can see the following list of the package version changes: + +* **Angular** package version has been updated to **v18.1.x**. See [#20436](https://github.com/abpframework/abp/issues/20436) for more info. +* [Updated Markdig.Signed from v0.33.0 to v0.37.0](https://github.com/abpframework/abp/pull/20195) - [NuGet](https://www.nuget.org/packages/Markdig.Signed) +* [Updated Hangfire from v1.8.6 to v1.8.12](https://github.com/abpframework/abp/pull/20009) - [NuGet](https://www.nuget.org/packages/Hangfire.AspNetCore) +* [Updated SixLabors.ImageSharp from v3.0.2 to v3.1.4](https://github.com/abpframework/abp/pull/19643) - [NuGet](https://www.nuget.org/packages/SixLabors.ImageSharp) +* [Updated Blazorise from v1.5.0 to v1.5.2](https://github.com/abpframework/abp/pull/19841) - [NuGet](https://www.nuget.org/packages/Blazorise) +* [Updated datatables.net from v1.11.4 to v2.0.2](https://github.com/abpframework/abp/pull/19340) - [NPM](https://www.npmjs.com/package/datatables.net) + +## Community News + +### The New ABP Platform Is Live! + +![new-platform-cover-image.png](3a141ff6dbebdf8dd69c114127b7aa71.png) + +We're thrilled to announce that the **new ABP.IO Platform** is now live! Our team has been hard at unifying and enhancing the entire platform to deliver a seamless, user-friendly experience. We consolidated all our services under a single domain: [abp.io](https://abp.io/); added a new mega menu that makes finding what you need much easier and faster, and also improved the UX of our application and combined both ABP (open-source) and ABP Commercial (paid) documents into a single comprehensive resource. + +> Read the blog post to learn more about this unification 👉 [The new ABP Platform is live!](https://abp.io/blog/new-abp-platform-is-live) + +### Announcing ABP Studio (Beta) General Availability + +We're really excited to announce that the **ABP Studio (beta)** is generally available to everyone. It is now downloadable on the [get started page](https://abp.io/get-started) of the [new ABP Platform website](https://abp.io/blog/new-abp-platform-is-live). + +![studio-beta-cover-image.png](3a141ff6f9de25f4020d8ce7b2c3dd82.png) + +> Read the blog post to learn more about the ABP Studio (Beta) 👉 [Announcing ABP Studio (beta) General Availability](https://abp.io/blog/announcing-abp-studio-general-availability) + +### Introducing the New ABP CLI + +As described above, we recently [unified the ABP platform in a single domain (abp.io)](https://abp.io/blog/new-abp-platform-is-live) and made some changes in our templating system to simplify your development. Also, we released more stable **ABP Studio** versions, which can dramatically improve and speed up your development time. + +Besides all of these changes, we have also introduced a [new ABP CLI](https://abp.io/docs/latest/cli/index) to bring you a more streamlined and efficient experience, which also extends the current commands. + +![new-abp-cli-cover-image.png](3a141ff70d3a8a6018dde07c5d56b595.png) + +The new ABP CLI extends the old ABP CLI, adds more features that are used by ABP Studio behind the scenes, and is also fully compatible with the new templating system. We created a blog post, which you can read at [https://abp.io/blog/introducing-the-new-abp-cli](https://abp.io/blog/introducing-the-new-abp-cli) to highlight the reason behind this change and insights into the new ABP CLI, you can check it out if you want to learn more. + +### New ABP Community Articles + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Ahmed Tarek](https://twitter.com/AhmedTarekHasa1) has created **three** new community articles: + * [🧪 Unit Testing Best Practices In .NET C# 🤷‍♂️](https://abp.io/community/articles/-unit-testing-best-practices-in-.net-c--mnx65npu) + * [Memory Management In .NET](https://abp.io/community/articles/memory-management-in-.net-rqwbtzvl) + * [🧵 How String In .NET C# Works 🤷‍♂️](https://abp.io/community/articles/-how-string-in-.net-c-works--vj6d2pnm) + +* [Anto Subash](https://twitter.com/antosubash) has created **two** new community videos: + * [ABP React Template V2](https://abp.io/community/videos/abp-react-template-v2-ilc4cyqr) + * [Migrating Tye to Aspire - .NET Microservice with ABP](https://abp.io/community/videos/migrating-tye-to-aspire-.net-microservice-with-abp-ga1t4ckr) + +* [HeadChannel Team](https://headchannel.co.uk/) has created **two** new community articles: + * [Managing Baseline Creation in Applications Based on ABP Framework](https://abp.io/community/articles/managing-baseline-creation-in-applications-based-on-abp-framework-yiacte5c) + * [How to Test The System Using PostgreSQL and TestContainers](https://abp.io/community/articles/how-to-test-the-system-using-postgresql-and-testcontainers-8yh8t0j8) + +* [Create a Generic HTTP Service to Consume a Web API](https://abp.io/community/articles/create-a-generic-http-service-to-consume-a-web-api-yidme2kq) by [Bart Van Hoey](https://github.com/bartvanhoey) +* [Use User-Defined Function Mapping for Global Filter](https://abp.io/community/articles/use-userdefined-function-mapping-for-global-filter-pht26l07) by [Liming Ma](https://github.com/maliming) +* [How to use .NET Aspire with ABP framework](https://abp.io/community/articles/how-to-use-.net-aspire-with-abp-framework-h29km4kk) by [Berkan Şaşmaz](https://twitter.com/berkansasmazz) +* [Exciting New Feature in ABP.IO CMS Kit: Marked Item System](https://abp.io/community/articles/exciting-new-feature-in-abp.io-cms-kit-marked-item-system.-2hvpq0me) by [Suhaib Mousa](https://abp.io/community/members/suhaibmousa032@gmail.com) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community. + +## Conclusion + +This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://abp.io/docs/8.3/release-info/road-map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v8.3 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-08-12-join-abp-at-net-conf-focus-on-ai/post.md b/docs/en/Community-Articles/2024-08-12-join-abp-at-net-conf-focus-on-ai/post.md new file mode 100644 index 0000000000..432ece093c --- /dev/null +++ b/docs/en/Community-Articles/2024-08-12-join-abp-at-net-conf-focus-on-ai/post.md @@ -0,0 +1,46 @@ +We’re excited to announce that **[ABP](https://abp.io)** is sponsoring the **[.NET Conf: Focus on AI](https://focus.dotnetconf.net)**, taking place virtually on **August 20, 2024**. This one-day event, hosted by Microsoft team, together with .NET community, will showcase how AI can supercharge the .NET applications. + +## About .NET Conf + +.NET Conf has been a virtual event since the beginning, and this year brings a 1-day focus event all about artificial intelligence tools and libraries with the .NET platform. And “.NET Conf: Focus” is a series of smaller, live events that are delivered throughout the year, each focusing on specific things you can do with .NET. + +This 1-day event features live sessions with speakers from the community, Microsoft, and the .NET team. You can ask questions live on X, Mastodon, YouTube, or Twitch, and gain valuable knowledge to enhance your skills as a .NET developer. + +## What to Expect? + +Get ready for deep dives into AI integration, practical examples, and insights from industry experts and community leaders. Ideal for all .NET developers, especially if you are looking to enhance your applications with AI. You’ll get to hear from industry experts and community leaders. Plus you’ll get to learn from partners and companies who are already successfully integrating AI into their .NET applications. + +### Keynote: State of .NET + AI. + +***Scott Hanselman*** and ***Maria Naggaga Nakanwagi*** will discuss AI basics, Large Language Models (LLMs), and the latest advancements in AI within the .NET ecosystem, including insights into various SDKs and integration strategies. + +### Session Highlights + +* **Getting Started with AI in .NET** by *Stephen Toub* +* **NET Aspire and Semantic Kernel** by *Steve Sanderson* and *Matthew Bolanos* +* **Interactive AI with Blazor and .NET** by *Dan Roth* +* **AI Models in .NET: From Local to Cloud** by *Bruno Capuano* +* **RAG with .NET and Azure SQL** by *Davide Mauri* +* **Semantic Search in .NET with Milvus** by *Tim Spann* +* **H&R Block’s AI Journey with .NET and Azure** by *Vin Kamat* + +## Win an ABP License! + +As part of our sponsorship, we’re giving away 15 ABP Personal Licenses during the event! ABP license provides powerful tools to help you build robust and scalable .NET applications. Simply **[register](https://developer.microsoft.com/en-us/reactor/events/23325/)** the event for a chance to win. + +## Last Week for 20% Off⏳ + +We’re also celebrating the launch of our [New Website](https://www.abp.io/) with 20% off All ABP Licenses—but hurry, this offer ends soon! Visit [abp.io](https://abp.io) to grab this limited-time deal. The last day is **August 17th, 2024**. Don’t miss out! + +*** + +📅 **Date**: August 20th + +⏰ **Time**: 4:00 PM - 12:00 AM (UTC) Coordinated Universal Time + +🔴 **Livestream**: X, Mastodon, YouTube or Twitch + +*** + + + **[Register](https://developer.microsoft.com/en-us/reactor/events/23325/)** now! \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218818c8481d12de92c7b257113.png b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218818c8481d12de92c7b257113.png new file mode 100644 index 0000000000..7dbf8f7912 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218818c8481d12de92c7b257113.png differ diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218a38e2fd4a8c44943d8aa0b11.png b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218a38e2fd4a8c44943d8aa0b11.png new file mode 100644 index 0000000000..269159c651 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218a38e2fd4a8c44943d8aa0b11.png differ diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218c8262a2a4da395a93f4e94d0.png b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218c8262a2a4da395a93f4e94d0.png new file mode 100644 index 0000000000..46c8de76da Binary files /dev/null and b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218c8262a2a4da395a93f4e94d0.png differ diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218df7be4403013931b9dd94a6c.png b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218df7be4403013931b9dd94a6c.png new file mode 100644 index 0000000000..3459635322 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218df7be4403013931b9dd94a6c.png differ diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218f3e4ecc0aed21065b80a534d.png b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218f3e4ecc0aed21065b80a534d.png new file mode 100644 index 0000000000..8556ff38af Binary files /dev/null and b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146218f3e4ecc0aed21065b80a534d.png differ diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a1462191f25bb51fba69cdb759edba6.png b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a1462191f25bb51fba69cdb759edba6.png new file mode 100644 index 0000000000..7b4fdbba8e Binary files /dev/null and b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a1462191f25bb51fba69cdb759edba6.png differ diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a1462193e86ee8e2460974db1783388.png b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a1462193e86ee8e2460974db1783388.png new file mode 100644 index 0000000000..9398fa1070 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a1462193e86ee8e2460974db1783388.png differ diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146219582b520fef94c9a95bd36167.png b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146219582b520fef94c9a95bd36167.png new file mode 100644 index 0000000000..082c567f8c Binary files /dev/null and b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a146219582b520fef94c9a95bd36167.png differ diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a14621978a2335ed0a66c96393e7b1a.png b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a14621978a2335ed0a66c96393e7b1a.png new file mode 100644 index 0000000000..6584dfc015 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a14621978a2335ed0a66c96393e7b1a.png differ diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a1462199053fbd8b20fa92db1c15860.png b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a1462199053fbd8b20fa92db1c15860.png new file mode 100644 index 0000000000..68dddcad64 Binary files /dev/null and b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/3a1462199053fbd8b20fa92db1c15860.png differ diff --git a/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/post.md b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/post.md new file mode 100644 index 0000000000..a26346e8b9 --- /dev/null +++ b/docs/en/Community-Articles/2024-08-14-new-abp-documentation-system-everything-you-need-in-one-place-/post.md @@ -0,0 +1,73 @@ +We have combined the ABP (open-source) and ABP Commercial (paid) documents into a single, comprehensive resource. This unification brings you a better experience in the documentation system, helps you find what you're looking for more easily, allows you to read the documents that are related to each other one after the other, and also provides Google Search and Google Translation support for the documents. + +Let's see what's new with the unified documentation system in detail: + +## All Documentation In One Place 📃 + +We decided to combine the ABP (open-source) and ABP Commercial (paid) documents into a single place, along with [the new ABP Platform Unification](https://abp.io/blog/new-abp-platform-is-live). + +The new documentation address is [abp.io/docs](https://abp.io/docs) and seen like below: + +![abp-docs.png](3a146218818c8481d12de92c7b257113.png) + +This unified documentation brings you a better search capability with Google Search support, allows you to not need to switch between documentation websites to read both framework and commercial features, look what you are looking for more easily from the unified menu structure, following new features and their documentation in a more stable and easier way. + +## Accessing Documents with Older Versions🗃️ + +From v8.2, with the new documentation system, since we merged all documents into a single place, you don't need to select if you want to show a framework or commercial document. However, if you want to access an old document, for example, if you are using an older version of ABP or don't want to create the solutions from ABP Studio and instead prefer ABP CLI (in the getting started and startup template docs, ABP Studio is shown for project creation and other features, for instance), you can change the version from the version select-box (prior to v8.2), and select which document type (framework or commercial) you want to read and then find/choose the document that you want: + +![old-docs.png](3a146218a38e2fd4a8c44943d8aa0b11.png) + +You can access any old-version document as you would before, by specifying the version. But we suggest you update your solution to v8.2+ and start using ABP Studio! By doing that, you can get more benefits from the new features, and edge-cutting features of ABP Studio and easily manage your application from development to production! + +## Documentation Updates 🚀 + +With the [announcement of ABP Studio (beta) General Availability](https://abp.io/blog/announcing-abp-studio-general-availability), we made some improvements in our documents. Starting from v8.2, since ABP Studio is the suggested way to create and manage your applications, we updated the [Get started](https://abp.io/docs/latest/get-started) documentation and some other documents along with, and explained project creation via ABP Studio. If you prefer [creating a new solution with the ABP CLI](https://abp.io/docs/latest/cli), you can use the new ABP CLI as you did the old one before. + +Besides that, we revised all of our documents, updated most of them according to the [new ABP Platform unification](https://abp.io/blog/new-abp-platform-is-live). For example, we merged our migration guide documents into single documents for each version and categorized the related topics you need to do when updating your solutions under the **open-source** and **pro** sections, so either you are an open-source template user or a license owner, you can easily jump to the related section and read them easily and accordingly: + +![in-this-document.png](3a146218c8262a2a4da395a93f4e94d0.png) + +Since we combined ABP (framework) and ABP Commercial documents, we added information notes in each document that indicate if the related feature is in your license plan or not. An example screenshot from ABP Suite documentation can be seen as follow: + +![suite-license-note.png](3a146218df7be4403013931b9dd94a6c.png) + +Also, for the application modules, we added **(PRO)** postfixes in the navigation menu for you to easily understand if the module is for license owners or open-source users. Thanks to that you can easily distinguish the related application modules and read the related module documentation to understand it: + +![pro-modules.png](3a146218f3e4ecc0aed21065b80a534d.png) + +## New Navigation Tree 📚 + +With the documentation unification, we re-structured the navigation tree of the documents: + +![navigation-menu.png](3a1462191f25bb51fba69cdb759edba6.png) + +The new navigation tree allows you to find any document you want in a more desired way, in the related sub-menu. For example, if you want to learn more about *modularity*, you can find under the **Framework > Architecture > Modularity** menu items, or if you want to learn more about the ABP Studio, you can find the all related docs under the root **Tools** menu. + +## Google Translate & Search Capabilities 🔎 + +In ABP v8.3, we made some improvements in the [Docs Module](https://abp.io/docs/8.3/modules/docs), added Google Search support for better findings in the documentation, and introduced Google Translation for the documentation system. After implementing these features, we integrated them into our documentation system and removed the languages select box from the menu: + +![google-translate-and-search.png](3a1462193e86ee8e2460974db1783388.png) + +From now on, we will provide documents in English only. The reason behind that is, that with the new Google Translate support, you can directly translate any documentation to the desired language (of course, must be one of the supported languages). Thanks to the Google Translate feature, you can read the official documentation in your own language, and we as the core team, don't need to synchronize the documentation between different languages, it was really hard to keep them up to date, and now they all will be available all the time in the all supported languages. + +![google-search-result.png](3a146219582b520fef94c9a95bd36167.png) + +Also, thanks to Google Search, now you can search specific keywords to easily find the related topic in the documentation. For example, if you search the **Validation** keyword, Google will list all related documents according to their importance and relevancy: + +## Feedbacks 📝 + +Besides all changes, we also added a **feedback section** at the end of each document. You can share your thoughts, suggestions, or criticism for specific documentation. We would like to hear more from you about our documentation quality and get suggestions from each one of you to improve our documents and platform, so it will be much appreciated if you share your feedback for any documentation you want, please don't hesitate! + +![docs-feedbacks.png](3a14621978a2335ed0a66c96393e7b1a.png) + +You can either directly scroll down to the bottom directly for a certain document, or click the **Feedback** action button to navigate to the feedbacks section, and provide feedback: + +![docs-feedback-section.png](3a1462199053fbd8b20fa92db1c15860.png) + +## Conclusion 🎯 + +To see the new ABP documentation system, please visit the [abp.io/docs](https://abp.io/docs/latest/) website. Check out the new navigation tree, read the documents you want, provide feedback to help us improve our documents and more... + +We look forward to your feedback and continued support as we grow together! Thanks in advance 🙏 diff --git a/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/POST.md b/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/POST.md index 295b509029..cd4c3177a1 100644 --- a/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/POST.md +++ b/docs/en/Community-Articles/2024-08-28-Understanding-AOT-vs-JIT/POST.md @@ -1,7 +1,3 @@ - - -![book](images/cover.png) - Ahead-of-Time (AOT) compilation and Just-in-Time (JIT) compilation are two different methods for compiling Angular applications. Here's a breakdown of the differences between them: ### **Ahead-of-Time (AOT) Compilation** @@ -61,4 +57,4 @@ Ahead-of-Time (AOT) compilation and Just-in-Time (JIT) compilation are two diffe ### **Best Practices:** - **Use AOT** for production builds to ensure faster load times, smaller bundle sizes, and more secure applications. -- **Use JIT** during development to take advantage of quicker builds and easier debugging. \ No newline at end of file +- **Use JIT** during development to take advantage of quicker builds and easier debugging. diff --git a/docs/en/Community-Articles/2024-08-29-What-is-Angular-Schematics/Post.md b/docs/en/Community-Articles/2024-08-29-What-is-Angular-Schematics/Post.md index c13c5ab345..5ea6cb6528 100644 --- a/docs/en/Community-Articles/2024-08-29-What-is-Angular-Schematics/Post.md +++ b/docs/en/Community-Articles/2024-08-29-What-is-Angular-Schematics/Post.md @@ -1,7 +1,5 @@ # What is Angular Schematics? -![Cover Image](cover.png) - **Angular Schematics** is a powerful tool which is part of the Angular CLI that allows developers to automate various development tasks by **generating and modifying code**. Schematics provides a way to create **templates and boilerplate code** for Angular applications or libraries, enabling consistency and reducing the amount of repetitive work. ### Key Concepts of Angular Schematics: @@ -82,4 +80,4 @@ Here are the direct links for the Angular Schematics resources: ### Conclusion: -Angular Schematics is a powerful tool for automating repetitive tasks, generating consistent code, and managing project upgrades. By leveraging schematics, Angular developers can save time, reduce errors, and enforce best practices across their projects. \ No newline at end of file +Angular Schematics is a powerful tool for automating repetitive tasks, generating consistent code, and managing project upgrades. By leveraging schematics, Angular developers can save time, reduce errors, and enforce best practices across their projects. diff --git a/docs/en/Community-Articles/2024-09-01-Do-You-Need-MultiTenancy/Post.md b/docs/en/Community-Articles/2024-09-01-Do-You-Need-MultiTenancy/Post.md index b80917f4c4..a294a1f2e6 100644 --- a/docs/en/Community-Articles/2024-09-01-Do-You-Need-MultiTenancy/Post.md +++ b/docs/en/Community-Articles/2024-09-01-Do-You-Need-MultiTenancy/Post.md @@ -2,8 +2,6 @@ This article discusses whether you need a multi-tenancy architecture for your next project. Answer my critical questions to decide if multi-tenancy suits your application or not! -![Cover image](cover.png) - ## What’s Multi-tenancy? It’s an architectural approach to building SaaS solutions. In this model, the hardware and software resources are shared between tenants, and application data is virtually or physically isolated between tenants. Here, **the main goal is minimizing costs and maximizing customer count**. diff --git a/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/3a14f8d3e5f86b230ae92e5734b8400b.png b/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/3a14f8d3e5f86b230ae92e5734b8400b.png new file mode 100644 index 0000000000..30883ebf92 Binary files /dev/null and b/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/3a14f8d3e5f86b230ae92e5734b8400b.png differ diff --git a/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/3a153ae9a87ee1b9eb8b2782b82e1789.png b/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/3a153ae9a87ee1b9eb8b2782b82e1789.png new file mode 100644 index 0000000000..a182c04647 Binary files /dev/null and b/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/3a153ae9a87ee1b9eb8b2782b82e1789.png differ diff --git a/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/post.md b/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/post.md new file mode 100644 index 0000000000..55f7b80294 --- /dev/null +++ b/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/post.md @@ -0,0 +1,77 @@ +[ABP](https://abp.io/) 8.3 stable version has been released today. + +## What's New With Version 8.3? + +All the new features were explained in detail in the [8.3 RC Announcement Post](https://blog.abp.io/abp/announcing-abp-8-3-release-candidate), so there is no need to review them again. You can check it out for more details. + +## Getting Started with 8.3 + +### Creating New Solutions + +You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli) to create new solutions. + +By default, ABP Studio uses stable versions to create solutions. Therefore, it will be creating the solution with the latest stable version, which is v8.3 for now, so you don't need to specify the version. + +### How to Upgrade an Existing Solution + +You can upgrade your existing solutions with either ABP Studio or ABP CLI. In the following sections, both approaches are explained: + +### Upgrading via ABP Studio + +If you are already using the ABP Studio, you can upgrade it to the latest version to align it with ABP v8.3. ABP Studio periodically checks for updates in the background, and when a new version of ABP Studio is available, you will be notified through a modal. Then, you can update it by confirming the opened modal. See [the documentation](https://abp.io/docs/latest/studio/installation#upgrading) for more info. + +After upgrading the ABP Studio, if you are using a stable version, such as v8.2.0, then you can open your solution in the application, and simply click the **Upgrade ABP Packages** action button to instantly upgrade your solution: + +![upgrade-abp-packages.png](3a153ae9a87ee1b9eb8b2782b82e1789.png) + +If you are using an RC version, you can use the **Switch to stable** option as follows: + +![switch-to-stable.png](3a14f8d3e5f86b230ae92e5734b8400b.png) + +### Upgrading via ABP CLI + +Alternatively, you can upgrade your existing solution via ABP CLI. First, you need to install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet, you can run the following command: + +```bash +dotnet tool install -g Volo.Abp.Studio.Cli +``` + +Or to update the existing CLI, you can run the following command: + +```bash +dotnet tool update -g Volo.Abp.Studio.Cli +``` + +After installing/updating the ABP CLI, you can use the [`update` command](https://abp.io/docs/latest/CLI#update) to update all the ABP related NuGet and NPM packages in your solution as follows: + +```bash +abp update +``` + +> You can run this command in the root folder of your solution. + +## Migration Guides + +There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v8.2 or earlier: [ABP Version 8.3 Migration Guide](https://abp.io/docs/8.3/release-info/migration-guides/abp-8-3) + +## Community News + +### New ABP Community Posts + +As always, exciting articles have been contributed by the ABP community. I will highlight some of them here: + +* [Alper Ebicoglu](https://twitter.com/alperebicoglu) has created **three** new community articles: + * [Do You Really Need Multi-tenancy?](https://abp.io/community/articles/do-you-really-need-multitenancy-hpwn44r3) + * [What is Angular Schematics?](https://abp.io/community/articles/what-is-angular-schematics-2z4jusf5) + * [Understanding Angular AOT vs JIT Compilations](https://abp.io/community/articles/understanding-angular-aot-vs-jit-compilations-0r0a0a3f) +* [Dynamic Widget Communication](https://abp.io/community/articles/dynamic-widget-communication-uvun7q23) by [Suhaib Mousa](https://suhaibmousa.com/) +* [Introducing the Google Cloud Storage BLOB Provider](https://abp.io/community/articles/introducing-the-google-cloud-storage-blob-provider-yrt6azc0) by [Engincan Veske](https://twitter.com/EngincanVeske) +* [Switching Between Organization Units](https://abp.io/community/articles/switching-between-organization-units-i5tokpzt) by [Liming Ma](https://github.com/maliming) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community. + +## About the Next Version + +The next feature version will be 9.0. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-09-18-Blazor-9-New-Features/post.md b/docs/en/Community-Articles/2024-09-18-Blazor-9-New-Features/post.md index bc73c13210..1d78b493e4 100644 --- a/docs/en/Community-Articles/2024-09-18-Blazor-9-New-Features/post.md +++ b/docs/en/Community-Articles/2024-09-18-Blazor-9-New-Features/post.md @@ -2,8 +2,6 @@ In this article, I'll highlight .NET 9's Blazor updates and important features for ASP.NET Core 9.0. These features are based on the latest .NET 9 Preview 7. -![Cover](cover.png) - ## .NET MAUI Blazor Hybrid App and Web App solution template There's a new solution template to create .**NET MAUI native** and **Blazor web client** apps. This new template allows to choose a Blazor interactive render mode, it uses a shared Razor class library to maintain the UI's Razor components. diff --git a/docs/en/Community-Articles/2024-09-24-Angular-Difference-Btw-Promise-Observable/post.md b/docs/en/Community-Articles/2024-09-24-Angular-Difference-Btw-Promise-Observable/post.md index 39d722a293..9f8ae4c9d7 100644 --- a/docs/en/Community-Articles/2024-09-24-Angular-Difference-Btw-Promise-Observable/post.md +++ b/docs/en/Community-Articles/2024-09-24-Angular-Difference-Btw-Promise-Observable/post.md @@ -2,10 +2,6 @@ In this article, I will mention the differences between `Promise` and `Observable` . They are used in TypeScript (Angular) for handling async operations but have different use cases and behaviors. Let's see these six differences... -![Cover](cover.png) - - - ## 1. Eager or Lazy Evaluation - **Promise**: A `promise` is **eager**! This means that as soon as a `promise` is created, it executes the operation, like initiating immediately an HTTP request. **You can't control the execution start time; it begins right away!** diff --git a/docs/en/Community-Articles/2024-10-01-SignalR-9-New-Features/Post.md b/docs/en/Community-Articles/2024-10-01-SignalR-9-New-Features/Post.md index c004d45eba..c92e38f764 100644 --- a/docs/en/Community-Articles/2024-10-01-SignalR-9-New-Features/Post.md +++ b/docs/en/Community-Articles/2024-10-01-SignalR-9-New-Features/Post.md @@ -1,11 +1,6 @@ ### ASP.NET Core SignalR New Features — Summary - In this article, I’ll highlight the latest .**NET 9 SignalR updates** for ASP.NET Core 9.0. -![Cover](cover.png) - - - ### SignalR Hub Accepts Base Classes SignalR `Hub` class can now get a base class of a polymorphic class. As you see in the example below, I can send `Animal` to `Process` method. Before .NET 9, we could only pass the derived classes: `Cat` and `Dog`. diff --git a/docs/en/Community-Articles/2024-10-09-Cookies-vs-Local-Storage/Post.md b/docs/en/Community-Articles/2024-10-09-Cookies-vs-Local-Storage/Post.md index bac7f69596..b7122253ab 100644 --- a/docs/en/Community-Articles/2024-10-09-Cookies-vs-Local-Storage/Post.md +++ b/docs/en/Community-Articles/2024-10-09-Cookies-vs-Local-Storage/Post.md @@ -1,9 +1,5 @@ # When to Use Cookies, When to Use Local Storage? -![cover](cover.png) - - - ## Cookies vs Local Storage When you want to save client-side data on browsers, you can use `Cookies` or `Local Storage` of the browser. While these methods look similar, they have different behaviors. You need to decide based on the specific use-case, security concerns and the data size being stored. I'll clarify the differences between these methods. @@ -60,4 +56,4 @@ When you want to save client-side data on browsers, you can use `Cookies` or `Lo In many cases, you might use both cookies and local storage, depending on the specific requirements of different parts of your application. There are also other places where you can store the client-side data. You can check out [this article](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage) for more information. -Happy coding 🧑🏽‍💻 \ No newline at end of file +Happy coding 🧑🏽‍💻 diff --git a/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/Post.md b/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/Post.md index 67e451f0df..4710cc0a99 100644 --- a/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/Post.md +++ b/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/Post.md @@ -2,8 +2,6 @@ With every release, .NET becomes faster & faster! You get these improvements for free by just updating your project to the latest .NET! -![Cover Image](cover.png) - It’s very interesting that **20% of these improvements** are implemented by **open-source volunteers** rather than Microsoft employees. These improvements mostly focus on cloud-native and high-throughput applications. I’ll briefly list them below. ![From Microsoft Blog Post](cited-from-microsoft-blog-post.png) diff --git a/docs/en/Community-Articles/2024-10-10-join-abp-at-net-developerdays-2024-in-warsaw/3a159dc42380a0d65ce759e472f2ee36.jpg b/docs/en/Community-Articles/2024-10-10-join-abp-at-net-developerdays-2024-in-warsaw/3a159dc42380a0d65ce759e472f2ee36.jpg new file mode 100644 index 0000000000..56286ddec1 Binary files /dev/null and b/docs/en/Community-Articles/2024-10-10-join-abp-at-net-developerdays-2024-in-warsaw/3a159dc42380a0d65ce759e472f2ee36.jpg differ diff --git a/docs/en/Community-Articles/2024-10-10-join-abp-at-net-developerdays-2024-in-warsaw/3a159dc4edf425d98a235ee37c5a4e83.jpg b/docs/en/Community-Articles/2024-10-10-join-abp-at-net-developerdays-2024-in-warsaw/3a159dc4edf425d98a235ee37c5a4e83.jpg new file mode 100644 index 0000000000..d6d1e8d37d Binary files /dev/null and b/docs/en/Community-Articles/2024-10-10-join-abp-at-net-developerdays-2024-in-warsaw/3a159dc4edf425d98a235ee37c5a4e83.jpg differ diff --git a/docs/en/Community-Articles/2024-10-10-join-abp-at-net-developerdays-2024-in-warsaw/post.md b/docs/en/Community-Articles/2024-10-10-join-abp-at-net-developerdays-2024-in-warsaw/post.md new file mode 100644 index 0000000000..d905ec3eef --- /dev/null +++ b/docs/en/Community-Articles/2024-10-10-join-abp-at-net-developerdays-2024-in-warsaw/post.md @@ -0,0 +1,32 @@ +We are excited to announce that ABP will participate in the upcoming .NET DeveloperDays 2024, which will take place on **October 22-23** in beautiful Warsaw, Poland. As a **gold sponsor** of the event, we invite you to visit our booth and discover our latest innovations and solutions. + +## Event Highlights +.NET Developer Days is one of the premier conferences for .NET developers, featuring: +* **Over 1,000 attendees** from around the globe, including developers, engineers, and industry leaders. +* **50+ expert speakers** sharing insights on the latest trends and technologies in .NET development. +* **40+ sessions and workshops** covering various topics ensure something for everyone. + +## About .NET DeveloperDays +For those new to the scene, .NET DeveloperDays is a premier conference where software developers come together to explore various topics in the .NET ecosystem. This event actively brings together experts worldwide to share their knowledge on the latest technologies and best practices. Organized by a dedicated team passionate about advancing the .NET community, it’s a fantastic opportunity to learn, network, and connect with like-minded professionals in the software development field. + +## What to Expect at Our Booth +At our booth, you'll have the opportunity to: +* Engage with the ABP team and discuss how the ABP Framework can enhance your development projects. +* Discover exclusive surprises and experiences tailored for attendees. +* Network with fellow developers and share insights into best practices in .NET development. +The ABP.IO team is eager to connect with the community and explore the latest insights from the conference. Stay tuned for more updates as we prepare for this exciting event! + +Here are some previews from the events we sponsored before, so you know what to expect in .NET DeveloperDays 2024 in Warsaw: + +#### NDC London 2023: +![3a0d5e7c5833ae0ab6f3395339b17dd8.jpg](3a159dc42380a0d65ce759e472f2ee36.jpg) + +#### DevNot Summit 2022: +![3a0d5e7e6fba0856fb5444f7c63256af.jpg](3a159dc4edf425d98a235ee37c5a4e83.jpg) + +## Connect with Us +We look forward to meeting you at our booth! Make sure to stop by to learn more about our solutions and participate in the exciting surprises we have planned. + +## See You There! +Don’t miss this incredible opportunity to connect with the .NET community. Mark your calendars for **October 22-23**, and we hope to see you in **Warsaw**! +For more details about the event, visit the official .NET DeveloperDays website [here](https://developerdays.eu/warsaw/). \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/POST.md b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/POST.md index 9e996d2099..fe7b706b5a 100644 --- a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/POST.md +++ b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/POST.md @@ -2,8 +2,6 @@ In this article, I will compare [.NET Aspire](https://learn.microsoft.com/en-us/dotnet/aspire/) by [ABP Studio](https://abp.io/docs/latest/studio) by explaining their similarities and differences. -![cover](cover.png) - ## Introduction While .NET Aspire and ABP Studio are tools for different purpose with different scope and they have different approaches to solve the problems, many developers still may confuse since they also have some similar functionalities and solves some common problems. diff --git a/docs/en/Community-Articles/2024-10-17-join-abp-at-the-net-conf-2024/post.md b/docs/en/Community-Articles/2024-10-17-join-abp-at-the-net-conf-2024/post.md new file mode 100644 index 0000000000..1e44ccd9c5 --- /dev/null +++ b/docs/en/Community-Articles/2024-10-17-join-abp-at-the-net-conf-2024/post.md @@ -0,0 +1,27 @@ +ABP is excited to sponsor the 14th annual [.NET Conf](https://www.dotnetconf.net/)! We've proudly supported the .NET community for years and recognize the importance of this premier virtual event. Mark your calendars for November 12-14, 2024, and join us for 3 incredible days of learning, networking, and fun. We invite you to be a part of this celebration and explore the latest advancements in the .NET ecosystem. + +*Important News🚀 ABP Team Lead, Halil İbrahim Kalkan, will be a speaker on Day 3, discussing how to build modular monolith applications.* + +## About the Event + +.NET Conf is a significant virtual event in the world of .NET development, attracting a large global audience. This 3-day conference features a packed schedule with a variety of offerings: + +* Day One: Dedicated to the latest version of .NET, .NET 9, and includes presentations by the .NET team about its new features. +* Day Two: Offers a more in-depth look at the capabilities of .NET and begins a 24-hour continuous broadcast of sessions. +* Day Three: Continues the 24-hour broadcast, featuring speakers from all over the world presenting in their respective time zones. + +### What to Expect +* Live sessions throughout the conference with speakers from both the .NET team and the broader .NET community. +* Interactive elements like live Q&A sessions on Twitter and engagement opportunities on Twitch. +* Virtual attendee parties with trivia games and prizes give the conference a fun, social element. +* The Student Zone caters specifically to beginners in .NET development. + +As a purely virtual event since its inception, .NET Conf has grown to draw over 100,000 live viewers and supports hundreds of local events around the world. This year marks the 14th iteration of the conference. + +For more details, be sure to check out the full agenda [here](https://www.dotnetconf.net/agenda). 📅 + +## Win an ABP License! +We're excited to sponsor CodeParty and Swag Bag at this year's .NET Conf! We'll give away a team license and 25 personal licenses to lucky attendees. Don't miss your chance to win 🎉 + +We look forward to seeing you at .NET Conf and can’t wait to connect with the global .NET community! + diff --git a/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/post.md b/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/post.md index 2a75a97df3..bc8bd691b5 100644 --- a/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/post.md +++ b/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/post.md @@ -1,9 +1,5 @@ # ABP Now Supports .NET 9 -![Cover image](cover.png) - - - **.NET 9.0.100-rc.2** has been released on **October 8, 2024**. To align with the latest .NET, we also released the ABP Platform [9.0.0-rc.1](https://github.com/abpframework/abp/releases/tag/9.0.0-rc.1) version. **With this release, ABP now supports .NET 9.** diff --git a/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfa21c2faf9913de8f5443660fa.png b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfa21c2faf9913de8f5443660fa.png new file mode 100644 index 0000000000..32f6d01edb Binary files /dev/null and b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfa21c2faf9913de8f5443660fa.png differ diff --git a/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfa610aa504fb1416a2546b6a8a.png b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfa610aa504fb1416a2546b6a8a.png new file mode 100644 index 0000000000..95b999560e Binary files /dev/null and b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfa610aa504fb1416a2546b6a8a.png differ diff --git a/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfa959101255e1a85f541ce4614.png b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfa959101255e1a85f541ce4614.png new file mode 100644 index 0000000000..4d329ccc7b Binary files /dev/null and b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfa959101255e1a85f541ce4614.png differ diff --git a/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfabbc1464978d26844d3cb9207.png b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfabbc1464978d26844d3cb9207.png new file mode 100644 index 0000000000..37ddf06eb4 Binary files /dev/null and b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfabbc1464978d26844d3cb9207.png differ diff --git a/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfad838c45d58e8d5902469b414.jpg b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfad838c45d58e8d5902469b414.jpg new file mode 100644 index 0000000000..eb9fe26dfd Binary files /dev/null and b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfad838c45d58e8d5902469b414.jpg differ diff --git a/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfafbaa2c6adf6c9f32a366ca1f.jpg b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfafbaa2c6adf6c9f32a366ca1f.jpg new file mode 100644 index 0000000000..1210f13283 Binary files /dev/null and b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/3a15cbfafbaa2c6adf6c9f32a366ca1f.jpg differ diff --git a/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/post.md b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/post.md new file mode 100644 index 0000000000..9e22660332 --- /dev/null +++ b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/post.md @@ -0,0 +1,219 @@ +Today, we are happy to release the [ABP](https://abp.io/) version **9.0 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 v9.0! Thanks to all of you. + +## Get Started with the 9.0 RC + +You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli). + +By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI: + +![studio-switch-to-preview.png](3a15cbfa21c2faf9913de8f5443660fa.png) + +## Migration Guide + +There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v8.x: [ABP Version 9.0 Migration Guide](https://abp.io/docs/9.0/release-info/migration-guides/abp-9-0) + +## What's New with ABP v9.0? + +In this section, I will introduce some major features released in this version. +Here is a brief list of titles explained in the next sections: + +* Upgraded to .NET 9.0 +* Introducing the **Extension Property Policy** +* Allow wildcards for Redirect Allowed URLs +* Docs Module: Show larger images on the same page +* Google Cloud Storage BLOB Provider +* Removed React Native mobile option from free templates +* Suite: Better naming for multiple navigation properties to the same entity +* CMS Kit Pro: Feedback feature improvements + +### Upgraded to .NET 9.0 + +We've upgraded ABP to .NET 9.0, so you need to move your solutions to .NET 9.0 if you want to use ABP 9.0. You can check [Microsoft’s Migrate from ASP.NET Core 8.0 to 9.0 documentation](https://learn.microsoft.com/en-us/aspnet/core/migration/80-90), to see how to update an existing ASP.NET Core 8.0 project to ASP.NET Core 9.0. + +> **Note:** Since the stable version of .NET 9 hasn't been released yet, we upgraded ABP to .NET v9.0-rc.2. We will update the entire ABP Platform to .NET 9 stable, after Microsoft releases it on November 13-14 with the stable ABP 9.0 release. + +### Introducing the Extension Property Policy + +ABP provides a module entity extension system, which is a high level extension system that allows you to define new properties for existing entities of the dependent modules. This is a powerful way to dynamically add additional properties to entities without modifying the core structure. However, managing these properties across different modules and layers can become complex, especially when different policies or validation rules are required. + +**Extension Property Policy** feature allows developers to define custom policies for these properties, such as access control, validation, and data transformation, directly within ABP. + +**Example:** + +```csharp +ObjectExtensionManager.Instance.Modules().ConfigureIdentity(identity => +{ + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( //property type: string + "SocialSecurityNumber", //property name + property => + { + //validation rules + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4}); + + //Global Features + property.Policy.GlobalFeatures = new ExtensionPropertyGlobalFeaturePolicyConfiguration() + { + Features = new[] {"GlobalFeatureName1", "GlobalFeatureName2"}, + RequiresAll = true + }; + + //Features + property.Policy.Features = new ExtensionPropertyFeaturePolicyConfiguration() + { + Features = new[] {"FeatureName1", "FeatureName2"}, + RequiresAll = false + }; + + //Permissions + property.Policy.Permissions = new ExtensionPropertyPermissionPolicyConfiguration() + { + PermissionNames = new[] {"AbpTenantManagement.Tenants.Update", "AbpTenantManagement.Tenants.Delete"}, + RequiresAll = true + }; + } + ); + }); +}); +``` + +### Allow Wildcards for RedirectAllowedURLs + +In this version, we made an improvement to the `RedirectAllowedUrls` configuration, which now allows greater flexibility in defining redirect URLs. Previously, developers faced restrictions when configuring URL redirects. Specifically, the `RedirectAllowedUrls` did not support using **wildcards (*)**, limiting how developers could specify which URLs were permissible for redirects. + +With the new changes in [#20628](https://github.com/abpframework/abp/pull/20628), the restriction has been relaxed, allowing developers to define redirect URLs that include wildcards. This makes it easier to handle scenarios where a broad range of URLs need to be allowed, without explicitly listing each one. + +```json +{ + "App": { + //... + "RedirectAllowedUrls": "http://*.domain,http://*.domain:4567" + } +``` + +### Docs Module: Show Larger Images + +As developers, we rely heavily on clear documentation to understand complex concepts and workflows. Often, an image is worth more than a thousand words, especially when explaining intricate user interfaces, workflows, or code structures. In recognition of this, we recently rolled out an improvement to the Docs Module that enables larger images to be displayed more effectively. + +![docs-image-larger.png](3a15cbfa610aa504fb1416a2546b6a8a.png) + +Before this enhancement, images embedded in documentation were often limited in size, which sometimes made it difficult to see the details in the diagrams, screenshots, or other visual contents. Now, images can be displayed at a larger size, offering better clarity and usability. + +> See [https://github.com/abpframework/abp/pull/20557](https://github.com/abpframework/abp/pull/20557) for more information. + +### Google Cloud Storage BLOB Provider + +ABP provides a BLOB Storing System, which allows you to work with BLOBs. This system is typically used to store file contents in a project and read these file contents when they are needed. Since ABP provides an abstraction to work with BLOBs, it also provides some pre-built storage providers such as [Azure](https://abp.io/docs/latest/framework/infrastructure/blob-storing/azure), [Aws](https://abp.io/docs/latest/framework/infrastructure/blob-storing/aws) and [Aliyun](https://abp.io/docs/latest/framework/infrastructure/blob-storing/aliyun). + +In this version, we have introduced a new BLOB Storage Provider for Google Cloud Storage: [`Volo.Abp.BlobStoring.Google`](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Google) + +You can [read the documentation](https://abp.io/docs/9.0/framework/infrastructure/blob-storing/google) for configurations and use Google Cloud Storage as your BLOB Storage Provider easily. + +### Removed React Native Mobile Option From Free Templates + +In this version, we removed the **React Native** mobile option from the open source templates due to maintaining reasons. We updated the related documents and the ABP CLI (both old & new CLI) for this change, and with v9.0, you will not be able to create a free template with react-native as the mobile option. + +> **Note:** Pro templates still provide the **React Native** as the mobile option and we will continue supporting it. + +If you want to access the open-source React-Native template, you can visit the abp-archive repository from [here](https://github.com/abpframework/abp-archive). + +### Suite: Better Naming For Multiple Navigation Properties + +Prior to this version, when you defined multiple (same) navigation properties to same entity, then ABP Suite was renaming them with a duplicate number. + +As an example,let's assume that you have a book with an author and coauthor, prior to this version ABP Suite was creating a DTO class as below: + +```csharp +public class BookWithNavigationPropertiesDto +{ + public BookDto Book { get; set; } + + public AuthorDto Author { get; set; } + + public AuthorDto Author1 { get; set; } +} +``` + +Notice, that since the book entity has two same navigation properties, ABP Suite renamed them with a duplicate number. In this version, ABP Suite will ask you to define a propertyName for the **navigation properties** and you'll be able to specify a meaningful name such as (*CoAuthor*, in this example): + +```csharp +public class BookWithNavigationPropertiesDto +{ + public BookDto Book { get; set; } + + public AuthorDto Author { get; set; } + + //used the specified property name + public AuthorDto CoAuthor { get; set; } +} +``` + +ABP Suite respects the specified property name for the related navigation property and generates codes regarding that (by removing the *Id* postfix for the related places): + +![suite-navigation-properties.png](3a15cbfa959101255e1a85f541ce4614.png) + +### CMS Kit Pro: Feedback Feature Improvements + +In this version, we revised the [CMS Kit's Feedback Feature](https://abp.io/docs/9.0/modules/cms-kit-pro/page-feedback) and as a result, we made the following improvements: + +* A new **auto-handle** setting has been added to the settings page. When this feature is enabled, if feedback is submitted without a user note, the feedback is automatically marked as handled. +* You can now require users to enter a note when submitting negative feedback. This can be configured in the settings page, ensuring that users provide context when they submit critical feedback. +* We've added a feedback user ID that is saved in local storage. This allows you to track the number of unique users submitting feedback or determine if the same user is sending new feedback on updated documents. + +> For further information about the Page Feedback System, please refer to the [documentation](https://abp.io/docs/9.0/modules/cms-kit-pro/page-feedback). + +## Community News + +### Join ABP at the .NET Conf 2024! + +ABP is excited to sponsor the [14th annual .NET Conf](https://www.dotnetconf.net/)! We've proudly supported the .NET community for years and recognize the importance of this premier virtual event. Mark your calendars for November 12-14, 2024, and join us for 3 incredible days of learning, networking, and fun. + +![dotnet-conf-2024.png](3a15cbfabbc1464978d26844d3cb9207.png) + +Also, don't miss out on the co-founder of [Volosoft](https://volosoft.com/) and Lead Developer of [ABP](https://abp.io/), [Halil Ibrahim Kalkan](https://x.com/hibrahimkalkan)'s talk about "Building Modular Monolith Applications with ASP.NET Core and ABP Studio" at 10:00 - 10:30 AM GMT+3 on Thursday, November 14. + +### ABP Team Attended the .NETDeveloperDays 2024 + +We are thrilled to announce that we sponsored the [.NETDevelopersDays 2024](https://developerdays.eu/warsaw/) event. It's one of the premier conferences for .NET developers with **over 1.000 attendees**, **50+ expert speakers**, and **40+ sessions and workshops**. + +![dotnet-developer-days-2024.jpg](3a15cbfad838c45d58e8d5902469b414.jpg) + +Core team members of the ABP Framework, [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan), [İsmail Çağdaş](https://x.com/ismcagdas), [Enis Necipoğlu](https://x.com/EnisNecipoglu), and [Tarık Özdemir](https://x.com/mtozdemir) attended [.NETDevelopersDays 2024](https://developerdays.eu/warsaw/) on October 22-23, 2024 at Warsaw, Poland. + +These 2 days with the team were all about chatting and having fun with amazing attendees and speakers. We met with talented and passionate software developers and introduced the [ABP](https://github.com/abpframework/abp) - web application framework built on ASP.NET Core - to them. + +Also, we made a raffle and gifted an Xbox Series S to the lucky winner at the event: + +![abp-team-raffle.jpg](3a15cbfafbaa2c6adf6c9f32a366ca1f.jpg) + +Thanks to everyone who joined the fun and visited our booth :) + +### New ABP Community Articles + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Alper Ebiçoğlu](https://twitter.com/alperebicoglu) has created **five** new community articles: + * [When to Use Cookies, When to Use Local Storage?](https://abp.io/community/articles/when-to-use-cookies-when-to-use-local-storage-uexsjunf) + * [.NET 9 Performance Improvements Summary](https://abp.io/community/articles/.net-9-performance-improvements-summary-gmww3gl8) + * [ASP.NET Core SignalR New Features — Summary](https://abp.io/community/articles/asp.net-core-signalr-new-features-summary-kcydtdgq) + * [Difference Between "Promise" and "Observable" in Angular](https://abp.io/community/articles/difference-between-promise-and-observable-in-angular-bxv97pkc) + * [ASP.NET Core Blazor 9.0 New Features Summary 🆕](https://abp.io/community/articles/asp.net-core-blazor-9.0-new-features-summary--x0fovych) +* [Mohammad AlMohammad AlMahmoud](https://abp.io/community/members/Mohammad97Dev) has created **two** new community articles: + * [Implementing Multi-Language Functionality With ABP Framework](https://abp.io/community/articles/implementing-multilanguage-functionality-with-abp-framework-loq7kfx4) + * [Configure Quartz.Net in Abp FrameWork](https://abp.io/community/articles/configure-quartz.net-in-abp-framework-3bveq4y1) +* [.NET Aspire vs ABP Studio: Side by Side](https://abp.io/community/articles/.net-aspire-vs-abp-studio-side-by-side-t1c73d1l) by [Halil İbrahim Kalkan](https://twitter.com/hibrahimkalkan) +* [PoC of using GrapesJS for ABPs CMS Kit](https://abp.io/community/articles/poc-of-using-grapesjs-for-abps-cms-kit-1rmv4q41) by [Jack Fistelmann](https://abp.io/community/members/jfistelmann) +* [ABP-Powered Web App with Inertia.js, React, and Vite](https://abp.io/community/articles/abppowered-web-app-with-inertia.js-react-and-vite-j7cccvad) by [Anto Subash](https://antosubash.com/) +* [Multi-Tenancy Support in Angular Apps with ABP.IO](https://abp.io/community/articles/multitenancy-support-in-angular-apps-with-abp.io-lw9l36c5) by [HeadChannel Team](https://headchannel.co.uk/) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community. + +## Conclusion + +This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://abp.io/docs/9.0/release-info/road-map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v9.0 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-10-28-event-recap-abp-community-talks-20246/post.md b/docs/en/Community-Articles/2024-10-28-event-recap-abp-community-talks-20246/post.md new file mode 100644 index 0000000000..4a3093ea66 --- /dev/null +++ b/docs/en/Community-Articles/2024-10-28-event-recap-abp-community-talks-20246/post.md @@ -0,0 +1,104 @@ +Watch Full Video: https://www.youtube.com/watch?v=5_pGF42dDoE + +**Key Speakers:** + +* **Alper Ebicoglu:** ABP Core Team, provided updates on the ABP Framework and community contributions. +* **Halil İbrahim Kalkan:** ABP Core Team, presented on modular system design and implementation with ABP Framework. +* **Ariful Islam:** Co-founder and COO of Wafi Solutions, shared insights on using ABP in real-world projects. + +*** +**I. ABP Community News (Alper Ebicoglu)** + +* Highlighted recent articles on the ABP Community platform covering topics like: +* Multilanguage functionality in ABP Framework. +* Cookies vs. local storage in web applications. +* .NET 9 features and ABP Framework compatibility. +* Integration of ABP with Inertia.js, React, and Vite. +* SignalR enhancements in .NET 9. +* Announced the release of ABP Framework version 8.3 with numerous bug fixes and improvements. +* Recognized top contributors to the ABP Community platform. + +*** +**II. Modular Monolith Application Development (Halil İbrahim Kalkan)** + +**A. Why Modularity?** + +* **Reducing and managing code complexity:** Enables parallel development, simplifies code maintenance, and allows for easier onboarding of new developers. +* **Modular deployment:** Allows customized deployments based on client needs, including or excluding specific modules. +* **Microservice migration:** Provides a foundation for future migration to a microservice architecture. + +**B. Module Types:** + +* **Business Modules:** Core functionalities directly related to the application’s business logic. +* **Aggregator Modules:** Combine data from multiple modules, typically for reporting or dashboards. +* **Infrastructure Modules:** Provide shared functionalities like settings management, permission management, background jobs, etc. +* **Generic Modules:** Offer cross-cutting concerns like audit logging, GDPR compliance, etc. + +**C. Architectural Considerations:** + +* **Database:** Single database: Easier for reporting and transactions, with potential scaling limitations. +* **Separate databases:** Improved data isolation, scalability, and more complex reporting and transactions. +* **Codebase:** Single solution: Easier for small teams and rapid development, potential for tighter coupling. +* **Separate solutions:** Encourages module isolation and increased complexity for multi-module development. +* **Monorepo vs. multirepo:** Monorepo simplifies versioning and deployment, while multirepo allows for more independent development. +* **User Interface:** + * **Unified UI:** Simpler to develop pages utilizing multiple modules, less modular UI. + * **Modular UI:** Promotes UI module isolation and challenges in integrating UI across modules. + * **Component-based UI:** Balances modularity with cross-module integration. + +**D. Module Integration:** + +* **Dependencies:** Modules should depend on each other’s contracts (interfaces, DTOs, events), not implementations. +* **Communication patterns:** Direct API calls are suitable for read operations and prioritize caching. +* **Integration events:** Best for side effects triggered by changes in one module affecting another. + +**E. ABP Framework Tutorial:** + +* Demonstrated a step-by-step tutorial available on the ABP Framework website, covering: +* Creating a new solution with ABP Studio. +* Building modules with DDD principles. +* Implementing module integration using services and events. +* Performing database operations across modules. + +*** +**III. Real-World ABP Experiences (Ariful Islam)** + +* Shared experiences from using ABP Framework for various projects, including large-scale SaaS applications. +* Highlighted the benefits of ABP in addressing challenges like: +* Multi-tenancy implementation. +* Supporting both cloud and on-premise deployments. +* Implementing recurring payments with Stripe. +* Building modular applications tailored to diverse customer needs. +* Emphasized the value of ABP’s: +* Pre-built modules and features (multi-tenancy, roles, settings, identity). +* DDD implementation and architectural guidance. +* Documentation and open-source projects as learning resources. +* Customization capabilities through extension methods and data filters. + +*** +**IV. Q&A Session** + +* Addressed various community questions, including: +* Creating projects with multiple modules and Angular UI. +* Availability of simplified module templates. +* Choosing between modular monolith and single-layered architecture. +* Security controls are available in ABP Framework. +* Plans to move away from jQuery in ABP’s UI. + +*** +**V. Key Takeaways:** + +* ABP Framework provides a robust foundation for building modular monolith applications with .NET. +* Modularity offers significant advantages for managing complexity, enabling flexible deployment, and easing potential microservice migration. +* The ABP Framework community is active and offers valuable resources for learning and sharing experiences. +* The ABP team continuously evolves the framework, adds new features, and addresses community needs. + +**Quotes:** + +> “I honestly did not find any alternative to ABP for SaaS applications. It is very easy to get started.” — Ariful Islam. + +> “ABP provides us with nice architecture and nice documentation. We learn a lot from ABP documentation and the projects.” — Ariful Islam. + +> “ABP Studio is not a replacement for ABP Suite. You can use ABP Suite to create CRUD pages, and it’s inside ABP Studio.” — Alper Ebicoglu. + +This briefing document provides an overview of the key discussions and insights from the ABP Community Talks. For more detailed information, it is recommended that you review the full recording and access the resources mentioned. \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3cde67065ed071a042e44ce0d13.jpeg b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3cde67065ed071a042e44ce0d13.jpeg new file mode 100644 index 0000000000..8682ca4a08 Binary files /dev/null and b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3cde67065ed071a042e44ce0d13.jpeg differ diff --git a/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3ce8cf18f4a1b72e06a87567a78.jpeg b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3ce8cf18f4a1b72e06a87567a78.jpeg new file mode 100644 index 0000000000..f3e96339da Binary files /dev/null and b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3ce8cf18f4a1b72e06a87567a78.jpeg differ diff --git a/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3cf48ca345072f98110818ab66c.jpeg b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3cf48ca345072f98110818ab66c.jpeg new file mode 100644 index 0000000000..6185e1bb0a Binary files /dev/null and b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3cf48ca345072f98110818ab66c.jpeg differ diff --git a/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3cfecfed99d1d25920ffab494f7.jpeg b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3cfecfed99d1d25920ffab494f7.jpeg new file mode 100644 index 0000000000..705c2b4775 Binary files /dev/null and b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3cfecfed99d1d25920ffab494f7.jpeg differ diff --git a/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3d0e32368c765310f0cc76f72b0.jpeg b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3d0e32368c765310f0cc76f72b0.jpeg new file mode 100644 index 0000000000..9473fd16ea Binary files /dev/null and b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/3a15e3d0e32368c765310f0cc76f72b0.jpeg differ diff --git a/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/post.md b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/post.md new file mode 100644 index 0000000000..6fb8098135 --- /dev/null +++ b/docs/en/Community-Articles/2024-10-28-event-recap-net-developer-days-2024/post.md @@ -0,0 +1,27 @@ +The ABP team has just returned from an incredible experience at .NET DeveloperDays 2024, and we’re thrilled to share the highlights of this fantastic event! In past years, we attended the conference as participants and had such a great time that we decided to take it a step further by sponsoring this year. As a gold sponsor for 2024, it was an unforgettable experience to engage with the vibrant .NET community in Warsaw. The energy at the event was terrific, and the opportunity to connect with developers, engineers, and industry leaders made it truly special. + +![WhatsApp Image 2024-10-23 at 10.18.45.jpeg](3a15e3cde67065ed071a042e44ce0d13.jpeg) + +## Event Highlights + +With over 800 attendees and more than 30 inspiring speakers, .NET DeveloperDays 2024 was a hub of knowledge-sharing, innovation, and networking. The two-day main conference focused entirely on .NET, providing a unique space for developers from around the world to come together, share insights, and grow collectively. + +![WhatsApp Image 2024-10-22 at 16.41.44.jpeg](3a15e3ce8cf18f4a1b72e06a87567a78.jpeg) + +.NET DeveloperDays 2024 showcased an outstanding lineup of speakers, offering a well-balanced mix of both advanced and foundational topics for .NET developers. Attendees had the chance to dive deep into cutting-edge advancements in .NET and C# with Johnny Hooyberghs, explore the curious and often tricky aspects of C# in Nick Chapsas’ engaging session, "Cursed C#," and discover best practices for clean microservices communication using CQRS and event sourcing with Oliver Sturm. These sessions, along with over 30 others, offered invaluable learning and networking opportunities for developers eager to stay ahead in the fast-moving .NET ecosystem. + +![WhatsApp Image 2024-10-23 at 13.08.45.jpeg](3a15e3cf48ca345072f98110818ab66c.jpeg) + +We were fortunate to engage with developers from diverse backgrounds, discuss the exciting work we do at ABP, and exchange ideas. This conference has reinforced the importance of learning and growing together with the community. + +![WhatsApp Image 2024-10-23 at 12.11.53.jpeg](3a15e3cfecfed99d1d25920ffab494f7.jpeg) + +The experience was inspiring, not only because of the innovative sessions but also because of the amazing people we met. + +## Raffle Tradition +As is tradition, we held a raffle at the event. Congratulations to the lucky winner, and thank you to everyone who participated! + +![WhatsApp Image 2024-10-23 at 14.20.25.jpeg](3a15e3d0e32368c765310f0cc76f72b0.jpeg) + +## A Special Thank You +A huge thank you to everyone who stopped by our booth, and spent time with our amazing team. We look forward to continuing this journey with the .NET community! diff --git a/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/post.md b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/post.md index 3e950c38c0..f257577ac2 100644 --- a/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/post.md +++ b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/post.md @@ -1,8 +1,6 @@ Built-in OpenAPI Document Generation with .NET 9 — No more SwaggerUI! 👋 ======================================================================== -![Cover](cover.png) - What’s Swagger UI? ------------------ diff --git a/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/3a16616d10340c7e12d1e7b47aff921f.png b/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/3a16616d10340c7e12d1e7b47aff921f.png new file mode 100644 index 0000000000..30883ebf92 Binary files /dev/null and b/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/3a16616d10340c7e12d1e7b47aff921f.png differ diff --git a/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/3a16616d38e49ac84cbb0b8628adccf6.png b/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/3a16616d38e49ac84cbb0b8628adccf6.png new file mode 100644 index 0000000000..7263b68e10 Binary files /dev/null and b/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/3a16616d38e49ac84cbb0b8628adccf6.png differ diff --git a/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/post.md b/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/post.md new file mode 100644 index 0000000000..30ff978de6 --- /dev/null +++ b/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/post.md @@ -0,0 +1,89 @@ +Today, [ABP](https://abp.io/) 9.0 stable version has been released based on [.NET 9.0](https://dotnet.microsoft.com/en-us/download/dotnet/9.0). You can create solutions with ABP 9.0 starting from ABP Studio v0.9.11 or using the ABP CLI as explained in the following sections. + +## What's New With Version 9.0? + +All the new features were explained in detail in the [9.0 RC Announcement Post](https://abp.io/blog/announcing-abp-9-0-release-candidate), so there is no need to review them again. You can check it out for more details. + +## Getting Started with 9.0 + +### Creating New Solutions + +You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli) to create new solutions. + +By default, ABP Studio uses stable versions to create solutions. Therefore, it will be creating the solution with the latest stable version, which is v9.0 for now, so you don't need to specify the version. **You can create solutions with ABP 9.0 starting from v0.9.11.** + +### How to Upgrade an Existing Solution + +You can upgrade your existing solutions with either ABP Studio or ABP CLI. In the following sections, both approaches are explained: + +### Upgrading via ABP Studio + +If you are already using the ABP Studio, you can upgrade it to the latest version to align it with ABP v9.0. ABP Studio periodically checks for updates in the background, and when a new version of ABP Studio is available, you will be notified through a modal. Then, you can update it by confirming the opened modal. See [the documentation](https://abp.io/docs/latest/studio/installation#upgrading) for more info. + +After upgrading the ABP Studio, then you can open your solution in the application, and simply click the **Switch to stable** action button to instantly upgrade your solution: + +![switch-to-stable.png](3a16616d10340c7e12d1e7b47aff921f.png) + +> Please note that ABP CLI & ABP Studio only upgrade the related ABP packages, so you need to upgrade the other packages for .NET 9.0 manually. + +### Upgrading via ABP CLI + +Alternatively, you can upgrade your existing solution via ABP CLI. First, you need to install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet, you can run the following command: + +```bash +dotnet tool install -g Volo.Abp.Studio.Cli +``` + +Or to update the existing CLI, you can run the following command: + +```bash +dotnet tool update -g Volo.Abp.Studio.Cli +``` + +After installing/updating the ABP CLI, you can use the [`update` command](https://abp.io/docs/latest/CLI#update) to update all the ABP related NuGet and NPM packages in your solution as follows: + +```bash +abp update +``` + +You can run this command in the root folder of your solution to update all ABP related packages. + +> Please note that ABP CLI & ABP Studio only upgrade the related ABP packages, so you need to upgrade the other packages for .NET 9.0 manually. + +## Migration Guides + +There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v8.x: [ABP Version 9.0 Migration Guide](https://abp.io/docs/9.0/release-info/migration-guides/abp-9-0) + +## Community News + +### ABP Community Talks 2024.7: What’s New with .NET 9 & ABP 9? + +![community-talks.png](3a16616d38e49ac84cbb0b8628adccf6.png) + +In this episode of ABP Community Talks, 2024.7; we will dive into the features that came with .NET 9.0 with [Alper Ebicoglu](https://github.com/ebicoglu), [Engincan Veske](https://github.com/EngincanV), [Berkan Sasmaz](https://github.com/berkansasmaz) and [Ahmet Faruk Ulu](https://github.com/ahmetfarukulu). + +### Highlights from .NET 9.0 + +Our team has closely followed the ASP.NET Core and Entity Framework Core 9.0 releases, read Microsoft's guides and documentation, and adapted the changes to our ABP.IO Platform. We are proud to say that we've shipped the ABP 9.0 based on .NET 9.0 just after Microsoft's .NET 9.0 release. + +In addition to the ABP's .NET 9.0 upgrade, our team has created many great articles to highlight the important features coming with ASP.NET Core 9.0 and Entity Framework Core 9.0. + +> You can read [this post](https://volosoft.com/blog/Highlights-for-ASP-NET-Entity-Framework-Core-NET-9-0) to see the list of all articles. + +### New ABP Community Articles + +In addition to [the articles to highlight .NET 9.0 features written by our team](https://volosoft.com/blog/Highlights-for-ASP-NET-Entity-Framework-Core-NET-9-0), here are some of the recent posts added to the [ABP Community](https://abp.io/community): + +* [Video: Building Modular Monolith Applications with ASP.NET Core & ABP Studio](https://abp.io/community/videos/building-modular-monolith-applications-with-asp.net-core-abp-studio-66znukvf) by [Halil İbrahim Kalkan](https://x.com/hibrahimkalkan) +* [How to create your Own AI Bot on WhatsApp Using an ABP.io Template](https://abp.io/community/articles/how-to-create-your-own-ai-bot-on-whatsapp-using-the-abp-framework-c6jgvt9c) by [Michael Kokula](https://abp.io/community/members/Michal_Kokula) +* [ABP Now Supports .NET 9](https://abp.io/community/articles/abp-now-supports-.net-9-zpkznc4f) by [Alper Ebiçoğlu](https://x.com/alperebicoglu) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community. + +## 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/9.0/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v9.0 and provide feedback to help us release more stable versions. + +Thanks for being a part of this community! diff --git a/docs/en/Community-Articles/2024-11-21-unlock-exclusive-savings-with-abps-black-friday-campaign/post.md b/docs/en/Community-Articles/2024-11-21-unlock-exclusive-savings-with-abps-black-friday-campaign/post.md new file mode 100644 index 0000000000..780979b737 --- /dev/null +++ b/docs/en/Community-Articles/2024-11-21-unlock-exclusive-savings-with-abps-black-friday-campaign/post.md @@ -0,0 +1,28 @@ +The season of deals is here, and we're excited to announce our Black Friday campaign packed with exclusive offers you won’t want to miss. Whether you're an existing customer or new to our products, this is your chance to maximize your savings and enhance your experience with our solutions. + +#### 📅 **Campaign Dates** + +Mark your calendars! The Black Friday campaign is live from **November 25 to December 2**. +Don’t miss this limited-time opportunity to take your software to the next level. + +#### 🔥 **What's Included?** + +Here’s why this campaign is unmissable: + +**Open to Everyone:** This campaign is available for both new and existing customers. + +**Stack Your Savings:** Combine this offer with our multi-year discounts for even greater value. + +**Flexible Upgrades:** Thinking about upgrading to a higher package? Now’s the perfect time! + +**More Developer Seats?** *No Problem!* Additional developer seats are also eligible under this campaign, so you can grow your team effortlessly. + +#### 💡 **Why Act Now?** + +Take advantage of this campaign to unlock advanced features, expand your team, or upgrade your plan while saving big. These offers won’t last forever—secure your savings before the campaign ends on December 2! + +### [Don't wait! Visit our pricing page to learn more.](https://abp.io/pricing?utm_source=abpwebsite&utm_medium=referral&utm_campaign=bf24blog) + +*** + +Stay tuned for more updates and exclusive content by subscribing to our newsletter below. \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-12-01-OpenAI-Integration/POST.md b/docs/en/Community-Articles/2024-12-01-OpenAI-Integration/POST.md index c07509d2e3..830f0d094a 100644 --- a/docs/en/Community-Articles/2024-12-01-OpenAI-Integration/POST.md +++ b/docs/en/Community-Articles/2024-12-01-OpenAI-Integration/POST.md @@ -2,8 +2,6 @@ In this article, I will show you how to integrate and use the [OpenAI API](https://github.com/openai/openai-dotnet?tab=readme-ov-file#getting-started) with the [ABP Framework](https://abp.io/). We will explore step-by-step how these technologies can work together to enhance your application with powerful AI capabilities, such as natural language processing, image generation, and more. -![cover-image](cover-image.png) - ## Creating an ABP Project To begin integrating OpenAI API with ABP Framework, you first need to create an ABP project. Follow these steps to create and set up your ABP project: @@ -62,6 +60,8 @@ dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease > Replace the value of the `Key` with your OpenAI API key. +> **Important Security Note**: Storing sensitive information like API keys in `appsettings.json` is not recommended due to security concerns. Please refer to the [official Microsoft documentation](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets) for secure secret management best practices. + Next, add the following code to the `ConfigureServices` method in `OpenAIIntegrationBlazorModule`: ```csharp @@ -382,4 +382,4 @@ To showcase the integration of the OpenAI API with the ABP Framework, we impleme ## Conclusion -In this article, we covered how to integrate the OpenAI API with the ABP Framework by creating a sample project, setting up the OpenAI services, and implementing examples for conversational AI, knowledge-based assistance, and image generation. By following these steps, you can add powerful AI-driven capabilities to your application, making it more interactive, intelligent, and capable of meeting user needs effectively. \ No newline at end of file +In this article, we covered how to integrate the OpenAI API with the ABP Framework by creating a sample project, setting up the OpenAI services, and implementing examples for conversational AI, knowledge-based assistance, and image generation. By following these steps, you can add powerful AI-driven capabilities to your application, making it more interactive, intelligent, and capable of meeting user needs effectively. diff --git a/docs/en/Community-Articles/2024-12-16-abp-studio-goes-aot-faster-startups-with-ready-to-run-r2r-publishing/post.md b/docs/en/Community-Articles/2024-12-16-abp-studio-goes-aot-faster-startups-with-ready-to-run-r2r-publishing/post.md new file mode 100644 index 0000000000..5bf7b9e181 --- /dev/null +++ b/docs/en/Community-Articles/2024-12-16-abp-studio-goes-aot-faster-startups-with-ready-to-run-r2r-publishing/post.md @@ -0,0 +1,65 @@ +We're excited that [ABP Studio](https://abp.io/studio) now supports [Ready-to-Run (R2R) publishing](https://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run) (starting from v0.9.16+), a hybrid form of ahead-of-time (AOT) compilation. This enhancement significantly improves the startup time and overall performance of ABP Studio, making it faster and more performant than ever before. + +Let's dive into what R2R publishing is, how it works, and the benefits it brings to ABP Studio. + +## What is Ready-to-Run (R2R) Publishing? + +Ready-to-Run (R2R) is a form of AOT compilation available in the .NET ecosystem. Unlike traditional just-in-time (JIT) compilation, R2R precompiles parts of your application to native code before deployment. This precompiled code helps reduce the startup time by minimizing the work needed during runtime. + +However, R2R isn't a complete AOT compilation. Instead, it's a hybrid approach because it stores both: + +* **Native code for precompiled methods** (to improve startup time and performance) + +* **Intermediate Language (IL) code** for methods that may need further JIT compilation + +This hybrid nature is why R2R binaries are typically larger. For ABP Studio, the storage size increased by ~150 MB with R2R enabled, but the trade-off is well worth it for the performance and startup-time gains. + +## How R2R (Ready-to-Run) Improves ABP Studio + +### Faster Startup Time 🚀 + +One of the biggest advantages of R2R publishing is its impact on startup times. In our local tests, enabling R2R resulted in startup times being **reduced by 2.5x** ⬇️. + +This means you can get to work faster, without waiting for the application to being startup from the beginning. Whether you're launching ABP Studio to manage projects, generate code, or deploy applications, the improved responsiveness is noticeable. + +### Performance Enhancements 📈 + +In addition to faster startups, R2R publishing contributes to overall performance improvements. By precompiling frequently used methods, R2R reduces the workload on the JIT compiler during execution, leading to smoother and more efficient operations. + +### Trade-offs: Increased Storage Size 🆙 + +With great performance comes a slight trade-off: storage size. R2R binaries include both **native** and **IL code**, which increases the file size. In the case of ABP Studio, the storage footprint increased by ~150 MB. However, the substantial improvements in speed and responsiveness make this a worthwhile investment. + +## How to Enable R2R Publishing in Your Applications? + +If you're developing applications and want to benefit from R2R, here's a quick guide on how to enable it in your .NET projects: + +1. You can add the following configuration to your final project's `.csproj` file: + +```xml + + true + +``` + +2. Then, publish your application with the `dotnet publish` command: + +```bash +dotnet publish -c Release +``` + +Alternatively, you can specify the _PublishReadyToRun_ flag directly to the `dotnet publish` command as follows: + +```bash +dotnet publish -c Release -r win-x64 -p:PublishReadyToRun=true +``` + +That's it! Your application will now include precompiled native code for faster startup and great performance benefits. + +> Please refer to the [official documentation](https://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run) before publishing your application with R2R. + +## Conclusion + +As ABP team, we're always looking for ways to improve the developer experience. By adopting **Ready-to-Run (R2R) publishing** for ABP Studio, we're aiming to deliver a faster and more efficient tool for your development needs. + +Stay tuned for more updates and enhancements as we continue to optimize ABP Studio and please provide us with your invaluable feedback. \ No newline at end of file diff --git a/docs/en/Community-Articles/2025-01-03-ABP-Background-Workers-vs-Jobs/background-jobs-vs-background-workers.md b/docs/en/Community-Articles/2025-01-03-ABP-Background-Workers-vs-Jobs/background-jobs-vs-background-workers.md new file mode 100644 index 0000000000..43a3c3a813 --- /dev/null +++ b/docs/en/Community-Articles/2025-01-03-ABP-Background-Workers-vs-Jobs/background-jobs-vs-background-workers.md @@ -0,0 +1,407 @@ +# ABP Framework: Background Jobs vs Background Workers — When to Use Which? + +In the ABP Framework, **Background Jobs** and **Background Workers** serve different purposes but can sometimes seem interchangeable. Sometimes it can be confusing. Let’s clarify their differences, and I'll show you some real-world cases to help you understand how to decide between these two. We have official documents for these: + +📕 **Background Workers ABP Document** https://abp.io/docs/latest/framework/infrastructure/background-workers + +📘 **Background Jobs ABP Document** https://abp.io/docs/latest/framework/infrastructure/background-jobs + + +--- + +I posted this article because recently, I came across [this support ticket](https://abp.io/support/questions/5931/Background-Jobs-vs-Background-Workers-when-to-use-which) on the ABP support website. I thought these terms could be confusing for devs. He has two tasks and is asking whether he needs to use Background Worker or Background Job. + +* The first one is `FileRecievedActivity.` He says it's running 2 times a day. So, it's a recurring activity that needs to run in the background. So `FileRecievedActivity` is a "Background Worker". +* The second one is `ProcessQueueFiles`. It sounds like a polling task. It runs whenever a new file comes to the directory. So, it's also a recurring task that needs to be scheduled every 1 minute. Hence the `ProcessQueueFiles` is also "Backgrounder Worker." + +![https://abp.io/support/questions/5931/Background-Jobs-vs-Background-Workers-when-to-use-which](support-question.png) + + + +## Background Workers 🔄 */Looping/* + +The background workers are stateless and runs in-memory as long as the application is up and ready. + +- **Purpose**: Long-running, periodic tasks that run continuously in the background. They are queued and executed asynchronously. +- **Lifetime:** Runs throughout the application's lifetime. +- **Scheduling:** Executes on a fixed schedule, like every X minutes / hours... +- **Infrastructure**: ABP uses an in-memory implementation for running background workers. You can also use the 3rd party tools for running your background worker: + * [Quartz + ABP integration](https://abp.io/docs/latest/framework/infrastructure/background-workers/quartz) + * [Hangfire + ABP integration](https://abp.io/docs/latest/framework/infrastructure/background-workers/hangfire) + + + +**Use Cases:** Use background workers for any task that needs to run repeatedly at fixed intervals. For example "Health checks", "Periodic cleanup tasks", "Monitoring tasks", "Processing daily data"... In the last section, you will find real-world examples. + + + +> In Microsoft Docs, this topic is called "Background Tasks". Check out [Microsoft's official doc for running background tasks](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services). + + + +--- + + + +## Background Jobs ▶ */One time/* + +* **Purpose:** One-time tasks that need to be queued and can be executed in the background. Here the main goal is not to block the application to run the task. + +- **Lifetime**: Executes one time and completes. + +- **Scheduling**: Can be delayed/scheduled for a specific time. + +- **Infrastructure**: ABP uses in-memory implementation but you can also use the below 3rd party tools: + + * [Hangfire + ABP implementation](https://abp.io/docs/latest/framework/infrastructure/background-jobs/hangfire) + + * [RabbitMQ + ABP implementation](https://abp.io/docs/latest/framework/infrastructure/background-jobs/rabbitmq) + + * [Quartz + ABP implementation](https://abp.io/docs/latest/framework/infrastructure/background-jobs/quartz) + + + +**Use Cases:** Use background jobs to send emails, process uploaded files, generating reports, any fire-and-forget tasks or tasks that need retry mechanisms. + + + +> In Microsoft docs this topic is called as "Background Tasks". Check out [Microsoft's official background jobs doc](https://learn.microsoft.com/en-us/azure/architecture/best-practices/background-jobs). + + + +## When to Use Which? + +### Use Background Workers when: + +- You need continuous, recurring execution + +- The task should run as long as the application is running + +- You don't need persistence in task state + +- You want in-memory, efficient execution + + + +### Use Background Jobs when: + +- You need one-time execution + +- The task should survive application restarts + +- You need guaranteed execution + +- You want built-in retry mechanisms + +- You need to queue multiple instances of the same task + + + +## Technical Differences + +```csharp +// A Background Worker Example +public class MyBackgroundWorker : AsyncPeriodicBackgroundWorkerBase +{ + public MyBackgroundWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory) + : base(timer, serviceScopeFactory) + { + Timer.Period = 5000; // Runs every 5 seconds + } +} + +// A Background Job Example +public class MyBackgroundJob : AsyncBackgroundJob +{ + public override async Task ExecuteAsync(MyArgs args) + { + // Executes once when triggered + } +} + +// Triggering a Background Job +await _backgroundJobManager.EnqueueAsync( + new MyArgs { /* ... */ }, + delay: TimeSpan.FromHours(2) +); +``` + + + + +> While background workers no additional infrastructure needed, background jobs requires a database to persist jobs (or a distributed cache/message broker depending on the implementation) + + + + + +## 🚩 Background Worker Examples + + + +### 1) Querying an external API + +- **Scenario**: Continuously fetch data from an external API at regular intervals. +- **Why a Background Worker?**: You need a long-running process to poll the API and handle the results. + +```csharp +public class ApiPollingWorker : AsyncPeriodicBackgroundWorkerBase +{ + private readonly IAmazonPriceService _apiService; + + public ApiPollingWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, IAmazonPriceService apiService) + : base(timer, serviceScopeFactory) + { + _apiService = apiService; + Timer.Period = 60000; // Run every 1 minute + } + + protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) + { + var data = await _apiService.FetchPricesAsync(); + // Process the data + } +} +``` + +Here are practical examples of **Background Workers** that demonstrate how to use them effectively within the ABP Framework. Background Workers are ideal for long-running or periodic tasks that require stateful or persistent execution. + + + +### 2) Polling an External API + +- **Scenario**: Continuously fetch data from an external API at regular intervals. +- **Why a Background Worker?**: You need a long-running process to poll the API and handle the results. + +``` +csharpCopy codepublic class ApiPollingWorker : AsyncPeriodicBackgroundWorkerBase +{ + private readonly IApiService _apiService; + + public ApiPollingWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, IApiService apiService) + : base(timer, serviceScopeFactory) + { + _apiService = apiService; + Timer.Period = 60000; // Run every 1 minute + } + + protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) + { + var data = await _apiService.FetchDataAsync(); + // Process the data + } +} +``` + + + +### 3) Processing a Queue + +- **Scenario**: Continuously process items from a queue, such as Azure Service Bus or RabbitMQ. +- **Why a Background Worker?**: This requires a stateful, persistent process to monitor and handle the queue. + +```csharp +public class QueueProcessingWorker : AsyncBackgroundWorker +{ + private readonly IQueueService _queueService; + + public QueueProcessingWorker(IServiceScopeFactory serviceScopeFactory, IQueueService queueService) + : base(serviceScopeFactory) + { + _queueService = queueService; + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) + { + var message = await _queueService.GetNextMessageAsync(); + if (message != null) + { + await _queueService.ProcessMessageAsync(message); + } + await Task.Delay(1000, stoppingToken); // Delay for throttling + } + } +} +``` + + + +### 4) Maintaining a Database + +- **Scenario**: Perform periodic database maintenance, rebuild indices or cleanup tasks. +- **Why a Background Worker?**: These are recurring tasks requiring regular execution. + +```csharp +public class DatabaseCleanupWorker : AsyncPeriodicBackgroundWorkerBase +{ + private readonly ICleanupService _cleanupService; + + public DatabaseCleanupWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, ICleanupService cleanupService) + : base(timer, serviceScopeFactory) + { + _cleanupService = cleanupService; + Timer.Period = 3600000; // Run every hour + } + + protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) + { + await _cleanupService.DeleteOldRecordsAsync(); + } +} +``` + + + +### 5) Running a Health Check Service + +- **Scenario**: Periodically check the health of connected services and log their status. +- **Why a Background Worker?**: Periodic health checks are naturally suited to background workers. + +```csharp +public class HealthCheckWorker : AsyncPeriodicBackgroundWorkerBase +{ + private readonly IHealthCheckService _healthCheckService; + + public HealthCheckWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, IHealthCheckService healthCheckService) + : base(timer, serviceScopeFactory) + { + _healthCheckService = healthCheckService; + Timer.Period = 60000; // Run every minute + } + + protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) + { + await _healthCheckService.PerformChecksAsync(); + } +} +``` + + + +--- + + + +## 🚩 Background Job Examples + + + +### 1) Email Notifications + +- **Scenario**: Sending a welcome email to new users. +- **Why a Background Job?**: The email sending process doesn’t need to block the main application thread. It can run in the background, and failed jobs can be retried. + +```csharp +public class SendWelcomeEmailJob : IBackgroundJob +{ + private readonly IEmailSender _emailSender; + + public SendWelcomeEmailJob(IEmailSender emailSender) + { + _emailSender = emailSender; + } + + public async Task ExecuteAsync(string emailAddress) + { + await _emailSender.SendAsync( + emailAddress, + "Welcome!", + "Thank you for signing up to our service." + ); + } +} +``` + + + +### 2) Data Import/Export + +- **Scenario**: Exporting a large dataset to a CSV file and notifying the user once complete. +- **Why a Background Job?**: Long-running tasks like file generation can be processed asynchronously. + +```csharp +public class ExportDataJob : IBackgroundJob +{ + private readonly IDataExporter _dataExporter; + private readonly INotificationService _notificationService; + + public ExportDataJob(IDataExporter dataExporter, INotificationService notificationService) + { + _dataExporter = dataExporter; + _notificationService = notificationService; + } + + public async Task ExecuteAsync(int userId) + { + var filePath = await _dataExporter.ExportAsync(userId); + await _notificationService.NotifyAsync(userId, "Your data export is complete: " + filePath); + } +} +``` + + + +### 3) Push Notifications + +- **Scenario**: Sending push notifications to users about specific events (e.g., “Your order has been shipped!”). +- **Why a Background Job?**: Push notifications are non-blocking and can be handled in bulk in the background. + +```csharp +public class SendPushNotificationJob : IBackgroundJob +{ + private readonly IPushNotificationService _pushNotificationService; + + public SendPushNotificationJob(IPushNotificationService pushNotificationService) + { + _pushNotificationService = pushNotificationService; + } + + public async Task ExecuteAsync(PushNotificationInput input) + { + await _pushNotificationService.SendAsync(input.UserId, input.Message); + } +} +``` + + + +### 4) File Upload Processing + +- **Scenario**: Processing a file uploaded by a user (e.g., parsing, validating, and saving to a database). +- **Why a Background Job?**: File processing can be offloaded to the background, ensuring quick user feedback. + +```csharp +public class ProcessFileUploadJob : IBackgroundJob +{ + private readonly IFileParser _fileParser; + private readonly IDataService _dataService; + + public ProcessFileUploadJob(IFileParser fileParser, IDataService dataService) + { + _fileParser = fileParser; + _dataService = dataService; + } + + public async Task ExecuteAsync(FileProcessingInput input) + { + var parsedData = await _fileParser.ParseAsync(input.FilePath); + await _dataService.SaveAsync(parsedData); + } +} +``` + + + +## Final Words + +Use **Background Workers** for stateful, continuous operations and **Background Jobs** for isolated, retriable units of work. + +I hope this article will clarify these terms in ABP Framework. + +https://abp.io/ a complete web application platform. + +Happy coding😊 + + diff --git a/docs/en/Community-Articles/2025-01-03-ABP-Background-Workers-vs-Jobs/cover.png b/docs/en/Community-Articles/2025-01-03-ABP-Background-Workers-vs-Jobs/cover.png new file mode 100644 index 0000000000..ce7ebd6b15 Binary files /dev/null and b/docs/en/Community-Articles/2025-01-03-ABP-Background-Workers-vs-Jobs/cover.png differ diff --git a/docs/en/Community-Articles/2025-01-03-ABP-Background-Workers-vs-Jobs/support-question.png b/docs/en/Community-Articles/2025-01-03-ABP-Background-Workers-vs-Jobs/support-question.png new file mode 100644 index 0000000000..39ac71d8e1 Binary files /dev/null and b/docs/en/Community-Articles/2025-01-03-ABP-Background-Workers-vs-Jobs/support-question.png differ diff --git a/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179addd003079681f0b02a4e00c96e.png b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179addd003079681f0b02a4e00c96e.png new file mode 100644 index 0000000000..32f6d01edb Binary files /dev/null and b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179addd003079681f0b02a4e00c96e.png differ diff --git a/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179ade018718fbdf909f1d5f224dfb.png b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179ade018718fbdf909f1d5f224dfb.png new file mode 100644 index 0000000000..7cdb5df408 Binary files /dev/null and b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179ade018718fbdf909f1d5f224dfb.png differ diff --git a/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179ade1481e5e85d35cd60aeeddb1b.png b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179ade1481e5e85d35cd60aeeddb1b.png new file mode 100644 index 0000000000..1c4082874d Binary files /dev/null and b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179ade1481e5e85d35cd60aeeddb1b.png differ diff --git a/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179ade326fb5d8185ce5dcc0d4dac0.png b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179ade326fb5d8185ce5dcc0d4dac0.png new file mode 100644 index 0000000000..0936bcb024 Binary files /dev/null and b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/3a179ade326fb5d8185ce5dcc0d4dac0.png differ diff --git a/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/post.md b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/post.md new file mode 100644 index 0000000000..2c3a98ac49 --- /dev/null +++ b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/post.md @@ -0,0 +1,145 @@ +We are happy to release [ABP](https://abp.io) version **9.1 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 v9.1! Thanks to you in advance. + +## Get Started with the 9.1 RC + +You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli). + +By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI: + +![studio-switch-to-preview.png](3a179addd003079681f0b02a4e00c96e.png) + +## Migration Guide + +* [ABP Version 9.1 Migration Guide](https://abp.io/docs/9.1/release-info/migration-guides/abp-9-1) + +## What's New with ABP v9.1? + +In this section, I will introduce some major features released in this version. +Here is a brief list of titles explained in the next sections: + +* Upgraded to Angular 19 +* Upgraded to OpenIddict 6.0 +* New Blazor WASM Bundling System +* Idle Session Warning +* Lazy Expandable Feature for Documentation + +### Upgraded to Angular 19 + +We've upgraded the Angular templates and packages to **Angular 19**. This upgrade brings the latest features and improvements from the Angular ecosystem to ABP-based applications, including better performance and development experience. + +### Upgraded to OpenIddict 6.0 + +OpenIddict 6.0 has been released and we've upgraded the OpenIddict packages to version 6.0 in ABP 9.1. This brings enhanced security features and improved authentication capabilities. The migration is straightforward and mainly involves updating some constant names: + +- `OpenIddictConstants.Permissions.Endpoints.Logout` is now `OpenIddictConstants.Permissions.Endpoints.EndSession` +- `OpenIddictConstants.Permissions.Endpoints.Device` is now `OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization` + +If you're using IdentityModel packages directly, you'll need to upgrade them to the latest stable version (8.3.0). This update ensures your applications stay current with the latest security standards and best practices. + +> Please refer to the [OpenIddict 6.0 migration guide](https://abp.io/docs/9.1/release-info/migration-guides/openiddict5-to-6) for more information. + +### New Blazor WASM Bundling System + +We've implemented a new bundling system for Blazor WebAssembly applications that eliminates the need to manually run the `abp bundle` command. This system automatically handles JavaScript and CSS file bundling at runtime, significantly improving both development experience and application loading performance. + +**Key improvements include:** + +- Automatic bundling of JavaScript and CSS files without manual intervention +- Dynamic file generation through the host application +- Better integration with the ABP module system +- Improved asset management through the virtual file system + +The new system is particularly beneficial for modular applications, as it allows modules to contribute their assets automatically to the global bundles. This results in a more maintainable and efficient asset management system for Blazor WebAssembly applications. + +> Please refer to [this documentation](https://abp.io/docs/9.1/framework/ui/blazor/global-scripts-styles) for more information. + +### Idle Session Warning + +We've introduced a new idle session warning feature for the [Account (Pro) Module](https://abp.io/docs/latest/modules/account-pro) that helps manage user sessions more effectively. This security enhancement automatically monitors user activity and manages session timeouts in a user-friendly way. + +![idle-session-settings.png](3a179ade018718fbdf909f1d5f224dfb.png) + +The feature can be easily configured through the administration interface, where administrators can: + +- Enable/disable the idle session timeout +- Set custom timeout duration in minutes +- Configure when users should be signed out + +When a user becomes inactive for the configured duration, they'll receive a warning dialog: + +![session-expiration-warning.png](3a179ade1481e5e85d35cd60aeeddb1b.png) + +**Key features and behaviors:** + +- Tracks real user activity (mouse movements, keyboard presses) across all tabs +- Works on a per-browser session basis - affects all tabs of the same session +- Maintains session if user is active in any tab of the application +- Provides a countdown timer before automatic sign-out +- Offers options to "Stay signed in" or "Sign out now" + +This feature significantly improves application security while maintaining a smooth user experience by preventing unexpected session expirations and data loss. + +### Lazy Expandable Feature for Documentation + +We've introduced a new lazy expandable feature to the documentation system that significantly improves navigation through large documentation sections. This enhancement addresses common challenges when dealing with extensive documentation hierarchies by introducing smart menu management. + +**Key benefits and features:** + +- **Cleaner Navigation:** The menu stays concise by hiding sub-items until they're needed, reducing visual clutter +- **Better Performance:** Reduces the initial load of the navigation tree by loading sub-items on demand +- **Improved Search Experience:** Makes filtering documentation items more efficient by showing only relevant top-level items +- **Context-Aware Expansion:** Automatically expands relevant sections when viewing specific documentation pages + +The feature works by marking certain documentation sections as "lazy expandable" in the navigation configuration. When users navigate to a document within a lazy expandable section, the system automatically expands the relevant menu items while keeping other sections collapsed. + +This improvement is particularly valuable for complex documentation areas like tutorials, solution templates, and extensive module documentation, where having all navigation items visible at once could be overwhelming. + +An example of lazy expandable feature from the [ABP's BookStore Tutorial](https://abp.io/docs/latest/tutorials/book-store/part-01): + +```json + { + "text": "Book Store Application", + "isLazyExpandable": true, + "path": "tutorials/book-store", + "items": [ + { + "text": "Overview", + "path": "tutorials/book-store", + "isIndex": true + }, + //other items... + ] + } +``` + +![lazy-expandable.png](3a179ade326fb5d8185ce5dcc0d4dac0.png) + +### Others + +Some other highlights from this release: + +* Updated Iyzico NuGet packages to the latest version, which is used in the [ABP's Payment Module](https://abp.io/docs/latest/modules/payment#payment-module-pro). +* Removed optional _secondaryIds_ from path. See: [#21307](https://github.com/abpframework/abp/pull/21307) +* [CMS Kit Pro](https://abp.io/docs/latest/modules/cms-kit-pro): Added automatic deletion of comments when a blog post is deleted - comments are now automatically removed when their associated blog post is deleted. +* Avoiding global blocking in distributed event handlers (See [#21716](https://github.com/abpframework/abp/pull/21716)). + +## Community News + +### New ABP Community Articles + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Integrating ABP Modules in Your ASP.NET Core Web API Project. A Step-by-Step Guide](https://abp.io/community/articles/integrating-abp-modules-in-your-asp.net-core-web-api-project.-a-stepbystep-guide-jtbyosnr) by [Sajankumar Vijayan](https://abp.io/community/members/connect) +* [ABP Framework: Background Jobs vs Background Workers](https://abp.io/community/articles/abp-framework-background-jobs-vs-background-workers-when-to-use-which-t98pzjv6) — When to Use Which? by [Alper Ebiçoğlu](https://twitter.com/alperebicoglu) +* [The new Unit Test structure in ABP application](https://abp.io/community/articles/the-new-unit-test-structure-in-abp-application-4vvvp2oy) by [Liming Ma](https://github.com/maliming) +* [How to Use OpenAI API with ABP Framework](https://abp.io/community/articles/how-to-use-openai-api-with-abp-framework-rsfvihla) by [Berkan Şaşmaz](https://github.com/berkansasmaz) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community. + +## Conclusion + +This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://abp.io/docs/9.1/release-info/road-map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v9.1 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! \ No newline at end of file diff --git a/docs/en/Community-Articles/2025-01-22-abp-studio-now-supports-macos-intel-/3a17a07b91b89169ba833586d80024db.png b/docs/en/Community-Articles/2025-01-22-abp-studio-now-supports-macos-intel-/3a17a07b91b89169ba833586d80024db.png new file mode 100644 index 0000000000..f5d5ca6987 Binary files /dev/null and b/docs/en/Community-Articles/2025-01-22-abp-studio-now-supports-macos-intel-/3a17a07b91b89169ba833586d80024db.png differ diff --git a/docs/en/Community-Articles/2025-01-22-abp-studio-now-supports-macos-intel-/post.md b/docs/en/Community-Articles/2025-01-22-abp-studio-now-supports-macos-intel-/post.md new file mode 100644 index 0000000000..6e9f4d9b55 --- /dev/null +++ b/docs/en/Community-Articles/2025-01-22-abp-studio-now-supports-macos-intel-/post.md @@ -0,0 +1,44 @@ +We are excited to announce that [ABP Studio, our cross-platform desktop application for ABP developers](https://abp.io/studio), now supports Intel-based Mac computers! + +This addition expands our platform compatibility, ensuring that developers using Intel-powered Macs can also benefit from the powerful features of ABP Studio. + +## What is ABP Studio? + +For those who aren't familiar with it, [ABP Studio](https://abp.io/studio) is a powerful desktop application that makes ABP development faster and easier. It offers: + +* Easy creation of new solutions (from simple applications to microservices) +* Visual architecture management for modular-monolith and microservice solutions +* Solution exploration tools for entities, services, and HTTP APIs +* Simplified running, debugging, and monitoring of multi-application or microservice solutions +* Kubernetes cluster integration capabilities +* and more... + +## Extended Platform Support + +ABP Studio has been proudly supporting multiple platforms, and we're excited to add MacOS Intel to our list of supported architectures. You can now use ABP Studio on: + +* Windows x64 +* Windows ARM +* MacOS Apple Silicon (M1/M2/M3) +* MacOS Intel **(New!)** + +## Why This Matters + +This update is particularly important for developers who are using Intel-based Mac computers. Previously, ABP Studio was only available for Apple Silicon Macs (for MacOS), but we understand that many developers are still using Intel-based Macs. With this release, we're ensuring that all Mac users can access our development tools, regardless of their processor architecture. + +## Getting Started + +Installing ABP Studio on your Intel-based Mac is straightforward: + +1. Go to [abp.io/studio](https://abp.io/studio) +2. Click on the download button and select "MacOS Intel" from the dropdown menu +3. Once downloaded, open the installer package +4. Follow the installation wizard to complete the setup + +![abp-studio-macos-intel.png](3a17a07b91b89169ba833586d80024db.png) + +## Conclusion + +As the ABP team, we're always looking for ways to improve the developer experience. By supporting Intel-based Macs, we're ensuring that all Mac users can access our development tools, regardless of their processor architecture. + +Stay tuned for more updates and enhancements as we continue to optimize ABP Studio and please provide us with your invaluable feedback. Thanks in advance! diff --git a/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/1a06907364a779fb8bad39f3e6890219.jpg b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/1a06907364a779fb8bad39f3e6890219.jpg new file mode 100644 index 0000000000..6e756f8072 Binary files /dev/null and b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/1a06907364a779fb8bad39f3e6890219.jpg differ diff --git a/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a0d5e7a636a849847e69dec153c7e07.jpg b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a0d5e7a636a849847e69dec153c7e07.jpg new file mode 100644 index 0000000000..7a6a0c86e9 Binary files /dev/null and b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a0d5e7a636a849847e69dec153c7e07.jpg differ diff --git a/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a0d5e7aaa5d774528cc6afeeae8e88b.jpg b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a0d5e7aaa5d774528cc6afeeae8e88b.jpg new file mode 100644 index 0000000000..35494d6935 Binary files /dev/null and b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a0d5e7aaa5d774528cc6afeeae8e88b.jpg differ diff --git a/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a0d5e7c5833ae0ab6f3395339b17dd8.jpg b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a0d5e7c5833ae0ab6f3395339b17dd8.jpg new file mode 100644 index 0000000000..56286ddec1 Binary files /dev/null and b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a0d5e7c5833ae0ab6f3395339b17dd8.jpg differ diff --git a/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a108c28bb8b56956ba1e9486162c9fb.png b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a108c28bb8b56956ba1e9486162c9fb.png new file mode 100644 index 0000000000..cb03ca7462 Binary files /dev/null and b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/3a108c28bb8b56956ba1e9486162c9fb.png differ diff --git a/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/post.md b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/post.md new file mode 100644 index 0000000000..f392de4f8c --- /dev/null +++ b/docs/en/Community-Articles/2025-01-22-get-ready-for-ndc-london-2025-/post.md @@ -0,0 +1,49 @@ + +We are starting the new year fast, and as usual, we’re proud to announce that ABP.IO is sponsoring NDC London 2025! This marks the sixth consecutive year that ABP.IO has supported this important conference for software developers. + + +## About NDC London 2025 📅 + +The Norwegian Developers Conference (NDC) is one of the biggest conferences in Europe for .NET and Agile development. NDC London 2025 will be a 5-day event held from January 27-31 at the Queen Elizabeth II Centre in London. + +The event will cover a wide range of topics, including .NET, Agile, C++, Cloud, DevOps, JavaScript, Security, UX, Mobile, and more. With over 100 speakers and sessions, it’s a great chance to learn about the latest technologies and best practices. Well-known speakers such as Scott Hanselman, Laila Bougria, Scott Hunter, and Nick Chapsas will share their knowledge. + +The conference includes 2 days of workshops and 3 days of sessions, giving developers the chance to learn, meet experts, and explore the future of software development. + + +## ABP.IO at NDC London 2025 💻 + +ABP.IO is excited to be part of NDC London 2025 and connect with developers in the .NET ecosystem. As a platform built to simplify software development, ABP.IO provides a range of tools, templates, and modules to help you build modern applications faster. + +### Visit our booth to discover: + +* **Full Source Code:** Complete control for tailored, maintainable solutions. +* **Startup Templates:** Ready-made for microservices, modular monoliths, and simple monoliths. +* **Pre-Built Modules:** Save time with Identity, CMS Kit, Audit Logging, Blogging, Chat, Payment, and more. +* **Customizable UI Themes:** Modern designs with LeptonX and Basic Theme. +* **Powerful Tools:** Streamline workflows with ABP Studio and ABP Suite. + +Don’t miss the chance to explore ABP, a SaaS product built on the open-source ABP Framework, and learn how it can accelerate your development. + +Here are some previews from the events we sponsored before! + +### NDC London 2024: +![team.png](3a108c28bb8b56956ba1e9486162c9fb.png) + + +### NDC London 2023: +![IMG\_0014.jpg](3a0d5e7c5833ae0ab6f3395339b17dd8.jpg) + +![20230125\_084840.jpg](3a0d5e7aaa5d774528cc6afeeae8e88b.jpg) + + +### NDC London 2020: +![00f93d44fcdeb12edd6039f3e6787472.jpg](3a0d5e7a636a849847e69dec153c7e07.jpg) + +![image](1a06907364a779fb8bad39f3e6890219.jpg) + + +## Join Us! 🤝 +Mark your calendars for NDC London 2025 from January 27-31! Come meet the ABP team, connect with fellow developers, and explore the future of software development. + +Don’t miss out on our exciting raffle and promotions! Stay tuned for more updates! 🎁 diff --git a/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/Load-User-Profile.jpg b/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/Load-User-Profile.jpg new file mode 100644 index 0000000000..85f736050f Binary files /dev/null and b/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/Load-User-Profile.jpg differ diff --git a/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/POST.md b/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/POST.md new file mode 100644 index 0000000000..cea4bb82eb --- /dev/null +++ b/docs/en/Community-Articles/2025-01-23-Fixing-OpenIddict-Certificate-Issues/POST.md @@ -0,0 +1,77 @@ +# Fixing OpenIddict Certificate Issues in IIS or Azure + +When deploying an ABP application with OpenIddict to IIS or Azure, you may encounter issues with loading PFX/PKCS12 certificates. This article explains how to properly configure certificate loading to ensure it works correctly in these environments. + +## The Problem + +When running under IIS or Azure, the application pool identity may not have sufficient permissions to access certificate private keys. This commonly results in errors such as: + +- `System.Security.Cryptography.CryptographicException: Access denied.` +- `WindowsCryptographicException: Access is denied.` +- `System.Security.Cryptography.CryptographicException: The system cannot find the file specified.` + +## The Solution + +### Using AddDevelopmentEncryptionAndSigningCertificate + +For development environments using `DevelopmentEncryptionAndSigningCertificate`, you must configure the application pool to load a user profile. + +> Note: We strongly recommend using `DevelopmentEncryptionAndSigningCertificate` only in development environments. For production, always create and use a separate certificate. + +![Application Pool Configuration](Load-User-Profile.jpg) + +### Using AddProductionEncryptionAndSigningCertificate + +The ABP OpenIddict module provides an `AddProductionEncryptionAndSigningCertificate` extension method. By default, the template project attempts to load an `openiddict.pfx` certificate in production environments. + +To ensure proper certificate loading in IIS or Azure, you need to specify appropriate `X509KeyStorageFlags` when calling this method: + +```csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + var hostingEnvironment = context.Services.GetHostingEnvironment(); + + if (!hostingEnvironment.IsDevelopment()) + { + PreConfigure(options => + { + options.AddDevelopmentEncryptionAndSigningCertificate = false; + }); + + PreConfigure(serverBuilder => + { + var flag = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet; + serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", "YourCertificatePassword", flag); + }); + } +} +``` + +## Understanding X509KeyStorageFlags + +The configuration uses two important flags: + +* `X509KeyStorageFlags.MachineKeySet`: Specifies that the key belongs to the local computer key store, binding the key pair's lifecycle to the computer rather than a specific user. +* `X509KeyStorageFlags.EphemeralKeySet`: Indicates that the key will be stored only in memory and not persisted to disk or key store, enhancing security for runtime-only certificate requirements. + +Using these flags in combination helps prevent permission-related issues in IIS and Azure environments. + +## Troubleshooting Guide + +If you continue to experience issues, verify the following: + +* Confirm that the certificate password is correct +* Verify that the `openiddict.pfx` file exists in your deployment +* Ensure the certificate is valid - you can generate a new one using: + ```bash + dotnet dev-certs https -v -ep openiddict.pfx -p YourCertificatePassword + ``` +* Check the stdout logs for related errors (See [how to get stdout-log](https://abp.io/docs/latest/solution-templates/layered-web-application/deployment/deployment-iis?UI=Blazor&DB=EF&Tiered=No#how-to-get-stdout-log)) + +## References + +- [ABP OpenIddict Deployment](https://abp.io/docs/latest/solution-templates/layered-web-application/deployment/openiddict-deployment) +- [ABP IIS Deployment](https://abp.io/docs/latest/solution-templates/layered-web-application/deployment/deployment-iis) +- [ABP Azure Deployment](https://abp.io/docs/latest/solution-templates/layered-web-application/deployment/azure-deployment/azure-deployment) +- [How to Generate a New Certificate](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-dev-certs#how-to-generate-a-new-certificate) +- [Load User Profile in IIS](https://learn.microsoft.com/en-us/iis/manage/configuring-security/application-pool-identities#load-user-profile-for-an-application-pool) diff --git a/docs/en/Community-Articles/2025-01-24-Understanding-Transactions-in-ABP-Unit-Of-Work/POST.md b/docs/en/Community-Articles/2025-01-24-Understanding-Transactions-in-ABP-Unit-Of-Work/POST.md new file mode 100644 index 0000000000..929203c6a0 --- /dev/null +++ b/docs/en/Community-Articles/2025-01-24-Understanding-Transactions-in-ABP-Unit-Of-Work/POST.md @@ -0,0 +1,325 @@ +# Understanding Transactions in ABP Unit of Work + +[The Unit of Work](https://en.wikipedia.org/wiki/Unit_of_work) is a software design pattern that maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems to ensure that all changes are made within a single transaction. + +## Transaction Management Overview + +One of the primary responsibilities of the Unit of Work is managing database transactions. It provides the following transaction management features: + +- Automatically manages database connections and transaction scopes, eliminating the need for manual transaction control +- Ensures business operation integrity by making all database operations within a unit of work either succeed or roll back completely +- Supports configuration of transaction isolation levels and timeout periods +- Supports nested transactions and transaction propagation + +## Transaction Behavior + +### Default Transaction Settings + +You can modify the default behavior through the following configuration: + +```csharp +Configure(options => +{ + /* + Modify the default transaction behavior for all unit of work: + - UnitOfWorkTransactionBehavior.Enabled: Always enable transactions, all requests will start a transaction + - UnitOfWorkTransactionBehavior.Disabled: Always disable transactions, no requests will start a transaction + - UnitOfWorkTransactionBehavior.Auto: Automatically decide whether to start a transaction based on HTTP request type + */ + options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; + + // Set default timeout + options.Timeout = TimeSpan.FromSeconds(30); + + // Set default isolation level + options.IsolationLevel = IsolationLevel.ReadCommitted; +}); +``` + +### Automatic Transaction Management + +ABP Framework implements automatic management of Unit of Work and transactions through middlewares, MVC global filters, and interceptors. In most cases, you don't need to manage them manually + +### Transaction Behavior for HTTP Requests + +By default, the framework adopts an intelligent transaction management strategy for HTTP requests: +- `GET` requests won't start a transactional unit of work because there is no data modification +- Other HTTP requests (`POST/PUT/DELETE` etc.) will start a transactional unit of work + +### Manual Transaction Control + +If you need to manually start a new unit of work, you can customize whether to start a transaction and set the transaction isolation level and timeout: + +```csharp +// Start a transactional unit of work +using (var uow = _unitOfWorkManager.Begin( + isTransactional: true, + isolationLevel: IsolationLevel.RepeatableRead, + timeout: 30 +)) +{ + // Execute database operations within transaction + await uow.CompleteAsync(); +} +``` + +```csharp +// Start a non-transactional unit of work +using (var uow = _unitOfWorkManager.Begin( + isTransactional: false +)) +{ + // Execute database operations without transaction + await uow.CompleteAsync(); +} +``` + +### Configuring Transactions Using `[UnitOfWork]` Attribute + +You can customize transaction behavior by using the `UnitOfWorkAttribute` on methods, classes, or interfaces: + +```csharp +[UnitOfWork( + IsTransactional = true, + IsolationLevel = IsolationLevel.RepeatableRead, + Timeout = 30 +)] +public virtual async Task ProcessOrderAsync(int orderId) +{ + // Execute database operations within transaction +} +``` + +### Non-Transactional Unit of Work + +In some scenarios, you might not need transaction support. You can create a non-transactional unit of work by setting `IsTransactional = false`: + +```csharp +public virtual async Task ImportDataAsync(List items) +{ + using (var uow = _unitOfWorkManager.Begin( + isTransactional: false + )) + { + foreach (var item in items) + { + await _repository.InsertAsync(item, autoSave: true); + // Each InsertAsync will save to database immediately + // If subsequent operations fail, saved data won't be rolled back + } + + await uow.CompleteAsync(); + } +} +``` + +Applicable scenarios: +- Batch import data scenarios where partial success is accepted +- Read-only operations, such as queries +- Scenarios with low data consistency requirements + +### Methods to Commit Transactions + +#### In Transactional Unit of Work + +A Unit of Work provides several methods to commit changes to the database: + +1. **IUnitOfWork.SaveChangesAsync** + +```csharp +await _unitOfWorkManager.Current.SaveChangesAsync(); +``` + +2. **autoSave parameter in repositories** + +```csharp +await _repository.InsertAsync(entity, autoSave: true); +``` + +Both `autoSave` and `SaveChangesAsync` commit changes in the current context to the database. However, these are not applied until `CompleteAsync` is called. If the unit of work throws an exception or `CompleteAsync` is not called, the transaction will be rolled back. It means all the DB operations will be reverted back. Only after successfully executing `CompleteAsync` will the transaction be permanently committed to the database. + +3. **CompleteAsync** + +```csharp +using (var uow = _unitOfWorkManager.Begin()) +{ + // Execute database operations + await uow.CompleteAsync(); +} +``` + +When you manually control the Unit of Work with `UnitOfWorkManager`, the `CompleteAsync` method is crucial for transaction completion. The unit of work maintains a `DbTransaction` object internally, and the `CompleteAsync` method invokes `DbTransaction.CommitAsync` to commit the transaction. The transaction will not be committed if `CompleteAsync` is either not executed or fails to execute successfully. + +This method not only commits all database transactions but also: + +- Executes and processes all pending domain events within the Unit of Work +- Executes all registered post-operations and cleanup tasks within the Unit of Work +- Releases all DbTransaction resources upon disposal of the Unit of Work object + +> Note: `CompleteAsync` method should be called only once. Multiple calls are not supported. + +#### In Non-Transactional Unit of Work + +In non-transactional Unit of Work, these methods behave differently: + +Both `autoSave` and `SaveChangesAsync` will persist changes to the database immediately, and these changes cannot be rolled back. Even in non-transactional Unit of Work, calling the `CompleteAsync` method remains necessary as it handles other essential tasks. + +Example: +```csharp +using (var uow = _unitOfWorkManager.Begin(isTransactional: false)) +{ + // Changes are persisted immediately and cannot be rolled back + await _repository.InsertAsync(entity1, autoSave: true); + + // This operation persists independently of the previous operation + await _repository.InsertAsync(entity2, autoSave: true); + + await uow.CompleteAsync(); +} +``` + +### Methods to Roll Back Transactions + +#### In Transactional Unit of Work + +A unit of work provides multiple approaches to roll back transactions: + +1. **Automatic Rollback** + +For transactions automatically managed by the ABP Framework, any uncaught exceptions during the request will trigger an automatic rollback. + +2. **Manual Rollback** + +For manually managed transactions, you can explicitly invoke the `RollbackAsync` method to immediately roll back the current transaction. + +> Important: Once `RollbackAsync` is called, the entire Unit of Work transaction will be rolled back immediately, and any subsequent calls to `CompleteAsync` will have no effect. + +```csharp +using (var uow = _unitOfWorkManager.Begin( + isTransactional: true, + isolationLevel: IsolationLevel.RepeatableRead, + timeout: 30 +)) +{ + await _repository.InsertAsync(entity); + + if (someCondition) + { + await uow.RollbackAsync(); + return; + } + + await uow.CompleteAsync(); +} +``` + +The `CompleteAsync` method attempts to commit the transaction. If any exceptions occur during this process, the transaction will not be committed. + +Here are two common exception scenarios: + +1. **Exception Handling Within Unit of Work** + +```csharp +using (var uow = _unitOfWorkManager.Begin( + isTransactional: true, + isolationLevel: IsolationLevel.RepeatableRead, + timeout: 30 +)) +{ + try + { + await _bookRepository.InsertAsync(book); + await uow.SaveChangesAsync(); + await _productRepository.UpdateAsync(product); + await uow.CompleteAsync(); + } + catch (Exception) + { + // Exceptions can occur in InsertAsync, SaveChangesAsync, UpdateAsync, or CompleteAsync + // Even if some operations succeed, the transaction remains uncommitted to the database + // While you can explicitly call RollbackAsync to roll back the transaction, + // the transaction will not be committed anyway if CompleteAsync fails to execute + throw; + } +} +``` + +2. **Exception Handling Outside Unit of Work** + +```csharp +try +{ + using (var uow = _unitOfWorkManager.Begin( + isTransactional: true, + isolationLevel: IsolationLevel.RepeatableRead, + timeout: 30 + )) + { + await _bookRepository.InsertAsync(book); + await uow.SaveChangesAsync(); + await _productRepository.UpdateAsync(product); + await uow.CompleteAsync(); + } +} +catch (Exception) +{ + // Exceptions can occur in UpdateAsync, SaveChangesAsync, UpdateAsync, or CompleteAsync + // Even if some operations succeed, the transaction remains uncommitted to the database + // Since CompleteAsync was not successfully executed, the transaction will not be committed + throw; +} +``` + +#### In Non-Transactional Unit of Work + +In non-transactional units of work, operations are irreversible. Changes saved using `autoSave: true` or `SaveChangesAsync()` are persisted immediately, and the `RollbackAsync` method has no effect. + +## Transaction Management Best Practices + +### 1. Remember to Commit Transactions + +When manually controlling transactions, remember to call the `CompleteAsync` method to commit the transaction after operations are complete. + +### 2. Pay Attention to Context + +If a unit of work already exists in the current context, `UnitOfWorkManager.Begin` method and` UnitOfWorkAttribute` will **reuse it**. Specify `requiresNew: true` to force create a new unit of work. + +```csharp +[UnitOfWork] +public async Task Method1() +{ + using (var uow = _unitOfWorkManager.Begin( + requiresNew: true, + isTransactional: true, + isolationLevel: IsolationLevel.RepeatableRead, + timeout: 30 + )) + { + await Method2(); + await uow.CompleteAsync(); + } +} +``` + +### 3. Use `virtual` Methods + +To be able to use Unit of Work attribute, you must use the `virtual` modifier for methods in dependency injection class services, because ABP Framework uses interceptors, and it cannot intercept non `virtual` methods, thus unable to implement Unit of Work functionality. + +### 4. Avoid Long Transactions + +Enabling long-running transactions can lead to resource locking, excessive transaction log usage, and reduced concurrent performance, while rollback costs are high and may exhaust database connection resources. It's recommended to split into shorter transactions, reduce lock holding time, and optimize performance and reliability. + +## Transaction-Related Recommendations + +- Choose appropriate transaction isolation levels based on business requirements +- Avoid overly long transactions, long-running operations should be split into multiple small transactions +- Use the `requiresNew` parameter reasonably to control transaction boundaries +- Pay attention to setting appropriate transaction timeout periods +- Ensure transactions can properly roll back when exceptions occur +- For read-only operations, it's recommended to use non-transactional Unit of Work to improve performance + +## References + +- [ABP Unit of Work](https://abp.io/docs/latest/framework/architecture/domain-driven-design/unit-of-work) +- [EF Core Transactions](https://docs.microsoft.com/en-us/ef/core/saving/transactions) +- [Transaction Isolation Levels](https://docs.microsoft.com/en-us/dotnet/api/system.data.isolationlevel) diff --git a/docs/en/Community-Articles/2025-01-24-Understanding-Transactions-in-ABP-Unit-Of-Work/pic.png b/docs/en/Community-Articles/2025-01-24-Understanding-Transactions-in-ABP-Unit-Of-Work/pic.png new file mode 100644 index 0000000000..d6805a806e Binary files /dev/null and b/docs/en/Community-Articles/2025-01-24-Understanding-Transactions-in-ABP-Unit-Of-Work/pic.png differ diff --git a/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/POST.md b/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/POST.md new file mode 100644 index 0000000000..f5602650ae --- /dev/null +++ b/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/POST.md @@ -0,0 +1,114 @@ +# Customizing Authentication Flow with OpenIddict Events in ABP Framework + +[ABP's OpenIddict Module](https://abp.io/docs/latest/modules/openiddict) provides an integration with the [OpenIddict](https://github.com/openiddict/openiddict-core) library, which provides advanced authentication features like **single sign-on**, **single log-out**, and **API access control**. + +OpenIddict provides an event-driven model ([event models](https://documentation.openiddict.com/introduction#events-model)) that allows developers to customize authentication and authorization processes. This event model enables handling actions such as user **sign-in**, **sign-out**, **token validation**, and **request handling** dynamically. + +In this article, we will explore OpenIddict event models, their key use cases, and how to implement them effectively. + +## Understanding OpenIddict Event Model + +OpenIddict events are primarily used within the OpenIddict server component. These events provide hooks into the OpenID Connect flow, allowing developers to modify behavior at different stages of authentication & authorization processes. + +They are triggered during critical moments such as: + +* User authentication (sign-in) +* Session termination (sign-out) +* Token validation and generation +* Request processing +* Error handling + +OpenIddict provides multiple server events, under the `OpenIddictServerEvents` static class to make them easier to find (also provides additonal validation events under the `OpenIddictValidationEvents` static class). + +Here are some of the pre-defined `OpenIddictServerEvents`: + +![](openiddict-server-events.png) + +Each event represents a specific checkpoint in the **request processing pipeline**, such as validating an OpenID Connect request, extracting request parameters, processing the request, or generating a response. As an application developer, you simply need to create event handlers that subscribe to these predefined events to implement your custom logic at the desired pipeline stage. + +## Example: How to add custom logic when a user signs out? + +Let's walkthrough a practical example of implementing custom sign-out logic using OpenIddict events. + +### Step 1: Create a Custom Event Handler + +First, create a handler that implements `IOpenIddictServerHandler`: + +```csharp +using System.Threading.Tasks; +using OpenIddict.Server; + +namespace MySolution; + +public class SignOutEventHandler : IOpenIddictServerHandler +{ + public static OpenIddictServerHandlerDescriptor Descriptor { get; } + = OpenIddictServerHandlerDescriptor.CreateBuilder() + .UseSingletonHandler() + .SetOrder(100_000) + .SetType(OpenIddictServerHandlerType.Custom) + .Build(); + + public ValueTask HandleAsync(OpenIddictServerEvents.ProcessSignOutContext context) + { + // Implement your custom sign-out logic here + + // Examples: + // - Clear custom session data + // - Perform audit logging + // - Notify other services + // - Clean up user-specific resources + + return ValueTask.CompletedTask; + } +} +``` + +The handler configuration includes several important components: + +* `Descriptor` - Defines how the handler should be registered and executed +* `SetOrder` - Determines the execution order when multiple handlers exist +* `SetType` - Specifies this as a custom handler implementation +* `UseSingletonHandler` - Sets lifetime of the class as _Singleton_ + +### Step 2: Register the Event Handler + +Register your custom handler in your application's module configuration: + +```csharp +//... + +public class MySolutionAuthServerModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(serverBuilder => + { + serverBuilder.AddEventHandler(SignOutEventHandler.Descriptor); + }); + } + + //... +} +``` + +That's it! After these steps, your `SignOutEventHandler.HandleAsync()` method should be triggered after each signout request. You can also use other pre-defined server events for other stages of the authentication & authorization processes such as; + +* `OpenIddictServerEvents.ProcessSignInContext` -> after each sign-in, +* `OpenIddictServerEvents.ProcessErrorContext` -> when an error occurs in the authentication, +* `OpenIddictServerEvents.ProcessChallengeContext` -> called when processing a challenge operation, +* and other 40+ server events... + +Each event provides access to the relevant context, allowing you to access and modify the authentication flow's behavior. + +## Conclusion + +ABP Framework integrates OpenIddict as its authentication and authorization module. OpenIddict provides an event-driven model that allows developers to customize authentication and authorization processes within their ABP applications. It's pre-installed & pre-configured in the ABP's startup templates. + +OpenIddict provides a powerful and flexible way to customize authentication flows. By leveraging these events, developers can implement complex authentication scenarios while maintaining clean, maintainable code. + +## References + +* [OpenIddict Documentation](https://documentation.openiddict.com/introduction#events-model) +* [ABP OpenIddict Module Documentation](https://abp.io/docs/latest/modules/openiddict) +* [Advanced OpenIddict Scenarios](https://kevinchalet.com/2018/07/02/implementing-advanced-scenarios-using-the-new-openiddict-rc3-events-model/) \ No newline at end of file diff --git a/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/cover-image.png b/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/cover-image.png new file mode 100644 index 0000000000..11d9ff05ea Binary files /dev/null and b/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/cover-image.png differ diff --git a/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/openiddict-server-events.png b/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/openiddict-server-events.png new file mode 100644 index 0000000000..3514304f15 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/openiddict-server-events.png differ diff --git a/docs/en/Community-Articles/2025-02-07-boost-your-abpio-skills-with-33-off-all-live-training/3a1802935f9d8ce06a01985a7ffe3f6e.png b/docs/en/Community-Articles/2025-02-07-boost-your-abpio-skills-with-33-off-all-live-training/3a1802935f9d8ce06a01985a7ffe3f6e.png new file mode 100644 index 0000000000..05d6e8d37d Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-boost-your-abpio-skills-with-33-off-all-live-training/3a1802935f9d8ce06a01985a7ffe3f6e.png differ diff --git a/docs/en/Community-Articles/2025-02-07-boost-your-abpio-skills-with-33-off-all-live-training/post.md b/docs/en/Community-Articles/2025-02-07-boost-your-abpio-skills-with-33-off-all-live-training/post.md new file mode 100644 index 0000000000..ab7807795b --- /dev/null +++ b/docs/en/Community-Articles/2025-02-07-boost-your-abpio-skills-with-33-off-all-live-training/post.md @@ -0,0 +1,31 @@ +Are you looking to enhance your expertise in ABP.IO and accelerate your development skills? Now is the perfect time! We’re excited to announce *[33% discount on all our ABP.IO live training packages](https://abp.io/trainings?utm_source=referral&utm_medium=website&utm_campaign=training_abpblogpost)* for a limited time. + +#### Why Join ABP.IO Training? + +ABP.IO training programs are designed to help developers, architects, and teams master the ABP Framework efficiently. Whether you're new to the framework or looking to deepen your knowledge, our courses cover everything you need to build robust and scalable applications with ABP.IO. + +#### What You’ll Gain: + +✔ Comprehensive live training from ABP.IO team experts + +✔ Hands-on learning with real-world applications + +✔ Best practices for building modern web applications + +✔ Certification to showcase your expertise + +#### [Limited-Time 33% Discount – Don’t Miss Out!](https://abp.io/trainings?utm_source=referral&utm_medium=website&utm_campaign=training_abpblogpost) + +For a short period, all training packages are available at a 33% discount. This is a great opportunity to upskill yourself or train your team at a significantly reduced cost. + +#### How to Get the Discount? + +Simply visit our training page, select your preferred package, add your note if needed and send your training request, that's all! ABP Training Team will reply to your request via email soon. + +[![](3a1802935f9d8ce06a01985a7ffe3f6e.png)](https://youtu.be/ZzIyze_cm8o?si=3UnSFXBZaCOiF3Xq) + +#### Take Advantage of This Offer Today + +Invest in your skills and advance your career with ABP.IO training. This offer won’t last long, so grab your spot now! + +### 👉 [Sign up for training now and start building with ABP.IO](https://abp.io/trainings?utm_source=referral&utm_medium=website&utm_campaign=training_abpblogpost) \ No newline at end of file diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f257fa2cd5692469499ebbbcc81e.jpeg b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f257fa2cd5692469499ebbbcc81e.jpeg new file mode 100644 index 0000000000..9cad91b810 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f257fa2cd5692469499ebbbcc81e.jpeg differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f2586874e8f616e16e6bdff66b18.jpeg b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f2586874e8f616e16e6bdff66b18.jpeg new file mode 100644 index 0000000000..7d51dab13a Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f2586874e8f616e16e6bdff66b18.jpeg differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f258a3ad253b6ecc090b581d7d40.jpeg b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f258a3ad253b6ecc090b581d7d40.jpeg new file mode 100644 index 0000000000..e709fa7d98 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f258a3ad253b6ecc090b581d7d40.jpeg differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f259130be60868d1944d8692d3fe.jpeg b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f259130be60868d1944d8692d3fe.jpeg new file mode 100644 index 0000000000..25d9efa20f Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f259130be60868d1944d8692d3fe.jpeg differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f25d4ceb1dbe944934951c9f7d32.jpeg b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f25d4ceb1dbe944934951c9f7d32.jpeg new file mode 100644 index 0000000000..f425cac32f Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f25d4ceb1dbe944934951c9f7d32.jpeg differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f33dafbd9e5e68713350903bce0e.jpeg b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f33dafbd9e5e68713350903bce0e.jpeg new file mode 100644 index 0000000000..9b0b95f791 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a17f33dafbd9e5e68713350903bce0e.jpeg differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180135f252ecd60630681b0e23a517.png b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180135f252ecd60630681b0e23a517.png new file mode 100644 index 0000000000..c93caf4366 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180135f252ecd60630681b0e23a517.png differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a1801391e123159404397616216103d.png b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a1801391e123159404397616216103d.png new file mode 100644 index 0000000000..ab3edcc260 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a1801391e123159404397616216103d.png differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180ca3de1eb496455c4c3341721ab3.jpg b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180ca3de1eb496455c4c3341721ab3.jpg new file mode 100644 index 0000000000..7bceee338c Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180ca3de1eb496455c4c3341721ab3.jpg differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180ca5122043881595c75c6ea661de.jpg b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180ca5122043881595c75c6ea661de.jpg new file mode 100644 index 0000000000..95942671c8 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180ca5122043881595c75c6ea661de.jpg differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180ca776481fe9cb89b439988e99e1.jpg b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180ca776481fe9cb89b439988e99e1.jpg new file mode 100644 index 0000000000..847bff8724 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/3a180ca776481fe9cb89b439988e99e1.jpg differ diff --git a/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/post.md b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/post.md new file mode 100644 index 0000000000..1cd1ea2205 --- /dev/null +++ b/docs/en/Community-Articles/2025-02-07-event-recap-ndc-london-2025/post.md @@ -0,0 +1,41 @@ +The ABP team recently returned from an exhilarating week at NDC London 2025, held from January 27 to 31 at the Queen Elizabeth II Centre in Westminster. As a proud sponsor, we were thrilled to engage with the global developer community at this premier software development conference. + +![stand1.jpeg](3a17f257fa2cd5692469499ebbbcc81e.jpeg) + +#### Event Highlights + +NDC London 2025 featured a comprehensive agenda, including two days of deep-dive workshops followed by three days of insightful conference sessions. The event covered a wide array of topics such as .NET, cloud computing, AI, microservices, and more. Notable sessions included “AI without the BS, for humans” by Scott Hanselman and “C#’s Functional Journey” by Mads Torgersen.  + +![speaks1.jpeg](3a17f2586874e8f616e16e6bdff66b18.jpeg) + +![speaks2.jpeg](3a17f258a3ad253b6ecc090b581d7d40.jpeg) + +[![](3a1801391e123159404397616216103d.png)](https://www.youtube.com/shorts/9y7PYyvq-9k) + +#### ABP’s Presence + +[Our booth became a hub for meaningful interactions](https://www.youtube.com/shorts/9y7PYyvq-9k), where we showcased the latest features of the ABP Framework and received invaluable feedback from the developer community. We were delighted to see a significant number of attendees expressing interest in our platform and its capabilities. + +![xbox2.jpeg](3a17f25d4ceb1dbe944934951c9f7d32.jpeg) + +![stand2.jpeg](3a17f259130be60868d1944d8692d3fe.jpeg) + +#### Networking and Community Engagement + +The conference provided ample opportunities for networking, including the NDC Party, which was a fantastic occasion to connect with fellow developers and industry leaders in a relaxed setting.  + +[**As is tradition**, we held a raffle at the event with an **Xbox Series X** as the prize]. Congratulations to the lucky winner, and thank you to everyone who participated! + +[![](3a180135f252ecd60630681b0e23a517.png)](https://youtube.com/shorts/sb-CembIV-s?si=Zlno7ZuZme1EaQph) + +![xbox.jpeg](3a17f33dafbd9e5e68713350903bce0e.jpeg) + +#### Looking Ahead + +Our participation in NDC London 2025 has further strengthened our commitment to supporting and advancing the developer community. We are excited to implement the insights gained and continue our journey of innovation and collaboration. + +We extend our heartfelt thanks to the organizers, speakers, and attendees for making NDC London 2025 an unforgettable experience. We look forward to participating in future events and continuing to contribute to the vibrant developer ecosystem. + +Stay tuned for more updates and see you at the next event! + +**The ABP Team** \ No newline at end of file diff --git a/docs/en/Community-Articles/2025-02-12-Migrate-DB-From-Your-Web-Project/Post.md b/docs/en/Community-Articles/2025-02-12-Migrate-DB-From-Your-Web-Project/Post.md new file mode 100644 index 0000000000..4278a75eab --- /dev/null +++ b/docs/en/Community-Articles/2025-02-12-Migrate-DB-From-Your-Web-Project/Post.md @@ -0,0 +1,179 @@ +In some scenarios, you might prefer to **update your ABP project's database by simply visiting a URL** rather than running a console application (such as a typical `DbMigrator` project). This post demonstrates how to do that in an ABP application. In my sample application I used the single-layer project but you can benefit the same approach for other templates. My sample project name was created with this name: **Acme.BookStore**. + +------ + +## Step 1: Remove the Existing Localization Middleware + +Open your web project's module class file—this is typically in `BookStoreModule.cs` if you’re using the no-layer template. +Or if your project is multi-layered, it's `BookStoreWebModule.cs`. Find the below line and **remove** it: + +```csharp +app.UseAbpRequestLocalization(); +``` + +The reason is that the localization middleware depends on the database, which does not yet exist! +We'll add this middleware conditionally in the next step. + +------ + +## Step 2: Conditionally Use the Localization Middleware + +We only want `AbpRequestLocalizationMiddleware` for routes **other than** our new migration endpoint (`/api/migrate`). To achieve this, we use [Middleware Branching](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/). Our new controller will work on `/api/migrate` endpoint, so let's add a condition for this specific URL. + +```csharp +app.UseWhen(httpContext => + !httpContext.Request.Path.StartsWithSegments("/api/migrate", StringComparison.OrdinalIgnoreCase), + appBuilder => + { + appBuilder.UseAbpRequestLocalization(); + } +); +``` + +This ensures all requests except `/api/migrate` will still use `AbpRequestLocalization` middleware. + +------ + +## Step 3: Create the Migration Controller + +Create a new file named `MigrationController.cs` under your `Controllers` folder or wherever you store controllers. +Then copy-paste the following class: + +```csharp +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Data; +using Volo.Abp.Identity; +using Volo.Abp.MultiTenancy; +using Volo.Saas.Tenants; + +namespace Acme.BookStore.Web.Controllers //TODO: you may need to fix this namespace! +{ + [Route("api")] + [IgnoreAntiforgeryToken] + public class MigrationController : AbpController + { + private const string DefaultAdminEmail = "admin@admin.com"; + private const string DefaultAdminPassword = "My-Admin-Password"; + + private readonly IDataSeeder _dataSeeder; + private readonly ITenantRepository _tenantRepository; + private readonly ICurrentTenant _currentTenant; + private readonly IEnumerable _dbSchemaMigrators; + + public MigrationController( + IDataSeeder dataSeeder, + ITenantRepository tenantRepository, + ICurrentTenant currentTenant, + IEnumerable dbSchemaMigrators) + { + _dataSeeder = dataSeeder; + _tenantRepository = tenantRepository; + _currentTenant = currentTenant; + _dbSchemaMigrators = dbSchemaMigrators; + } + + [HttpGet] + [Route("migrate")] + public async Task MigrateAsync(CancellationToken cancellationToken) + { + try + { + Logger.LogInformation("Started database migrations..."); + + await MigrateDatabaseSchemaAsync(); + await SeedDataAsync(); + + Logger.LogInformation("Successfully completed host database migrations. Started migrating tenant databases..."); + + if (_currentTenant.IsAvailable) // or check MultiTenancyConsts.IsEnabled + { + await MigrateTenantDatabases(cancellationToken); + } + + Logger.LogInformation("Successfully completed all database migrations."); + return Ok("Migration and seed completed successfully."); + } + catch (Exception ex) + { + return BadRequest($"An error occurred during migration: {ex.Message}"); + } + } + + private async Task MigrateTenantDatabases(CancellationToken cancellationToken) + { + var tenants = await _tenantRepository.GetListAsync(includeDetails: true, cancellationToken: cancellationToken); + + var migratedDatabaseSchemas = new HashSet(); + foreach (var tenant in tenants) + { + using (_currentTenant.Change(tenant.Id)) + { + if (tenant.ConnectionStrings.Any()) + { + var tenantConnectionStrings = tenant.ConnectionStrings + .Select(x => x.Value) + .ToList(); + + if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) + { + await MigrateDatabaseSchemaAsync(tenant); + migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); + } + } + + await SeedDataAsync(tenant); + } + + Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); + } + } + + private async Task MigrateDatabaseSchemaAsync(Tenant tenant = null) + { + Logger.LogInformation($"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database..."); + foreach (var migrator in _dbSchemaMigrators) + { + await migrator.MigrateAsync(); + } + } + + private async Task SeedDataAsync(Tenant tenant = null) + { + Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed..."); + + await _dataSeeder.SeedAsync( + new DataSeedContext(tenant?.Id) + .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, DefaultAdminEmail) + .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, DefaultAdminPassword) + ); + } + } +} +``` + + + +------ + + + +## Step 4: Navigate to the Migration URL + +Build and run your web application. Then visit: + +``` +https://your-website.com/api/migrate +``` + +If your database did not exist, it will be created, and the default data will be seeded. If you enabled multi-tenancy, the tenant databases will also be migrated in this solution. + +------ + + + +**That’s all there is to it!** By adding a simple controller and selectively applying the localization middleware, you can migrate your ABP app’s database with a single URL. + + + +Happy coding 😊 \ No newline at end of file diff --git a/docs/en/Community-Articles/2025-02-12-Migrate-DB-From-Your-Web-Project/cover.png b/docs/en/Community-Articles/2025-02-12-Migrate-DB-From-Your-Web-Project/cover.png new file mode 100644 index 0000000000..94c7f3d98c Binary files /dev/null and b/docs/en/Community-Articles/2025-02-12-Migrate-DB-From-Your-Web-Project/cover.png differ diff --git a/docs/en/Community-Articles/2025-02-16-Using-Pushed-Authorization-Requests-In-ABP-Framework/POST.md b/docs/en/Community-Articles/2025-02-16-Using-Pushed-Authorization-Requests-In-ABP-Framework/POST.md new file mode 100644 index 0000000000..52f8e5d204 --- /dev/null +++ b/docs/en/Community-Articles/2025-02-16-Using-Pushed-Authorization-Requests-In-ABP-Framework/POST.md @@ -0,0 +1,179 @@ +![par](cover.png) + +# Using Pushed Authorization Requests In ABP Framework + +`Pushed Authorization Requests (PAR)` is a new `OAuth 2.0` feature that allows clients to push the payload of an `OAuth 2.0` authorization request to the authorization server via a direct request and provides them with a request URI that is used as reference to the data in a subsequent call to the authorization endpoint. This feature is defined in [RFC 9156](https://tools.ietf.org/html/rfc9156). + +## Authorization Code Flow + +Let's examine the current `Code Flow` in the ABP Framework project. + +A typical ABP layered architecture usually includes the following projects: + +- `Acme.AuthServer`: OAuth 2.0 authorization server integrated with `OpenIddict`. +- `Acme.HttpApi.Host`: API project that uses the `JWT Bearer` authentication scheme and authenticates through the `Acme.AuthServer` project. +- `Acme.Web`: An UI project configured with an `OpenID Connect` authentication scheme to authenticate through the `Acme.AuthServer` project. + +When we attempt to use `OpenID Connect` authentication in the `Acme.Web` project, it constructs an authorization request and redirects the browser to the `Acme.AuthServer` project. + +```csharp +GET https//auth-server.acme.com/connect/authorize + +Query String Parameters: + +client_id: AbpApp +redirect_uri: https://web.acme.com/signin-oidc +response_type: code +scope: openid profile email roles phone AbpAPI +response_mode: form_post +nonce: YzVkMj... +state: CfDJ8N... +``` + +> If you have enabled `Pkce`, the `code_challenge` and `code_challenge_method` parameters will also appear in the request. + +```csharp +code_challenge: mJxMdU... +code_challenge_method: S256 +``` + +After the user successfully authenticates on the `Acme.AuthServer` project (via username/password or social login providers) and approves the requested permissions on the consent screen/page, it returns a `code` to the `Acme.Web` project. + +The `Acme.AuthServer` project will construct either a `POST` or `GET` request to the `Acme.Web` project. + +```csharp +POST https://web.acme.com/signin-oidc + +Form Data Parameters(application/x-www-form-urlencoded): + +code: LPjZ6C... +state: state: CfDJ8N... +iss: https://auth-server.acme.com/ +``` + +When the `Acme.Web` project receives the `code`, it sends an HTTP request from the application (**not the browser**) to `Acme.AuthServer` to request an `access token` using the received `code`. + +```csharp +POST https://auth-server.acme.com/connect/token + +Form Data Parameters(application/x-www-form-urlencoded): + +client_id: AbpApp +client_secret: secret +code: LPjZ6C... +grant_type: authorization_code +``` + +At this point, the `Code Flow` authentication process is complete, and we can use the `access token` to access APIs on the `Acme.HttpApi.Host` project. + +> The `Hybrid Flow` and `Implicit Flow` are similar to `Code Flow`. We'll focus on `Code Flow` in this discussion. + +However, `Code Flow` may have the following issues: + +* The authorization request can be altered. Usually, the client application redirects the user's browser to the authorization server with the authorization URL. Nothing prevents a malicious actor from changing one or more parameters of this request before sending it to the authorization server. +* No guarantee of the request's provenance. The authorization request is normally built by the client application, and the user's browser is in charge of sending it to the authorization server. However, there is no guarantee that the request has been built by the client application. Anyone can build an authorization request once they know a few data, such as the client ID and the redirect URI. +* No guarantee of confidentiality. Although the browser sends the authorization request via HTTPS, the request parameters can be intercepted by third-party applications, such as a proxy, a load balancer, or even a browser plugin. A malicious network component of this type can inject or change the request parameters, not to mention that the request itself can be logged. +* Browser limitations. Finally, a very complex query string in the authorization request may incur possible browser limitations on URL length. + +OAuth 2.0 defined `Pushed Authorization Requests (PAR)` to address these issues. + +## Pushed Authorization Requests (PAR) + +[OpenIdDict 6.1.0](https://documentation.openiddict.com/configuration/pushed-authorization-requests) started supporting `Pushed Authorization Requests (PAR)`. The ABP Framework(`>=9.2.0`) promptly upgraded its `OpenIddict` version and added PAR configuration in the [Volo.OpenIddict.Pro module](https://abp.io/modules/Volo.OpenIddict.Pro). + +You can configure `Pushed Authorization Requests (PAR)` when `creating/updating` an `Application`. + +![par](par.png) + +Let's examine the authentication flow using `Pushed Authorization Requests (PAR)`. + +When we attempt to use OpenID Connect authentication in the `Acme.Web` project, it sends an HTTP request from the application (**not the browser**) to the authorization server's `par` endpoint. + +```csharp +POST https://auth-server.acme.com/connect/par + +Form Data Parameters: + +client_id: AbpApp +client_secret: secret +redirect_uri: https://web.acme.com/signin-oidc +response_type: code +scope: openid profile email roles phone AbpAPI +response_mode: form_post +nonce: YzVkMjZmN... +state: CfDJ8NwA4... +``` + +> If you have enabled `Pkce`, the code_challenge and code_challenge_method parameters will also appear in the `POST` request. + +```csharp +code_challenge: mJxMdULFXnvdWfaDUfyDIb77IFlMpGyKkHN1_UWYKDk +code_challenge_method: S256 +``` + +After successful verification and validation, the authorization server returns a `request_uri` to the `Acme.Web` application. + +```json +{ + "request_uri": "urn:ietf:params:oauth:request_uri:1FPVWnrwFAesetV-r-66_b7BAF_vCQm7UmPWfBqRENg", + "expires_in": 3599 +} +``` + +Upon receiving a successful response, the `Acme.Web` project constructs an authorization request and redirects the browser to the authorization server. + +```csharp +GET https//auth-server.acme.com/connect/authorize + +Query String Parameters: +client_id: AbpApp +request_uri: urn:ietf:params:oauth:request_uri:1FPVWnrwFAesetV-r-66_b7BAF_vCQm7UmPWfBqRENg +``` + +Similarly, after the user authorizes on the `Acme.AuthServer` project, it returns a `code` to the `Acme.Web` project, which can then be used to request an `access token`, just like in the standard `Code Flow` described above. + +## Configuring and Enabling PAR in ABP Application + +The ABP [OpenIddict module](https://abp.io/modules/Volo.OpenIddict) enables the `PAR` feature by default. + +In ASP.NET Core 9.0, the [OpenIdConnect authentication handler](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.OpenIdConnect)'s [OpenIdConnectOptions](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.openidconnect.openidconnectoptions) includes a new [PushedAuthorizationBehavior](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.openidconnect.openidconnectoptions.pushedauthorizationbehavior) parameter that you can configure in your application. + +| Name | Description| +|-|-| +| UseIfAvailable | Use Pushed Authorization (PAR) if the PAR endpoint is available in the identity provider's discovery document or the explicit OpenIdConnectConfiguration. **This is the default value.** | +| Disable| Never use Pushed Authorization (PAR), even if the PAR endpoint is available in the identity provider's discovery document or the explicit OpenIdConnectConfiguration. If the identity provider's discovery document indicates that it requires Pushed Authorization (PAR), the handler will fail. | +| Require | Always use Pushed Authorization (PAR), and emit errors if the PAR endpoint is not available in the identity provider's discovery document or the explicit OpenIdConnectConfiguration. | + +```csharp +AddAbpOpenIdConnect("oidc", options => +{ + //... + options.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Require; + //... +}); +``` + +The `UseIfAvailable` value is the default behavior, and ABP has enabled the `PAR` endpoint globally. Make sure all your web applications have been granted the `OpenIddictConstants.Permissions.Endpoints.PushedAuthorization` permission to use the PAR endpoint. If not, you should disable the `PushedAuthorizationBehavior` in the `OpenIdConnectOptions`. + +```csharp +AddAbpOpenIdConnect("oidc", options => +{ + //... + options.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Disable; + //... +}); +``` + +> Not all authentication clients support PAR. For example, Blazor WASM does not yet support it. + +## Summary + +`Pushed Authorization Requests (PAR)` is a security enhancement for `OAuth 2.0` that significantly improves the security and reliability of the `authorization code flow`. Given its security benefits, we strongly recommend implementing `PAR` in your production applications. + +## References + +- [Volo.OpenIddict.Pro module](https://abp.io/modules/Volo.OpenIddict.Pro) +- [What Are OAuth Pushed Authorization Requests (PAR)?](https://auth0.com/blog/what-are-oauth-push-authorization-requests-par/) +- [OpenIddict Pushed Authorization Requests (PAR)](https://documentation.openiddict.com/configuration/pushed-authorization-requests) +- [Support for Pushed Authorization (PAR) in OIDC Handler](https://github.com/dotnet/aspnetcore/pull/55069) +- [RFC 9156](https://tools.ietf.org/html/rfc9156) diff --git a/docs/en/Community-Articles/2025-02-16-Using-Pushed-Authorization-Requests-In-ABP-Framework/cover.png b/docs/en/Community-Articles/2025-02-16-Using-Pushed-Authorization-Requests-In-ABP-Framework/cover.png new file mode 100644 index 0000000000..d32c344d8e Binary files /dev/null and b/docs/en/Community-Articles/2025-02-16-Using-Pushed-Authorization-Requests-In-ABP-Framework/cover.png differ diff --git a/docs/en/Community-Articles/2025-02-16-Using-Pushed-Authorization-Requests-In-ABP-Framework/par.png b/docs/en/Community-Articles/2025-02-16-Using-Pushed-Authorization-Requests-In-ABP-Framework/par.png new file mode 100644 index 0000000000..6ea04d502e Binary files /dev/null and b/docs/en/Community-Articles/2025-02-16-Using-Pushed-Authorization-Requests-In-ABP-Framework/par.png differ diff --git a/docs/en/Community-Articles/2025-02-20-Encryption-and-Decryption-in-ABP-Framework/POST.md b/docs/en/Community-Articles/2025-02-20-Encryption-and-Decryption-in-ABP-Framework/POST.md new file mode 100644 index 0000000000..b726f70920 --- /dev/null +++ b/docs/en/Community-Articles/2025-02-20-Encryption-and-Decryption-in-ABP-Framework/POST.md @@ -0,0 +1,70 @@ +# Encryption and Decryption in ABP Framework + +The ABP Framework provides various implementations of encryption and decryption to protect sensitive data. Here are three main encryption scenarios and their implementations: + +## User Passwords + +ABP's Identity module uses HMAC-SHA512 combined with PBKDF2 algorithm for password hashing. The process is as follows: + +- Encryption process: + - System generates a random 128-bit salt + - Combines password and salt, performs 100,000 iterations using HMAC-SHA512 and PBKDF2 algorithms + - Stores the final hash value combined with the salt (Note: stored ciphertext cannot be reversed to plaintext) + +- Verification process: + - System extracts the stored salt + - Recalculates the hash value of the provided password using the same algorithm and iterations + - Compares the results; verification succeeds if matched, fails if not + +## String Encryption + +ABP's `IStringEncryptionService` uses AES algorithm (CBC mode) for string encryption and decryption. It mainly encrypts and decrypts strings like settings and configuration information. The process is as follows: + +- Encryption process: + - Derives encryption key from passphrase and salt using Rfc2898DeriveBytes (PBKDF2) algorithm + - Encrypts using AES algorithm with 256-bit key (controlled by Options.Keysize) + - Uses initialization vector (Options.InitVectorBytes) to ensure encryption security + +- Decryption process: + - Uses the same passphrase and salt + - Goes through the same key derivation process + - Restores the encrypted content to original text + +> Note: If you modify any encryption parameters like passphrase, salt, key size, etc., ensure all applications using encryption use the same parameters, otherwise decryption will fail. For example, encrypted settings in the database will become undecryptable. + +## OAuth2/AuthServer Signing and Encryption + +ABP uses the OpenIddict library for OAuth2 authentication server implementation, which uses two types of credentials to protect generated tokens: + +- Credential types: + - Signing credentials: Prevent token tampering, can be asymmetric (like RSA or ECDSA keys) or symmetric + - Encryption credentials: Ensure token content confidentiality, prevent unauthorized access and reading + +- Environment configuration: + - Development environment: + - Automatically creates two separate RSA certificates + - One for signing, another for encryption + - Production environment: + - ABP Studio generates a single RSA certificate (`openiddict.pfx`) when creating project + - This certificate is used for both signing and encryption operations + +- Custom options: + - Can replace default certificate with self-generated RSA certificate + - Supports symmetric encryption (like AES), but not recommended for production + +## Data Protection + +Besides the above encryption and decryption features, ASP.NET Core's built-in components and services may use data protection, such as encrypting private data in cookies or generating links for email confirmation or password recovery. For details, refer to [ASP.NET Core Data Protection](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/introduction) + +## Summary + +The ABP Framework protects data security through various encryption mechanisms: from HMAC-SHA512 hashing for user passwords, to AES encryption for configuration information, and RSA certificate signing and encryption in OAuth2 authentication, while also integrating ASP.NET Core's data protection features. + +For production environments, it's recommended to use strong passphrases and custom salt values, prioritize asymmetric encryption algorithms, and ensure proper management and backup of all encryption credentials. + +## References + +- [Hash passwords in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/consumer-apis/password-hashing) +- [String Encryption](https://abp.io/docs/latest/framework/infrastructure/string-encryption) +- [Encryption and signing credentials](https://documentation.openiddict.com/configuration/encryption-and-signing-credentials) +- [ASP.NET Core Data Protection](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/introduction) diff --git a/docs/en/Community-Articles/2025-02-20-Using-OutboxInbox-Pattern-for-Reliable-Event-Handling-in-a-Multi-Module-Monolithic-Application/POST.md b/docs/en/Community-Articles/2025-02-20-Using-OutboxInbox-Pattern-for-Reliable-Event-Handling-in-a-Multi-Module-Monolithic-Application/POST.md new file mode 100644 index 0000000000..b3a5b145e9 --- /dev/null +++ b/docs/en/Community-Articles/2025-02-20-Using-OutboxInbox-Pattern-for-Reliable-Event-Handling-in-a-Multi-Module-Monolithic-Application/POST.md @@ -0,0 +1,234 @@ +# Using Outbox/Inbox Pattern for Reliable Event Handling in a Multi-Module Monolithic Application + +This article explains how to implement reliable event handling using the `Outbox/Inbox` pattern in a modular monolithic application with multiple databases. We'll use the `ModularCRM` project as an example (how that project was created is explained in [this document](https://abp.io/docs/latest/tutorials/modular-crm)). + +## Project Background + +`ModularCRM` is a monolithic application that integrates multiple ABP framework open-source modules, including: + +- `Account` +- `Identity` +- `Tenant Management` +- `Permission Management` +- `Setting Management` +- And other open-source modules + +Besides the ABP framework modules, the project contains three business modules: + +- Order module (`Ordering`), using `MongoDB` database +- Product module (`Products`), using `SQL Server` database +- Payment module (`Payment`), using `MongoDB` database + +The project configures separate database connection strings for `ModularCRM` and the three business modules in `appsettings.json`: + +```json +{ + "ConnectionStrings": { + "Default": "Server=localhost,1434;Database=ModularCrm;User Id=sa;Password=1q2w3E***;TrustServerCertificate=true", + "Products": "Server=localhost,1434;Database=ModularCrm_Products;User Id=sa;Password=1q2w3E***;TrustServerCertificate=true", + "Ordering": "mongodb://localhost:27017/ModularCrm_Ordering?replicaSet=rs0", + "Payment": "mongodb://localhost:27017/ModularCrm_Payment?replicaSet=rs0" + } +} +``` + +## Business Scenario + +These modules communicate through the ABP framework's `DistributedEventBus` to implement the following business flow: + +> This is a simple example flow. Real business flows are more complex. The sample code is for demonstration purposes. + +1. Order module: Publishes `OrderPlacedEto` event when an order is placed +2. Product module: Subscribes to `OrderPlacedEto` event and reduce product stock +3. Payment module: Subscribes to `OrderPlacedEto` event, processes payment, then publishes `PaymentCompletedEto` event +4. Order module: Subscribes to `PaymentCompletedEto` event and updates order status to `Delivered` + +When implementing this flow, we need to ensure: + +- Transaction consistency between order creation and event publishing +- Transaction consistency when modules process messages +- Reliable message delivery (including persistence, confirmation, and retry mechanisms) + +Using the default implementation of the ABP framework's distributed event bus cannot meet these requirements, so we need to add a new mechanism that is also provided by the ABP Framework. + +## Outbox/Inbox Pattern Solution + +To meet these requirements, we use the `Outbox/Inbox` pattern: + +### Outbox Pattern + +- Saves distributed events with database operations in the same transaction +- Sends events to distributed message service through background jobs +- Ensures consistency between data updates and event publishing +- Prevents message loss during system failures + +### Inbox Pattern + +- First saves received distributed events to the database +- Processes events in a transactional way +- Ensures messages are processed only once by saving processed message records +- Maintains processing state for reliable handling + +> For how to enable and configure `Outbox/Inbox` in projects and modules, see: https://abp.io/docs/latest/framework/infrastructure/event-bus/distributed#outbox-inbox-for-transactional-events + +### Module Configuration + +Each module needs to configure separate `Outbox/Inbox`. Since it's a monolithic application, all message processing classes are in the same project, so we need to configure `Outbox/Inbox` for each module with `Selector/EventSelector` to ensure that the module only sends and receives the messages it cares about, avoiding message duplication processing. + +**ModularCRM Main Application Configuration** + +It will send and receive messages from all ABP framework open-source modules. + +```csharp +// This selector will match all abp built-in modules and the current module. +Func abpModuleSelector = type => type.Namespace != null && (type.Namespace.StartsWith("Volo.") || type.Assembly == typeof(ModularCrmModule).Assembly); + +Configure(options => +{ + options.Inboxes.Configure("ModularCrm", config => + { + config.UseDbContext(); + config.EventSelector = abpModuleSelector; + config.HandlerSelector = abpModuleSelector; + }); + + options.Outboxes.Configure("ModularCrm", config => + { + config.UseDbContext(); + config.Selector = abpModuleSelector; + }); +}); +``` + +**Order Module Configuration** + +It only sends `OrderPlacedEto` events and receives `PaymentCompletedEto` events and executes `OrderPaymentCompletedEventHandler`. + +```csharp +Configure(options => +{ + options.Inboxes.Configure(OrderingDbProperties.ConnectionStringName, config => + { + config.UseMongoDbContext(); + config.EventSelector = type => type == typeof(PaymentCompletedEto); + config.HandlerSelector = type => type == typeof(OrderPaymentCompletedEventHandler); + }); + + options.Outboxes.Configure(OrderingDbProperties.ConnectionStringName, config => + { + config.UseMongoDbContext(); + config.Selector = type => type == typeof(OrderPlacedEto); + }); +}); +``` + +> Here, the `EventSelector` and `HandlerSelector` checks only a single type. If you have multiple events and event handlers, you can check the given type if it is included in an array of types. + +**Product Module Configuration** + +It only receives `EntityCreatedEto` and `OrderPlacedEto` events and executes `ProductsOrderPlacedEventHandler` and `ProductsUserCreatedEventHandler`. It does not send any events now. + +```csharp +Configure(options => +{ + options.Inboxes.Configure(ProductsDbProperties.ConnectionStringName, config => + { + config.UseDbContext(); + config.EventSelector = type => type == typeof(EntityCreatedEto) || type == typeof(OrderPlacedEto); + config.HandlerSelector = type => type == typeof(ProductsOrderPlacedEventHandler) || type == typeof(ProductsUserCreatedEventHandler); + }); + + // Outboxes are not used in this module + options.Outboxes.Configure(ProductsDbProperties.ConnectionStringName, config => + { + config.UseDbContext(); + config.Selector = type => false; + }); +}); +``` + +**Payment Module Configuration** + +It only sends `PaymentCompletedEto` events and receives `OrderPlacedEto` events and executes `PaymentOrderPlacedEventHandler`. + +```csharp +Configure(options => +{ + options.Inboxes.Configure(PaymentDbProperties.ConnectionStringName, config => + { + config.UseMongoDbContext(); + config.EventSelector = type => type == typeof(OrderPlacedEto); + config.HandlerSelector = type => type == typeof(PaymentOrderPlacedEventHandler); + }); + + options.Outboxes.Configure(PaymentDbProperties.ConnectionStringName, config => + { + config.UseMongoDbContext(); + config.Selector = type => type == typeof(PaymentCompletedEto); + }); +}); +``` + +## Running ModularCRM Simulation Business Flow + +1. Run the following command in the `ModularCrm` directory: + +``` +# Start SQL Server and MongoDB databases in Docker +docker-compose up -d + +# Restore and install project npm dependencies +abp install-lib + +# Migrate databases +dotnet run --project ModularCrm --migrate-database + +# Start the application +dotnet run --project ModularCrm +``` + +2. Navigate to `https://localhost:44303/` to view the application homepage + +![index](index.png) + +3. Enter a customer name and select a product, then submit an order. After a moment, refresh the page to see the order, product, and payment information. + +![order](order.png) + +Application logs display the complete processing flow: + +``` +[Ordering Module] Order created: OrderId: b7ad3f47-0e77-bb81-082f-3a1834503e88, ProductId: 0f95689f-4cb6-36f5-68bd-3a18344d32c9, CustomerName: john + +[Products Module] OrderPlacedEto event received: OrderId: b7ad3f47-0e77-bb81-082f-3a1834503e88, CustomerName: john, ProductId: 0f95689f-4cb6-36f5-68bd-3a18344d32c9 +[Products Module] Stock count decreased for ProductId: 0f95689f-4cb6-36f5-68bd-3a18344d32c9 + +[Payment Module] OrderPlacedEto event received: OrderId: b7ad3f47-0e77-bb81-082f-3a1834503e88, CustomerName: john, ProductId: 0f95689f-4cb6-36f5-68bd-3a18344d32c9 +[Payment Module] Payment processing completed for OrderId: b7ad3f47-0e77-bb81-082f-3a1834503e88 + +[Ordering Module] PaymentCompletedEto event received: OrderId: b7ad3f47-0e77-bb81-082f-3a1834503e88, PaymentId: d0a41ead-ee0f-714c-e254-3a1834504d65, PaymentMethod: CreditCard, PaymentAmount: ModularCrm.Payment.Payment.PaymentCompletedEto +[Ordering Module] Order state updated to Delivered for OrderId: b7ad3f47-0e77-bb81-082f-3a1834503e88 +``` + +In addition, when a new user registers, the product module will also receive the `EntityCreatedEto` event, and we will send an email to the new user, just to demonstrate the `Outbox/Inbox Selector` mechanism. + +``` +[Products Module] UserCreated event received: UserId: "9a1f2bd0-5b28-210a-9e56-3a18344d310a", UserName: admin +[Products Module] Sending a popular products email to admin@abp.io... +``` + +## Summary + +By introducing the `Outbox/Inbox` pattern, we have achieved: + +1. Transactional message sending and receiving +2. Reliable message processing mechanism +3. Modular event processing in a multi-database environment + +ModularCRM project not only implements reliable message processing but also demonstrates how to handle multi-database scenarios gracefully in a monolithic application. Project source code: https://github.com/abpframework/abp-samples/tree/master/ModularCrm-OutboxInbox-Pattern + +## Reference + +- [Outbox/Inbox for transactional events](https://abp.io/docs/latest/framework/infrastructure/event-bus/distributed#outbox-inbox-for-transactional-events) +- [ConnectionStrings](https://abp.io/docs/latest/framework/fundamentals/connection-strings) +- [ABP Studio: Single Layer Solution Template](https://abp.io/docs/latest/solution-templates/single-layer-web-application) diff --git a/docs/en/Community-Articles/2025-02-20-Using-OutboxInbox-Pattern-for-Reliable-Event-Handling-in-a-Multi-Module-Monolithic-Application/index.png b/docs/en/Community-Articles/2025-02-20-Using-OutboxInbox-Pattern-for-Reliable-Event-Handling-in-a-Multi-Module-Monolithic-Application/index.png new file mode 100644 index 0000000000..cadd2c29c1 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-20-Using-OutboxInbox-Pattern-for-Reliable-Event-Handling-in-a-Multi-Module-Monolithic-Application/index.png differ diff --git a/docs/en/Community-Articles/2025-02-20-Using-OutboxInbox-Pattern-for-Reliable-Event-Handling-in-a-Multi-Module-Monolithic-Application/order.png b/docs/en/Community-Articles/2025-02-20-Using-OutboxInbox-Pattern-for-Reliable-Event-Handling-in-a-Multi-Module-Monolithic-Application/order.png new file mode 100644 index 0000000000..4c66eff9c0 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-20-Using-OutboxInbox-Pattern-for-Reliable-Event-Handling-in-a-Multi-Module-Monolithic-Application/order.png differ diff --git a/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/3a183abfe065ba8bacdd56ef05d9a4cd.jpg b/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/3a183abfe065ba8bacdd56ef05d9a4cd.jpg new file mode 100644 index 0000000000..a84abea379 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/3a183abfe065ba8bacdd56ef05d9a4cd.jpg differ diff --git a/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/3a183ac7b768a9a7523278ab07847b3c.jpg b/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/3a183ac7b768a9a7523278ab07847b3c.jpg new file mode 100644 index 0000000000..2a279d7ad2 Binary files /dev/null and b/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/3a183ac7b768a9a7523278ab07847b3c.jpg differ diff --git a/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/3a183ac7c4767cabf12d657ac90f4c17.jpg b/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/3a183ac7c4767cabf12d657ac90f4c17.jpg new file mode 100644 index 0000000000..57a50c2c6e Binary files /dev/null and b/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/3a183ac7c4767cabf12d657ac90f4c17.jpg differ diff --git a/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/post.md b/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/post.md new file mode 100644 index 0000000000..98b924409b --- /dev/null +++ b/docs/en/Community-Articles/2025-02-21-catch-us-at-basta-frankfurt-2025/post.md @@ -0,0 +1,28 @@ +We are excited to share some fantastic news with our community! We are proud to announce that ABP.IO is going to be at the BASTA! Conference on March 03-07, 2025 in Frankfurt and İsmail Çağdaş from our dev team is going to be a speaker on March 04! + +#### **About BASTA!** +For those who don’t know, BASTA! is the leading independent conference for Microsoft technologies in the German-speaking world. For over 20 years, it has been setting standards in the areas of C#, .NET and cloud and web technologies and is considered a must-attend event for Microsoft, cloud, web developers and key players in the software industry. BASTA! is a conference for developers and IT professionals who want to stay up to date with the latest technologies. + +#### **ABP at [BASTA! Mainz 2023](https://abp.io/blog/BASTA-Mainz-2023-What-a-Blast-in-Germany)** +![basta 2023.jpg](3a183abfe065ba8bacdd56ef05d9a4cd.jpg) + +![2222.jpg](3a183ac7b768a9a7523278ab07847b3c.jpg) + +![3333.jpg](3a183ac7c4767cabf12d657ac90f4c17.jpg) +##### +#### **What to Expect at [BASTA! 2025](https://basta.net/frankfurt-en/)** +The most exciting part is İsmail Çağdaş from the ABP developer team will be speaking at the conference on March 04 about the concepts of monoliths and microservices will be briefly explored, along with how modular monoliths bring together the advantages of these two architectures. Using the ABP Framework as an example, the session will highlight its modularity features and demonstrate how it can assist in creating and developing a modular monolith application. Finally, best practices for developing modular monoliths will be discussed, showing how these practices can pave the way for transitioning to a microservice-based architecture when necessary. + +If you want to find out more information about İsmail Çağdaş's session, [check here](https://basta.net/microservices-apis/modular-monoliths-architecture-abp/?loc=ffm): + +#### **Connect with Us** +We have exciting raffles and surprises planned at our booth and look forward to sharing more information about our solutions with you there. + +#### **Join Us Online** +Don't worry if you can't join us in person, our online booth is going to be there for you! The Expo of the online version of BASTA! is open for the main conference days. + +Tuesday, March 4, 2025: 9:00 am – approx. 6:00 pm + +Wednesday, March 5, 2025: 9:00 am – approx. 6:00 pm + +Thursday, March 6, 2025: 9:00 am – approx. 5:45 pm diff --git a/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250304_122158.webp b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250304_122158.webp new file mode 100644 index 0000000000..0157ed9011 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250304_122158.webp differ diff --git a/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250304_153010.webp b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250304_153010.webp new file mode 100644 index 0000000000..3d563385fe Binary files /dev/null and b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250304_153010.webp differ diff --git a/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250304_153413.webp b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250304_153413.webp new file mode 100644 index 0000000000..c6789858c7 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250304_153413.webp differ diff --git a/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250305_151043.webp b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250305_151043.webp new file mode 100644 index 0000000000..13feb34d6b Binary files /dev/null and b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/20250305_151043.webp differ diff --git a/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/IMG_4732-2000px.webp b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/IMG_4732-2000px.webp new file mode 100644 index 0000000000..9b566f8509 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/IMG_4732-2000px.webp differ diff --git a/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/IMG_4770-2000px.webp b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/IMG_4770-2000px.webp new file mode 100644 index 0000000000..6f0b03ffa4 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/IMG_4770-2000px.webp differ diff --git a/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/IMG_4915-2000px.webp b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/IMG_4915-2000px.webp new file mode 100644 index 0000000000..fc30a3d4b2 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/IMG_4915-2000px.webp differ diff --git a/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/Screenshot_2025-03-04_at_13.47.28.webp b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/Screenshot_2025-03-04_at_13.47.28.webp new file mode 100644 index 0000000000..4df621a674 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/Screenshot_2025-03-04_at_13.47.28.webp differ diff --git a/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/post.md b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/post.md new file mode 100644 index 0000000000..7f11d88059 --- /dev/null +++ b/docs/en/Community-Articles/2025-03-10-WE-HAD-A-BLAST-AT-BASTA-FRANKFURT-2025/post.md @@ -0,0 +1,39 @@ +![](20250304_122158.webp) + +Our team had an amazing time at BASTA\! Frankfurt 2025, held from March 3 to 8 at the Frankfurt am Main Marriott Hotel. As a sponsor for this major conference for asp.net web developers, we were thrilled to connect with so many talented participants. + +**Event Highlights** + +![](20250304_153010.webp) + +![](20250304_153413.webp) + +The conference hosted many talented developers as speakers. One of them was İsmail Çağdaş who’s a lead developer from ABP team who talked about the concepts of monoliths and microservices. He explained how modular monoliths combine the strengths of these two architectures, using the ABP Framework as an example to showcase its modularity features and demonstrate how to build and develop a modular monolith application. + +**ABP’S Presence** + +![](IMG_4732-2000px.webp) + +![](IMG_4770-2000px.webp) + +At our booth we displayed the latest features of the ABP Framework and gathered valuable feedback from especially dotnet developers. So many attendees showed interest in ABP which was very exciting. It was great engaging with so many participants who wanted to learn more about how ABP provides the infrastructure and tools to create business solutions. + +We're also very grateful to our booth neighbor, Xceed and it was a lot of fun connecting with them during the conference. For those who don’t know, Xceed provides comprehensive UI components that allow developers to focus on innovation and their business requirements. + +**Networking and Community Engagement** + +We organized two raffles during the event, where attendees had the chance to win 2 great prizes. One attendee won a LEGO set and another won an Amazon Kindle. We were happy to see many people attending our raffles, it definitely made this event more fun. Congratulations to the winners and thanks to those who participated\! + +![](IMG_4915-2000px.webp) + +![](20250305_151043.webp) + +**Looking Ahead** + +BASTA\! Frankfurt 2025 strengthened our commitment to the developer community. We want to continue our support for asp.net core developers, helping them create asp.net applications and optimize their workflows for web applications. + +**Gratitude and Future Events** + +Thank you to the organizers, speakers, and attendees for making BASTA\! Frankfurt 2025 such a fantastic experience. We look forward to future events and continued contributions to the net framework developers. + +We look forward to sharing more updates with you soon. We hope to see you at our next event\! diff --git a/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/abp-js-proxy.png b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/abp-js-proxy.png new file mode 100644 index 0000000000..d7cfd05c5e Binary files /dev/null and b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/abp-js-proxy.png differ diff --git a/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/post.md b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/post.md new file mode 100644 index 0000000000..bc0b390b03 --- /dev/null +++ b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/post.md @@ -0,0 +1,324 @@ +# Using Vue components in a Razor Pages ABP Application + +In modern web development, integrating dynamic front-end frameworks with server-side technologies has become increasingly essential for creating responsive and interactive applications. This article explores how to effectively use Vue components within Razor Pages in an ABP Framework application. We will delve into the process of consuming endpoints through ABP Client Proxies, leveraging ABP's powerful localization features to enhance user experience, and implementing ABP permissions to ensure secure access control. By the end of this guide, you will have a comprehensive understanding of how to seamlessly blend Vue.js with Razor Pages, empowering you to build robust and user-friendly applications. + +This article won't use any SPA approach. The goal of this article is to use Razor Pages with simple Vue components to eliminate jQuery while developing MVC application. + +> **🎉 Also video version is available!** +> +> [Watch on YouTube Now!](https://youtu.be/sZ8iSMovHZs?si=GynuJjsLEI1p2g6w) + +## Creating the Solution + +Let's create a simple TODO list application to demonstrate how to use Vue components in Razor Pages. I'll build a really simple backend without a connection to a database for demonstration purposes. We will focus on the frontend part. + +- Creating a solution with ABP CLI: + +```bash +abp new MyTodoApp -t app-nolayers -csf +``` + +## Configure Vue + +We need to add the `@abp/vue` package to the project to use Vue components. + +```bash +npm install @abp/vue +``` + +- Install client libraries by using ABP CLI: + +```bash +abp install-libs +``` + +As a last step, we need to configure our bundle in the `ConfigureBundles` method in the `MyTodoAppModule.cs` file: + +```csharp +private void ConfigureBundles() +{ + Configure(options => + { + // ... + + options.ScriptBundles.Configure( + // Or BasicThemeBundles.Scripts.Global + // Or LeptonXLiteThemeBundles.Scripts.Global + // 👇 Depends on the theme you are using + LeptonXThemeBundles.Scripts.Global, + bundle => + { + bundle.AddFiles("/global-scripts.js"); + // 👇 Make sure to add this line + bundle.AddContributors(typeof(VueScriptContributor)); + } + ); + }); +} +``` + +> If your IDE doesn't recognize the namespace of the `VueScriptContributor`, you can add it manually: +> +> ```csharp +> using Volo.Abp.AspNetCore.Mvc.UI.Packages.Vue; +> ``` + +Now we're ready to use Vue components in our Razor Pages. + +## Creating a Vue Component + +Let's create a simple Vue component to display the TODO list. + +### Passing a simple message to the component + +- Remove existing HTML codes in `Index.cshtml` and replace with the following code: + +```html +
+ +
+``` + +- Navigate to the `Index.cshtml.js` file and add the following code: +```js +Vue.component('message-component', { + template: '
Hello, {{ message }}
', + props: ['message'] +}); + +new Vue({ + el: '#vue-app' +}); +``` + +Run the application and you should see the following output: + +![Vue Component](./vue-message.png) + +> _Hard refresh might be required to see the component since we added a new vue js file to the bundle._ +> +> If still you can't see the component, please check the browser console for any errors. + +### Interacting with the component + +Let's add a button to the component to interact with the component. + +- Add another component in the `Index.cshtml` file: + +```html +
+ + +
+``` + +```js +Vue.component('counter-component', { + template:` +
+
+

Count: {{ count }}

+ +
+
+ `, + data: function () { + return { + count: 0 + }; + }, + methods: { + increment: function () { + this.count++; + } + } +}); +``` + +> _Do not replicate `new Vue({})` code block in the file. It's already in the `Index.cshtml.js` file. Keep it at the bottom of the file as it is._ + +Run the application and you should see the following output: + +![Vue Component](./vue-counter-result.gif) + + +## Using ABP Client Proxy, Authorization and Localization + + +### Building the backend +Before we go, let's build our backend to use in the component. + +- Creating a simple Application Service: + +```csharp +public class TodoAppService : MyTodoAppAppService, ITodoAppService +{ + public static List Items { get; } = new List(); + + [Authorize("Todo.Create")] + public async Task AddTodoItemAsync(TodoItem input) + { + Items.Add(input); + return input; + } + + [Authorize("Todo")] + public async Task> GetAllAsync() + { + await Task.Delay(1500); + return Items; + } +} +``` + +- `TodoItem.cs` + +```csharp +public class TodoItem +{ + public string Description { get; set; } + public bool IsDone { get; set; } +} +``` + +- `ITodoAppService.cs` + +```csharp +public interface ITodoAppService +{ + Task> GetAllAsync(); + Task AddTodoItemAsync(TodoItem input); +} +``` + +- Run the application and if you can see the following client proxy in the browser console, you're ready to go: + + ![Client Proxy](./abp-js-proxy.png) + +> [!NOTE] +> If you can't see the client proxy in the browser console, please check the [Dynamic JavaScript Proxies](https://abp.io/docs/latest/framework/ui/mvc-razor-pages/dynamic-javascript-proxies) to learn how to enable it. + +- Add a new permission in the `MyTodoAppPermissionDefinitionProvider.cs` file: +```csharp +public override void Define(IPermissionDefinitionContext context) +{ + var myGroup = context.AddGroup(MyTodoAppPermissions.GroupName); + + var todo = myGroup.AddPermission("Todo"); + todo.AddChild("Todo.Create"); +} +``` +> _I go without localization or constants for simplicity._ + +- Add a localization key in the `en.json` file: + +```json +{ + "TodoItems": "Todo Items Localized" +} +``` + +### Building the Vue Component: Using ABP Localization, Authorization and Client Proxy + +Since the component it directly loaded into the page, we can access the `abp` object on the page. + +So we can use: + +- `abp.localization.localize()` to localize a string. +- `abp.auth.isGranted()` to check the authorization. +- `myTodoApp.todo.getAll()` and `myTodoApp.todo.addTodoItem` to call the Application Service. + +inside **Vue Component** code. + +- Let's add another component named `todo-component` and usee all the **ABP Features** in it. + +```html +
+ + +
+``` + +- Implement the `todo-component` in `Index.cshtml.js` file: + +```js +Vue.component('todo-component', { + template: ` +
+
+

{{ abp.localization.localize('TodoItems') }}

+
+
+
+
+ Loading... +
+
+
    +
  • + + +
  • +
+

No todos yet

+
+ +
+ `, + data: function () { + return { + newTodo: { + description: '', + isDone: false + }, + isBusy: false, + todos: [] + }; + }, + methods: { + addTodo() { + myTodoApp.todo.addTodoItem(this.newTodo); + this.newTodo = { description: '', isDone: false }; + this.todos.push(this.newTodo); + + // Preferrable, you can load entire list of todos again. + // this.loadTodos(); + }, + async loadTodos() { + if (!abp.auth.isGranted('Todo')) { + return; + } + this.isBusy = true; + this.todos = await myTodoApp.todo.getAll(); + this.isBusy = false; + } + }, + mounted() { + this.loadTodos(); + } +}); +``` + +And see the result: + +![Vue Component](./todo-component-result.gif) + + +Since we use `abp.auth.isGranted()` to check the authorization, we can see the component only if we have the permission. + +Whenever you remove `Todo.Create` permission, you can see the component is not rendered. + +![Todo Permission](./todo-permission.png) + + +You won't see the card footer: + +![Todo Permission](./todo-permission-vue.png) diff --git a/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/todo-component-result.gif b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/todo-component-result.gif new file mode 100644 index 0000000000..2eb50ee5c3 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/todo-component-result.gif differ diff --git a/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/todo-permission-vue.png b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/todo-permission-vue.png new file mode 100644 index 0000000000..10a11c146f Binary files /dev/null and b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/todo-permission-vue.png differ diff --git a/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/todo-permission.png b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/todo-permission.png new file mode 100644 index 0000000000..f68e6eb20c Binary files /dev/null and b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/todo-permission.png differ diff --git a/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/vue-counter-result.gif b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/vue-counter-result.gif new file mode 100644 index 0000000000..656f001535 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/vue-counter-result.gif differ diff --git a/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/vue-message.png b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/vue-message.png new file mode 100644 index 0000000000..a61963af44 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-18-Using-Vue-Components/vue-message.png differ diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 5bcb0d9b26..d6d24fa271 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -130,7 +130,7 @@ { "text": "Book Store Application (with ABP Suite)", "isLazyExpandable": true, - "path": "tutorials/book-store-with-abp-suite/index.md", + "path": "tutorials/book-store-with-abp-suite", "items": [ { "text": "Overview", @@ -162,11 +162,11 @@ { "text": "Modular Monolith Application", "isLazyExpandable": true, - "path": "tutorials/modular-crm/index.md", + "path": "tutorials/modular-crm", "items": [ { "text": "Overview", - "path": "tutorials/modular-crm/index.md", + "path": "tutorials/modular-crm", "isIndex": true }, { @@ -206,11 +206,11 @@ { "text": "Microservice Solution", "isLazyExpandable": true, - "path": "tutorials/microservice/index.md", + "path": "tutorials/microservice", "items": [ { "text": "Overview", - "path": "tutorials/microservice/index.md", + "path": "tutorials/microservice", "isIndex": true }, { @@ -246,19 +246,19 @@ { "text": "Mobile Application Development", "isLazyExpandable": true, - "path": "tutorials/mobile/index.md", + "path": "tutorials/mobile", "items": [ { "text": "Overview", - "path": "tutorials/mobile/index.md" + "path": "tutorials/mobile" }, { "text": "MAUI", - "path": "tutorials/mobile/maui/index.md" + "path": "tutorials/mobile/maui" }, { "text": "React Native", - "path": "tutorials/mobile/react-native/index.md" + "path": "tutorials/mobile/react-native" } ] }, @@ -487,7 +487,8 @@ }, { "text": "Exception Handling", - "path": "framework/fundamentals/exception-handling.md" + "path": "framework/fundamentals/exception-handling.md", + "keywords": ["Error"] }, { "text": "Localization", @@ -2620,7 +2621,7 @@ }, { "text": "Knowledge Base", - "path": "kb/index.md" + "path": "kb" }, { "text": "Penetration Test Report", diff --git a/docs/en/framework/architecture/best-practices/mongodb-integration.md b/docs/en/framework/architecture/best-practices/mongodb-integration.md index 1930984e2e..c39f6443a0 100644 --- a/docs/en/framework/architecture/best-practices/mongodb-integration.md +++ b/docs/en/framework/architecture/best-practices/mongodb-integration.md @@ -114,7 +114,7 @@ public async Task FindByNormalizedUserNameAsync( bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync()) + return await (await GetQueryableAsync()) .FirstOrDefaultAsync( u => u.NormalizedUserName == normalizedUserName, GetCancellationToken(cancellationToken) @@ -125,10 +125,10 @@ public async Task FindByNormalizedUserNameAsync( `GetCancellationToken` fallbacks to the `ICancellationTokenProvider.Token` to obtain the cancellation token if it is not provided by the caller code. * **Do** ignore the `includeDetails` parameters for the repository implementation since MongoDB loads the aggregate root as a whole (including sub collections) by default. -* **Do** use the `GetMongoQueryableAsync()` method to obtain an `IQueryable` to perform queries wherever possible. Because; - * `GetMongoQueryableAsync()` method automatically uses the `ApplyDataFilters` method to filter the data based on the current data filters (like soft delete and multi-tenancy). +* **Do** use the `GetQueryableAsync()` method to obtain an `IQueryable` to perform queries wherever possible. Because; + * `GetQueryableAsync()` method automatically uses the `ApplyDataFilters` method to filter the data based on the current data filters (like soft delete and multi-tenancy). * Using `IQueryable` makes the code as much as similar to the EF Core repository implementation and easy to write and read. -* **Do** implement data filtering if it is not possible to use the `GetMongoQueryable()` method. +* **Do** implement data filtering if it is not possible to use the `GetQueryableAsync()` method. ## Module Class diff --git a/docs/en/framework/architecture/domain-driven-design/repositories.md b/docs/en/framework/architecture/domain-driven-design/repositories.md index 9050e7d3c3..04848a59e8 100644 --- a/docs/en/framework/architecture/domain-driven-design/repositories.md +++ b/docs/en/framework/architecture/domain-driven-design/repositories.md @@ -393,19 +393,6 @@ This method is suggested; * If you are developing an application and you **don't plan to change** EF Core in the future, or you can **tolerate** it if you need to change it later. We believe that's reasonable if you are developing a final application. -#### MongoDB Case - -If you are using [MongoDB](../../data/mongodb), you need to add the [Volo.Abp.MongoDB](https://www.nuget.org/packages/Volo.Abp.MongoDB) NuGet package to your project. Even in this case, you can't directly use async LINQ extensions (like `ToListAsync`) because MongoDB doesn't provide async extension methods for `IQueryable`, but provides for `IMongoQueryable`. You need to cast the query to `IMongoQueryable` first to be able to use the async extension methods. - -**Example: Cast `IQueryable` to `IMongoQueryable` and use `ToListAsync()`** - -````csharp -var queryable = await _personRepository.GetQueryableAsync(); -var people = ((IMongoQueryable) queryable - .Where(p => p.Name.Contains(nameFilter))) - .ToListAsync(); -```` - ### Option-2: Use the IRepository Async Extension Methods ABP provides async extension methods for the repositories, just similar to async LINQ extension methods. diff --git a/docs/en/framework/infrastructure/background-jobs/index.md b/docs/en/framework/infrastructure/background-jobs/index.md index 35f761ddf1..5aa58a7d3e 100644 --- a/docs/en/framework/infrastructure/background-jobs/index.md +++ b/docs/en/framework/infrastructure/background-jobs/index.md @@ -236,6 +236,79 @@ Background Jobs module implements `IBackgroundJobStore` using various data acces > Background Jobs module is already installed to the startup templates by default and it works based on your ORM/data access choice. +### Using the Same Storage for Background Jobs & Workers + +If multiple applications share the same storage for background jobs and workers (`Default, Hangfire, RabbitMQ, and Quartz`), you should configure the provider options to use the application name for isolation. + +#### Default Background Job/Workers + +Set `ApplicationName` property in `AbpBackgroundJobWorkerOptions` to your application's name: + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(options => + { + options.ApplicationName = context.Services.GetApplicationName()!; + }); +} +```` + +#### Hangfire Background Job/Workers + +Set `DefaultQueuePrefix` property in `AbpHangfireOptions` to your application's name: + +````csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + Configure(options => + { + options.DefaultQueuePrefix = context.Services.GetApplicationName()!; + }); +} +```` + +#### Quartz Background Job/Workers + +Set the `quartz.scheduler.instanceName` property to your application's name: + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + var configuration = context.Services.GetConfiguration(); + PreConfigure(options => + { + options.Properties = new NameValueCollection + { + ["quartz.scheduler.instanceName"] = context.Services.GetApplicationName(), + + ["quartz.jobStore.dataSource"] = "BackgroundJobsDemoApp", + ["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz", + ["quartz.jobStore.tablePrefix"] = "QRTZ_", + ["quartz.serializer.type"] = "json", + ["quartz.dataSource.BackgroundJobsDemoApp.connectionString"] = configuration.GetConnectionString("Default"), + ["quartz.dataSource.BackgroundJobsDemoApp.provider"] = "SqlServer", + ["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz", + }; + }); +} +```` + +#### RabbitMQ Background Job + +Set `DefaultQueueNamePrefix` and `DefaultDelayedQueueNamePrefix` properties in `AbpRabbitMqBackgroundJobOptions` to your application's name: + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(options => + { + options.DefaultQueueNamePrefix = context.Services.GetApplicationName()!.EndsWith('.') + options.DefaultQueueNamePrefix; + options.DefaultDelayedQueueNamePrefix = context.Services.GetApplicationName()!.EndsWith('.') + options.DefaultDelayedQueueNamePrefix; + }); +} +```` + ### Clustered Deployment The default background job manager is compatible with [clustered environments](../../../deployment/clustered-environment.md) (where multiple instances of your application run concurrently). It uses a [distributed lock](../distributed-locking.md) to ensure that the jobs are executed only in a single application instance at a time. diff --git a/docs/en/framework/infrastructure/background-workers/index.md b/docs/en/framework/infrastructure/background-workers/index.md index 9f5d15e114..884ea60c25 100644 --- a/docs/en/framework/infrastructure/background-workers/index.md +++ b/docs/en/framework/infrastructure/background-workers/index.md @@ -132,6 +132,80 @@ If that's a problem for your workers, you have the following options: * Stop the background workers (set `AbpBackgroundWorkerOptions.IsEnabled` to `false`) in all application instances except one of them, so only the single instance runs the workers. * Stop the background workers (set `AbpBackgroundWorkerOptions.IsEnabled` to `false`) in all application instances and create a dedicated application (maybe a console application running in its own container or a Windows Service running in the background) to execute all the background tasks. This can be a good option if your background workers consume high system resources (CPU, RAM or Disk), so you can deploy that background application to a dedicated server and your background tasks don't affect your application's performance. + +### Using the Same Storage for Background Jobs & Workers + +If multiple applications share the same storage for background jobs and workers (`Default, Hangfire, RabbitMQ, and Quartz`), you should configure the provider options to use the application name for isolation. + +#### Default Background Job/Workers + +Set `ApplicationName` property in `AbpBackgroundJobWorkerOptions` to your application's name: + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(options => + { + options.ApplicationName = context.Services.GetApplicationName()!; + }); +} +```` + +#### Hangfire Background Job/Workers + +Set `DefaultQueuePrefix` property in `AbpHangfireOptions` to your application's name: + +````csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + Configure(options => + { + options.DefaultQueuePrefix = context.Services.GetApplicationName()!; + }); +} +```` + +#### Quartz Background Job/Workers + +Set `quartz.scheduler.instanceName` property to your application's name: + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + var configuration = context.Services.GetConfiguration(); + PreConfigure(options => + { + options.Properties = new NameValueCollection + { + ["quartz.scheduler.instanceName"] = context.Services.GetApplicationName(), + + ["quartz.jobStore.dataSource"] = "BackgroundJobsDemoApp", + ["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz", + ["quartz.jobStore.tablePrefix"] = "QRTZ_", + ["quartz.serializer.type"] = "json", + ["quartz.dataSource.BackgroundJobsDemoApp.connectionString"] = configuration.GetConnectionString("Default"), + ["quartz.dataSource.BackgroundJobsDemoApp.provider"] = "SqlServer", + ["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz", + }; + }); +} +```` + +#### RabbitMQ Background Job + +Set `DefaultQueueNamePrefix` and `DefaultDelayedQueueNamePrefix` properties in `AbpRabbitMqBackgroundJobOptions` to your application's name: + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(options => + { + options.DefaultQueueNamePrefix = context.Services.GetApplicationName()!.EndsWith('.') + options.DefaultQueueNamePrefix; + options.DefaultDelayedQueueNamePrefix = context.Services.GetApplicationName()!.EndsWith('.') + options.DefaultDelayedQueueNamePrefix; + }); +} +```` + ## Integrations Background worker system is extensible and you can change the default background worker manager with your own implementation or on of the pre-built integrations. diff --git a/docs/en/framework/infrastructure/blob-storing/bunny.md b/docs/en/framework/infrastructure/blob-storing/bunny.md new file mode 100644 index 0000000000..4c5fb5ef0f --- /dev/null +++ b/docs/en/framework/infrastructure/blob-storing/bunny.md @@ -0,0 +1,64 @@ +# BLOB Storing Bunny Provider + +BLOB Storing Bunny Provider can store BLOBs in [bunny.net Storage](https://bunny.net/storage/). + +> Read the [BLOB Storing document](../blob-storing) to understand how to use the BLOB storing system. This document only covers how to configure containers to use a Bunny BLOB as the storage provider. + +## Installation + +Use the ABP CLI to add [Volo.Abp.BlobStoring.Bunny](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Bunny) NuGet package to your project: + +* Install the [ABP CLI](../../../cli) if you haven't installed before. +* Open a command line (terminal) in the directory of the `.csproj` file you want to add the `Volo.Abp.BlobStoring.Bunny` package. +* Run `abp add-package Volo.Abp.BlobStoring.Bunny` command. + +If you want to do it manually, install the [Volo.Abp.BlobStoring.Bunny](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Bunny) NuGet package to your project and add `[DependsOn(typeof(AbpBlobStoringBunnyModule))]` to the [ABP module](../../architecture/modularity/basics.md) class inside your project. + +## Configuration + +Configuration is done in the `ConfigureServices` method of your [module](../../architecture/modularity/basics.md) class, as explained in the [BLOB Storing document](../blob-storing). + +**Example: Configure to use the Bunny storage provider by default** + +````csharp +Configure(options => +{ + options.Containers.ConfigureDefault(container => + { + container.UseBunny(Bunny => + { + Bunny.AccessKey = "your Bunny account access key"; + Bunny.Region = "the code of the main storage zone region"; // "de" is the default value + Bunny.ContainerName = "your bunny storage zone name"; + Bunny.CreateContainerIfNotExists = true; + }); + }); +}); + +```` + +> See the [BLOB Storing document](../blob-storing) to learn how to configure this provider for a specific container. + +### Options + +* **AccessKey** (string): Bunny Account Access Key. [Where do I find my Access key?](https://support.bunny.net/hc/en-us/articles/360012168840-Where-do-I-find-my-API-key) +* **Region** (string?): The code of the main storage zone region (Possible values: DE, NY, LA, SG). +* **ContainerName** (string): You can specify the container name in Bunny. If this is not specified, it uses the name of the BLOB container defined with the `BlobContainerName` attribute (see the [BLOB storing document](../blob-storing)). Please note that Bunny has some **rules for naming containers**: + * Storage Zone names must be a globaly unique. + * Storage Zone names must be between **4** and **64** characters long. + * Storage Zone names can consist only of **lowercase** letters, numbers, and hyphens (-). +* **CreateContainerIfNotExists** (bool): Default value is `false`, If a container does not exist in Bunny, `BunnyBlobProvider` will try to create it. + +## Bunny Blob Name Calculator + +Bunny Blob Provider organizes BLOB name and implements some conventions. The full name of a BLOB is determined by the following rules by default: + +* Appends `host` string if [current tenant](../../architecture/multi-tenancy) is `null` (or multi-tenancy is disabled for the container - see the [BLOB Storing document](../blob-storing) to learn how to disable multi-tenancy for a container). +* Appends `tenants/` string if current tenant is not `null`. +* Appends the BLOB name. + +## Other Services + +* `BunnyBlobProvider` is the main service that implements the Bunny BLOB storage provider, if you want to override/replace it via [dependency injection](../../fundamentals/dependency-injection.md) (don't replace `IBlobProvider` interface, but replace `BunnyBlobProvider` class). +* `IBunnyBlobNameCalculator` is used to calculate the full BLOB name (that is explained above). It is implemented by the `DefaultBunnyBlobNameCalculator` by default. +* `IBunnyClientFactory` is implemented by `DefaultBunnyClientFactory` by default. You can override/replace it,if you want customize. diff --git a/docs/en/framework/infrastructure/blob-storing/index.md b/docs/en/framework/infrastructure/blob-storing/index.md index f95a90e410..676757ad80 100644 --- a/docs/en/framework/infrastructure/blob-storing/index.md +++ b/docs/en/framework/infrastructure/blob-storing/index.md @@ -23,6 +23,7 @@ The ABP has already the following storage provider implementations: * [Minio](./minio.md): Stores BLOBs on the [MinIO Object storage](https://min.io/). * [Aws](./aws.md): Stores BLOBs on the [Amazon Simple Storage Service](https://aws.amazon.com/s3/). * [Google](./google.md): Stores BLOBs on the [Google Cloud Storage](https://cloud.google.com/storage). +* [Bunny](./bunny.md): Stores BLOBs on the [Bunny.net Storage](https://bunny.net/storage/). More providers will be implemented by the time. You can [request](https://github.com/abpframework/abp/issues/new) it for your favorite provider or [create it yourself](./custom-provider.md) and [contribute](../../../contribution) to the ABP. diff --git a/docs/en/framework/infrastructure/entity-cache.md b/docs/en/framework/infrastructure/entity-cache.md index 03d0e8c548..64a03ad4c4 100644 --- a/docs/en/framework/infrastructure/entity-cache.md +++ b/docs/en/framework/infrastructure/entity-cache.md @@ -12,6 +12,11 @@ ABP provides an entity caching system that works on top of the [distributed cach ```csharp public class Product : AggregateRoot { + public Product(Guid id) + { + Id = id; + } + public string Name { get; set; } public string Description { get; set; } public float Price { get; set; } diff --git a/docs/en/framework/ui/angular/images/angular-advanced-entity-filters-with-custom-content-above-filter.png b/docs/en/framework/ui/angular/images/angular-advanced-entity-filters-with-custom-content-above-filter.png index ac81a885ec..3ad1593e42 100644 Binary files a/docs/en/framework/ui/angular/images/angular-advanced-entity-filters-with-custom-content-above-filter.png and b/docs/en/framework/ui/angular/images/angular-advanced-entity-filters-with-custom-content-above-filter.png differ diff --git a/docs/en/framework/ui/angular/images/angular-advanced-entity-filters-with-form.png b/docs/en/framework/ui/angular/images/angular-advanced-entity-filters-with-form.png index d0827ed369..cd8f091379 100644 Binary files a/docs/en/framework/ui/angular/images/angular-advanced-entity-filters-with-form.png and b/docs/en/framework/ui/angular/images/angular-advanced-entity-filters-with-form.png differ diff --git a/docs/en/framework/ui/angular/images/angular-advanced-entity-filters.png b/docs/en/framework/ui/angular/images/angular-advanced-entity-filters.png index 5ae22b56a4..5a9b3f84ef 100644 Binary files a/docs/en/framework/ui/angular/images/angular-advanced-entity-filters.png and b/docs/en/framework/ui/angular/images/angular-advanced-entity-filters.png differ diff --git a/docs/en/framework/ui/blazor/toolbars.md b/docs/en/framework/ui/blazor/toolbars.md index b365116b2d..8ed30f1364 100644 --- a/docs/en/framework/ui/blazor/toolbars.md +++ b/docs/en/framework/ui/blazor/toolbars.md @@ -8,12 +8,26 @@ There is only one **standard toolbar** named "Main" (defined as a constant: `Sta In the screenshot above, there are two items added to the main toolbar: Language switch component & user menu. You can add your own items here. -Also, [LeptonX Lite Theme](../../../ui-themes/lepton-x-lite/blazor.md) has 2 different toolbars for desktop and mobile views which defined as constants: `LeptonXLiteToolbars.Main`, `LeptonXLiteToolbars.MainMobile`. +Also, [LeptonX Lite Theme](../../../ui-themes/lepton-x-lite/blazor.md) and [LeptonX Theme](../../../ui-themes/lepton-x/blazor.md) has 2 different toolbars for desktop and mobile views which defined as constants. + +**LeptonX Lite Theme** + +- `LeptonXLiteToolbars.Main` +- `LeptonXLiteToolbars.MainMobile` | LeptonXLiteToolbars.Main | LeptonXLiteToolbars.MainMobile | | :---: | :---: | | ![leptonx](../../../images/leptonxlite-toolbar-main-example.png) | ![leptonx](../../../images/leptonxlite-toolbar-mainmobile-example.png) | +**LeptonX Theme** + +- `LeptonXToolbars.Main` +- `LeptonXToolbars.MainMobile` + +| LeptonXToolbars.Main | LeptonXToolbars.MainMobile | +| :---: | :---: | +| ![leptonx](../../../images/leptonx-toolbar-main-example.png) | ![leptonx](../../../images/leptonx-toolbar-mainmobile-example.png) | + ## Example: Add a Notification Icon In this example, we will add a **notification (bell) icon** to the left of the language switch item. A item in the toolbar should be a **Razor Component**. So, first, create a new razor component in your project (the location of the component doesn't matter): diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md index 970d35b851..043f811d49 100644 --- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md +++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md @@ -1,6 +1,6 @@ # ASP.NET Core MVC / Razor Pages UI: JavaScript Notify API -Notify API is used to show toast style, auto disappearing UI notifications to the end user. It is implemented by the [Toastr](https://github.com/CodeSeven/toastr) library by default. +Notify API is used to show toast style, auto disappearing UI notifications to the end user. ## Quick Example @@ -26,20 +26,23 @@ There are four types of pre-defined notifications; * `abp.notify.warn(...)` * `abp.notify.error(...)` -All of the methods above gets the following parameters; +All of the methods above accept the following parameters: * `message`: A message (`string`) to show to the user. * `title`: An optional title (`string`). -* `options`: Additional options to be passed to the underlying library, to the Toastr by default. - -## Toastr Configuration - -The notification API is implemented by the [Toastr](https://github.com/CodeSeven/toastr) library by default. You can see its own configuration options. - -**Example: Show toast messages on the top right of the page** - -````js -toastr.options.positionClass = 'toast-top-right'; -```` - -> ABP sets this option to `toast-bottom-right` by default. You can override it just as shown above. \ No newline at end of file +* `options`: Additional options to customize the notification. Available options: + * `life`: Display duration in milliseconds (default: `5000`) + * `sticky`: Keep toast visible until manually closed (default: `false`) + * `closable`: Show close button (default: `true`) + * `tapToDismiss`: Click anywhere on toast to dismiss (default: `false`) + * `containerKey`: Key for multiple container support (optional) + * `iconClass`: Custom icon class (optional) + * `position`: Position configuration (optional) + * `top`: Distance from top (default: `'auto'`) + * `right`: Distance from right (default: `'30px'`) + * `bottom`: Distance from bottom (default: `'30px'`) + * `left`: Distance from left (default: `'auto'`) + +## Global Configuration + +`AbpToastService.setDefaultOptions` method can be used to set default options for all notifications. This method should be called before any notification is shown. diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/form-elements.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/form-elements.md index 9230075ed3..b59ecf8dd3 100644 --- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/form-elements.md +++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/form-elements.md @@ -10,7 +10,7 @@ See the [form elements demo page](https://bootstrap-taghelpers.abp.io/Components ## abp-input -`abp-input` tag creates a Bootstrap form input for a given c# property. It uses [Asp.Net Core Input Tag Helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-7.0#the-input-tag-helper) in background, so every data annotation attribute of `input` tag helper of Asp.Net Core is also valid for `abp-input`. +`abp-input` tag creates a Bootstrap form input for a given c# property. It uses [Asp.Net Core Input Tag Helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-9.0#the-input-tag-helper) in background, so every data annotation attribute of `input` tag helper of Asp.Net Core is also valid for `abp-input`. Usage: @@ -89,7 +89,7 @@ You can set some of the attributes on your c# property, or directly on HTML tag. * `required-symbol`: Adds the required symbol `(*)` to the label when the input is required. The default value is `True`. * `floating-label`: Sets the label as floating label. The default value is `False`. -`asp-format`, `name` and `value` attributes of [Asp.Net Core Input Tag Helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-7.0#the-input-tag-helper) are also valid for `abp-input` tag helper. +`asp-format`, `name` and `value` attributes of [Asp.Net Core Input Tag Helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-9.0#the-input-tag-helper) are also valid for `abp-input` tag helper. ### Label & Localization @@ -101,7 +101,7 @@ You can set the label of the input in several ways: ## abp-select -`abp-select` tag creates a Bootstrap form select for a given c# property. It uses [ASP.NET Core Select Tag Helper](https://docs.microsoft.com/tr-tr/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-select-tag-helper) in background, so every data annotation attribute of `select` tag helper of ASP.NET Core is also valid for `abp-select`. +`abp-select` tag creates a Bootstrap form select for a given c# property. It uses [ASP.NET Core Select Tag Helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-9.0#the-select-tag-helper) in background, so every data annotation attribute of `select` tag helper of ASP.NET Core is also valid for `abp-select`. `abp-select` tag needs a list of `Microsoft.AspNetCore.Mvc.Rendering.SelectListItem ` to work. It can be provided by `asp-items` attriube on the tag or `[SelectItems()]` attribute on c# property. (if you are using [abp-dynamic-form](dynamic-forms.md), c# attribute is the only way.) @@ -432,4 +432,4 @@ newPicker.insertAfter($('body')); * `startDateName`: Sets the name of the hidden start date input. * `endDateName`: Sets the name of the hidden end date input. * `dateName`: Sets the name of the hidden date input. -* Other [datepicker options](https://www.daterangepicker.com/#options). Eg: `startDate: "2020-01-01"`. \ No newline at end of file +* Other [datepicker options](https://www.daterangepicker.com/#options). Eg: `startDate: "2020-01-01"`. diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/modals.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/modals.md index eff7d5ebe3..47ae472719 100644 --- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/modals.md +++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/modals.md @@ -9,7 +9,7 @@ Basic usage: ````xml -Launch modal +Launch modal diff --git a/docs/en/framework/ui/mvc-razor-pages/toolbars.md b/docs/en/framework/ui/mvc-razor-pages/toolbars.md index 8c7660e596..04860b9adb 100644 --- a/docs/en/framework/ui/mvc-razor-pages/toolbars.md +++ b/docs/en/framework/ui/mvc-razor-pages/toolbars.md @@ -8,12 +8,26 @@ There is only one **standard toolbar** named "Main" (defined as a constant: `Sta In the screenshot above, there are two items added to the main toolbar: Language switch component & user menu. You can add your own items here. -Also, [LeptonX Lite Theme](../../../ui-themes/lepton-x-lite/asp-net-core.md) has 2 different toolbars for desktop and mobile views which defined as constants: `LeptonXLiteToolbars.Main`, `LeptonXLiteToolbars.MainMobile`. +Also, [LeptonX Lite Theme](../../../ui-themes/lepton-x-lite/asp-net-core.md) and [LeptonX Theme](../../../ui-themes/lepton-x/mvc.md) has 2 different toolbars for desktop and mobile views which defined as constants. + +**LeptonX Lite Theme** + +- `LeptonXLiteToolbars.Main` +- `LeptonXLiteToolbars.MainMobile` | LeptonXLiteToolbars.Main | LeptonXLiteToolbars.MainMobile | | :---: | :---: | | ![leptonx](../../../images/leptonxlite-toolbar-main-example.png) | ![leptonx](../../../images/leptonxlite-toolbar-mainmobile-example.png) | +**LeptonX Theme** + +- `LeptonXToolbars.Main` +- `LeptonXToolbars.MainMobile` + +| LeptonXToolbars.Main | LeptonXToolbars.MainMobile | +| :---: | :---: | +| ![leptonx](../../../images/leptonx-toolbar-main-example.png) | ![leptonx](../../../images/leptonx-toolbar-mainmobile-example.png) | + ## Example: Add a Notification Icon In this example, we will add a **notification (bell) icon** to the left of the language switch item. A item in the toolbar should be a **view component**. So, first, create a new view component in your project: diff --git a/docs/en/guides/microservice-mongodb.md b/docs/en/guides/microservice-mongodb.md index f857370d09..4c5042802b 100644 --- a/docs/en/guides/microservice-mongodb.md +++ b/docs/en/guides/microservice-mongodb.md @@ -97,9 +97,9 @@ Here we use `BookStore.ProductService` project as an example: int skipCount = 0, CancellationToken cancellationToken = default) { - var query = ApplyFilter(await GetMongoQueryableAsync(cancellationToken), filterText, name, priceMin, priceMax); + var query = ApplyFilter(await GetQueryableAsync(cancellationToken), filterText, name, priceMin, priceMax); query = query.OrderBy(string.IsNullOrWhiteSpace(sorting) ? ProductConsts.GetDefaultSorting(false) : sorting); - return await query.As>().PageBy>(skipCount, maxResultCount).ToListAsync(cancellationToken); + return await query.PageBy(skipCount, maxResultCount).ToListAsync(cancellationToken); } public async Task GetCountAsync( @@ -109,8 +109,8 @@ Here we use `BookStore.ProductService` project as an example: float? priceMax = null, CancellationToken cancellationToken = default) { - var query = ApplyFilter(await GetMongoQueryableAsync(cancellationToken), filterText, name, priceMin, priceMax); - return await query.As>().LongCountAsync(GetCancellationToken(cancellationToken)); + var query = ApplyFilter(await GetQueryableAsync(cancellationToken), filterText, name, priceMin, priceMax); + return await query.LongCountAsync(GetCancellationToken(cancellationToken)); } protected virtual IQueryable ApplyFilter( diff --git a/docs/en/images/js-notify-success.png b/docs/en/images/js-notify-success.png index d5300f3468..1068bf8621 100644 Binary files a/docs/en/images/js-notify-success.png and b/docs/en/images/js-notify-success.png differ diff --git a/docs/en/images/leptonx-toolbar-main-example.png b/docs/en/images/leptonx-toolbar-main-example.png new file mode 100644 index 0000000000..104d3763ee Binary files /dev/null and b/docs/en/images/leptonx-toolbar-main-example.png differ diff --git a/docs/en/images/leptonx-toolbar-mainmobile-example.png b/docs/en/images/leptonx-toolbar-mainmobile-example.png new file mode 100644 index 0000000000..f872dab8d7 Binary files /dev/null and b/docs/en/images/leptonx-toolbar-mainmobile-example.png differ diff --git a/docs/en/kb/can-not-login-with-admin-user.md b/docs/en/kb/can-not-login-with-admin-user.md index d69695b503..300a1a5c8f 100644 --- a/docs/en/kb/can-not-login-with-admin-user.md +++ b/docs/en/kb/can-not-login-with-admin-user.md @@ -1,5 +1,36 @@ -# KB#0003: Can not login with the admin user +# KB#0003: Cannot login with the admin user -* Try username `admin` and Password `1q2w3E*`. -* Try to migrate database. If you have a `DbMigrator` application in your solution, use it. It will seed initial data and create the admin user for you. -* If not works, read the README.MD file in your solution, or check the [Getting Started](https://abp.io/docs/latest/get-started) document. +## Use the Correct Username and Password + +You may have entered the wrong password. The username is `admin`, and the password is `1q2w3E*`. Note that the password is case-sensitive. + +## Forgot to Seed Initial Data + +You may need to add migrations and update the database using the EF Core CLI. If your solution includes a `DbMigrator` application, you must run the `DbMigrator` application to seed the initial data. + +If your project does not include a `DbMigrator` application, there might be a `migrate-database.ps1` script available. You can use it to migrate and seed the initial data. + +> The no-layer application typically support a `--migrate-database` option for migrating and seeding initial data. + +> Example: +> ```bash +> dotnet run --migrate-database +> ``` + +## Tenant Admin User + +If you cannot log in as a tenant admin user, ensure the tenant database is created and seeded, Use the password that was set during tenant creation. + +> The tenant seeding process is handled by the template project. If it is not completed, please check the `Logs` file for any error logs. + +## Check the `AbpUsers` Table + +If you have performed migration and seeded the initial data, check the `AbpUsers` table in the database. Ensure that the user record exists. If your tenant has a separate database, check the tenant database as well. + +Passwords are stored in hashed format, not plain text. If you suspect the password is incorrect, you can delete the user record and re-seed the initial data using the `DbMigrator` application or the `migrate-database.ps1` script. + +## Other Issues + +If the issue persists, refer to the `README.MD` file in your solution or consult the [Getting Started](https://abp.io/docs/latest/get-started) documentation. + +Feel free to create an issue in the [ABP GitHub repository](https://github.com/abpframework/abp/issues/new/choose) or contact [ABP Commercial Support](https://abp.io/support/questions/New) for assistance. diff --git a/docs/en/release-info/migration-guides/MongoDB-Driver-2-to-3.md b/docs/en/release-info/migration-guides/MongoDB-Driver-2-to-3.md new file mode 100644 index 0000000000..79c0d70573 --- /dev/null +++ b/docs/en/release-info/migration-guides/MongoDB-Driver-2-to-3.md @@ -0,0 +1,59 @@ +# Migrating from MongoDB Driver 2 to 3 + +## Introduction + +The release of MongoDB Driver 3 includes numerous user-requested fixes and improvements that were deferred in previous versions due to backward compatibility concerns. It also features internal improvements to reduce technical debt and enhance maintainability. One major update is the removal of a significant portion of the public API (primarily from `MongoDB.Driver.Core`), which was not intended for public use. The removed APIs were marked as deprecated in version 2.30.0. + +Please refer to the [upgrade guide](https://www.mongodb.com/docs/drivers/csharp/current/upgrade/v3/) for a complete list of breaking changes and upgrade guidelines. + +## Repository Changes + +Some method signatures in the `MongoDbRepository` class have been updated because the `IMongoQueryable` has been removed. The specific changes are as follows: + +- The new `GetQueryableAsync` method has been added to return `IQueryable`. +- The `GetMongoQueryable` and `GetMongoQueryableAsync` methods return `IQueryable` instead of `IMongoQueryable`, +- The `GetMongoQueryable` and `GetMongoQueryableAsync` methods are marked as obsolete, You should use the new `GetQueryableAsync` method instead. + +Please update your application by searching for and replacing these method calls. + +> The return value of the `GetQueryableAsync` method is `IQueryable`, which can be used directly to perform queries, similar to EF Core. Remove all instances of `IMongoQueryable` in your project and replace them with `IQueryable`. + +**Previous code example:** + +```csharp +var myEntity = await (await GetMongoQueryableAsync()).As>().FirstOrDefaultAsync(x => x.Id == id); +``` + +**Updated code example:** + +```csharp +var myEntity = await GetQueryableAsync().FirstOrDefaultAsync(x => x.Id == id); +``` + +## Unit Test Changes + +Previously, we used the [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) library for unit testing. However, it does not support the latest version of [MongoDB.Driver 3.x](https://github.com/mongodb/mongo-go-driver). You should replace it with [MongoSandbox](https://github.com/wassim-k/MongoSandbox). + +In your unit test project files, replace the following: + +```xml + + + + +``` + +With: + +```xml + + + + +``` + +In your unit test classes, replace `using EphemeralMongo` with `using MongoSandbox`. + +## Official Upgrade Guide + +We recommend reviewing the [upgrade guide](https://www.mongodb.com/docs/drivers/csharp/current/upgrade/v3/) for MongoDB Driver 3 to ensure a smooth migration process. diff --git a/docs/en/solution-templates/layered-web-application/deployment/deployment-docker-compose.md b/docs/en/solution-templates/layered-web-application/deployment/deployment-docker-compose.md index a9e106221b..fe2d226d53 100644 --- a/docs/en/solution-templates/layered-web-application/deployment/deployment-docker-compose.md +++ b/docs/en/solution-templates/layered-web-application/deployment/deployment-docker-compose.md @@ -15,7 +15,7 @@ This guide will guide you through how to build docker images for your applicatio ## Building Docker Images -Each application contains a dockerfile called `Dockerfile.local` for building the docker image. As the naming implies, these Dockerfiles are not multi-stage Dockerfiles and require the project to be built in `Release` mode to create the image. Currently, if you are building your images using CI & CD pipeline, you either need to include the SDK to your pipeline before building the images or add your own [multi-stage dockerfiles](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/docker/building-net-docker-images?view=aspnetcore-7.0). +Each application contains a dockerfile called `Dockerfile.local` for building the docker image. As the naming implies, these Dockerfiles are not multi-stage Dockerfiles and require the project to be built in `Release` mode to create the image. Currently, if you are building your images using CI & CD pipeline, you either need to include the SDK to your pipeline before building the images or add your own [multi-stage dockerfiles](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/docker/building-net-docker-images?view=aspnetcore-9.0). Since they are not multi-staged Dockerfiles, if you want to build the images individually, you can navigate to the related to-be-hosted application folder and run the following command: @@ -31,7 +31,7 @@ docker build -f Dockerfile.local -t mycompanyname/myappname:version . To manually build your application image. -To ease the process, application templates provide a build script to build all the images with a single script under `etc/build` folder named `build-images-locally.ps1`. +To ease the process, application templates provide a build script to build all the images with a single script under `etc/docker-compose` folder named `build-images-locally.ps1`. Based on your application name, UI and type, a build image script will be generated. {{ if UI == "MVC"}} @@ -204,8 +204,8 @@ DbMigrator is a console application that is used to migrate the database of your `Dockerfile.local` is provided under this project as below; ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:7.0 -COPY bin/Release/net7.0/publish/ app/ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 +COPY bin/Release/net9.0/publish/ app/ WORKDIR /app ENTRYPOINT ["dotnet", "BookStore.DbMigrator.dll"] ``` @@ -226,7 +226,7 @@ docker build -f Dockerfile.local -t acme/bookstore-db-migrator:latest . #Builds In the **WebModule** under authentication configuration, there is an extra configuration for containerized environment support: ```csharp -if (Convert.ToBoolean(configuration["AuthServer:IsContainerizedOnLocalhost"])) +if (Convert.ToBoolean(configuration["AuthServer:IsOnK8s"])) { context.Services.Configure("oidc", options => { @@ -268,13 +268,13 @@ if (Convert.ToBoolean(configuration["AuthServer:IsContainerizedOnLocalhost"])) This is used when the **AuthServer is running on docker containers(or pods)** to configure the redirection URLs for the internal network and the web. The application must be redirected to real DNS (localhost in this case) when the `/authorize` and `/logout` requests over the browser but handle the token validation inside the isolated network without going out to the internet. `"AuthServer:MetaAddress"` appsetting should indicate the container/pod service name while the `AuthServer:Authority` should be pointing to real DNS for the browser to redirect. -The `appsettings.json` file does not contain `AuthServer:IsContainerizedOnLocalhost` and `AuthServer:MetaAddress` settings since they are used for orchestrated deployment scenarios, you can see these settings are overridden by the `docker-compose.yml` file. +The `appsettings.json` file does not contain `AuthServer:IsOnK8s` and `AuthServer:MetaAddress` settings since they are used for orchestrated deployment scenarios, you can see these settings are overridden by the `docker-compose.yml` file. `Dockerfile.local` is provided under this project as below; ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:7.0 -COPY bin/Release/net7.0/publish/ app/ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 +COPY bin/Release/net9.0/publish/ app/ WORKDIR /app ENTRYPOINT ["dotnet", "Acme.BookStore.Web.dll"] ``` @@ -289,11 +289,11 @@ docker build -f Dockerfile.local -t acme/bookstore-web:latest . #Builds the imag ​ {{ end }} {{ if Tiered == "No" }}MVC/Razor Pages application is a server-side rendering application that contains both the OpenID-provider and the Http.Api endpoints within self; it will be a single application to deploy. `Dockerfile.local` is provided under this project as below; ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base -COPY bin/Release/net7.0/publish/ app/ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base +COPY bin/Release/net9.0/publish/ app/ WORKDIR /app -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src RUN dotnet dev-certs https -v -ep authserver.pfx -p 2D7AA457-5D33-48D6-936F-C48E5EF468ED @@ -318,36 +318,17 @@ if (!hostingEnvironment.IsDevelopment()) options.AddDevelopmentEncryptionAndSigningCertificate = false; }); - PreConfigure(builder => + PreConfigure(serverBuilder => { - builder.AddSigningCertificate(GetSigningCertificate(hostingEnvironment, configuration)); - builder.AddEncryptionCertificate(GetSigningCertificate(hostingEnvironment, configuration)); - builder.SetIssuer(new Uri(configuration["AuthServer:Authority"])); + serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", configuration["AuthServer:CertificatePassPhrase"]!); + serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!)); }); } ``` This configuration disables the *DevelopmentEncryptionAndSigningCertificate* and uses a self-signed certificate called `authserver.pfx`. for **signing and encrypting the tokens**. This certificate is created when the docker image is built using the `dotnet dev-certs` tooling. It is a sample-generated certificate, and it is **recommended** to update it for the production environment. You can check the [OpenIddict Encryption and signing credentials documentation](https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html) for different options and customization. -The `GetSigningCertificate` method is a private method located under the same **WebModule**: - -```csharp -private X509Certificate2 GetSigningCertificate(IWebHostEnvironment hostingEnv, IConfiguration configuration) -{ - var fileName = "authserver.pfx"; - var passPhrase = "2D7AA457-5D33-48D6-936F-C48E5EF468ED"; - var file = Path.Combine(hostingEnv.ContentRootPath, fileName); - - if (!File.Exists(file)) - { - throw new FileNotFoundException($"Signing Certificate couldn't found: {file}"); - } - - return new X509Certificate2(file, passPhrase); -} -``` - -> You can always create any self-signed certificate using any other tooling outside the Dockerfile. You need to remember to set them as **embedded resource** since the `GetSigningCertificate` method will be checking this file physically. +> You can always create any self-signed certificate using any other tooling outside the Dockerfile. You need to remember to set them as **embedded resource**. If you don't want to use the `build-images-locally.ps1` to build the images or to build this image individually and manually, navigate to the **Web** folder and run: @@ -369,7 +350,7 @@ docker build -f Dockerfile.local -t acme/bookstore-web:latest . #Builds the imag In the **BlazorModule** under authentication configuration, there is an extra configuration for containerized environment support: ```csharp -if (Convert.ToBoolean(configuration["AuthServer:IsContainerizedOnLocalhost"])) +if (Convert.ToBoolean(configuration["AuthServer:IsOnK8s"])) { context.Services.Configure("oidc", options => { @@ -411,13 +392,13 @@ if (Convert.ToBoolean(configuration["AuthServer:IsContainerizedOnLocalhost"])) This is used when the **AuthServer is running on docker containers(or pods)** to configure the redirection URLs for the internal network and the web. The application must be redirected to real DNS (localhost in this case) when the `/authorize` and `/logout` requests over the browser but handle the token validation inside the isolated network without going out to the internet. `"AuthServer:MetaAddress"` appsetting should indicate the container/pod service name while the `AuthServer:Authority` should be pointing to real DNS for the browser to redirect. -The `appsettings.json` file does not contain `AuthServer:IsContainerizedOnLocalhost` and `AuthServer:MetaAddress` settings since they are used for orchestrated deployment scenarios, you can see these settings are overridden by the `docker-compose.yml` file. +The `appsettings.json` file does not contain `AuthServer:IsOnK8s` and `AuthServer:MetaAddress` settings since they are used for orchestrated deployment scenarios, you can see these settings are overridden by the `docker-compose.yml` file. `Dockerfile.local` is provided under this project as below; ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:7.0 -COPY bin/Release/net7.0/publish/ app/ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 +COPY bin/Release/net9.0/publish/ app/ WORKDIR /app ENTRYPOINT ["dotnet", "Acme.BookStore.Blazor.dll"] ``` @@ -432,11 +413,11 @@ docker build -f Dockerfile.local -t acme/bookstore-blazor:latest . #Builds the i ​ {{ end }} {{ if Tiered == "No" }}Blazor Server application is a server-side rendering application that contains both the OpenID-provider and the Http.Api endpoints within self; it will be a single application to deploy. `Dockerfile.local` is provided under this project as below; ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base -COPY bin/Release/net7.0/publish/ app/ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base +COPY bin/Release/net9.0/publish/ app/ WORKDIR /app -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src RUN dotnet dev-certs https -v -ep authserver.pfx -p 2D7AA457-5D33-48D6-936F-C48E5EF468ED @@ -461,36 +442,17 @@ if (!hostingEnvironment.IsDevelopment()) options.AddDevelopmentEncryptionAndSigningCertificate = false; }); - PreConfigure(builder => + PreConfigure(serverBuilder => { - builder.AddSigningCertificate(GetSigningCertificate(hostingEnvironment, configuration)); - builder.AddEncryptionCertificate(GetSigningCertificate(hostingEnvironment, configuration)); - builder.SetIssuer(new Uri(configuration["AuthServer:Authority"])); + serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", configuration["AuthServer:CertificatePassPhrase"]!); + serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!)); }); } ``` This configuration disables the *DevelopmentEncryptionAndSigningCertificate* and uses a self-signed certificate called `authserver.pfx`. for **signing and encrypting the tokens**. This certificate is created when the docker image is built using the `dotnet dev-certs` tooling. It is a sample-generated certificate, and it is **recommended** to update it for the production environment. You can check the [OpenIddict Encryption and signing credentials documentation](https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html) for different options and customization. -The `GetSigningCertificate` method is a private method located under the same **BlazorModule**: - -```csharp -private X509Certificate2 GetSigningCertificate(IWebHostEnvironment hostingEnv, IConfiguration configuration) -{ - var fileName = "authserver.pfx"; - var passPhrase = "2D7AA457-5D33-48D6-936F-C48E5EF468ED"; - var file = Path.Combine(hostingEnv.ContentRootPath, fileName); - - if (!File.Exists(file)) - { - throw new FileNotFoundException($"Signing Certificate couldn't found: {file}"); - } - - return new X509Certificate2(file, passPhrase); -} -``` - -> You can always create any self-signed certificate using any other tooling outside the dockerfile. You need to remember to set them as **embedded resource** since the `GetSigningCertificate` method will be checking this file physically. +> You can always create any self-signed certificate using any other tooling outside the Dockerfile. You need to remember to set them as **embedded resource**. If you don't want to use the `build-images-locally.ps1` to build the images or to build this image individually and manually, navigate to the **BlazorModule** folder and run: @@ -562,7 +524,7 @@ server { } ``` -This configuration allows returning the `dynamic-env.json` file as a static file, which ABP Angular application uses for environment variables in one of the first initial requests when rendering the page. **The `dynamic-env.json` file you need to override is located under `aspnet-core/etc/docker`** folder. +This configuration allows returning the `dynamic-env.json` file as a static file, which ABP Angular application uses for environment variables in one of the first initial requests when rendering the page. **The `dynamic-env.json` file you need to override is located under `aspnet-core/etc/docker-compose`** folder. ​ {{ if Tiered == "No" }} @@ -645,8 +607,8 @@ docker build -f Dockerfile.local -t acme/bookstore-angular:latest . #Builds the The Blazor application uses [nginx:alpine-slim](https://hub.docker.com/layers/library/nginx/alpine-slim/images/sha256-0f859db466fda2c52f62b48d0602fb26867d98edbd62c26ae21414b3dea8d8f4?context=explore) base image to host the blazor application. You can modify the base image based on your preference in the `Dockerfile.local` which provided under the Blazor folder of your solution as below; ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS build -COPY bin/Release/net7.0/publish/ app/ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS build +COPY bin/Release/net9.0/publish/ app/ FROM nginx:alpine-slim AS final WORKDIR /usr/share/nginx/html @@ -701,11 +663,11 @@ docker build -f Dockerfile.local -t acme/bookstore-blazor:latest . #Builds the i This is the backend application that contains the openid-provider functionality as well. The `dockerfile.local` is located under the `Http.Api.Host` project as below; ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base -COPY bin/Release/net7.0/publish/ app/ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base +COPY bin/Release/net9.0/publish/ app/ WORKDIR /app -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src RUN dotnet dev-certs https -v -ep authserver.pfx -p 2D7AA457-5D33-48D6-936F-C48E5EF468ED @@ -730,36 +692,17 @@ if (!hostingEnvironment.IsDevelopment()) options.AddDevelopmentEncryptionAndSigningCertificate = false; }); - PreConfigure(builder => + PreConfigure(serverBuilder => { - builder.AddSigningCertificate(GetSigningCertificate(hostingEnvironment, configuration)); - builder.AddEncryptionCertificate(GetSigningCertificate(hostingEnvironment, configuration)); - builder.SetIssuer(new Uri(configuration["AuthServer:Authority"])); + serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", configuration["AuthServer:CertificatePassPhrase"]!); + serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!)); }); } ``` This configuration disables the *DevelopmentEncryptionAndSigningCertificate* and uses a self-signed certificate called `authserver.pfx`. for **signing and encrypting the tokens**. This certificate is created when the docker image is built using the `dotnet dev-certs` tooling. It is a sample-generated certificate, and it is **recommended** to update it for the production environment. You can check the [OpenIddict Encryption and signing credentials documentation](https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html) for different options and customization. -The `GetSigningCertificate` method is a private method located under the same **HttpApiHostModule**: - -```csharp -private X509Certificate2 GetSigningCertificate(IWebHostEnvironment hostingEnv, IConfiguration configuration) -{ - var fileName = "authserver.pfx"; - var passPhrase = "2D7AA457-5D33-48D6-936F-C48E5EF468ED"; - var file = Path.Combine(hostingEnv.ContentRootPath, fileName); - - if (!File.Exists(file)) - { - throw new FileNotFoundException($"Signing Certificate couldn't found: {file}"); - } - - return new X509Certificate2(file, passPhrase); -} -``` - -> You can always create any self-signed certificate using any other tooling outside of the dockerfile. You need to keep in mind to set them as **embedded resource** since the `GetSigningCertificate` method will be checking this file physically. +> You can always create any self-signed certificate using any other tooling outside the Dockerfile. You need to remember to set them as **embedded resource**. If you don't want to use the `build-images-locally.ps1` to build the images or to build this image individually and manually, navigate to **Http.Api.Host** folder and run: @@ -777,11 +720,11 @@ docker build -f Dockerfile.local -t acme/bookstore-api:latest . #Builds the imag This is the backend application that contains the OpenID-provider functionality as well. The `dockerfile.local` is located under the `Http.Api.Host` project as below; ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base -COPY bin/Release/net7.0/publish/ app/ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base +COPY bin/Release/net9.0/publish/ app/ WORKDIR /app -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src RUN dotnet dev-certs https -v -ep authserver.pfx -p 2D7AA457-5D33-48D6-936F-C48E5EF468ED @@ -806,36 +749,17 @@ if (!hostingEnvironment.IsDevelopment()) options.AddDevelopmentEncryptionAndSigningCertificate = false; }); - PreConfigure(builder => + PreConfigure(serverBuilder => { - builder.AddSigningCertificate(GetSigningCertificate(hostingEnvironment, configuration)); - builder.AddEncryptionCertificate(GetSigningCertificate(hostingEnvironment, configuration)); - builder.SetIssuer(new Uri(configuration["AuthServer:Authority"])); + serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", configuration["AuthServer:CertificatePassPhrase"]!); + serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!)); }); } ``` -This configuration disables the *DevelopmentEncryptionAndSigningCertificate* and uses a self-signed certificate called `authserver.pfx`. for **signing and encrypting the tokens**. This certificate is created when the docker image is built using the `dotnet dev-certs` tooling. It is a sample-generated certificate, and it is **recommended** to update it for the production environment. You can check the [OpenIddict Encryption and signing credentials documentation](https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html) for different customization options. - -The `GetSigningCertificate` method is a private method located under the same **HttpApiHostModule**: - -```csharp -private X509Certificate2 GetSigningCertificate(IWebHostEnvironment hostingEnv, IConfiguration configuration) -{ - var fileName = "authserver.pfx"; - var passPhrase = "2D7AA457-5D33-48D6-936F-C48E5EF468ED"; - var file = Path.Combine(hostingEnv.ContentRootPath, fileName); - - if (!File.Exists(file)) - { - throw new FileNotFoundException($"Signing Certificate couldn't found: {file}"); - } - - return new X509Certificate2(file, passPhrase); -} -``` +This configuration disables the *DevelopmentEncryptionAndSigningCertificate* and uses a self-signed certificate called `authserver.pfx`. for **signing and encrypting the tokens**. This certificate is created when the docker image is built using the `dotnet dev-certs` tooling. It is a sample-generated certificate, and it is **recommended** to update it for the production environment. You can check the [OpenIddict Encryption and signing credentials documentation](https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html) for different options and customization. -> You can always create any self-signed certificate using any other tooling outside the dockerfile. You need to remember to set them as **embedded resource** since the `GetSigningCertificate` method will be checking this file physically. +> You can always create any self-signed certificate using any other tooling outside the Dockerfile. You need to remember to set them as **embedded resource**. If you don't want to use the `build-images-locally.ps1` to build the images or to build this image individually and manually, navigate to **Http.Api.Host** folder and run: @@ -855,11 +779,11 @@ docker build -f Dockerfile.local -t acme/bookstore-api:latest . #Builds the imag This is the openid-provider application, the authentication server, which should be individually hosted compared to non-tiered application templates. The `dockerfile.local` is located under the `AuthServer` project as below; ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base -COPY bin/Release/net7.0/publish/ app/ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base +COPY bin/Release/net9.0/publish/ app/ WORKDIR /app -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src RUN dotnet dev-certs https -v -ep authserver.pfx -p 2D7AA457-5D33-48D6-936F-C48E5EF468ED @@ -884,36 +808,17 @@ if (!hostingEnvironment.IsDevelopment()) options.AddDevelopmentEncryptionAndSigningCertificate = false; }); - PreConfigure(builder => + PreConfigure(serverBuilder => { - builder.AddSigningCertificate(GetSigningCertificate(hostingEnvironment, configuration)); - builder.AddEncryptionCertificate(GetSigningCertificate(hostingEnvironment, configuration)); - builder.SetIssuer(new Uri(configuration["AuthServer:Authority"])); + serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", configuration["AuthServer:CertificatePassPhrase"]!); + serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!)); }); } ``` This configuration disables the *DevelopmentEncryptionAndSigningCertificate* and uses a self-signed certificate called `authserver.pfx`. for **signing and encrypting the tokens**. This certificate is created when the docker image is built using the `dotnet dev-certs` tooling. It is a sample-generated certificate, and it is **recommended** to update it for the production environment. You can check the [OpenIddict Encryption and signing credentials documentation](https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html) for different options and customization. -The `GetSigningCertificate` method is a private method located under the same **AuthServerModule**: - -```csharp -private X509Certificate2 GetSigningCertificate(IWebHostEnvironment hostingEnv, IConfiguration configuration) -{ - var fileName = "authserver.pfx"; - var passPhrase = "2D7AA457-5D33-48D6-936F-C48E5EF468ED"; - var file = Path.Combine(hostingEnv.ContentRootPath, fileName); - - if (!File.Exists(file)) - { - throw new FileNotFoundException($"Signing Certificate couldn't found: {file}"); - } - - return new X509Certificate2(file, passPhrase); -} -``` - -> You can always create any self-signed certificate using any other tooling outside the dockerfile. You need to remember to set them as **embedded resource** since the `GetSigningCertificate` method will be checking this file physically. +> You can always create any self-signed certificate using any other tooling outside the Dockerfile. You need to remember to set them as **embedded resource**. If you don't want to use the `build-images-locally.ps1` to build the images or to build this image individually and manually, navigate to the **AuthServer** folder and run: @@ -927,8 +832,8 @@ docker build -f Dockerfile.local -t acme/bookstore-authserver:latest . #Builds t This is the backend application that exposes the endpoints and swagger UI. It is not a multi-stage dockerfile; hence you need to have already built this application in **Release mode** to use this dockerfile. The `dockerfile.local` is located under the `Http.Api.Host` project as below; ```dockerfile -FROM mcr.microsoft.com/dotnet/aspnet:7.0 -COPY bin/Release/net7.0/publish/ app/ +FROM mcr.microsoft.com/dotnet/aspnet:9.0 +COPY bin/Release/net9.0/publish/ app/ WORKDIR /app ENTRYPOINT ["dotnet", "Acme.BookStore.HttpApi.Host.dll"] ``` @@ -944,7 +849,7 @@ docker build -f Dockerfile.local -t acme/bookstore-api:latest . #Builds the imag ## Running Docker-Compose on Localhost -Under the `etc/docker` folder, you can find the `docker-compose.yml` to run your application. To ease the running process, the template provides `run-docker.ps1` (and `run-docker.sh`) scripts that handle the HTTPS certificate creation, which is used in environment variables; +Under the `etc/docker-compose` folder, you can find the `docker-compose.yml` to run your application. To ease the running process, the template provides `run-docker.ps1` (and `run-docker.sh`) scripts that handle the HTTPS certificate creation, which is used in environment variables; ```powershell $currentFolder = $PSScriptRoot @@ -1203,7 +1108,7 @@ This is the angular application we deploy on http://localhost:4200 by default us > Don't forget to rebuild the `acme/bookstore-angular:latest` image after updating the `nginx.conf` file. -The bookstore-angular service mounts the `etc/docker/dynamic-env.json` file to change the existing dynamic-env.json file, which is copied during image creation, to change the environment variables on deployment time instead of re-creating the docker image after each environmental variable change. **Do not forget to override the `dynamic-env.json` located under the `aspnet-core/etc/docker`** folder. +The bookstore-angular service mounts the `etc/docker-compose/dynamic-env.json` file to change the existing dynamic-env.json file, which is copied during image creation, to change the environment variables on deployment time instead of re-creating the docker image after each environmental variable change. **Do not forget to override the `dynamic-env.json` located under the `aspnet-core/etc/docker-compose`** folder. > If you are not using Docker with WSL, you may have problems with the volume mount permissions. You need to grant docker to be able to use the local file system. See this [SO answer](https://stackoverflow.com/a/20652410) for more information. @@ -1438,7 +1343,7 @@ bookstore-web: - Kestrel__Certificates__Default__Password=91f91912-5ab0-49df-8166-23377efaf3cc - App__SelfUrl=https://localhost:44353 - AuthServer__RequireHttpsMetadata=false {{ if Tiered == "Yes" }} - - AuthServer__IsContainerizedOnLocalhost=true + - AuthServer__IsOnK8s=true - AuthServer__Authority=https://localhost:44334/ - RemoteServices__Default__BaseUrl=http://bookstore-api - RemoteServices__AbpAccountPublic__BaseUrl=http://bookstore-authserver @@ -1464,7 +1369,7 @@ This is the MVC/Razor Page application docker service is using the `acme/booksto The MVC/Razor Page is a server-side rendering application that uses the **hybrid flow**. This flow uses **browser** to login/logout process to the OpenID-provider but issues the **access_token from the back-channel** (server-side). To achieve this functionality, the module class has extra `OpenIdConnectOptions` to override some of the events: ```csharp -if (Convert.ToBoolean(configuration["AuthServer:IsContainerizedOnLocalhost"])) +if (Convert.ToBoolean(configuration["AuthServer:IsOnK8s"])) { context.Services.Configure("oidc", options => { @@ -1511,7 +1416,7 @@ if (Convert.ToBoolean(configuration["AuthServer:IsContainerizedOnLocalhost"])) {{ if Tiered == "Yes" }} -- `AuthServer__IsContainerizedOnLocalhost` is the configuration to enable the **OpenIdConnectOptions** to provide a different endpoint for the MetaAddress of the OpenID-provider and intercepting the URLS for *authorization* and *logout* endpoints. +- `AuthServer__IsOnK8s` is the configuration to enable the **OpenIdConnectOptions** to provide a different endpoint for the MetaAddress of the OpenID-provider and intercepting the URLS for *authorization* and *logout* endpoints. - `AuthServer__MetaAddress` is the `.well-known/openid-configuration` endpoint for issuing access_token and internal token validation. It is the containerized `http://bookstore-authserver` by default. @@ -1691,7 +1596,7 @@ bookstore-blazor: - Kestrel__Certificates__Default__Password=91f91912-5ab0-49df-8166-23377efaf3cc - App__SelfUrl=https://localhost:44314 - AuthServer__RequireHttpsMetadata=false {{ if Tiered == "Yes" }} - - AuthServer__IsContainerizedOnLocalhost=true + - AuthServer__IsOnK8s=true - AuthServer__Authority=https://localhost:44334/ - AuthServer__MetaAddress=http://bookstore-authserver - RemoteServices__Default__BaseUrl=http://bookstore-api @@ -1718,7 +1623,7 @@ This is the Blazor Server application Docker service is using the `acme/bookstor The Blazor Server is a server-side rendering application that uses the **hybrid flow**. This flow uses **browser** to login/logout process to the OpenID-provider but issues the **access_token from the back-channel** (server-side). To achieve this functionality, the module class has extra `OpenIdConnectOptions` to override some of the events: ```csharp -if (Convert.ToBoolean(configuration["AuthServer:IsContainerizedOnLocalhost"])) +if (Convert.ToBoolean(configuration["AuthServer:IsOnK8s"])) { context.Services.Configure("oidc", options => { @@ -1765,7 +1670,7 @@ if (Convert.ToBoolean(configuration["AuthServer:IsContainerizedOnLocalhost"])) {{ if Tiered == "Yes" }} -- `AuthServer__IsContainerizedOnLocalhost` is the configuration to enable the **OpenIdConnectOptions** to provide a different endpoint for the MetaAddress of the OpenID-provider and intercept the URLS for *authorization* and *logout* endpoints. +- `AuthServer__IsOnK8s` is the configuration to enable the **OpenIdConnectOptions** to provide a different endpoint for the MetaAddress of the OpenID-provider and intercept the URLS for *authorization* and *logout* endpoints. - `AuthServer__MetaAddress` is the `.well-known/openid-configuration` endpoint for issuing the access_token and internal token validation. It is the containerized `http://bookstore-authserver` by default. diff --git a/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md b/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md index 79382f1b0a..3d33cbd7a1 100644 --- a/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md +++ b/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md @@ -254,6 +254,35 @@ We can visit the websites from a browser. ![Tiered IIS deployment](../../../images/iis-sample-tiered-deployment.gif) +## Fix 405 Method Not Allowed Error + +Remove `WebDAV` modules and handlers from the `Web.config` file. + +```xml + + + + + + + + + + + +``` + +Also remove the `WebDAV Publishing` feature from your computer if it's not being used. To do so, follow these steps: + +1. Select Start, type Turn Windows features on or off in the Start Search box, and then select Turn Windows features on or off. +2. In the Windows Features window, expand Internet Information Services -> World Wide Web Services -> Common HTTP Features. +3. Uncheck the WebDAV Publishing feature. + +See: + +- https://learn.microsoft.com/en-us/aspnet/web-api/overview/testing-and-debugging/troubleshooting-http-405-errors-after-publishing-web-api-applications#resolve-http-405-errors +- https://learn.microsoft.com/en-us/troubleshoot/developer/webapps/iis/site-behavior-performance/http-error-405-website#resolution-for-cause-3 + ## How to get stdout-log If your application is running on IIS and getting errors like `502.5, 500.3x`, you can enable stdout logs to see the error details. diff --git a/docs/en/solution-templates/layered-web-application/solution-structure.md b/docs/en/solution-templates/layered-web-application/solution-structure.md index 680df73a59..3afd1b1274 100644 --- a/docs/en/solution-templates/layered-web-application/solution-structure.md +++ b/docs/en/solution-templates/layered-web-application/solution-structure.md @@ -214,3 +214,7 @@ This project is an application that hosts the API of the solution. It has its ow Just like the default structure, this project contains the User Interface (UI) of the application. It contains razor pages, JavaScript files, style files, images and so on... This project contains an `appsettings.json` file, but this time it does not have a connection string because it never connects to the database. Instead, it mainly contains the endpoint of the remote API server and the authentication server. + +### Docker Compose + +The **docker-compose** configuration files in the `etc/docker-compose` folder is configured to run the solution with Docker. See [Docker Deployment using Docker Compose](deployment/deployment-docker-compose.md) for more information. \ No newline at end of file diff --git a/docs/en/studio/running-applications.md b/docs/en/studio/running-applications.md index 3c6cb101aa..9188f202ae 100644 --- a/docs/en/studio/running-applications.md +++ b/docs/en/studio/running-applications.md @@ -233,3 +233,11 @@ CLI applications uses the [powershell](https://learn.microsoft.com/en-us/powersh - `Remove`: This option allows you to delete the selected application. > When CLI applications start chain icon won't be visible, because only C# applications can connect the ABP Studio. + +## Docker Compose + +You can manually run applications using [Docker Compose](https://docs.docker.com/compose/). This allows for easy setup and management of multi-container Docker applications. To get started, ensure you have Docker and Docker Compose installed on your machine. + +Refer to the [Deployment with Docker Compose](../solution-templates/layered-web-application/deployment/deployment-docker-compose.md) documentation for detailed instructions on how to configure and run your applications using `docker-compose`. + +> Note: The **Docker Compose** is not available in the ABP Studio interface. \ No newline at end of file diff --git a/docs/en/tutorials/book-store/part-07.md b/docs/en/tutorials/book-store/part-07.md index 0708ecfcb9..92108c4a35 100644 --- a/docs/en/tutorials/book-store/part-07.md +++ b/docs/en/tutorials/book-store/part-07.md @@ -180,7 +180,7 @@ public class MongoDbAuthorRepository public async Task FindByNameAsync(string name) { - var queryable = await GetMongoQueryableAsync(); + var queryable = await GetQueryableAsync(); return await queryable.FirstOrDefaultAsync(author => author.Name == name); } @@ -190,14 +190,13 @@ public class MongoDbAuthorRepository string sorting, string filter = null) { - var queryable = await GetMongoQueryableAsync(); + var queryable = await GetQueryableAsync(); return await queryable - .WhereIf>( + .WhereIf>( !filter.IsNullOrWhiteSpace(), author => author.Name.Contains(filter) ) .OrderBy(sorting) - .As>() .Skip(skipCount) .Take(maxResultCount) .ToListAsync(); diff --git a/docs/en/ui-themes/lepton-x/blazor.md b/docs/en/ui-themes/lepton-x/blazor.md index 6ae4bc7da1..5e49752ebb 100644 --- a/docs/en/ui-themes/lepton-x/blazor.md +++ b/docs/en/ui-themes/lepton-x/blazor.md @@ -269,6 +269,37 @@ Layout options of Blazor UI can be manageable via using **LeptonXThemeMvcOptions }); ``` +### Toolbars + +LeptonX includes separeted toolbars for desktop & mobile. You can manage toolbars independently. Toolbar names can be accessible in the **LeptonXToolbars** class. + +- `LeptonXToolbars.Main` +- `LeptonXToolbars.MainMobile` + +```csharp +public async Task ConfigureToolbarAsync(IToolbarConfigurationContext context) +{ + if (context.Toolbar.Name == LeptonXToolbars.Main) + { + context.Toolbar.Items.Add(new ToolbarItem(typeof(MyDesktopComponent))); + } + + if (context.Toolbar.Name == LeptonXToolbars.MainMobile) + { + context.Toolbar.Items.Add(new ToolbarItem(typeof(MyMobileComponent))); + } + + return Task.CompletedTask; +} +``` + +{{if UI == "BlazorServer"}} + +> _You can visit the [Toolbars Documentation](../../framework/ui/blazor/toolbars.md) for better understanding._ + +{{end}} + + ## Layouts **LeptonX** offers two **ready-made layouts** for your web application. One of them is **placed** with the **menu items** on the **top** and the other with the **menu items** on the **sides**. diff --git a/docs/en/ui-themes/lepton-x/mvc.md b/docs/en/ui-themes/lepton-x/mvc.md index a317e8b9ed..ce12a0ea95 100644 --- a/docs/en/ui-themes/lepton-x/mvc.md +++ b/docs/en/ui-themes/lepton-x/mvc.md @@ -81,8 +81,32 @@ Configure(options => > > If your layout is **TopMenu**, then you have to add them under the **wwwroot/Themes/LeptonX/Global/top-menu/css/** folder. +### Toolbars + +LeptonX includes separeted toolbars for desktop & mobile. You can manage toolbars independently. Toolbar names can be accessible in the **LeptonXToolbars** class. + +- `LeptonXToolbars.Main` +- `LeptonXToolbars.MainMobile` + +```csharp +public async Task ConfigureToolbarAsync(IToolbarConfigurationContext context) +{ + if (context.Toolbar.Name == LeptonXToolbars.Main) + { + context.Toolbar.Items.Add(new ToolbarItem(typeof(MyDesktopComponent))); + } + + if (context.Toolbar.Name == LeptonXToolbars.MainMobile) + { + context.Toolbar.Items.Add(new ToolbarItem(typeof(MyMobileComponent))); + } + + return Task.CompletedTask; +} +``` + +> _You can visit the [Toolbars Documentation](../../framework/ui/mvc-razor-pages/toolbars.md) for better understanding._ -#### Handling Style Changes You can add extra logic by using javascript API when style is changed with the following event. ```js diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index c0454d3edf..db7bc55ff2 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -485,6 +485,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Bundlin EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Components.MauiBlazor.Bundling", "src\Volo.Abp.AspNetCore.Components.MauiBlazor.Bundling\Volo.Abp.AspNetCore.Components.MauiBlazor.Bundling.csproj", "{70720321-DED4-464F-B913-BDA5BBDD7982}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Bunny", "src\Volo.Abp.BlobStoring.Bunny\Volo.Abp.BlobStoring.Bunny.csproj", "{1BBCBA72-CDB6-4882-96EE-D4CD149433A2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Bunny.Tests", "test\Volo.Abp.BlobStoring.Bunny.Tests\Volo.Abp.BlobStoring.Bunny.Tests.csproj", "{BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1447,6 +1451,14 @@ Global {70720321-DED4-464F-B913-BDA5BBDD7982}.Debug|Any CPU.Build.0 = Debug|Any CPU {70720321-DED4-464F-B913-BDA5BBDD7982}.Release|Any CPU.ActiveCfg = Release|Any CPU {70720321-DED4-464F-B913-BDA5BBDD7982}.Release|Any CPU.Build.0 = Release|Any CPU + {1BBCBA72-CDB6-4882-96EE-D4CD149433A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1BBCBA72-CDB6-4882-96EE-D4CD149433A2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1BBCBA72-CDB6-4882-96EE-D4CD149433A2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1BBCBA72-CDB6-4882-96EE-D4CD149433A2}.Release|Any CPU.Build.0 = Release|Any CPU + {BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1691,6 +1703,8 @@ Global {C753DDD6-5699-45F8-8669-08CE0BB816DE} = {447C8A77-E5F0-4538-8687-7383196D04EA} {75AA8A90-B3F6-43DF-ADA7-0990DEF44E2C} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {70720321-DED4-464F-B913-BDA5BBDD7982} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {1BBCBA72-CDB6-4882-96EE-D4CD149433A2} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs index f020d032c2..cc27fc30cc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs @@ -88,6 +88,9 @@ public static class AbpOpenIdConnectExtensions } }; + // The application needs to be granted the `OpenIddictConstants.Permissions.Endpoints.PushedAuthorization` permission to use the PAR endpoint. + // You can enable it after you have granted the `PushedAuthorization` permission. + options.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Disable; configureOptions?.Invoke(options); }); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelper.cs index 64dfdc0fdb..96c06fad2b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelper.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Options; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form.DatePicker; @@ -45,9 +46,9 @@ public abstract class public bool AddMarginBottomClass { get; set; } = true; - protected AbpDatePickerBaseTagHelper(AbpDatePickerBaseTagHelperService service) : base(service) + protected AbpDatePickerBaseTagHelper(AbpDatePickerBaseTagHelperService service, IOptionsFactory optionsFactory) : base(service) { - _abpDatePickerOptionsImplementation = new AbpDatePickerOptions(); + _abpDatePickerOptionsImplementation = optionsFactory.Create(string.Empty); } public void SetDatePickerOptions(IAbpDatePickerOptions options) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelper.cs index e8a8a60b3c..74f58b0f23 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelper.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Options; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form.DatePicker; @@ -8,7 +9,10 @@ public class AbpDatePickerTagHelper : AbpDatePickerBaseTagHelper optionsFactory) + : base(service, optionsFactory) { } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDateRangePickerTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDateRangePickerTagHelper.cs index 5a052d8877..5717e283a9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDateRangePickerTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDateRangePickerTagHelper.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Options; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form.DatePicker; @@ -10,8 +11,10 @@ public class AbpDateRangePickerTagHelper : AbpDatePickerBaseTagHelper optionsFactory) + : base(service, optionsFactory) { } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs index 9d1bac7f5f..115d6eeb02 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs @@ -106,11 +106,11 @@ public class AbpPaginationTagHelperService : AbpTagHelperService GetPreviousButtonAsync(TagHelperContext context, TagHelperOutput output) { var localizationKey = "PagerPrevious"; - var currentPage = TagHelper.Model.CurrentPage == 1 - ? TagHelper.Model.CurrentPage.ToString() - : (TagHelper.Model.CurrentPage - 1).ToString(); + var currentPage = TagHelper.Model.CurrentPage > 1 + ? (TagHelper.Model.CurrentPage - 1).ToString() + : "1"; return - "
  • \r\n" + + "
  • \r\n" + (await RenderAnchorTagHelperLinkHtmlAsync(context, output, currentPage, localizationKey)) + "
  • "; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs index 227bc0fd71..8d5700159f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs @@ -89,7 +89,7 @@ public class AbpTabTagHelperService : AbpTagHelperService var id = TagHelper.Name; var attributes = GetTabContentAttributes(context, output); - var classAttributesAsString = attributes.Where(a => a.Name == "class").ToList().Select(a => a.Name).JoinAsString(" "); + var classAttributesAsString = attributes.Where(a => a.Name == "class").ToList().Select(a => a.Value).JoinAsString(" "); var otherAttributes = attributes.Where(a => a.Name != "class").ToList(); var wrapper = new TagBuilder("div"); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrScriptBundleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrScriptBundleContributor.cs deleted file mode 100644 index 226b076b7a..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrScriptBundleContributor.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using Volo.Abp.AspNetCore.Mvc.UI.Bundling; -using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery; -using Volo.Abp.Modularity; - -namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; - -[DependsOn(typeof(JQueryScriptContributor))] -public class ToastrScriptBundleContributor : BundleContributor -{ - public override void ConfigureBundle(BundleConfigurationContext context) - { - context.Files.AddIfNotContains("/libs/toastr/toastr.min.js"); - } -} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrStyleBundleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrStyleBundleContributor.cs deleted file mode 100644 index d00f9e3768..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Toastr/ToastrStyleBundleContributor.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using Volo.Abp.AspNetCore.Mvc.UI.Bundling; - -namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; - -public class ToastrStyleBundleContributor : BundleContributor -{ - public override void ConfigureBundle(BundleConfigurationContext context) - { - context.Files.AddIfNotContains("/libs/toastr/toastr.min.css"); - } -} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs index 5d8c15ba40..4bb1d80fef 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs @@ -12,7 +12,6 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.MalihuCustomScrollbar; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2; using Volo.Abp.AspNetCore.Mvc.UI.Packages.SweetAlert2; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Timeago; -using Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; using Volo.Abp.Modularity; namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; @@ -26,7 +25,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; typeof(Select2ScriptContributor), typeof(DatatablesNetBs5ScriptContributor), typeof(Sweetalert2ScriptContributor), - typeof(ToastrScriptBundleContributor), typeof(MalihuCustomScrollbarPluginScriptBundleContributor), typeof(LuxonScriptContributor), typeof(TimeagoScriptContributor), @@ -48,7 +46,7 @@ public class SharedThemeGlobalScriptContributor : BundleContributor "/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js", - "/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js", + "/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/authentication-state/authentication-state-listener.js" }); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs index f959d73f05..4f436a02b0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs @@ -7,7 +7,6 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.DatatablesNetBs5; using Volo.Abp.AspNetCore.Mvc.UI.Packages.FontAwesome; using Volo.Abp.AspNetCore.Mvc.UI.Packages.MalihuCustomScrollbar; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2; -using Volo.Abp.AspNetCore.Mvc.UI.Packages.Toastr; using Volo.Abp.Modularity; namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; @@ -16,7 +15,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; typeof(CoreStyleContributor), typeof(BootstrapStyleContributor), typeof(FontAwesomeStyleContributor), - typeof(ToastrStyleBundleContributor), typeof(Select2StyleContributor), typeof(MalihuCustomScrollbarPluginStyleBundleContributor), typeof(DatatablesNetBs5StyleContributor), @@ -30,7 +28,8 @@ public class SharedThemeGlobalStyleContributor : BundleContributor context.Files.AddRange(new BundleFile[] { "/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.css", - "/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-styles.css" + "/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-styles.css", + "/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.css", }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js index e3e1f8fe6c..9bbf0abd28 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js @@ -84,12 +84,9 @@ var abp = abp || {}; }; var _createButtonDropdown = function (record, field, tableInstance) { - if (field.items.length === 1) { + if (field.items.length === 1 && getVisibilityValue(field.items[0].visible, record, tableInstance)) { var firstItem = field.items[0]; - if (!getVisibilityValue(firstItem.visible, record, tableInstance)) { - return $(''); - } - + var $button = $(''); if (firstItem.displayNameHtml) { @@ -159,8 +156,9 @@ var abp = abp || {}; $dropdownButton.addClass(field.cssClass); } + var isEntityActionsDisabled = true; var $dropdownItemsContainer = $('
      ').addClass('dropdown-menu'); - + for (var i = 0; i < field.items.length; i++) { var fieldItem = field.items[i]; @@ -169,6 +167,7 @@ var abp = abp || {}; continue; } + isEntityActionsDisabled = false; var $dropdownItem = _createDropdownItem(record, fieldItem, tableInstance); if (fieldItem.enabled && !fieldItem.enabled({ record: record, table: tableInstance })) { @@ -180,11 +179,22 @@ var abp = abp || {}; if ($dropdownItemsContainer.find('li').length > 0) { $dropdownItemsContainer.appendTo($container); - } else { - $dropdownButton.addClass('d-none'); } - $dropdownButton.prependTo($container); + if (isEntityActionsDisabled) { + + $dropdownButton.attr('disabled', 'disabled'); + + var $tooltip = $('
      '); + $tooltip.attr('title', localize("EntityActionsDisabledTooltip")); + $tooltip.attr('data-bs-toggle', 'tooltip'); + new bootstrap.Tooltip($tooltip); + + $dropdownButton.appendTo($tooltip); + $tooltip.prependTo($container); + }else{ + $dropdownButton.prependTo($container); + } if (bootstrap) { new bootstrap.Dropdown($dropdownButton, { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.css b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.css new file mode 100644 index 0000000000..9ff4555d0c --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.css @@ -0,0 +1,141 @@ +.abp-toast-container { + position: fixed; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-end; + min-width: 350px; + min-height: 80px; + z-index: 1900; + right: 30px; + bottom: 30px; + pointer-events: none; +} + +.abp-toast { + pointer-events: auto; + display: grid; + grid-template-columns: 35px 1fr; + gap: 5px; + margin: 5px 0; + padding: 10px; + width: 350px; + user-select: none; + z-index: 9999; + color: #fff; + border-radius: 8px; + font-size: 16px; + box-shadow: 0 0 20px 0 rgba(76, 87, 125, 0.02); + animation: toastIn 0.3s ease-in-out; +} + +.abp-toast-success { + border: 2px solid #4fbf67; + background-color: #4fbf67; +} + +.abp-toast-error { + border: 2px solid #c00d49; + background-color: #c00d49; +} + +.abp-toast-info { + border: 2px solid #438aa7; + background-color: #438aa7; +} + +.abp-toast-warning { + border: 2px solid #ff9f38; + background-color: #ff9f38; +} + +.abp-toast-icon { + display: flex; + align-items: center; + justify-content: center; +} + +.abp-toast-icon .icon { + font-size: 30px; +} + +.abp-toast-content { + position: relative; + display: flex; + align-self: center; + flex-direction: column; + word-break: break-word; + padding-bottom: 2px; +} + +.abp-toast-close-button { + position: absolute; + top: 0; + right: 0; + display: flex; + align-items: center; + justify-content: center; + margin: 0; + padding: 0px 5px 0 0; + width: 25px; + height: 100%; + border: none; + border-radius: 50%; + background: transparent; + color: inherit; + cursor: pointer; +} + +.abp-toast-close-button:focus { + outline: none; +} + +.abp-toast-title { + margin: 0; + padding: 0; + font-size: 1rem; + font-weight: 600; +} + +.abp-toast-message { + margin: 0; + padding: 0; + max-width: 240px; +} + +@keyframes toastIn { + from { + transform: translateX(100%); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } +} + +@keyframes toastOut { + from { + transform: translateX(0); + opacity: 1; + } + to { + transform: translateX(100%); + opacity: 0; + } +} + +.toast-removing { + animation: toastOut 0.3s ease-in-out forwards; +} + +@media only screen and (max-width: 768px) { + .abp-toast-container { + min-width: 100%; + right: 0; + } + + .abp-toast { + width: 95%; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.js new file mode 100644 index 0000000000..a23d844ce6 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toast/abp-toast.js @@ -0,0 +1,207 @@ +function AbpToastService(globalOptions) { + // Static default configuration for all instances + if (!AbpToastService.defaultOptions) { + AbpToastService.defaultOptions = { + closable: true, + sticky: false, + life: 5000, + tapToDismiss: false, + containerKey: undefined, + iconClass: undefined, + position: { + top: 'auto', + right: '30px', + bottom: '30px', + left: 'auto' + } + }; + } + + // Find existing container or create new one + const containerId = globalOptions?.containerKey ? + `toast-container-${globalOptions.containerKey}` : + 'toast-container'; + + this.container = document.getElementById(containerId); + if (!this.container) { + this.container = document.createElement('div'); + this.container.id = containerId; + this.container.className = 'abp-toast-container'; + document.body.appendChild(this.container); + } + + this.toasts = []; + this.lastId = 0; + + // Merge user provided global options with defaults + this.globalOptions = this.extend({}, AbpToastService.defaultOptions, globalOptions); + + this.updateContainerPosition(); +} + +// Deep merge objects +AbpToastService.prototype.extend = function(target, ...sources) { + sources.forEach(source => { + for (const key in source) { + if (source[key] && typeof source[key] === 'object') { + target[key] = this.extend(target[key] || {}, source[key]); + } else { + target[key] = source[key]; + } + } + }); + return target; +}; + +// Update toast container position based on global options +AbpToastService.prototype.updateContainerPosition = function() { + const { position } = this.globalOptions; + Object.assign(this.container.style, position); +}; + +// Update global options +AbpToastService.prototype.setGlobalOptions = function(options) { + this.globalOptions = this.extend({}, this.globalOptions, options); + this.updateContainerPosition(); +}; + +// Get icon class based on severity +AbpToastService.prototype.getIconClass = function(severity, options) { + // Use custom icon class if provided + if (options.iconClass) { + return options.iconClass; + } + + const icons = { + success: 'fa fa-check', + info: 'fa fa-info-circle', + warning: 'fa fa-exclamation-triangle', + error: 'fa fa-exclamation-circle' + }; + return icons[severity] || 'fa fa-exclamation-triangle'; +}; + +// Create toast DOM element +AbpToastService.prototype.createToastElement = function(message, title, severity, options) { + const toast = document.createElement('div'); + toast.className = `abp-toast abp-toast-${severity}`; + + const closeButton = options.closable !== false ? + `` : ''; + + const titleHtml = title ? `
      ${title}
      ` : ''; + + toast.innerHTML = ` +
      + +
      +
      + ${closeButton} + ${titleHtml} +

      ${message}

      +
      `; + + // Add event listeners + const closeButtonElement = toast.querySelector('.abp-toast-close-button'); + if (closeButtonElement) { + closeButtonElement.addEventListener('click', () => this.remove(toast)); + } + + if (options.tapToDismiss) { + toast.addEventListener('click', () => this.remove(toast)); + } + + return toast; +}; + +// Show a toast with given options +AbpToastService.prototype.show = function(message, title, severity = 'neutral', options = {}) { + const mergedOptions = this.extend({}, this.globalOptions, options); + const id = ++this.lastId; + const toast = this.createToastElement(message, title, severity, mergedOptions); + + // Set data attributes for non-object options + Object.entries(mergedOptions) + .filter(([_, value]) => typeof value !== 'object') + .forEach(([key, value]) => toast.dataset[key] = value); + + toast.dataset.id = id; + this.container.appendChild(toast); + this.toasts.push(toast); + + // Auto remove if not sticky + if (!mergedOptions.sticky) { + setTimeout(() => this.remove(toast), mergedOptions.life); + } + + return id; +}; + +// Remove a toast with animation +AbpToastService.prototype.remove = function(toastElement) { + toastElement.classList.add('toast-removing'); + setTimeout(() => { + if (toastElement.parentNode === this.container) { + this.container.removeChild(toastElement); + } + this.toasts = this.toasts.filter(t => t !== toastElement); + }, 300); // Match animation duration +}; + +// Convenience methods for different severities +AbpToastService.prototype.success = function(message, title, options) { + return this.show(message, title, 'success', options); +}; + +AbpToastService.prototype.error = function(message, title, options) { + return this.show(message, title, 'error', options); +}; + +AbpToastService.prototype.info = function(message, title, options) { + return this.show(message, title, 'info', options); +}; + +AbpToastService.prototype.warning = function(message, title, options) { + return this.show(message, title, 'warning', options); +}; + +// Clear all toasts +AbpToastService.prototype.clear = function(containerKey) { + if (containerKey) { + this.toasts = this.toasts.filter(toast => { + const shouldRemove = toast.dataset.containerKey === containerKey; + if (shouldRemove) { + this.remove(toast); + } + return !shouldRemove; + }); + } else { + this.toasts.forEach(toast => this.remove(toast)); + } +}; + +// Static method to set default options for all instances +AbpToastService.setDefaultOptions = function(options) { + AbpToastService.defaultOptions = this.prototype.extend({}, AbpToastService.defaultOptions, options); +}; + +var abp = abp || {}; +(function () { + abp.notify.success = function (message, title, options) { + new AbpToastService().success(message, title, options); + }; + + abp.notify.info = function (message, title, options) { + new AbpToastService().info(message, title, options); + }; + + abp.notify.warn = function (message, title, options) { + new AbpToastService().warning(message, title, options); + }; + + abp.notify.error = function (message, title, options) { + new AbpToastService().error(message, title, options); + }; +})(); \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js deleted file mode 100644 index 37a7c40166..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js +++ /dev/null @@ -1,34 +0,0 @@ -var abp = abp || {}; -(function () { - - if (!toastr) { - return; - } - - /* DEFAULTS *************************************************/ - - toastr.options.positionClass = 'toast-bottom-right'; - - /* NOTIFICATION *********************************************/ - - var showNotification = function (type, message, title, options) { - toastr[type](message, title, options); - }; - - abp.notify.success = function (message, title, options) { - showNotification('success', message, title, options); - }; - - abp.notify.info = function (message, title, options) { - showNotification('info', message, title, options); - }; - - abp.notify.warn = function (message, title, options) { - showNotification('warning', message, title, options); - }; - - abp.notify.error = function (message, title, options) { - showNotification('error', message, title, options); - }; - -})(); \ No newline at end of file diff --git a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs index a94426adad..0a47399e49 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs @@ -5,17 +5,20 @@ using Hangfire; using Hangfire.States; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; +using Volo.Abp.Hangfire; namespace Volo.Abp.BackgroundJobs.Hangfire; [Dependency(ReplaceServices = true)] public class HangfireBackgroundJobManager : IBackgroundJobManager, ITransientDependency { - protected AbpBackgroundJobOptions Options { get; } + protected IOptions BackgroundJobOptions { get; } + protected IOptions HangfireOptions { get; } - public HangfireBackgroundJobManager(IOptions options) + public HangfireBackgroundJobManager(IOptions backgroundJobOptions, IOptions hangfireOptions) { - Options = options.Value; + BackgroundJobOptions = backgroundJobOptions; + HangfireOptions = hangfireOptions; } public virtual Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, @@ -33,13 +36,7 @@ public class HangfireBackgroundJobManager : IBackgroundJobManager, ITransientDep protected virtual string GetQueueName(Type argsType) { - var queueName = EnqueuedState.DefaultQueue; - var queueAttribute = Options.GetJob(argsType).JobType.GetCustomAttribute(); - if (queueAttribute != null) - { - queueName = queueAttribute.Queue; - } - - return queueName; + var queueAttribute = BackgroundJobOptions.Value.GetJob(argsType).JobType.GetCustomAttribute(); + return queueAttribute != null ? HangfireOptions.Value.DefaultQueuePrefix + queueAttribute.Queue : HangfireOptions.Value.DefaultQueue; } } diff --git a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs index cf88778089..1dbe4a6dcc 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs @@ -122,7 +122,7 @@ public class JobQueue : IJobQueue protected virtual Task EnsureInitializedAsync() { - if (ChannelAccessor != null) + if (ChannelAccessor != null && ChannelAccessor.Channel.IsOpen) { return Task.CompletedTask; } diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobWorkerOptions.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobWorkerOptions.cs index 3bc31e7a39..b339508028 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobWorkerOptions.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobWorkerOptions.cs @@ -2,6 +2,11 @@ public class AbpBackgroundJobWorkerOptions { + /// + /// Application name. + /// + public string? ApplicationName { get; set; } + /// /// Interval between polling jobs from . /// Default value: 5000 (5 seconds). diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs index 0d5441a4bc..4a9cec922c 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs @@ -9,6 +9,11 @@ public class BackgroundJobInfo { public Guid Id { get; set; } + /// + /// Application name. + /// + public virtual string? ApplicationName { get; set; } + /// /// Name of the job. /// diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs index 4313350098..a015e32d66 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs @@ -43,7 +43,7 @@ public class BackgroundJobWorker : AsyncPeriodicBackgroundWorkerBase, IBackgroun { var store = workerContext.ServiceProvider.GetRequiredService(); - var waitingJobs = await store.GetWaitingJobsAsync(WorkerOptions.MaxJobFetchCount); + var waitingJobs = await store.GetWaitingJobsAsync(WorkerOptions.ApplicationName, WorkerOptions.MaxJobFetchCount); if (!waitingJobs.Any()) { diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/DefaultBackgroundJobManager.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/DefaultBackgroundJobManager.cs index 7218776cfe..68851c5043 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/DefaultBackgroundJobManager.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/DefaultBackgroundJobManager.cs @@ -1,5 +1,7 @@ using System; using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Volo.Abp.BackgroundWorkers; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.Timing; @@ -16,16 +18,19 @@ public class DefaultBackgroundJobManager : IBackgroundJobManager, ITransientDepe protected IBackgroundJobSerializer Serializer { get; } protected IGuidGenerator GuidGenerator { get; } protected IBackgroundJobStore Store { get; } + protected IOptions BackgroundJobWorkerOptions { get; } public DefaultBackgroundJobManager( IClock clock, IBackgroundJobSerializer serializer, IBackgroundJobStore store, - IGuidGenerator guidGenerator) + IGuidGenerator guidGenerator, + IOptions backgroundJobWorkerOptions) { Clock = clock; Serializer = serializer; GuidGenerator = guidGenerator; + BackgroundJobWorkerOptions = backgroundJobWorkerOptions; Store = store; } @@ -41,6 +46,7 @@ public class DefaultBackgroundJobManager : IBackgroundJobManager, ITransientDepe var jobInfo = new BackgroundJobInfo { Id = GuidGenerator.Create(), + ApplicationName = BackgroundJobWorkerOptions.Value.ApplicationName, JobName = jobName, JobArgs = Serializer.Serialize(args), Priority = priority, diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs index 4a3a8d1ac0..7fcf8cc5b6 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs @@ -24,12 +24,13 @@ public interface IBackgroundJobStore /// /// Gets waiting jobs. It should get jobs based on these: - /// Conditions: !IsAbandoned And NextTryTime <= Clock.Now. + /// Conditions: ApplicationName is applicationName And !IsAbandoned And NextTryTime <= Clock.Now. /// Order by: Priority DESC, TryCount ASC, NextTryTime ASC. /// Maximum result: . /// + /// Application name. /// Maximum result count. - Task> GetWaitingJobsAsync(int maxResultCount); + Task> GetWaitingJobsAsync(string? applicationName, int maxResultCount); /// /// Deletes a job. diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs index 7abbc188ce..85916e8c37 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs @@ -35,9 +35,10 @@ public class InMemoryBackgroundJobStore : IBackgroundJobStore, ISingletonDepende return Task.CompletedTask; } - public virtual Task> GetWaitingJobsAsync(int maxResultCount) + public virtual Task> GetWaitingJobsAsync(string? applicationName, int maxResultCount) { var waitingJobs = _jobs.Values + .Where(t => t.ApplicationName == applicationName) .Where(t => !t.IsAbandoned && t.NextTryTime <= Clock.Now) .OrderByDescending(t => t.Priority) .ThenBy(t => t.TryCount) diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerBase.cs b/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerBase.cs index 0c1a5f3d26..0c9ba67603 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerBase.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerBase.cs @@ -13,7 +13,7 @@ public abstract class HangfireBackgroundWorkerBase : BackgroundWorkerBase, IHang public TimeZoneInfo? TimeZone { get; set; } = TimeZoneInfo.Utc; - public string Queue { get; set; } = EnqueuedState.DefaultQueue; + public string Queue { get; set; } = default!; public abstract Task DoWorkAsync(CancellationToken cancellationToken = default); } diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs b/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs index 9c79056ec2..1ed3561cac 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Hangfire; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.DynamicProxy; using Volo.Abp.Hangfire; @@ -30,15 +31,19 @@ public class HangfireBackgroundWorkerManager : BackgroundWorkerManager, ISinglet public async override Task AddAsync(IBackgroundWorker worker, CancellationToken cancellationToken = default) { + var abpHangfireOptions = ServiceProvider.GetRequiredService>().Value; + var defaultQueuePrefix = abpHangfireOptions.DefaultQueuePrefix; + var defaultQueue = abpHangfireOptions.DefaultQueue; + switch (worker) { case IHangfireBackgroundWorker hangfireBackgroundWorker: { var unProxyWorker = ProxyHelper.UnProxy(hangfireBackgroundWorker); - + RecurringJob.AddOrUpdate( hangfireBackgroundWorker.RecurringJobId, - hangfireBackgroundWorker.Queue, + hangfireBackgroundWorker.Queue.IsNullOrWhiteSpace() ? defaultQueue : defaultQueuePrefix + hangfireBackgroundWorker.Queue, () => ((IHangfireBackgroundWorker)unProxyWorker).DoWorkAsync(cancellationToken), hangfireBackgroundWorker.CronExpression, new RecurringJobOptions @@ -57,24 +62,24 @@ public class HangfireBackgroundWorkerManager : BackgroundWorkerManager, ISinglet { return; } - + var adapterType = typeof(HangfirePeriodicBackgroundWorkerAdapter<>).MakeGenericType(ProxyHelper.GetUnProxiedType(worker)); var workerAdapter = (Activator.CreateInstance(adapterType) as IHangfireBackgroundWorker)!; if (workerAdapter.RecurringJobId.IsNullOrWhiteSpace()) { - RecurringJob.AddOrUpdate( + RecurringJob.AddOrUpdate( () => workerAdapter.DoWorkAsync(cancellationToken), GetCron(period.Value), workerAdapter.TimeZone , - workerAdapter.Queue); + workerAdapter.Queue.IsNullOrWhiteSpace() ? defaultQueue : defaultQueuePrefix + workerAdapter.Queue); } else { - + RecurringJob.AddOrUpdate( workerAdapter.RecurringJobId, - workerAdapter.Queue, + workerAdapter.Queue.IsNullOrWhiteSpace() ? defaultQueue : defaultQueuePrefix + workerAdapter.Queue, () => workerAdapter.DoWorkAsync(cancellationToken), GetCron(period.Value), new RecurringJobOptions @@ -82,7 +87,7 @@ public class HangfireBackgroundWorkerManager : BackgroundWorkerManager, ISinglet TimeZone = workerAdapter.TimeZone }); } - + break; } @@ -121,4 +126,4 @@ public class HangfireBackgroundWorkerManager : BackgroundWorkerManager, ISinglet return cron; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor index 2547a7930c..44b8aa46e4 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor @@ -22,7 +22,7 @@ - No data available + @UiLocalizer["NoDataAvailableInDatatable"] @@ -119,7 +119,7 @@ } else { - + @{ var entity = context as IHasExtraProperties; diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs index 5a9bc08df5..682643893e 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text.RegularExpressions; using Blazorise.DataGrid; using Blazorise.Extensions; +using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns; @@ -35,12 +36,15 @@ public partial class AbpExtensibleDataGrid : ComponentBase [Parameter] public string? Class { get; set; } [Parameter] public bool Responsive { get; set; } - + [Parameter] public bool AutoGenerateColumns { get; set; } [Inject] public IStringLocalizerFactory StringLocalizerFactory { get; set; } = default!; + [Inject] + public IStringLocalizer UiLocalizer { get; set; } = default!; + protected virtual RenderFragment RenderCustomTableColumnComponent(Type type, object data) { return (builder) => diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor index 5e686afbda..cd1f908dcc 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/EntityActions.razor @@ -1,27 +1,29 @@ @typeparam TItem - @if ( Type == ActionType.Dropdown ) + @if ( Type == ActionType.Dropdown || (Type == ActionType.Button && DisabledOrNoActions())) { - @if ( HasPrimaryAction ) - { - - - } - else - { - - @ToggleText - - } - - @ChildContent - + + @if ( HasPrimaryAction ) + { + + + } + else + { + + @ToggleText + + } + + @ChildContent + + } else diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/FodyWeavers.xml b/framework/src/Volo.Abp.BlobStoring.Bunny/FodyWeavers.xml similarity index 63% rename from modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/FodyWeavers.xml rename to framework/src/Volo.Abp.BlobStoring.Bunny/FodyWeavers.xml index 4367b6b2c9..1715698ccd 100644 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/FodyWeavers.xml +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/FodyWeavers.xml @@ -1,3 +1,3 @@ - - + + \ No newline at end of file diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/FodyWeavers.xsd b/framework/src/Volo.Abp.BlobStoring.Bunny/FodyWeavers.xsd similarity index 100% rename from modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/FodyWeavers.xsd rename to framework/src/Volo.Abp.BlobStoring.Bunny/FodyWeavers.xsd diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo.Abp.BlobStoring.Bunny.abppkg b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo.Abp.BlobStoring.Bunny.abppkg new file mode 100644 index 0000000000..f4bad072d2 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo.Abp.BlobStoring.Bunny.abppkg @@ -0,0 +1,3 @@ +{ + "role": "lib.framework" +} \ No newline at end of file diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.abppkg.analyze.json b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo.Abp.BlobStoring.Bunny.abppkg.analyze.json similarity index 70% rename from modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.abppkg.analyze.json rename to framework/src/Volo.Abp.BlobStoring.Bunny/Volo.Abp.BlobStoring.Bunny.abppkg.analyze.json index ad8a90c8bd..b9e8bbba1b 100644 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.abppkg.analyze.json +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo.Abp.BlobStoring.Bunny.abppkg.analyze.json @@ -1,24 +1,19 @@ { - "name": "Volo.Abp.VirtualFileExplorer.DemoApp", - "hash": "a8ae8e893f31975f0699e38091b149aa", + "name": "Volo.Abp.BlobStoring.Bunny", + "hash": "", "contents": [ { - "namespace": "Volo.Abp.VirtualFileExplorer.DemoApp", + "namespace": "Volo.Abp.BlobStoring.Bunny", "dependsOnModules": [ { - "declaringAssemblyName": "Volo.Abp.Autofac", - "namespace": "Volo.Abp.Autofac", - "name": "AbpAutofacModule" + "declaringAssemblyName": "Volo.Abp.BlobStoring", + "namespace": "Volo.Abp.BlobStoring", + "name": "AbpBlobStoringModule" }, { - "declaringAssemblyName": "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic", - "namespace": "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic", - "name": "AbpAspNetCoreMvcUiBasicThemeModule" - }, - { - "declaringAssemblyName": "Volo.Abp.VirtualFileExplorer.Web", - "namespace": "Volo.Abp.VirtualFileExplorer.Web", - "name": "AbpVirtualFileExplorerWebModule" + "declaringAssemblyName": "Volo.Abp.Caching", + "namespace": "Volo.Abp.Caching", + "name": "AbpCachingModule" } ], "implementingInterfaces": [ @@ -66,7 +61,7 @@ } ], "contentType": "abpModule", - "name": "AbpVirtualFileExplorerDemoAppModule", + "name": "AbpBlobStoringBunnyModule", "summary": null } ] diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo.Abp.BlobStoring.Bunny.csproj b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo.Abp.BlobStoring.Bunny.csproj new file mode 100644 index 0000000000..2cd9c74ac6 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo.Abp.BlobStoring.Bunny.csproj @@ -0,0 +1,26 @@ + + + + + + + netstandard2.0;netstandard2.1;net8.0;net9.0 + enable + Nullable + false + false + false + + + + + + + + + + + + + + diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/AbpBunnyBlobStoringModule .cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/AbpBunnyBlobStoringModule .cs new file mode 100644 index 0000000000..3fe814f2f0 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/AbpBunnyBlobStoringModule .cs @@ -0,0 +1,16 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Caching; +using Volo.Abp.Modularity; + +namespace Volo.Abp.BlobStoring.Bunny; + +[DependsOn( + typeof(AbpBlobStoringModule), + typeof(AbpCachingModule))] +public class AbpBlobStoringBunnyModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddHttpClient(); + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyApiException.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyApiException.cs new file mode 100644 index 0000000000..1e10d4caa2 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyApiException.cs @@ -0,0 +1,18 @@ +using System; + +namespace Volo.Abp.BlobStoring.Bunny; + +public class BunnyApiException : Exception +{ + public BunnyApiException(string message) + : base(message) + { + + } + + public BunnyApiException(string message, Exception innerException) + : base(message, innerException) + { + + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobContainerConfigurationExtensions.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobContainerConfigurationExtensions.cs new file mode 100644 index 0000000000..03afe1c36d --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobContainerConfigurationExtensions.cs @@ -0,0 +1,24 @@ +using System; + +namespace Volo.Abp.BlobStoring.Bunny; + +public static class BunnyBlobContainerConfigurationExtensions +{ + public static BunnyBlobProviderConfiguration GetBunnyConfiguration( + this BlobContainerConfiguration containerConfiguration) + { + return new BunnyBlobProviderConfiguration(containerConfiguration); + } + + public static BlobContainerConfiguration UseBunny( + this BlobContainerConfiguration containerConfiguration, + Action bunnyConfigureAction) + { + containerConfiguration.ProviderType = typeof(BunnyBlobProvider); + containerConfiguration.NamingNormalizers.TryAdd(); + + bunnyConfigureAction(new BunnyBlobProviderConfiguration(containerConfiguration)); + + return containerConfiguration; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobNamingNormalizer.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobNamingNormalizer.cs new file mode 100644 index 0000000000..74c436e2e9 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobNamingNormalizer.cs @@ -0,0 +1,51 @@ +using System.Globalization; +using System.Text.RegularExpressions; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Localization; + +namespace Volo.Abp.BlobStoring.Bunny; + +public class BunnyBlobNamingNormalizer : IBlobNamingNormalizer, ITransientDependency +{ + private readonly static Regex ValidCharactersRegex = + new Regex(@"^[a-z0-9-]*$", RegexOptions.Compiled); + + private const int MinLength = 4; + private const int MaxLength = 64; + + public virtual string NormalizeBlobName(string blobName) => blobName; + + public virtual string NormalizeContainerName(string containerName) + { + Check.NotNullOrWhiteSpace(containerName, nameof(containerName)); + + using (CultureHelper.Use(CultureInfo.InvariantCulture)) + { + // Trim whitespace and convert to lowercase + var normalizedName = containerName + .Trim() + .ToLowerInvariant(); + + // Remove any invalid characters + normalizedName = Regex.Replace(normalizedName, "[^a-z0-9-]", string.Empty); + + // Validate structure + if (!ValidCharactersRegex.IsMatch(normalizedName)) + { + throw new AbpException( + $"Container name contains invalid characters: {containerName}. " + + "Only lowercase letters, numbers, and hyphens are allowed."); + } + + // Validate length + if (normalizedName.Length < MinLength || normalizedName.Length > MaxLength) + { + throw new AbpException( + $"Container name must be between {MinLength} and {MaxLength} characters. " + + $"Current length: {normalizedName.Length}"); + } + + return normalizedName; + } + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobProvider.cs new file mode 100644 index 0000000000..6c06bc3f95 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobProvider.cs @@ -0,0 +1,167 @@ +using System; +using System.IO; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using BunnyCDN.Net.Storage; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.BlobStoring.Bunny; + +public class BunnyBlobProvider : BlobProviderBase, ITransientDependency +{ + protected IBunnyBlobNameCalculator BunnyBlobNameCalculator { get; } + protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; } + protected IBunnyClientFactory BunnyClientFactory { get; } + + public BunnyBlobProvider( + IBunnyBlobNameCalculator bunnyBlobNameCalculator, + IBlobNormalizeNamingService blobNormalizeNamingService, + IBunnyClientFactory bunnyClientFactory) + { + BunnyBlobNameCalculator = bunnyBlobNameCalculator; + BlobNormalizeNamingService = blobNormalizeNamingService; + BunnyClientFactory = bunnyClientFactory; + } + + public async override Task SaveAsync(BlobProviderSaveArgs args) + { + var configuration = args.Configuration.GetBunnyConfiguration(); + var containerName = GetContainerName(args); + var blobName = BunnyBlobNameCalculator.Calculate(args); + + await ValidateContainerExistsAsync(containerName, configuration); + + var bunnyStorage = await GetBunnyCDNStorageAsync(args); + + if (!args.OverrideExisting && await BlobExistsAsync(bunnyStorage, containerName, blobName)) + { + throw new BlobAlreadyExistsException( + $"Blob '{args.BlobName}' already exists in container '{containerName}'. " + + $"Set {nameof(args.OverrideExisting)} to true to overwrite."); + } + + using var memoryStream = new MemoryStream(); + await args.BlobStream.CopyToAsync(memoryStream); + memoryStream.Position = 0; + + await bunnyStorage.UploadAsync(memoryStream, $"{containerName}/{blobName}"); + } + + public async override Task DeleteAsync(BlobProviderDeleteArgs args) + { + var blobName = BunnyBlobNameCalculator.Calculate(args); + var containerName = GetContainerName(args); + var bunnyStorage = await GetBunnyCDNStorageAsync(args); + + if (!await BlobExistsAsync(bunnyStorage, containerName, blobName)) + { + return false; + } + + try + { + return await bunnyStorage.DeleteObjectAsync($"{containerName}/{blobName}"); + } + catch (BunnyCDNStorageException ex) when (ex.Message.Contains("404")) + { + return false; + } + } + + public async override Task ExistsAsync(BlobProviderExistsArgs args) + { + var blobName = BunnyBlobNameCalculator.Calculate(args); + var containerName = GetContainerName(args); + var bunnyStorage = await GetBunnyCDNStorageAsync(args); + + return await BlobExistsAsync(bunnyStorage, containerName, blobName); + } + + public async override Task GetOrNullAsync(BlobProviderGetArgs args) + { + var blobName = BunnyBlobNameCalculator.Calculate(args); + var containerName = GetContainerName(args); + var bunnyStorage = await GetBunnyCDNStorageAsync(args); + + if (!await BlobExistsAsync(bunnyStorage, containerName, blobName)) + { + return null; + } + + try + { + return await bunnyStorage.DownloadObjectAsStreamAsync($"{containerName}/{blobName}"); + } + catch (WebException ex) when ((HttpStatusCode)ex.Status == HttpStatusCode.NotFound) + { + return null; + } + } + + protected virtual async Task BlobExistsAsync(BunnyCDNStorage bunnyStorage, string containerName, string blobName) + { + try + { + var fullBlobPath = $"/{containerName}/{blobName}"; + var directoryPath = Path.GetDirectoryName(fullBlobPath)?.Replace('\\', '/') + "/"; + + if (string.IsNullOrWhiteSpace(directoryPath)) + { + throw new Exception("Invalid directory path generated from blob name."); + } + + var objects = await bunnyStorage.GetStorageObjectsAsync(directoryPath); + return objects?.Any(o => o.FullPath == fullBlobPath) == true; + } + catch (BunnyCDNStorageException ex) when (ex.Message.Contains("404")) + { + return false; + } + catch (Exception ex) + { + throw new Exception($"Error while checking blob existence: {ex.Message}", ex); + } + } + + protected virtual async Task GetBunnyCDNStorageAsync(BlobProviderArgs args) + { + var configuration = args.Configuration.GetBunnyConfiguration(); + var containerName = GetContainerName(args); + var region = configuration.Region ?? "de"; + + return await BunnyClientFactory.CreateAsync( + configuration.AccessKey, + containerName, + region); + } + + protected virtual string GetContainerName(BlobProviderArgs args) + { + var configuration = args.Configuration.GetBunnyConfiguration(); + return configuration.ContainerName.IsNullOrWhiteSpace() + ? args.ContainerName + : BlobNormalizeNamingService.NormalizeContainerName(args.Configuration, configuration.ContainerName!); + } + + protected virtual async Task ValidateContainerExistsAsync( + string containerName, + BunnyBlobProviderConfiguration configuration + ) + { + try + { + await BunnyClientFactory.EnsureStorageZoneExistsAsync( + configuration.AccessKey, + containerName, + configuration.Region ?? "de", + configuration.CreateContainerIfNotExists); + } + catch (Exception ex) + { + throw new AbpException( + $"Failed to validate storage zone '{containerName}': {ex.Message}", + ex); + } + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobProviderConfiguration.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobProviderConfiguration.cs new file mode 100644 index 0000000000..0897c7f2b8 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobProviderConfiguration.cs @@ -0,0 +1,40 @@ +namespace Volo.Abp.BlobStoring.Bunny; + +public class BunnyBlobProviderConfiguration +{ + public string? Region { + get => _containerConfiguration.GetConfigurationOrDefault(BunnyBlobProviderConfigurationNames.Region, "de"); + set => _containerConfiguration.SetConfiguration(BunnyBlobProviderConfigurationNames.Region, value); + } + + /// + /// This name may only contain lowercase letters, numbers, and hyphens. (no spaces) + /// The name must also be between 4 and 64 characters long. + /// The name must be globaly unique + /// If this parameter is not specified, the ContainerName of the will be used. + /// + public string? ContainerName { + get => _containerConfiguration.GetConfigurationOrDefault(BunnyBlobProviderConfigurationNames.ContainerName); + set => _containerConfiguration.SetConfiguration(BunnyBlobProviderConfigurationNames.ContainerName, value); + } + + /// + /// Default value: false. + /// + public bool CreateContainerIfNotExists { + get => _containerConfiguration.GetConfigurationOrDefault(BunnyBlobProviderConfigurationNames.CreateContainerIfNotExists, false); + set => _containerConfiguration.SetConfiguration(BunnyBlobProviderConfigurationNames.CreateContainerIfNotExists, value); + } + + public string AccessKey { + get => _containerConfiguration.GetConfiguration(BunnyBlobProviderConfigurationNames.AccessKey); + set => _containerConfiguration.SetConfiguration(BunnyBlobProviderConfigurationNames.AccessKey, value); + } + + private readonly BlobContainerConfiguration _containerConfiguration; + + public BunnyBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration) + { + _containerConfiguration = containerConfiguration; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobProviderConfigurationNames.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobProviderConfigurationNames.cs new file mode 100644 index 0000000000..09d79076a6 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobProviderConfigurationNames.cs @@ -0,0 +1,15 @@ +namespace Volo.Abp.BlobStoring.Bunny; + +public static class BunnyBlobProviderConfigurationNames +{ + // The primary region for the storage zone (e.g., DE, NY, etc.) + public const string Region = "Bunny.Region"; + + // The name of the storage zone + public const string ContainerName = "Bunny.ContainerName"; + + // The API access key for the bunny.net account + public const string AccessKey = "Bunny.AccessKey"; + + public const string CreateContainerIfNotExists = "Bunny.CreateContainerIfNotExists"; +} diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyStorageZoneModel.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyStorageZoneModel.cs new file mode 100644 index 0000000000..e718531927 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyStorageZoneModel.cs @@ -0,0 +1,17 @@ +using System; + +namespace Volo.Abp.BlobStoring.Bunny; + +[Serializable] +public class BunnyStorageZoneModel +{ + public int Id { get; set; } + + public string Password { get; set; } = null!; + + public string Name { get; set; } = null!; + + public string? Region { get; set; } + + public bool Deleted { get; set; } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/DefaultBunnyBlobNameCalculator.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/DefaultBunnyBlobNameCalculator.cs new file mode 100644 index 0000000000..f06acb8c14 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/DefaultBunnyBlobNameCalculator.cs @@ -0,0 +1,21 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.BlobStoring.Bunny; + +public class DefaultBunnyBlobNameCalculator : IBunnyBlobNameCalculator, ITransientDependency +{ + protected ICurrentTenant CurrentTenant { get; } + + public DefaultBunnyBlobNameCalculator(ICurrentTenant currentTenant) + { + CurrentTenant = currentTenant; + } + + public virtual string Calculate(BlobProviderArgs args) + { + return CurrentTenant.Id == null + ? $"host/{args.BlobName}" + : $"tenants/{CurrentTenant.Id.Value.ToString("D")}/{args.BlobName}"; + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/DefaultBunnyClientFactory.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/DefaultBunnyClientFactory.cs new file mode 100644 index 0000000000..d22cff0e0a --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/DefaultBunnyClientFactory.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using BunnyCDN.Net.Storage; +using Microsoft.Extensions.Caching.Distributed; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Encryption; + +namespace Volo.Abp.BlobStoring.Bunny; + +public class DefaultBunnyClientFactory : IBunnyClientFactory, ITransientDependency +{ + private readonly IDistributedCache _cache; + private readonly IHttpClientFactory _httpClientFactory; + private readonly IStringEncryptionService _stringEncryptionService; + + private const string CacheKeyPrefix = "BunnyStorageZone:"; + private readonly static TimeSpan CacheDuration = TimeSpan.FromHours(12); + + public DefaultBunnyClientFactory( + IHttpClientFactory httpClient, + IDistributedCache cache, + IStringEncryptionService stringEncryptionService) + { + _cache = cache; + _httpClientFactory = httpClient; + _stringEncryptionService = stringEncryptionService; + } + + public virtual async Task CreateAsync(string accessKey, string containerName, string region = "de") + { + var cacheKey = $"{CacheKeyPrefix}{containerName}"; + var storageZoneInfo = await _cache.GetOrAddAsync( + cacheKey, + async () => { + var result = await GetStorageZoneAsync(accessKey, containerName); + if (result == null) + { + throw new AbpException($"Storage zone '{containerName}' not found"); + } + + // Encrypt the sensitive password before caching + result.Password = _stringEncryptionService.Encrypt(result.Password!)!; + return result; + }, + () => new DistributedCacheEntryOptions + { + AbsoluteExpiration = DateTimeOffset.Now.Add(CacheDuration) + } + ); + + if (storageZoneInfo == null) + { + throw new AbpException($"Could not retrieve storage zone information for container '{containerName}'"); + } + + // Decrypt the password before using it + var decryptedPassword = _stringEncryptionService.Decrypt(storageZoneInfo.Password); + + return new BunnyCDNStorage(containerName, decryptedPassword, region); + } + + public virtual async Task EnsureStorageZoneExistsAsync( + string accessKey, + string containerName, + string region = "de", + bool createIfNotExists = false) + { + var storageZone = await GetStorageZoneAsync(accessKey, containerName); + + if (storageZone == null) + { + if (!createIfNotExists) + { + throw new AbpException( + $"Storage zone '{containerName}' does not exist. " + + "Set createIfNotExists to true to create it automatically."); + } + + await CreateStorageZoneAsync(accessKey, containerName, region); + + // Clear the cache to force a refresh of the storage zone info + var cacheKey = $"{CacheKeyPrefix}{containerName}"; + await _cache.RemoveAsync(cacheKey); + } + } + + protected virtual async Task CreateStorageZoneAsync( + string accessKey, + string containerName, + string region) + { + using (var client = _httpClientFactory.CreateClient("BunnyApiClient")) + { + client.DefaultRequestHeaders.Add("AccessKey", accessKey); + + var payload = new Dictionary + { + { "Name", containerName }, + { "Region", region }, + { "ZoneTier", 0 } + }; + + var content = new StringContent( + JsonSerializer.Serialize(payload), + Encoding.UTF8, + "application/json"); + + var response = await client.PostAsync( + "https://api.bunny.net/storagezone", + content); + + if (!response.IsSuccessStatusCode) + { + var errorContent = await response.Content.ReadAsStringAsync(); + throw new AbpException( + $"Failed to create storage zone '{containerName}'. " + + $"Status: {response.StatusCode}, Error: {errorContent}"); + } + + var responseContent = await response.Content.ReadAsStringAsync(); + var createdZone = JsonSerializer.Deserialize(responseContent); + + if (createdZone == null) + { + throw new AbpException($"Failed to deserialize the created storage zone response for '{containerName}'"); + } + + return createdZone; + } + } + + protected virtual async Task GetStorageZoneAsync(string accessKey, string containerName) + { + using (var client = _httpClientFactory.CreateClient("BunnyApiClient")) + { + client.DefaultRequestHeaders.Add("AccessKey", accessKey); + var response = await client.GetAsync("https://api.bunny.net/storagezone"); + response.EnsureSuccessStatusCode(); + + var content = await response.Content.ReadAsStringAsync(); + var zones = JsonSerializer.Deserialize(content); + + return zones?.FirstOrDefault(x => x.Name.Equals(containerName, StringComparison.OrdinalIgnoreCase) && !x.Deleted); + } + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/IBunnyBlobNameCalculator.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/IBunnyBlobNameCalculator.cs new file mode 100644 index 0000000000..34a18aca46 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/IBunnyBlobNameCalculator.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.BlobStoring.Bunny; + +public interface IBunnyBlobNameCalculator +{ + string Calculate(BlobProviderArgs args); +} diff --git a/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/IBunnyClientFactory.cs b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/IBunnyClientFactory.cs new file mode 100644 index 0000000000..7e5db5ed41 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/IBunnyClientFactory.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using BunnyCDN.Net.Storage; + +namespace Volo.Abp.BlobStoring.Bunny; + +public interface IBunnyClientFactory +{ + Task CreateAsync(string accessKey, string containerName, string region = "de"); + + Task EnsureStorageZoneExistsAsync(string accessKey, string containerName, string region = "de", bool createIfNotExists = false); +} diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Logging/AbpLoggerExtensions.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Logging/AbpLoggerExtensions.cs index 18a93f7348..e1899f7efc 100644 --- a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Logging/AbpLoggerExtensions.cs +++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Logging/AbpLoggerExtensions.cs @@ -70,12 +70,12 @@ public static class AbpLoggerExtensions private static void LogKnownProperties(ILogger logger, Exception exception, LogLevel logLevel) { - if (exception is IHasErrorCode exceptionWithErrorCode) + if (exception is IHasErrorCode exceptionWithErrorCode && !exceptionWithErrorCode.Code.IsNullOrWhiteSpace()) { logger.LogWithLevel(logLevel, "Code:" + exceptionWithErrorCode.Code); } - if (exception is IHasErrorDetails exceptionWithErrorDetails) + if (exception is IHasErrorDetails exceptionWithErrorDetails && !exceptionWithErrorDetails.Details.IsNullOrWhiteSpace()) { logger.LogWithLevel(logLevel, "Details:" + exceptionWithErrorDetails.Details); } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs index af06d908f0..b73a56b166 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs @@ -11,7 +11,7 @@ public static class AbpModuleHelper public static List FindAllModuleTypes(Type startupModuleType, ILogger? logger) { var moduleTypes = new List(); - logger?.Log(LogLevel.Information, "Loaded ABP modules:"); + logger?.Log(LogLevel.Debug, "Loaded ABP modules:"); AddModuleAndDependenciesRecursively(moduleTypes, startupModuleType, logger); return moduleTypes; } @@ -72,7 +72,7 @@ public static class AbpModuleHelper } moduleTypes.Add(moduleType); - logger?.Log(LogLevel.Information, $"{new string(' ', depth * 2)}- {moduleType.FullName}"); + logger?.Log(LogLevel.Debug, $"{new string(' ', depth * 2)}- {moduleType.FullName}"); foreach (var dependedModuleType in FindDependedModuleTypes(moduleType)) { diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs index d56660be57..63ddc222bd 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEfCoreNavigationHelper.cs @@ -31,6 +31,14 @@ public class AbpEfCoreNavigationHelper : ITransientDependency protected virtual void EntityEntryTrackedOrStateChanged(EntityEntry entityEntry) { + if (entityEntry.State is EntityState.Unchanged or EntityState.Modified) + { + foreach (var entry in EntityEntries.Values.Where(x => x.NavigationEntries.Any())) + { + entry.UpdateNavigationEntries(); + } + } + if (entityEntry.State != EntityState.Unchanged) { return; @@ -189,6 +197,22 @@ public class AbpEfCoreNavigationHelper : ITransientDependency return navigationEntryProperty != null && navigationEntryProperty.IsModified; } + public virtual AbpNavigationEntry? GetNavigationEntry(EntityEntry entityEntry, int navigationEntryIndex) + { + var entryId = GetEntityEntryIdentity(entityEntry); + if (entryId == null) + { + return null; + } + + if (!EntityEntries.TryGetValue(entryId, out var abpEntityEntry)) + { + return null; + } + + return abpEntityEntry.NavigationEntries.ElementAtOrDefault(navigationEntryIndex); + } + protected virtual string? GetEntityEntryIdentity(EntityEntry entityEntry) { if (entityEntry.Entity is IEntity entryEntity && entryEntity.GetKeys().Length == 1) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs index 0aef48e0d1..4b8a531db1 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ChangeTrackers/AbpEntityEntry.cs @@ -1,3 +1,4 @@ +using System.Collections; using System.Collections.Generic; using System.Linq; using Microsoft.EntityFrameworkCore; @@ -32,6 +33,49 @@ public class AbpEntityEntry EntityEntry = entityEntry; NavigationEntries = EntityEntry.Navigations.Select(x => new AbpNavigationEntry(x, x.Metadata.Name)).ToList(); } + + public void UpdateNavigationEntries() + { + foreach (var navigationEntry in NavigationEntries) + { + if (IsModified || + EntityEntry.State == EntityState.Modified || + navigationEntry.IsModified || + navigationEntry.NavigationEntry.IsModified) + { + continue; + } + + var navigation = EntityEntry.Navigations.FirstOrDefault(n => n.Metadata.Name == navigationEntry.Name); + + var currentValue = AbpNavigationEntry.GetOriginalValue(navigation?.CurrentValue); + if (currentValue == null) + { + continue; + } + + switch (navigationEntry.OriginalValue) + { + case null: + navigationEntry.OriginalValue = currentValue; + break; + case IEnumerable originalValueCollection when currentValue is IEnumerable currentValueCollection: + { + var existingList = originalValueCollection.Cast().ToList(); + var newList = currentValueCollection.Cast().ToList(); + if (newList.Count > existingList.Count) + { + navigationEntry.OriginalValue = currentValue; + } + + break; + } + default: + navigationEntry.OriginalValue = currentValue; + break; + } + } + } } public class AbpNavigationEntry @@ -42,9 +86,29 @@ public class AbpNavigationEntry public bool IsModified { get; set; } + public List? OriginalValue { get; set; } + + public object? CurrentValue => NavigationEntry.CurrentValue; + public AbpNavigationEntry(NavigationEntry navigationEntry, string name) { NavigationEntry = navigationEntry; Name = name; + OriginalValue = GetOriginalValue(navigationEntry.CurrentValue); + } + + public static List? GetOriginalValue(object? currentValue) + { + if (currentValue is null) + { + return null; + } + + if (currentValue is IEnumerable enumerable) + { + return enumerable.Cast().ToList(); + } + + return new List { currentValue }; } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs index a52ac2f437..d50e6b89f6 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -193,16 +194,20 @@ public class EntityHistoryHelper : IEntityHistoryHelper, ITransientDependency } } - if (Options.SaveEntityHistoryWhenNavigationChanges && AbpEfCoreNavigationHelper != null) + if (AbpEfCoreNavigationHelper != null) { foreach (var (navigationEntry, index) in entityEntry.Navigations.Select((value, i) => ( value, i ))) { if (AbpEfCoreNavigationHelper.IsNavigationEntryModified(entityEntry, index)) { + var abpNavigationEntry = AbpEfCoreNavigationHelper.GetNavigationEntry(entityEntry, index); + var isCollection = navigationEntry.Metadata.IsCollection; propertyChanges.Add(new EntityPropertyChangeInfo { PropertyName = navigationEntry.Metadata.Name, - PropertyTypeFullName = navigationEntry.Metadata.ClrType.GetFirstGenericArgumentIfNullable().FullName! + PropertyTypeFullName = navigationEntry.Metadata.ClrType.GetFirstGenericArgumentIfNullable().FullName!, + OriginalValue = GetNavigationPropertyValue(abpNavigationEntry?.OriginalValue, isCollection), + NewValue = GetNavigationPropertyValue(abpNavigationEntry?.CurrentValue, isCollection) }); } } @@ -211,6 +216,44 @@ public class EntityHistoryHelper : IEntityHistoryHelper, ITransientDependency return propertyChanges; } + protected virtual string? GetNavigationPropertyValue(object? entity, bool isCollection) + { + switch (entity) + { + case null: + return null; + + case IEntity entryEntity: + var keys = entryEntity.GetKeys(); + return keys.Length == 0 ? null : string.Join(", ",keys).TruncateWithPostfix(EntityPropertyChangeInfo.MaxValueLength); + + case IEnumerable enumerable: + var keysList = new List(); + foreach (var item in enumerable) + { + var id = GetNavigationPropertyValue(item, false); + if (id != null) + { + keysList.Add(id); + } + } + + if (keysList.Count == 0) + { + return null; + } + + var serializedKeysEnumerable = keysList.Count == 1 && !isCollection + ? keysList.First() + : JsonSerializer.Serialize(keysList); + + return serializedKeysEnumerable.TruncateWithPostfix(EntityPropertyChangeInfo.MaxValueLength); + + default: + return null; + } + } + protected virtual bool IsCreated(EntityEntry entityEntry) { return entityEntry.State == EntityState.Added; diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs index 6c34b86904..2b75155e7b 100644 --- a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs +++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs @@ -1,5 +1,6 @@ using Hangfire; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; using Volo.Abp.Authorization; using Volo.Abp.Modularity; @@ -24,7 +25,10 @@ public class AbpHangfireModule : AbpModule var options = serviceProvider.GetRequiredService>().Value; return new AbpHangfireBackgroundJobServer(options.BackgroundJobServerFactory.Invoke(serviceProvider)); }); + + context.Services.TryAddEnumerable(ServiceDescriptor.Singleton, AbpHangfireOptionsConfiguration>()); } + public override void OnApplicationInitialization(ApplicationInitializationContext context) { _backgroundJobServer = context.ServiceProvider.GetRequiredService(); diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptions.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptions.cs index 98c45348c7..8ed90d17c7 100644 --- a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptions.cs +++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptions.cs @@ -12,6 +12,18 @@ namespace Volo.Abp.Hangfire; public class AbpHangfireOptions { + /// + /// This value is used to add prefix to all of the queues. Default is empty. + /// + public string DefaultQueuePrefix { get; set; } = string.Empty; + + /// + /// Hangfire queue name max length, default is 50. + /// + public int MaxQueueNameLength { get; set; } = 50; + + public string DefaultQueue { get; set; } = EnqueuedState.DefaultQueue; + public BackgroundJobServerOptions? ServerOptions { get; set; } public IEnumerable? AdditionalProcesses { get; set; } diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptionsConfiguration.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptionsConfiguration.cs new file mode 100644 index 0000000000..1fb5dcd8dc --- /dev/null +++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptionsConfiguration.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; +using Hangfire; +using Hangfire.States; +using Microsoft.Extensions.Options; + +namespace Volo.Abp.Hangfire; + +public class AbpHangfireOptionsConfiguration : IPostConfigureOptions +{ + public void PostConfigure(string? name, AbpHangfireOptions options) + { + if (options.DefaultQueuePrefix.IsNullOrWhiteSpace()) + { + return;; + } + + // The Queue name argument must consist of lowercase letters, digits, underscore, and dash characters only. + var queuesPrefix = Regex.Replace(options.DefaultQueuePrefix.ToLower().Replace(".", "_"), "[^a-z0-9_-]", ""); + if (queuesPrefix.IsNullOrWhiteSpace()) + { + throw new AbpException($"The QueuesPrefix({options.DefaultQueuePrefix}) is not valid, it must consist of lowercase letters, digits, underscore, and dash characters only."); + } + + options.DefaultQueuePrefix = queuesPrefix.EnsureEndsWith('_'); + + if (options.ServerOptions == null) + { + var queue = $"{options.DefaultQueuePrefix}{EnqueuedState.DefaultQueue}"; + if (queue.Length > options.MaxQueueNameLength) + { + throw new AbpException($"The maximum length of the Hangfire queue name({queue}) is {options.MaxQueueNameLength}, Please configure the AbpHangfireOptions.DefaultQueuePrefix manually."); + } + options.ServerOptions = new BackgroundJobServerOptions + { + Queues = new[] { queue } + }; + options.DefaultQueue = queue; + } + else + { + var queues = options.ServerOptions.Queues; + for (var i = 0; i < queues.Length; i++) + { + var queue = $"{options.DefaultQueuePrefix}{queues[i]}"; + if (queue.Length > options.MaxQueueNameLength) + { + throw new AbpException($"The maximum length of the Hangfire queue name({queue}) is {options.MaxQueueNameLength}, Please configure the AbpHangfireOptions.DefaultQueuePrefix manually."); + } + queues[i] = queue; + } + var defaultQueue = queues.FirstOrDefault(q => q.EndsWith(EnqueuedState.DefaultQueue)); + if (defaultQueue.IsNullOrWhiteSpace()) + { + defaultQueue = queues.FirstOrDefault(); + if (defaultQueue.IsNullOrWhiteSpace()) + { + throw new AbpException("There is no queue defined in the Hangfire configuration!"); + } + } + options.DefaultQueue = defaultQueue; + } + } +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs index a687ba2bf9..acd905b8c6 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/IMongoDbRepository.cs @@ -1,8 +1,8 @@ using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using MongoDB.Driver; -using MongoDB.Driver.Linq; using Volo.Abp.Domain.Entities; namespace Volo.Abp.Domain.Repositories.MongoDB; @@ -20,10 +20,13 @@ public interface IMongoDbRepository : IRepository Task> GetCollectionAsync(CancellationToken cancellationToken = default); - [Obsolete("Use GetMongoQueryableAsync method.")] - IMongoQueryable GetMongoQueryable(); + [Obsolete("Use GetQueryable method.")] + IQueryable GetMongoQueryable(); - Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null); + [Obsolete("Use GetQueryableAsync method.")] + Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null); + + Task> GetQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null); Task> GetAggregateAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null); } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs index 45629f76e5..fdc7464d6b 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs @@ -455,19 +455,19 @@ public class MongoDbRepository public async override Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)).ToListAsync(cancellationToken); + return await (await GetQueryableAsync(cancellationToken)).ToListAsync(cancellationToken); } public async override Task> GetListAsync(Expression> predicate, bool includeDetails = false, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)).Where(predicate).ToListAsync(cancellationToken); + return await (await GetQueryableAsync(cancellationToken)).Where(predicate).ToListAsync(cancellationToken); } public async override Task GetCountAsync(CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)).LongCountAsync(cancellationToken); + return await (await GetQueryableAsync(cancellationToken)).LongCountAsync(cancellationToken); } public async override Task> GetPagedListAsync( @@ -479,10 +479,9 @@ public class MongoDbRepository { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderByIf>(!sorting.IsNullOrWhiteSpace(), sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy>(skipCount, maxResultCount) .ToListAsync(cancellationToken); } @@ -493,14 +492,14 @@ public class MongoDbRepository { cancellationToken = GetCancellationToken(cancellationToken); - var entities = await (await GetMongoQueryableAsync(cancellationToken)) + var entities = await (await GetQueryableAsync(cancellationToken)) .Where(predicate) .ToListAsync(cancellationToken); await DeleteManyAsync(entities, autoSave, cancellationToken); } - public override async Task DeleteDirectAsync(Expression> predicate, CancellationToken cancellationToken = default) + public async override Task DeleteDirectAsync(Expression> predicate, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); @@ -527,12 +526,16 @@ public class MongoDbRepository [Obsolete("Use GetQueryableAsync method.")] protected override IQueryable GetQueryable() { - return GetMongoQueryable(); + return ApplyDataFilters( + SessionHandle != null + ? Collection.AsQueryable(SessionHandle) + : Collection.AsQueryable() + ); } public async override Task> GetQueryableAsync() { - return await GetMongoQueryableAsync(); + return await GetQueryableAsync(); } public async override Task FindAsync( @@ -542,34 +545,36 @@ public class MongoDbRepository { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(predicate) .SingleOrDefaultAsync(cancellationToken); } - [Obsolete("Use GetMongoQueryableAsync method.")] - public virtual IMongoQueryable GetMongoQueryable() + [Obsolete("Use GetQueryableAsync method.")] + public virtual IQueryable GetMongoQueryable() { - return ApplyDataFilters( - SessionHandle != null - ? Collection.AsQueryable(SessionHandle) - : Collection.AsQueryable() - ); + return GetQueryable(); + } + + [Obsolete("Use GetQueryableAsync method.")] + public virtual Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null) + { + return GetQueryableAsync(cancellationToken, options); } - public virtual Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) + public virtual async Task> GetQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? options = null) { - return GetMongoQueryableAsync(cancellationToken, aggregateOptions); + return await GetQueryableAsync(cancellationToken, options); } - protected virtual async Task> GetMongoQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) + protected virtual async Task> GetQueryableAsync(CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) { cancellationToken = GetCancellationToken(cancellationToken); var dbContext = await GetDbContextAsync(cancellationToken); var collection = dbContext.Collection(); - return ApplyDataFilters, TOtherEntity>( + return ApplyDataFilters, TOtherEntity>( dbContext.SessionHandle != null ? collection.AsQueryable(dbContext.SessionHandle, aggregateOptions) : collection.AsQueryable(aggregateOptions) @@ -810,7 +815,7 @@ public class MongoDbRepository { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Id!.Equals(id)) .FirstOrDefaultAsync(cancellationToken); } @@ -827,7 +832,7 @@ public class MongoDbRepository { cancellationToken = GetCancellationToken(cancellationToken); - var entities = await (await GetMongoQueryableAsync(cancellationToken)) + var entities = await (await GetQueryableAsync(cancellationToken)) .Where(x => ids.Contains(x.Id)) .ToListAsync(cancellationToken); diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs index 676450a5b8..353185c8e3 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDbCoreRepositoryExtensions.cs @@ -1,8 +1,8 @@ using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using MongoDB.Driver; -using MongoDB.Driver.Linq; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories.MongoDB; @@ -36,19 +36,26 @@ public static class MongoDbCoreRepositoryExtensions return repository.ToMongoDbRepository().GetCollectionAsync(cancellationToken); } - [Obsolete("Use GetMongoQueryableAsync method.")] - public static IMongoQueryable GetMongoQueryable(this IReadOnlyBasicRepository repository) + [Obsolete("Use GetQueryableAsync method.")] + public static IQueryable GetMongoQueryable(this IReadOnlyBasicRepository repository) where TEntity : class, IEntity { return repository.ToMongoDbRepository().GetMongoQueryable(); } - public static Task> GetMongoQueryableAsync(this IReadOnlyBasicRepository repository, CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) + [Obsolete("Use GetQueryableAsync method.")] + public static Task> GetMongoQueryableAsync(this IReadOnlyBasicRepository repository, CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) where TEntity : class, IEntity { return repository.ToMongoDbRepository().GetMongoQueryableAsync(cancellationToken, aggregateOptions); } + public static Task> GetQueryableAsync(this IReadOnlyBasicRepository repository) + where TEntity : class, IEntity + { + return repository.ToMongoDbRepository().GetQueryableAsync(); + } + public static Task> GetAggregateAsync(this IReadOnlyBasicRepository repository, CancellationToken cancellationToken = default, AggregateOptions? aggregateOptions = null) where TEntity : class, IEntity { diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs index c1d8b8f514..6ad2b0b359 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbDateTimeSerializer.cs @@ -5,7 +5,7 @@ using MongoDB.Bson.Serialization.Serializers; namespace Volo.Abp.MongoDB; -public class AbpMongoDbDateTimeSerializer : DateTimeSerializer +public class AbpMongoDbDateTimeSerializer : StructSerializerBase { protected DateTimeKind DateTimeKind { get; set; } protected bool DisableDateTimeNormalization { get; set; } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs index f61e9ddb45..91d2808010 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs @@ -1,5 +1,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using MongoDB.Bson; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Serializers; using Volo.Abp.Domain; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.Modularity; @@ -19,6 +22,8 @@ public class AbpMongoDbModule : AbpModule public override void ConfigureServices(ServiceConfigurationContext context) { + BsonSerializer.TryRegisterSerializer(new GuidSerializer(GuidRepresentation.Standard)); + context.Services.TryAddTransient( typeof(IMongoDbContextProvider<>), typeof(UnitOfWorkMongoDbContextProvider<>) diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs index 6a73af27f5..9d1b706d8b 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs @@ -68,7 +68,6 @@ public class MongoDbContextEventInbox : IMongoDbContextEventInb .WhereIf(transformedFilter != null, transformedFilter!) .OrderBy(x => x.CreationTime) .Take(maxCount) - .As>() .ToListAsync(cancellationToken: cancellationToken); return outgoingEventRecords diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs index 57b59038b5..6dc8817f02 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventOutbox.cs @@ -56,7 +56,6 @@ public class MongoDbContextEventOutbox : IMongoDbContextEventOu .WhereIf(transformedFilter != null, transformedFilter!) .OrderBy(x => x.CreationTime) .Take(maxCount) - .As>() .ToListAsync(cancellationToken: cancellationToken); return outgoingEventRecords diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs index 287f3ced0e..b7e896a27a 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoDbAsyncQueryableProvider.cs @@ -6,9 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; using Volo.Abp.Linq; -using MongoDB.Driver; using MongoDB.Driver.Linq; -using Volo.Abp.DynamicProxy; namespace Volo.Abp.MongoDB; @@ -16,344 +14,339 @@ public class MongoDbAsyncQueryableProvider : IAsyncQueryableProvider, ISingleton { public bool CanExecute(IQueryable queryable) { - return ProxyHelper.UnProxy(queryable) is IMongoQueryable; - } - - protected virtual IMongoQueryable GetMongoQueryable(IQueryable queryable) - { - return ProxyHelper.UnProxy(queryable).As>(); + return queryable.Provider is IMongoQueryProvider; } public Task ContainsAsync(IQueryable queryable, T item, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).Contains(item)); + return Task.FromResult(queryable.Contains(item)); } public Task AnyAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AnyAsync(cancellationToken); + return queryable.AnyAsync(cancellationToken); } public Task AnyAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AnyAsync(predicate, cancellationToken); + return queryable.AnyAsync(predicate, cancellationToken); } public Task AllAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).All(predicate)); + return Task.FromResult(queryable.All(predicate)); } public Task CountAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).CountAsync(cancellationToken); + return queryable.CountAsync(cancellationToken); } public Task CountAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).CountAsync(predicate, cancellationToken); + return queryable.CountAsync(predicate, cancellationToken); } public Task LongCountAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).LongCountAsync(cancellationToken); + return queryable.LongCountAsync(cancellationToken); } public Task LongCountAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).LongCountAsync(predicate, cancellationToken); + return queryable.LongCountAsync(predicate, cancellationToken); } public Task FirstAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).FirstAsync(cancellationToken); + return queryable.FirstAsync(cancellationToken); } public Task FirstAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).FirstAsync(predicate, cancellationToken); + return queryable.FirstAsync(predicate, cancellationToken); } public Task FirstOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).FirstOrDefaultAsync(cancellationToken)!; + return queryable.FirstOrDefaultAsync(cancellationToken)!; } public Task FirstOrDefaultAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).FirstOrDefaultAsync(predicate, cancellationToken)!; + return queryable.FirstOrDefaultAsync(predicate, cancellationToken)!; } public Task LastAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).Last()); + return Task.FromResult(queryable.Last()); } public Task LastAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).Last(predicate)); + return Task.FromResult(queryable.Last(predicate)); } public Task LastOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).LastOrDefault()); + return Task.FromResult(queryable.LastOrDefault()); } public Task LastOrDefaultAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return Task.FromResult(GetMongoQueryable(queryable).LastOrDefault(predicate)); + return Task.FromResult(queryable.LastOrDefault(predicate)); } public Task SingleAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SingleAsync(cancellationToken); + return queryable.SingleAsync(cancellationToken); } public Task SingleAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SingleAsync(predicate, cancellationToken); + return queryable.SingleAsync(predicate, cancellationToken); } public Task SingleOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SingleOrDefaultAsync(cancellationToken)!; + return queryable.SingleOrDefaultAsync(cancellationToken)!; } public Task SingleOrDefaultAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SingleOrDefaultAsync(predicate, cancellationToken)!; + return queryable.SingleOrDefaultAsync(predicate, cancellationToken)!; } public Task MinAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).MinAsync(cancellationToken); + return queryable.MinAsync(cancellationToken); } public Task MinAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).MinAsync(selector, cancellationToken); + return queryable.MinAsync(selector, cancellationToken); } public Task MaxAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).MaxAsync(cancellationToken); + return queryable.MaxAsync(cancellationToken); } public Task MaxAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).MaxAsync(selector, cancellationToken); + return queryable.MaxAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(cancellationToken); + return queryable.SumAsync(cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task SumAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).SumAsync(selector, cancellationToken); + return queryable.SumAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(cancellationToken); + return queryable.AverageAsync(cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task AverageAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).AverageAsync(selector, cancellationToken); + return queryable.AverageAsync(selector, cancellationToken); } public Task> ToListAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return GetMongoQueryable(queryable).ToListAsync(cancellationToken); + return queryable.ToListAsync(cancellationToken); } public async Task ToArrayAsync(IQueryable queryable, CancellationToken cancellationToken = default) { - return (await GetMongoQueryable(queryable).ToListAsync(cancellationToken)).ToArray(); + return (await queryable.ToListAsync(cancellationToken)).ToArray(); } } diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/AbpRabbitMqModule.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/AbpRabbitMqModule.cs index 60eecd0cd2..da010b83c9 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/AbpRabbitMqModule.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/AbpRabbitMqModule.cs @@ -20,6 +20,7 @@ public class AbpRabbitMqModule : AbpModule foreach (var connectionFactory in options.Connections.Values) { connectionFactory.DispatchConsumersAsync = true; + connectionFactory.AutomaticRecoveryEnabled = false; } }); } diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ChannelPool.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ChannelPool.cs index d795342c1d..b7ed4c80c8 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ChannelPool.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ChannelPool.cs @@ -42,6 +42,18 @@ public class ChannelPool : IChannelPool, ISingletonDependency poolItem.Acquire(); + if (poolItem.Channel.IsClosed) + { + poolItem.Dispose(); + Channels.TryRemove(channelName, out _); + poolItem = Channels.GetOrAdd( + channelName, + _ => new ChannelPoolItem(CreateChannel(channelName, connectionName)) + ); + + poolItem.Acquire(); + } + return new ChannelAccessor( poolItem.Channel, channelName, diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs index 8c046ffffd..5f4556b96a 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs @@ -24,21 +24,19 @@ public class ConnectionPool : IConnectionPool, ISingletonDependency public virtual IConnection Get(string? connectionName = null) { connectionName ??= RabbitMqConnections.DefaultConnectionName; - + var connectionFactory = Options.Connections.GetOrDefault(connectionName); try { - var lazyConnection = Connections.GetOrAdd( - connectionName, () => new Lazy(() => - { - var connection = Options.Connections.GetOrDefault(connectionName); - var hostnames = connection.HostName.TrimEnd(';').Split(';'); - // Handle Rabbit MQ Cluster. - return hostnames.Length == 1 ? connection.CreateConnection() : connection.CreateConnection(hostnames); - - }) - ); - - return lazyConnection.Value; + var connection = GetConnection(connectionName, connectionFactory); + + if (connection.IsOpen) + { + return connection; + } + + connection.Dispose(); + Connections.TryRemove(connectionName, out _); + return GetConnection(connectionName, connectionFactory); } catch (Exception) { @@ -47,6 +45,20 @@ public class ConnectionPool : IConnectionPool, ISingletonDependency } } + protected virtual IConnection GetConnection(string connectionName, ConnectionFactory connectionFactory) + { + return Connections.GetOrAdd( + connectionName, () => new Lazy(() => + { + var hostnames = connectionFactory.HostName.TrimEnd(';').Split(';'); + // Handle Rabbit MQ Cluster. + return hostnames.Length == 1 + ? connectionFactory.CreateConnection() + : connectionFactory.CreateConnection(hostnames); + }) + ).Value; + } + public void Dispose() { if (_isDisposed) diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json index c1097000c1..93cf62ab84 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json @@ -60,6 +60,7 @@ "AddNew": "اضف جديد", "ProfilePicture": "الصوره الشخصيه", "Theme": "سمة", - "NotAssigned": "غيرمعتمد" + "NotAssigned": "غيرمعتمد", + "EntityActionsDisabledTooltip": "ليس لديك إذن لتنفيذ أي إجراء." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json index 710a57a2a9..ff2d09fdf8 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json @@ -60,6 +60,7 @@ "AddNew": "Přidat nový", "ProfilePicture": "Profilový obrázek", "Theme": "Téma", - "NotAssigned": "Nepřiřazena" + "NotAssigned": "Nepřiřazena", + "EntityActionsDisabledTooltip": "Nemáte oprávnění provést žádnou akci." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json index a955a9066d..37c361c1e3 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json @@ -60,6 +60,7 @@ "AddNew": "Neue hinzufügen", "ProfilePicture": "Profilbild", "Theme": "Thema", - "NotAssigned": "Nicht zugeordnet" + "NotAssigned": "Nicht zugeordnet", + "EntityActionsDisabledTooltip": "Sie haben keine Berechtigung, Aktionen auszuführen." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json index 2abb92eab7..f7d837a361 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json @@ -54,6 +54,7 @@ "ManageYourAccount": "Διαχείριση Λογαριασμού", "OthersGroup": "άλλος", "Today": "Σήμερα", - "Apply": "Ισχύουν" + "Apply": "Ισχύουν", + "EntityActionsDisabledTooltip": "Δεν έχετε δικαίωμα να εκτελέσετε καμία ενέργεια." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json index 7bbcc9d82f..c5aaa5957c 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json @@ -55,6 +55,7 @@ "OthersGroup": "Other", "NotAssigned": "Not Assigned", "Today": "Today", - "Apply": "Apply" + "Apply": "Apply", + "EntityActionsDisabledTooltip": "You do not have permission to perform any action." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json index 8ea53bba77..7a5a806124 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json @@ -60,6 +60,7 @@ "AddNew": "Add new", "ProfilePicture": "Profile picture", "Theme": "Theme", - "NotAssigned": "Not Assigned" + "NotAssigned": "Not Assigned", + "EntityActionsDisabledTooltip": "You do not have permission to perform any action." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json index 7870ccff7b..132243a740 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json @@ -60,6 +60,7 @@ "AddNew": "Agregar nuevo", "ProfilePicture": "Foto de perfil", "Theme": "Tema", - "NotAssigned": "No asignado" + "NotAssigned": "No asignado", + "EntityActionsDisabledTooltip": "No tienes permisos para realizar ninguna acción." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json index c5cb5960bd..f1738957c9 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json @@ -54,6 +54,7 @@ "ManageYourAccount": "حساب خود را مدیریت کنید", "OthersGroup": "دیگر", "Today": "امروز", - "Apply": "درخواست دادن" + "Apply": "درخواست دادن", + "EntityActionsDisabledTooltip": "شما دسترسی به انجام هر گونه عملیات ندارید." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json index d2b5018e73..1af59eb720 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json @@ -60,6 +60,7 @@ "AddNew": "Lisää uusi", "ProfilePicture": "Profiilikuva", "Theme": "Teema", - "NotAssigned": "Ei määritetty" + "NotAssigned": "Ei määritetty", + "EntityActionsDisabledTooltip": "Sinulla ei ole oikeutta suorittaa mitään toimintoa." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json index 66e37491fb..8af5661d1a 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json @@ -60,6 +60,7 @@ "AddNew": "Ajouter un nouveau", "ProfilePicture": "Image de profil", "Theme": "Thème", - "NotAssigned": "Non attribué" + "NotAssigned": "Non attribué", + "EntityActionsDisabledTooltip": "Vous n'avez pas les permissions pour effectuer une action." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json index 7da0065d95..ba873b7685 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json @@ -60,6 +60,7 @@ "AddNew": "नया जोड़ो", "ProfilePicture": "प्रोफ़ाइल फोटो", "Theme": "विषय", - "NotAssigned": "सौंपा नहीं गया है" + "NotAssigned": "सौंपा नहीं गया है", + "EntityActionsDisabledTooltip": "आपके पास कोई कार्रवाई नहीं है जो करने के लिए है।" } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json index b1073d62e7..5b16c84963 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json @@ -60,6 +60,7 @@ "AddNew": "Dodaj novi", "ProfilePicture": "Profilna slika", "Theme": "Tema", - "NotAssigned": "Nije dodijeljeno" + "NotAssigned": "Nije dodijeljeno", + "EntityActionsDisabledTooltip": "Nemate dozvolu za izvođenje bilo kakve akcije." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json index 3df6177a9f..0539276498 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json @@ -60,6 +60,7 @@ "AddNew": "Új hozzáadása", "ProfilePicture": "Profil kép", "Theme": "Téma", - "NotAssigned": "Nem kijelölt" + "NotAssigned": "Nem kijelölt", + "EntityActionsDisabledTooltip": "Nincs jogosultsága bármely művelethez." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json index d2eba16bd8..8a1eda9e4e 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json @@ -60,6 +60,7 @@ "AddNew": "Bæta við nýju", "ProfilePicture": "Forsíðumynd", "Theme": "Þema", - "NotAssigned": "Ekki skráður" + "NotAssigned": "Ekki skráður", + "EntityActionsDisabledTooltip": "Þú hefur ekki aðgang að þessum aðgerðum." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json index ef255274df..77d4742680 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json @@ -60,6 +60,7 @@ "AddNew": "Aggiungere nuova", "ProfilePicture": "Immagine del profilo", "Theme": "Tema", - "NotAssigned": "Non assegnato" + "NotAssigned": "Non assegnato", + "EntityActionsDisabledTooltip": "Non hai i permessi per eseguire alcuna azione." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json index 85b8b4f88b..38182ec9e6 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json @@ -60,6 +60,7 @@ "AddNew": "Nieuw toevoegen", "ProfilePicture": "Profielfoto", "Theme": "Thema", - "NotAssigned": "Niet toegekend" + "NotAssigned": "Niet toegekend", + "EntityActionsDisabledTooltip": "U hebt geen toegang tot deze acties." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json index 6739b673d7..d7f321f3d6 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json @@ -60,6 +60,7 @@ "AddNew": "Dodaj nowe", "ProfilePicture": "Zdjęcie profilowe", "Theme": "Temat", - "NotAssigned": "Nie przypisano" + "NotAssigned": "Nie przypisano", + "EntityActionsDisabledTooltip": "Nie masz uprawnień do wykonania żadnej akcji." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json index 5c4a6790f7..13c8380fa3 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json @@ -60,6 +60,7 @@ "AddNew": "Adicionar novo", "ProfilePicture": "Foto do perfil", "Theme": "Tema", - "NotAssigned": "Não atribuído" + "NotAssigned": "Não atribuído", + "EntityActionsDisabledTooltip": "Você não tem permissão para executar qualquer ação." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json index c5850bef00..e03fd91f50 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json @@ -60,6 +60,7 @@ "AddNew": "Adăuga nou", "ProfilePicture": "Poză de profil", "Theme": "Temă", - "NotAssigned": "Nealocat" + "NotAssigned": "Nealocat", + "EntityActionsDisabledTooltip": "Nu aveți permisiune să efectuați nicio acțiune." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json index f329315488..57f3079cb4 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json @@ -60,6 +60,7 @@ "AddNew": "Добавить новое", "ProfilePicture": "Изображение профиля", "Theme": "Тема", - "NotAssigned": "Не назначен" + "NotAssigned": "Не назначен", + "EntityActionsDisabledTooltip": "У вас нет прав на выполнение каких-либо действий." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json index 6cc73f0cc6..eb0ba2958f 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json @@ -60,6 +60,7 @@ "AddNew": "Pridať nové", "ProfilePicture": "Profilový obrázok", "Theme": "Téma", - "NotAssigned": "Nepridelené" + "NotAssigned": "Nepridelené", + "EntityActionsDisabledTooltip": "Nemáte oprávnenie vykonávať žiadnu akciu." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json index 36d1bb14a6..bc3f795b34 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json @@ -60,6 +60,7 @@ "AddNew": "Dodaj novo", "ProfilePicture": "Profilna slika", "Theme": "Tema", - "NotAssigned": "Ni dodeljena" + "NotAssigned": "Ni dodeljena", + "EntityActionsDisabledTooltip": "Nimate pravic za izvajanje kakršne koli dejanje." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sv.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sv.json index 40aaa0073f..f0257637c1 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sv.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sv.json @@ -59,6 +59,7 @@ "AddNew": "Lägg till ny", "ProfilePicture": "Profilbild", "Theme": "Tema", - "NotAssigned": "Ej tilldelad" + "NotAssigned": "Ej tilldelad", + "EntityActionsDisabledTooltip": "Du har inte tillgång till dessa åtgärder." } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json index 2636d1087a..b21adf632a 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json @@ -60,6 +60,7 @@ "AddNew": "Yeni ekle", "ProfilePicture": "Profil resmi", "Theme": "Tema", - "NotAssigned": "Atanmadı" + "NotAssigned": "Atanmadı", + "EntityActionsDisabledTooltip": "Bu işlemi gerçekleştirmek için yeterli yetkiniz yok." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json index fca1f0954c..700798895f 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json @@ -60,6 +60,7 @@ "AddNew": "Thêm mới", "ProfilePicture": "Ảnh đại diện", "Theme": "chủ đề", - "NotAssigned": "Không được chỉ định" + "NotAssigned": "Không được chỉ định", + "EntityActionsDisabledTooltip": "Bạn không có quyền thực hiện bất kỳ hành động nào." } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json index 2824c1bbbc..60f70e1545 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json @@ -60,6 +60,7 @@ "AddNew": "添新", "ProfilePicture": "个人资料图片", "Theme": "主题", - "NotAssigned": "未分配" + "NotAssigned": "未分配", + "EntityActionsDisabledTooltip": "您没有权限执行任何操作。" } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json index 17dac54739..0f8fdeb254 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json @@ -60,6 +60,7 @@ "AddNew": "添新", "ProfilePicture": "個人資料圖片", "Theme": "主題", - "NotAssigned": "未分配" + "NotAssigned": "未分配", + "EntityActionsDisabledTooltip": "您沒有權限執行任何操作。" } } diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs index 954e6222ee..aa11d7ffde 100644 --- a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs +++ b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -512,7 +513,9 @@ public class Auditing_Tests : AbpAuditingTestBase x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && x.EntityChanges[1].PropertyChanges.Count == 1 && x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToOne) && - x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(AppEntityWithNavigationChildOneToOne).FullName)); + x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(AppEntityWithNavigationChildOneToOne).FullName && + x.EntityChanges[1].PropertyChanges[0].OriginalValue == null && + x.EntityChanges[1].PropertyChanges[0].NewValue == entityId.ToString())); AuditingStore.ClearReceivedCalls(); #pragma warning restore 4014 @@ -539,10 +542,13 @@ public class Auditing_Tests : AbpAuditingTestBase x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && x.EntityChanges[1].PropertyChanges.Count == 1 && x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToOne) && - x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(AppEntityWithNavigationChildOneToOne).FullName)); + x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(AppEntityWithNavigationChildOneToOne).FullName && + x.EntityChanges[1].PropertyChanges[0].OriginalValue == entityId.ToString() && + x.EntityChanges[1].PropertyChanges[0].NewValue == null)); AuditingStore.ClearReceivedCalls(); #pragma warning restore 4014 + var oneToManyId = ""; using (var scope = _auditingManager.BeginScope()) { using (var uow = _unitOfWorkManager.Begin()) @@ -561,6 +567,8 @@ public class Auditing_Tests : AbpAuditingTestBase await repository.UpdateAsync(entity); await uow.CompleteAsync(); await scope.SaveAsync(); + + oneToManyId = entity.OneToMany.First().Id.ToString(); } } @@ -572,36 +580,80 @@ public class Auditing_Tests : AbpAuditingTestBase x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && x.EntityChanges[1].PropertyChanges.Count == 1 && x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToMany) && - x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName)); + x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName && + x.EntityChanges[1].PropertyChanges[0].OriginalValue == null && + x.EntityChanges[1].PropertyChanges[0].NewValue == $"[\"{oneToManyId}\"]")); AuditingStore.ClearReceivedCalls(); #pragma warning restore 4014 + var newOneToManyId = ""; using (var scope = _auditingManager.BeginScope()) { using (var uow = _unitOfWorkManager.Begin()) { var entity = await repository.GetAsync(entityId); - entity.OneToMany = null; + entity.OneToMany.Add(new AppEntityWithNavigationChildOneToMany + { + AppEntityWithNavigationId = entity.Id, + ChildName = "ChildName2" + }); await repository.UpdateAsync(entity); await uow.CompleteAsync(); await scope.SaveAsync(); + + newOneToManyId = JsonSerializer.Serialize(entity.OneToMany.Select(x => x.Id).ToList()); } } #pragma warning disable 4014 AuditingStore.Received().SaveAsync(Arg.Is(x => x.EntityChanges.Count == 2 && - x.EntityChanges[0].ChangeType == EntityChangeType.Deleted && + x.EntityChanges[0].ChangeType == EntityChangeType.Created && x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithNavigationChildOneToMany).FullName && x.EntityChanges[1].ChangeType == EntityChangeType.Updated && x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && x.EntityChanges[1].PropertyChanges.Count == 1 && x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToMany) && - x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName)); + x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName && + x.EntityChanges[1].PropertyChanges[0].OriginalValue == $"[\"{oneToManyId}\"]" && + x.EntityChanges[1].PropertyChanges[0].NewValue == newOneToManyId)); + AuditingStore.ClearReceivedCalls(); +#pragma warning restore 4014 + + using (var scope = _auditingManager.BeginScope()) + { + using (var uow = _unitOfWorkManager.Begin()) + { + var entity = await repository.GetAsync(entityId); + + newOneToManyId = JsonSerializer.Serialize(entity.OneToMany.Select(x => x.Id).ToList()); + + entity.OneToMany = null; + + await repository.UpdateAsync(entity); + await uow.CompleteAsync(); + await scope.SaveAsync(); + } + } + +#pragma warning disable 4014 + AuditingStore.Received().SaveAsync(Arg.Is(x => x.EntityChanges.Count == 3 && + x.EntityChanges[0].ChangeType == EntityChangeType.Deleted && + x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithNavigationChildOneToMany).FullName && + x.EntityChanges[1].ChangeType == EntityChangeType.Deleted && + x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigationChildOneToMany).FullName && + x.EntityChanges[2].ChangeType == EntityChangeType.Updated && + x.EntityChanges[2].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && + x.EntityChanges[2].PropertyChanges.Count == 1 && + x.EntityChanges[2].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToMany) && + x.EntityChanges[2].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName && + x.EntityChanges[2].PropertyChanges[0].OriginalValue == newOneToManyId && + x.EntityChanges[2].PropertyChanges[0].NewValue == null)); AuditingStore.ClearReceivedCalls(); #pragma warning restore 4014 + var manyToManyId = ""; using (var scope = _auditingManager.BeginScope()) { using (var uow = _unitOfWorkManager.Begin()) @@ -619,6 +671,8 @@ public class Auditing_Tests : AbpAuditingTestBase await repository.UpdateAsync(entity); await uow.CompleteAsync(); await scope.SaveAsync(); + + manyToManyId = entity.ManyToMany.First().Id.ToString(); } } @@ -630,7 +684,9 @@ public class Auditing_Tests : AbpAuditingTestBase x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName && x.EntityChanges[1].PropertyChanges.Count == 1 && x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.ManyToMany) && - x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName)); + x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName && + x.EntityChanges[1].PropertyChanges[0].OriginalValue == null && + x.EntityChanges[1].PropertyChanges[0].NewValue == $"[\"{manyToManyId}\"]")); #pragma warning restore 4014 @@ -655,6 +711,8 @@ public class Auditing_Tests : AbpAuditingTestBase x.EntityChanges[0].PropertyChanges.Count == 1 && x.EntityChanges[0].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.ManyToMany) && x.EntityChanges[0].PropertyChanges[0].PropertyTypeFullName == typeof(List).FullName && + x.EntityChanges[0].PropertyChanges[0].OriginalValue == $"[\"{manyToManyId}\"]" && + x.EntityChanges[0].PropertyChanges[0].NewValue == null && x.EntityChanges[1].ChangeType == EntityChangeType.Updated && x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithNavigationChildManyToMany).FullName && diff --git a/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo.Abp.BlobStoring.Bunny.Tests.abppkg b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo.Abp.BlobStoring.Bunny.Tests.abppkg new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo.Abp.BlobStoring.Bunny.Tests.abppkg @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo.Abp.BlobStoring.Bunny.Tests.csproj b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo.Abp.BlobStoring.Bunny.Tests.csproj new file mode 100644 index 0000000000..408f630fe2 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo.Abp.BlobStoring.Bunny.Tests.csproj @@ -0,0 +1,19 @@ + + + + + + net9.0 + + 9f0d2c00-80c1-435b-bfab-2c39c8249091 + + + + + + + + + + + diff --git a/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/AbpBlobStoringBunnyTestBase.cs b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/AbpBlobStoringBunnyTestBase.cs new file mode 100644 index 0000000000..4f37cfca91 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/AbpBlobStoringBunnyTestBase.cs @@ -0,0 +1,19 @@ +using Volo.Abp.Testing; + +namespace Volo.Abp.BlobStoring.Bunny; + +public class AbpBlobStoringBunnyTestCommonBase : AbpIntegratedTest +{ + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } +} + +public class AbpBlobStoringBunnyTestBase : AbpIntegratedTest +{ + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } +} diff --git a/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/AbpBlobStoringBunnyTestModule.cs b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/AbpBlobStoringBunnyTestModule.cs new file mode 100644 index 0000000000..73066291ed --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/AbpBlobStoringBunnyTestModule.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute.Extensions; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace Volo.Abp.BlobStoring.Bunny; + +/// +/// This module will not try to connect to Bunny. +/// +[DependsOn( + typeof(AbpBlobStoringBunnyModule), + typeof(AbpBlobStoringTestModule) +)] +public class AbpBlobStoringBunnyTestCommonModule : AbpModule +{ +} + +[DependsOn( + typeof(AbpBlobStoringBunnyTestCommonModule) +)] +public class AbpBlobStoringBunnyTestModule : AbpModule +{ + private const string UserSecretsId = "9f0d2c00-80c1-435b-bfab-2c39c8249091"; + + private readonly string _randomContainerName = "abp-bunny-test-container-" + Guid.NewGuid().ToString("N"); + + private BunnyBlobProviderConfiguration _configuration; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(builderAction: builder => + { + builder.AddUserSecrets(UserSecretsId); + })); + + var configuration = context.Services.GetConfiguration(); + var accessKey = configuration["Bunny:AccessKey"]; + var region = configuration["Bunny:Region"]; + + Configure(options => + { + options.Containers.ConfigureAll((containerName, containerConfiguration) => + { + containerConfiguration.UseBunny(bunny => + { + bunny.AccessKey = accessKey; + bunny.Region = region; + bunny.CreateContainerIfNotExists = true; + bunny.ContainerName = _randomContainerName; + + _configuration = bunny; + }); + }); + }); + } +} diff --git a/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/BunnyBlobContainer_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/BunnyBlobContainer_Tests.cs new file mode 100644 index 0000000000..84b255e4c5 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/BunnyBlobContainer_Tests.cs @@ -0,0 +1,12 @@ +namespace Volo.Abp.BlobStoring.Bunny; + +/* +//Please set the correct connection string in secrets.json and continue the test. +public class BunnyBlobContainer_Tests : BlobContainer_Tests +{ + public BunnyBlobContainer_Tests() + { + + } +} +*/ diff --git a/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/BunnyBlobNameCalculator_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/BunnyBlobNameCalculator_Tests.cs new file mode 100644 index 0000000000..fc3b2d8365 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/BunnyBlobNameCalculator_Tests.cs @@ -0,0 +1,56 @@ +using System; +using Shouldly; +using Volo.Abp.MultiTenancy; +using Xunit; + +namespace Volo.Abp.BlobStoring.Bunny; + +public class BunnyBlobNameCalculatorTests : AbpBlobStoringBunnyTestCommonBase +{ + private readonly IBunnyBlobNameCalculator _calculator; + private readonly ICurrentTenant _currentTenant; + + private const string BunnyContainerName = "/"; + private const string BunnySeparator = "/"; + + public BunnyBlobNameCalculatorTests() + { + _calculator = GetRequiredService(); + _currentTenant = GetRequiredService(); + } + + [Fact] + public void Default_Settings() + { + _calculator.Calculate( + GetArgs("my-container", "my-blob") + ).ShouldBe($"host{BunnySeparator}my-blob"); + } + + [Fact] + public void Default_Settings_With_TenantId() + { + var tenantId = Guid.NewGuid(); + + using (_currentTenant.Change(tenantId)) + { + _calculator.Calculate( + GetArgs("my-container", "my-blob") + ).ShouldBe($"tenants{BunnySeparator}{tenantId:D}{BunnySeparator}my-blob"); + } + } + + private static BlobProviderArgs GetArgs( + string containerName, + string blobName) + { + return new BlobProviderGetArgs( + containerName, + new BlobContainerConfiguration().UseBunny(x => + { + x.ContainerName = containerName; + }), + blobName + ); + } +} diff --git a/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/DefaultBunnyBlobNamingNormalizerProvider_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/DefaultBunnyBlobNamingNormalizerProvider_Tests.cs new file mode 100644 index 0000000000..c4d3cd6878 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Bunny.Tests/Volo/Abp/BlobStoring/Bunny/DefaultBunnyBlobNamingNormalizerProvider_Tests.cs @@ -0,0 +1,57 @@ +using Shouldly; +using Xunit; + +namespace Volo.Abp.BlobStoring.Bunny; + +public class DefaultBunnyBlobNamingNormalizerProviderTests : AbpBlobStoringBunnyTestCommonBase +{ + private readonly IBlobNamingNormalizer _blobNamingNormalizer; + + public DefaultBunnyBlobNamingNormalizerProviderTests() + { + _blobNamingNormalizer = GetRequiredService(); + } + + [Fact] + public void NormalizeContainerName_Lowercase() + { + var filename = "ThisIsMyContainerName"; + filename = _blobNamingNormalizer.NormalizeContainerName(filename); + filename.ShouldBe("thisismycontainername"); + } + + [Fact] + public void NormalizeContainerName_Only_Letters_Numbers_Dash_Dots() + { + var filename = ",./this-i,/s-my-c,/ont,/ai+*/=!@#$n^&*er.name+/"; + filename = _blobNamingNormalizer.NormalizeContainerName(filename); + filename.ShouldBe("this-is-my-containername"); + } + + [Fact] + public void NormalizeContainerName_Min_Length() + { + var filename = "a"; + Assert.Throws(()=> + { + filename = _blobNamingNormalizer.NormalizeContainerName(filename); + }); + } + + [Fact] + public void NormalizeContainerName_Max_Length() + { + var longName = new string('a', 65); // 65 characters + var exception = Assert.Throws(() => + _blobNamingNormalizer.NormalizeContainerName(longName) + ); + } + + [Fact] + public void NormalizeContainerName_Dots() + { + var filename = ".this..is.-.my.container....name."; + filename = _blobNamingNormalizer.NormalizeContainerName(filename); + filename.ShouldBe("thisis-mycontainername"); + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj index ae688f1640..e2328fdca3 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj @@ -15,10 +15,10 @@ - - - - + + + + diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs index 9b70fe2681..ff6fe1face 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.MongoDB; @@ -11,7 +11,8 @@ public class MongoDbFixture : IDisposable { MongoDbRunner = MongoRunner.Run(new MongoRunnerOptions { - UseSingleNodeReplicaSet = true + UseSingleNodeReplicaSet = true, + ReplicaSetSetupTimeout = TimeSpan.FromSeconds(30) }); } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs index 0d5122228d..e2ad9088cb 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs @@ -18,9 +18,9 @@ public class Repository_Basic_Tests : Repository_Basic_Tests>().ShouldNotBeNull(); - ((IMongoQueryable)(await PersonRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas")).ShouldNotBeNull(); - (await PersonRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas").As>().ShouldNotBeNull(); + (await PersonRepository.GetQueryableAsync()).ShouldNotBeNull(); + ((IQueryable)(await PersonRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas")).ShouldNotBeNull(); + (await PersonRepository.GetQueryableAsync()).Where(p => p.Name == "Douglas").ShouldNotBeNull(); } [Fact] @@ -69,9 +69,9 @@ public class Repository_Basic_Tests : Repository_Basic_Tests c.Name == "ISTANBUL").ShouldBeNull(); - (await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "istanbul").ShouldBeNull(); - (await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "Istanbul").ShouldNotBeNull(); + (await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "ISTANBUL").ShouldBeNull(); + (await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "istanbul").ShouldBeNull(); + (await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "Istanbul").ShouldNotBeNull(); (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "douglas").ShouldNotBeNull(); (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "DOUGLAS").ShouldNotBeNull(); diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs index f8355b5466..1f0c0aa24d 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using MongoDB.Driver; using MongoDB.Driver.Linq; diff --git a/latest-versions.json b/latest-versions.json index 43d4fbb9ac..0ced5df485 100644 --- a/latest-versions.json +++ b/latest-versions.json @@ -1,4 +1,49 @@ [ + { + "version": "9.1.0", + "releaseDate": "", + "type": "stable", + "message": "", + "leptonx": { + "version": "4.1.0" + } + }, + { + "version": "9.0.6", + "releaseDate": "", + "type": "stable", + "message": "", + "leptonx": { + "version": "4.0.8" + } + }, + { + "version": "9.0.5", + "releaseDate": "", + "type": "stable", + "message": "", + "leptonx": { + "version": "4.0.6" + } + }, + { + "version": "9.0.4", + "releaseDate": "", + "type": "stable", + "message": "", + "leptonx": { + "version": "4.0.5" + } + }, + { + "version": "9.0.3", + "releaseDate": "", + "type": "stable", + "message": "", + "leptonx": { + "version": "4.0.4" + } + }, { "version": "9.0.2", "releaseDate": "", diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ar.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ar.json index 86d0ad8325..d3db345a9b 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ar.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ar.json @@ -68,6 +68,8 @@ "AccessDenied": "تم الرفض!", "AccessDeniedMessage": "ليس لديك حق الوصول إلى هذا المورد.", "OrRegisterWith": "أو التسجيل بـ:", - "RegisterUsingYourProviderAccount": "قم بالتسجيل باستخدام حسابك في {0}" + "RegisterUsingYourProviderAccount": "قم بالتسجيل باستخدام حسابك في {0}", + "RequireMigrateSeedTitle": "تعذر العثور على المستخدم المسؤول", + "RequireMigrateSeedMessage": "يرجى التأكد من تنفيذ seed قاعدة البيانات. راجع الوثائق للحلول الممكنة." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/cs.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/cs.json index aebaadc543..6967ed0d61 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/cs.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/cs.json @@ -68,6 +68,8 @@ "AccessDenied": "Přístup odepřen!", "AccessDeniedMessage": "K tomuto zdroji nemáte přístup.", "OrRegisterWith": "Nebo se registrujte pomocí:", - "RegisterUsingYourProviderAccount": "Registrovat pomocí vašeho účtu {0}" + "RegisterUsingYourProviderAccount": "Registrovat pomocí vašeho účtu {0}", + "RequireMigrateSeedTitle": "Nelze najít uživatele správce", + "RequireMigrateSeedMessage": "Ujistěte se, že je spuštěn seed databáze. Podívejte se na dokumentaci pro možná řešení." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/da.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/da.json index 24283d06c8..98cc684389 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/da.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/da.json @@ -65,6 +65,8 @@ "AccessDenied": "Adgang nægtet!", "AccessDeniedMessage": "Du har ikke adgang til denne ressource.", "OrRegisterWith": "Eller registrér med:", - "RegisterUsingYourProviderAccount": "Registrér med din {0} konto" + "RegisterUsingYourProviderAccount": "Registrér med din {0} konto", + "RequireMigrateSeedTitle": "Kunne ikke finde administratorbrugeren", + "RequireMigrateSeedMessage": "Sørg for, at databasens seed bliver udført. Se dokumentationen for mulige løsninger." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de.json index a6ff6d68c1..982a213753 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/de.json @@ -68,6 +68,8 @@ "AccessDenied": "Zugriff abgelehnt!", "AccessDeniedMessage": "Sie haben keinen Zugriff auf diese Ressource.", "OrRegisterWith": "Oder registrieren Sie sich mit:", - "RegisterUsingYourProviderAccount": "Registrieren Sie sich mit Ihrem {0} Benutzerkonto" + "RegisterUsingYourProviderAccount": "Registrieren Sie sich mit Ihrem {0} Benutzerkonto", + "RequireMigrateSeedTitle": "Der Administrator-Benutzer konnte nicht gefunden werden", + "RequireMigrateSeedMessage": "Bitte stellen Sie sicher, dass die Datenbank-Seed ausgeführt wird. Siehe Dokumentation für mögliche Lösungen." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/el.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/el.json index a64dca5ef5..594adbd31f 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/el.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/el.json @@ -66,6 +66,8 @@ "AccessDenied": "Δεν επιτρέπεται η πρόσβαση!", "AccessDeniedMessage": "Δεν έχετε πρόσβαση σε αυτόν τον πόρο.", "OrRegisterWith": "Ή εγγραφείτε με:", - "RegisterUsingYourProviderAccount": "Εγγραφείτε χρησιμοποιώντας τον λογαριασμό σας {0}" + "RegisterUsingYourProviderAccount": "Εγγραφείτε χρησιμοποιώντας τον λογαριασμό σας {0}", + "RequireMigrateSeedTitle": "Δεν βρέθηκε ο χρήστης διαχειριστή", + "RequireMigrateSeedMessage": "Βεβαιωθείτε ότι εκτελείται το seed της βάσης δεδομένων. Δείτε την τεκμηρίωση για πιθανές λύσεις." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en-GB.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en-GB.json index f4208335b5..09a93dca6f 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en-GB.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en-GB.json @@ -63,6 +63,8 @@ "PasswordResetInfoInEmail": "We received an account recovery request! If you initiated this request, click the following link to reset your password.", "ResetMyPassword": "Reset my password", "OrRegisterWith": "Or register with", - "RegisterUsingYourProviderAccount": "Register using your {0} account" + "RegisterUsingYourProviderAccount": "Register using your {0} account", + "RequireMigrateSeedTitle": "Could not find the admin user", + "RequireMigrateSeedMessage": "Please ensure that the database seed is executed. See documentation for possible solutions." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json index 39ca254f67..a230495c87 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json @@ -68,6 +68,8 @@ "AccessDenied": "Access denied!", "AccessDeniedMessage": "You do not have access to this resource.", "OrRegisterWith": "Or register with", - "RegisterUsingYourProviderAccount": "Register using your {0} account" + "RegisterUsingYourProviderAccount": "Register using your {0} account", + "RequireMigrateSeedTitle": "Could not find the admin user", + "RequireMigrateSeedMessage": "Please ensure that the database seed is executed. See documentation for possible solutions." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json index 6793e58986..f25046575a 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json @@ -36,6 +36,8 @@ "Manage": "Administrar", "MyAccount": "Mi cuenta", "OrRegisterWith": "O registrarse con", - "RegisterUsingYourProviderAccount": "Registrarse con su cuenta de {0} " + "RegisterUsingYourProviderAccount": "Registrarse con su cuenta de {0} ", + "RequireMigrateSeedTitle": "No se pudo encontrar el usuario administrador", + "RequireMigrateSeedMessage": "Asegúrese de que se ejecute la semilla de la base de datos. Consulte la documentación para posibles soluciones." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json index 4f7fbf94d8..814c41d218 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json @@ -68,6 +68,8 @@ "AccessDenied": "¡Acceso denegado!", "AccessDeniedMessage": "No tienes acceso a este recurso.", "OrRegisterWith": "O registrarse con:", - "RegisterUsingYourProviderAccount": "Registrarse con su cuenta de {0} " + "RegisterUsingYourProviderAccount": "Registrarse con su cuenta de {0} ", + "RequireMigrateSeedTitle": "No se pudo encontrar el usuario administrador", + "RequireMigrateSeedMessage": "Asegúrese de que se ejecute la semilla de la base de datos. Consulte la documentación para posibles soluciones." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fa.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fa.json index 4fc0685b79..e431b84548 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fa.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fa.json @@ -66,6 +66,8 @@ "AccessDenied": "دسترسی ممنوع!", "AccessDeniedMessage": "شما به این منبع دسترسی ندارید.", "OrRegisterWith": "یا ثبت نام کنید با:", - "RegisterUsingYourProviderAccount": "با استفاده از حساب {0} خود ثبت نام کنید" + "RegisterUsingYourProviderAccount": "با استفاده از حساب {0} خود ثبت نام کنید", + "RequireMigrateSeedTitle": "کاربر مدیر پیدا نشد", + "RequireMigrateSeedMessage": "لطفاً اطمینان حاصل کنید که seed پایگاه داده اجرا شده است. برای راه‌حل‌های ممکن مستندات را ببینید." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json index 2f0ae2c574..72acd91647 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json @@ -68,6 +68,8 @@ "AccessDenied": "Pääsy evätty!", "AccessDeniedMessage": "Sinulla ei ole pääsyä tähän resurssiin.", "OrRegisterWith": "Tai rekisteröidy:", - "RegisterUsingYourProviderAccount": "Rekisteröidy {0} -tililläsi" + "RegisterUsingYourProviderAccount": "Rekisteröidy {0} -tililläsi", + "RequireMigrateSeedTitle": "Järjestelmänvalvojaa ei löydy", + "RequireMigrateSeedMessage": "Varmista, että tietokannan siemennys on suoritettu. Katso dokumentaatio mahdollisia ratkaisuja varten." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json index fbeec12787..73a53b4bee 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json @@ -68,6 +68,8 @@ "AccessDenied": "Accès refusé!", "AccessDeniedMessage": "Vous n'avez pas accès à cette ressource.", "OrRegisterWith": "Or register with", - "RegisterUsingYourProviderAccount": "Register using your {0} account" + "RegisterUsingYourProviderAccount": "Register using your {0} account", + "RequireMigrateSeedTitle": "Impossible de trouver l'utilisateur administrateur", + "RequireMigrateSeedMessage": "Veuillez vous assurer que l'initialisation de la base de données est exécutée. Consultez la documentation pour les solutions possibles." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json index 9300e913f6..4264f6ebcf 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json @@ -68,6 +68,8 @@ "AccessDenied": "पहुंच अस्वीकृत!", "AccessDeniedMessage": "आपके पास इस संसाधन तक पहुँच नहीं है।", "OrRegisterWith": "या इसके साथ पंजीकरण करें:", - "RegisterUsingYourProviderAccount": "अपने {0} खाते का उपयोग करके पंजीकरण करें" + "RegisterUsingYourProviderAccount": "अपने {0} खाते का उपयोग करके पंजीकरण करें", + "RequireMigrateSeedTitle": "व्यवस्थापक उपयोगकर्ता नहीं मिला", + "RequireMigrateSeedMessage": "कृपया सुनिश्चित करें कि डेटाबेस सीड निष्पादित किया गया है। संभावित समाधानों के लिए दस्तावेज़ीकरण देखें।" } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hr.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hr.json index 8ec48e7a09..2262779dba 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hr.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hr.json @@ -68,6 +68,8 @@ "AccessDenied": "Pristup odbijen!", "AccessDeniedMessage": "Nemate pristup ovom resursu.", "OrRegisterWith": "Ili se registrirajte sa:", - "RegisterUsingYourProviderAccount": "Registrirajte se koristeći svoj {0} račun" + "RegisterUsingYourProviderAccount": "Registrirajte se koristeći svoj {0} račun", + "RequireMigrateSeedTitle": "Nije moguće pronaći administratorskog korisnika", + "RequireMigrateSeedMessage": "Molimo provjerite je li izvršeno početno punjenje baze podataka. Pogledajte dokumentaciju za moguća rješenja." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hu.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hu.json index 44e3794e24..c2a8d3d354 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hu.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hu.json @@ -68,6 +68,8 @@ "AccessDenied": "Hozzáférés megtagadva!", "AccessDeniedMessage": "Nincs hozzáférése ehhez az erőforráshoz.", "OrRegisterWith": "Vagy regisztráljon:", - "RegisterUsingYourProviderAccount": "Regisztráljon a(z) {0} fiókjával" + "RegisterUsingYourProviderAccount": "Regisztráljon a(z) {0} fiókjával", + "RequireMigrateSeedTitle": "Nem található az adminisztrátor felhasználó", + "RequireMigrateSeedMessage": "Kérjük, győződjön meg arról, hogy az adatbázis seed végrehajtásra került. Tekintse meg a dokumentációt a lehetséges megoldásokért." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/is.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/is.json index 693e200e9f..cb38ff2b6a 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/is.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/is.json @@ -68,6 +68,8 @@ "AccessDenied": "Aðgangi hafnað!", "AccessDeniedMessage": "Þú hefur ekki aðgang að þessari auðlind.", "OrRegisterWith": "Eða skráðu þig með:", - "RegisterUsingYourProviderAccount": "Skráðu þig með {0} aðganginum þínum" + "RegisterUsingYourProviderAccount": "Skráðu þig með {0} aðganginum þínum", + "RequireMigrateSeedTitle": "Ekki tókst að finna stjórnandann", + "RequireMigrateSeedMessage": "Vinsamlegast gakktu úr skugga um að gagnagrunnsfræið sé keyrt. Sjá fylgiskjöl fyrir mögulegar lausnir." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json index 60157a574b..a2a2a6db50 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json @@ -68,6 +68,8 @@ "AccessDenied": "Accesso negato!", "AccessDeniedMessage": "Non hai accesso a questa risorsa.", "OrRegisterWith": "Oppure registrati con:", - "RegisterUsingYourProviderAccount": "Registrati utilizzando il tuo account {0}" + "RegisterUsingYourProviderAccount": "Registrati utilizzando il tuo account {0}", + "RequireMigrateSeedTitle": "Impossibile trovare l'utente amministratore", + "RequireMigrateSeedMessage": "Assicurati che il seed del database sia eseguito. Consulta la documentazione per possibili soluzioni." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json index 200d35210d..a1c389d8a2 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json @@ -68,6 +68,8 @@ "AccessDenied": "Toegang geweigerd!", "AccessDeniedMessage": "U heeft geen toegang tot deze bron.", "OrRegisterWith": "Of registreer met:", - "RegisterUsingYourProviderAccount": "Registreer met uw {0} -account" + "RegisterUsingYourProviderAccount": "Registreer met uw {0} -account", + "RequireMigrateSeedTitle": "Kan de beheerder niet vinden", + "RequireMigrateSeedMessage": "Zorg ervoor dat het database seed wordt uitgevoerd. Zie documentatie voor mogelijke oplossingen." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pl-PL.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pl-PL.json index dc5c7952c3..028fc3100b 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pl-PL.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pl-PL.json @@ -68,6 +68,8 @@ "AccessDenied": "Brak dostępu!", "AccessDeniedMessage": "Nie masz dostępu do tego zasobu.", "OrRegisterWith": "Lub zarejestruj się za pomocą:", - "RegisterUsingYourProviderAccount": "Zarejestruj się za pomocą konta {0}" + "RegisterUsingYourProviderAccount": "Zarejestruj się za pomocą konta {0}", + "RequireMigrateSeedTitle": "Nie można znaleźć użytkownika administratora", + "RequireMigrateSeedMessage": "Upewnij się, że wykonano seed bazy danych. Zobacz dokumentację, aby poznać możliwe rozwiązania." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json index 3ea880a474..e92a6f1d5b 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json @@ -68,6 +68,8 @@ "AccessDenied": "Acesso negado!", "AccessDeniedMessage": "Você não tem acesso a este recurso.", "OrRegisterWith": "Ou registre-se com:", - "RegisterUsingYourProviderAccount": "Registre-se utilizando sua conta {0}" + "RegisterUsingYourProviderAccount": "Registre-se utilizando sua conta {0}", + "RequireMigrateSeedTitle": "Não foi possível encontrar o usuário administrador", + "RequireMigrateSeedMessage": "Certifique-se de que a semeadura do banco de dados seja executada. Consulte a documentação para possíveis soluções." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json index b7dbc5c244..63fea101b1 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json @@ -68,6 +68,8 @@ "AccessDenied": "Acces interzis!", "AccessDeniedMessage": "Nu aveţi acces la această resursă.", "OrRegisterWith": "Sau înregistraţi-vă cu:", - "RegisterUsingYourProviderAccount": "Înregistraţi-vă folosindu-vă contul {0}" + "RegisterUsingYourProviderAccount": "Înregistraţi-vă folosindu-vă contul {0}", + "RequireMigrateSeedTitle": "Nu s-a putut găsi utilizatorul admin", + "RequireMigrateSeedMessage": "Vă rugăm să vă asiguraţi că seed-ul bazei de date este executat. Consultaţi documentaţia pentru soluţii posibile." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json index d57b3c4e09..834fd7707b 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ru.json @@ -68,6 +68,8 @@ "AccessDenied": "В доступе отказано!", "AccessDeniedMessage": "У вас нет доступа к этому ресурсу.", "OrRegisterWith": "Или зарегистрируйтесь с помощью:", - "RegisterUsingYourProviderAccount": "Зарегистрируйтесь, используя свой {0} аккаунт" + "RegisterUsingYourProviderAccount": "Зарегистрируйтесь, используя свой {0} аккаунт", + "RequireMigrateSeedTitle": "Не удалось найти пользователя-администратора", + "RequireMigrateSeedMessage": "Пожалуйста, убедитесь, что выполнено начальное заполнение базы данных. Смотрите документацию для возможных решений." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sk.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sk.json index cbaf2b4ee7..0965e8aaa3 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sk.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sk.json @@ -68,6 +68,8 @@ "AccessDenied": "Prístup zamietnutý!", "AccessDeniedMessage": "K tomuto zdroju nemáte prístup.", "OrRegisterWith": "Alebo sa zaregistrujte pomocou:", - "RegisterUsingYourProviderAccount": "Zaregistrujte sa pomocou svojho {0} účtu" + "RegisterUsingYourProviderAccount": "Zaregistrujte sa pomocou svojho {0} účtu", + "RequireMigrateSeedTitle": "Nepodarilo sa nájsť používateľa správcu", + "RequireMigrateSeedMessage": "Uistite sa, že je spustené seed databázy. Pozrite si dokumentáciu pre možné riešenia." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json index fae736de5f..63820bc60f 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sl.json @@ -68,6 +68,8 @@ "AccessDenied": "Dostop zavrnjen!", "AccessDeniedMessage": "Nimate dostopa do tega vira.", "OrRegisterWith": "Ali pa se registrirajte z:", - "RegisterUsingYourProviderAccount": "Registrirajte se z uporabo vašega {0} računa" + "RegisterUsingYourProviderAccount": "Registrirajte se z uporabo vašega {0} računa", + "RequireMigrateSeedTitle": "Skrbniškega uporabnika ni mogoče najti", + "RequireMigrateSeedMessage": "Prepričajte se, da je seed baze podatkov izveden. Za možne rešitve glejte dokumentacijo." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sv.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sv.json index d06472ed7b..a03bf20e97 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sv.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/sv.json @@ -68,6 +68,8 @@ "AccessDenied": "Åtkomst nekad!", "AccessDeniedMessage": "Du har inte tillgång till denna resurs.", "OrRegisterWith": "Eller registrera dig med", - "RegisterUsingYourProviderAccount": "Registrera dig med ditt {0} konto" + "RegisterUsingYourProviderAccount": "Registrera dig med ditt {0} konto", + "RequireMigrateSeedTitle": "Kunde inte hitta administratörsanvändaren", + "RequireMigrateSeedMessage": "Se till att databasens seed körs. Se dokumentationen för möjliga lösningar." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json index 0e53963f9a..841cd18775 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json @@ -68,6 +68,8 @@ "AccessDenied": "Erişim reddedildi!", "AccessDeniedMessage": "Bu kaynağa erişiminiz yok.", "OrRegisterWith": "Veya bunlarla kayıt ol:", - "RegisterUsingYourProviderAccount": "{0} hesabınızla kayıt olun." + "RegisterUsingYourProviderAccount": "{0} hesabınızla kayıt olun.", + "RequireMigrateSeedTitle": "Yönetici kullanıcısı bulunamadı", + "RequireMigrateSeedMessage": "Lütfen veritabanı tohumunun yürütüldüğünden emin olun. Olası çözümler için belgelere bakın." } } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/vi.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/vi.json index 600ce9fa4f..e29ba0d7b9 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/vi.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/vi.json @@ -68,6 +68,8 @@ "AccessDenied": "Quyền truy cập bị từ chối!", "AccessDeniedMessage": "Bạn không có quyền truy cập vào tài nguyên này.", "OrRegisterWith": "Hoặc đăng ký bằng:", - "RegisterUsingYourProviderAccount": "Đăng ký bằng tài khoản {0} của bạn" + "RegisterUsingYourProviderAccount": "Đăng ký bằng tài khoản {0} của bạn", + "RequireMigrateSeedTitle": "Không thể tìm thấy người dùng quản trị", + "RequireMigrateSeedMessage": "Vui lòng đảm bảo rằng seed cơ sở dữ liệu được thực thi. Xem tài liệu để biết các giải pháp có thể." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json index e6af1b3b7e..094798b95c 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hans.json @@ -68,6 +68,8 @@ "AccessDenied": "拒绝访问!", "AccessDeniedMessage": "您无法访问此资源。", "OrRegisterWith": "或注册", - "RegisterUsingYourProviderAccount": "使用您的 {0} 账户注册" + "RegisterUsingYourProviderAccount": "使用您的 {0} 账户注册", + "RequireMigrateSeedTitle": "找不到管理员用户", + "RequireMigrateSeedMessage": "请确保已执行数据库种子数据。查看文档了解可能的解决方案。" } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json index 14cf84fc24..1657ce4a49 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/zh-Hant.json @@ -68,6 +68,8 @@ "AccessDenied": "拒絕訪問!", "AccessDeniedMessage": "您無權訪問此資源.", "OrRegisterWith": "或是註冊用:", - "RegisterUsingYourProviderAccount": "使用你的{0}帳號註冊" + "RegisterUsingYourProviderAccount": "使用你的{0}帳號註冊", + "RequireMigrateSeedTitle": "找不到管理員用戶", + "RequireMigrateSeedMessage": "請確保已執行資料庫種子資料。查看文檔了解可能的解決方案。" } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Installer/InstallationNotes.md b/modules/account/src/Volo.Abp.Account.Installer/InstallationNotes.md new file mode 100644 index 0000000000..2289069146 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Installer/InstallationNotes.md @@ -0,0 +1,9 @@ +# Installation Notes for Account Module + +Account module implements the basic authentication features like login, register, forgot password and account management. + +This module is based on [Microsoft's Identity library](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-6.0&tabs=visual-studio) and the [Identity Module](https://docs.abp.io/en/abp/latest/modules/identity). It has [IdentityServer](https://docs.abp.io/en/abp/latest/modules/identity-server) integration (based on the [IdentityServer Module](https://docs.abp.io/en/abp/latest/modules/identity-server)) and [OpenIddict](https://github.com/openiddict) integration (based on the [Openiddict Module](https://docs.abp.io/en/abp/latest/modules/openiddict)) to provide single sign-on, access control and other advanced authentication features. + +## Documentation + +For detailed information and usage instructions, please visit the [Account Module documentation](https://abp.io/docs/latest/Modules/Account). \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs index 0a2aadd64a..b8ca910eba 100644 --- a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs @@ -11,6 +11,7 @@ using System.Diagnostics; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Identity; using Volo.Abp.Account.Settings; using Volo.Abp.DependencyInjection; @@ -35,8 +36,9 @@ public class IdentityServerSupportedLoginModel : LoginModel IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache, IIdentityServerInteractionService interaction, IClientStore clientStore, - IEventService identityServerEvents) - : base(schemeProvider, accountOptions, identityOptions, identityDynamicClaimsPrincipalContributorCache) + IEventService identityServerEvents, + IWebHostEnvironment webHostEnvironment) + : base(schemeProvider, accountOptions, identityOptions, identityDynamicClaimsPrincipalContributorCache, webHostEnvironment) { Interaction = interaction; ClientStore = clientStore; diff --git a/modules/account/src/Volo.Abp.Account.Web.OpenIddict/Pages/Account/OpenIddictSupportedLoginModel.cs b/modules/account/src/Volo.Abp.Account.Web.OpenIddict/Pages/Account/OpenIddictSupportedLoginModel.cs index d7998eb826..0390bf0f52 100644 --- a/modules/account/src/Volo.Abp.Account.Web.OpenIddict/Pages/Account/OpenIddictSupportedLoginModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web.OpenIddict/Pages/Account/OpenIddictSupportedLoginModel.cs @@ -2,6 +2,7 @@ using System; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Options; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; @@ -24,8 +25,9 @@ public class OpenIddictSupportedLoginModel : LoginModel IOptions accountOptions, IOptions identityOptions, IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache, - AbpOpenIddictRequestHelper openIddictRequestHelper) - : base(schemeProvider, accountOptions, identityOptions, identityDynamicClaimsPrincipalContributorCache) + AbpOpenIddictRequestHelper openIddictRequestHelper, + IWebHostEnvironment webHostEnvironment) + : base(schemeProvider, accountOptions, identityOptions, identityDynamicClaimsPrincipalContributorCache, webHostEnvironment) { OpenIddictRequestHelper = openIddictRequestHelper; } diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml index 2b0fcb9c2c..1c883936b4 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml @@ -22,6 +22,14 @@ } +@if (Model.ShowRequireMigrateSeedMessage) +{ +
      +

      @L["RequireMigrateSeedTitle"]

      +

      @L["RequireMigrateSeedMessage"]

      +
      +} +

      @L["Login"]

      diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs index 6ab8350b60..c17eb1e28f 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs @@ -10,6 +10,8 @@ using System.Diagnostics; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; using Volo.Abp.Account.Settings; using Volo.Abp.Auditing; using Volo.Abp.Identity; @@ -53,18 +55,22 @@ public class LoginModel : AccountPageModel protected AbpAccountOptions AccountOptions { get; } protected IOptions IdentityOptions { get; } protected IdentityDynamicClaimsPrincipalContributorCache IdentityDynamicClaimsPrincipalContributorCache { get; } + protected IWebHostEnvironment WebHostEnvironment { get; } public bool ShowCancelButton { get; set; } + public bool ShowRequireMigrateSeedMessage { get; set; } public LoginModel( IAuthenticationSchemeProvider schemeProvider, IOptions accountOptions, IOptions identityOptions, - IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache) + IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache, + IWebHostEnvironment webHostEnvironment) { SchemeProvider = schemeProvider; IdentityOptions = identityOptions; AccountOptions = accountOptions.Value; IdentityDynamicClaimsPrincipalContributorCache = identityDynamicClaimsPrincipalContributorCache; + WebHostEnvironment = webHostEnvironment; } public virtual async Task OnGetAsync() @@ -130,6 +136,17 @@ public class LoginModel : AccountPageModel if (!result.Succeeded) { + if (LoginInput.UserNameOrEmailAddress == IdentityDataSeedContributor.AdminUserNameDefaultValue && + WebHostEnvironment.IsDevelopment()) + { + var adminUser = await UserManager.FindByNameAsync(IdentityDataSeedContributor.AdminUserNameDefaultValue); + if (adminUser == null) + { + ShowRequireMigrateSeedMessage = true; + return Page(); + } + } + Alerts.Danger(L["InvalidUserNameOrPassword"]); return Page(); } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ar.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ar.json index 3b94f7f834..58f1b5bf7a 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ar.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ar.json @@ -67,6 +67,9 @@ "EntityHistory": "تاريخ الكيان", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} بواسطة {2}.", + "MinutesAgo": "منذ {0} دقيقة", + "HoursAgo": "منذ {0} ساعة", + "DaysAgo": "منذ {0} يوم", "Created": "خلقت", "Updated": "محدث", "Deleted": "تم الحذف", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/cs.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/cs.json index ceeb244fc8..b415c41556 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/cs.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/cs.json @@ -67,6 +67,9 @@ "EntityHistory": "Historie entity", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} od {2}.", + "MinutesAgo": "před {0} minutami", + "HoursAgo": "před {0} hodinami", + "DaysAgo": "před {0} dny", "Created": "Vytvořeno", "Updated": "Aktualizováno", "Deleted": "Smazáno", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/de-DE.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/de-DE.json index 75e5c251c3..512556988f 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/de-DE.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/de-DE.json @@ -66,6 +66,9 @@ "EntityHistory": "Entitätsverlauf", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} durch {2}.", + "MinutesAgo": "Vor {0} Minuten", + "HoursAgo": "Vor {0} Stunden", + "DaysAgo": "Vor {0} Tagen", "Created": "Erstellt", "Updated": "Aktualisiert", "Deleted": "Gelöscht", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/de.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/de.json index 2f3152fca5..06d2a825f4 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/de.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/de.json @@ -67,6 +67,9 @@ "EntityHistory": "Entitätsgeschichte", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} von {2}.", + "MinutesAgo": "Vor {0} Minuten", + "HoursAgo": "Vor {0} Stunden", + "DaysAgo": "Vor {0} Tagen", "Created": "Erstellt", "Updated": "Aktualisiert", "Deleted": "Gelöscht", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json index fa7596e898..ac03e75db7 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json @@ -48,7 +48,7 @@ "ChangeType": "Change type", "ChangeTime": "Time", "NewValue": "New value", - "OriginalValue": "Original value", + "OriginalValue": "Old value", "PropertyName": "Property name", "PropertyTypeFullName": "Property Type Full Name", "Yes": "Yes", @@ -67,6 +67,9 @@ "EntityHistory": "Entity history", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} by {2}.", + "MinutesAgo": "{0} minutes ago", + "HoursAgo": "{0} hours ago", + "DaysAgo": "{0} days ago", "Created": "Created", "Updated": "Updated", "Deleted": "Deleted", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/es.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/es.json index 1227e0bc08..310b5de91b 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/es.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/es.json @@ -67,6 +67,9 @@ "EntityHistory": "Historial de entidad", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} por {2}.", + "MinutesAgo": "Hace {0} minutos", + "HoursAgo": "Hace {0} horas", + "DaysAgo": "Hace {0} días", "Created": "Creado", "Updated": "Actualizado", "Deleted": "Eliminado", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/fi.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/fi.json index 9870d85155..76b374f51a 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/fi.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/fi.json @@ -67,6 +67,9 @@ "EntityHistory": "Entiteettihistoria", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} kirjoittanut {2}.", + "MinutesAgo": "{0} minuuttia sitten", + "HoursAgo": "{0} tuntia sitten", + "DaysAgo": "{0} päivää sitten", "Created": "Luotu", "Updated": "Päivitetty", "Deleted": "Poistettu", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/fr.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/fr.json index ced0d637c9..5ea79065aa 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/fr.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/fr.json @@ -67,6 +67,9 @@ "EntityHistory": "Historique de l'entité", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} par {2}.", + "MinutesAgo": "Il y a {0} minutes", + "HoursAgo": "Il y a {0} heures", + "DaysAgo": "Il y a {0} jours", "Created": "Créé", "Updated": "Mise à jour", "Deleted": "Supprimé", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hi.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hi.json index 7c6a4b5587..7e1e84de7e 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hi.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hi.json @@ -67,6 +67,9 @@ "EntityHistory": "इकाई इतिहास", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} से {2}।", + "MinutesAgo": "{0} मिनट पहले", + "HoursAgo": "{0} घंटे पहले", + "DaysAgo": "{0} दिन पहले", "Created": "बनाया था", "Updated": "अद्यतन", "Deleted": "हटाए गए", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hr.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hr.json index ec6028c6a8..ed6c345578 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hr.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hr.json @@ -67,6 +67,9 @@ "EntityHistory": "Povijest entiteta", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} od {2}.", + "MinutesAgo": "prije {0} minuta", + "HoursAgo": "prije {0} sati", + "DaysAgo": "prije {0} dana", "Created": "Stvoreno", "Updated": "Ažurirano", "Deleted": "Izbrisano", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hu.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hu.json index 1122431190..816aa4c0d5 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hu.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/hu.json @@ -67,6 +67,9 @@ "EntityHistory": "Entitástörténet", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1}, szerző: {2}.", + "MinutesAgo": "{0} perce", + "HoursAgo": "{0} órája", + "DaysAgo": "{0} napja", "Created": "Létrehozva", "Updated": "Frissítve", "Deleted": "Törölve", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/is.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/is.json index cdf1217b36..fc556570ff 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/is.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/is.json @@ -67,6 +67,9 @@ "EntityHistory": "Saga eininga", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} eftir {2}.", + "MinutesAgo": "fyrir {0} mínútum", + "HoursAgo": "fyrir {0} klukkustundum", + "DaysAgo": "fyrir {0} dögum", "Created": "Búið til", "Updated": "Uppfært", "Deleted": "Eytt", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/it.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/it.json index 1a7823908a..6e3ef94959 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/it.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/it.json @@ -67,6 +67,9 @@ "EntityHistory": "Storia dell'entità", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} di {2}.", + "MinutesAgo": "{0} minuti fa", + "HoursAgo": "{0} ore fa", + "DaysAgo": "{0} giorni fa", "Created": "Creato", "Updated": "Aggiornato", "Deleted": "Eliminato", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/nl.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/nl.json index 6500e216b6..289b2318e3 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/nl.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/nl.json @@ -67,6 +67,9 @@ "EntityHistory": "Entiteitsgeschiedenis", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} door {2}.", + "MinutesAgo": "{0} minuten geleden", + "HoursAgo": "{0} uur geleden", + "DaysAgo": "{0} dagen geleden", "Created": "Gemaakt", "Updated": "Bijgewerkt", "Deleted": "Verwijderd", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/pl-PL.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/pl-PL.json index bbbc627b98..9f4f6db58f 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/pl-PL.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/pl-PL.json @@ -67,6 +67,9 @@ "EntityHistory": "Historia jednostki", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} autorstwa {2}.", + "MinutesAgo": "{0} minut temu", + "HoursAgo": "{0} godzin temu", + "DaysAgo": "{0} dni temu", "Created": "Utworzony", "Updated": "Zaktualizowano", "Deleted": "Usunięto", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/pt-BR.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/pt-BR.json index 8e5557e442..d88aba16a6 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/pt-BR.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/pt-BR.json @@ -67,6 +67,9 @@ "EntityHistory": "História da Entidade", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} por {2}.", + "MinutesAgo": "{0} minutos atrás", + "HoursAgo": "{0} horas atrás", + "DaysAgo": "{0} dias atrás", "Created": "Criado", "Updated": "Atualizado", "Deleted": "Excluído", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ro-RO.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ro-RO.json index 73da32a928..0b546c4866 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ro-RO.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ro-RO.json @@ -67,6 +67,9 @@ "EntityHistory": "Istoricul entității", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} de la {2}.", + "MinutesAgo": "acum {0} minute", + "HoursAgo": "acum {0} ore", + "DaysAgo": "acum {0} zile", "Created": "Creată", "Updated": "Actualizat", "Deleted": "Șters", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ru.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ru.json index 9dba5121ce..9d12238ac2 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ru.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/ru.json @@ -67,6 +67,9 @@ "EntityHistory": "История объекта", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} от {2}.", + "MinutesAgo": "{0} минут назад", + "HoursAgo": "{0} часов назад", + "DaysAgo": "{0} дней назад", "Created": "Созданный", "Updated": "Обновлено", "Deleted": "Удалено", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sk.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sk.json index 672f32dd44..ae3925ea79 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sk.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sk.json @@ -67,6 +67,9 @@ "EntityHistory": "História entity", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} vykonal {2}.", + "MinutesAgo": "pred {0} minútami", + "HoursAgo": "pred {0} hodinami", + "DaysAgo": "pred {0} dňami", "Created": "Vytvorená", "Updated": "Aktualizovaná", "Deleted": "Zmazaná", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sl.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sl.json index 324a03b6db..460e43458e 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sl.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sl.json @@ -67,6 +67,9 @@ "EntityHistory": "Zgodovina entitete", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} avtorja {2}.", + "MinutesAgo": "pred {0} minutami", + "HoursAgo": "pred {0} urami", + "DaysAgo": "pred {0} dnevi", "Created": "Ustvarjeno", "Updated": "Posodobljeno", "Deleted": "Izbrisano", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sv.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sv.json index 2432e63d33..3c57005a3d 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sv.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/sv.json @@ -67,6 +67,9 @@ "EntityHistory": "Enhetens historia", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} av {2}.", + "MinutesAgo": "{0} minuter sedan", + "HoursAgo": "{0} timmar sedan", + "DaysAgo": "{0} dagar sedan", "Created": "Skapad", "Updated": "Uppdaterad", "Deleted": "Borttagen", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/tr.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/tr.json index 6fb89d3b2b..b3e09335fc 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/tr.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/tr.json @@ -66,6 +66,9 @@ "EntityHistory": "Entity Geçmişi", "DaysAgoTitle": "{1} {0}.", "DaysAgoWithUserTitle": "{1} {2} tarafından {0}.", + "MinutesAgo": "{0} dakika önce", + "HoursAgo": "{0} saat önce", + "DaysAgo": "{0} gün önce", "Created": "Oluşturuldu", "Updated": "Güncellendi", "Deleted": "Silindi", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/vi.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/vi.json index 0ea4845071..933593c168 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/vi.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/vi.json @@ -67,6 +67,9 @@ "EntityHistory": "Lịch sử thực thể", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} của {2}.", + "MinutesAgo": "{0} phút trước", + "HoursAgo": "{0} giờ trước", + "DaysAgo": "{0} ngày trước", "Created": "Tạo", "Updated": "Đã cập nhật", "Deleted": "Đã xóa", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/zh-Hans.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/zh-Hans.json index 3f6099f04f..dc9cc4d667 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/zh-Hans.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/zh-Hans.json @@ -67,6 +67,9 @@ "EntityHistory": "实体历史", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} by {2}。", + "MinutesAgo": "{0}分钟前", + "HoursAgo": "{0}小时前", + "DaysAgo": "{0}天前", "Created": "创建", "Updated": "已更新", "Deleted": "已删除", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/zh-Hant.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/zh-Hant.json index 5b663c9568..dc0275186d 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/zh-Hant.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/zh-Hant.json @@ -67,6 +67,9 @@ "EntityHistory": "實體歷史", "DaysAgoTitle": "{0} {1}.", "DaysAgoWithUserTitle": "{0} {1} 通過 {2}.", + "MinutesAgo": "{0}分鐘前", + "HoursAgo": "{0}小時前", + "DaysAgo": "{0}天前", "Created": "建立", "Updated": "更新", "Deleted": "已刪除", diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter.cs new file mode 100644 index 0000000000..f50aec3d92 --- /dev/null +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter.cs @@ -0,0 +1,39 @@ +using System; +using System.Text.RegularExpressions; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AuditLogging; + +public class AuditLogEntityTypeFullNameConverter : ITransientDependency +{ + public virtual string Convert(string typeFullName) + { + var genericType = Regex.Match(typeFullName, @"(.+?)`1\[\["); + if (!genericType.Success) + { + return ReplaceGenericSymbol(typeFullName); + } + + var type = Regex.Match(typeFullName, @"`1\[\[(.+?), "); + if (!type.Success) + { + return typeFullName; + } + + if (type.Groups[1].Value.Contains("System.Nullable`1[[")) + { + return genericType.Groups[1].Value + "<" + type.Groups[1].Value.Replace("System.Nullable`1[[", "") + "?>"; + } + + return genericType.Groups[1].Value.Contains("System.Nullable") + ? type.Groups[1].Value + "?" + : genericType.Groups[1].Value + "<" + ReplaceGenericSymbol(type.Groups[1].Value) + ">"; + } + + protected virtual string ReplaceGenericSymbol(string typeFullName) + { + return typeFullName.Contains("`1+") + ? typeFullName.Substring(0, typeFullName.IndexOf("[[", StringComparison.Ordinal)).Replace("`1+", ".") + : typeFullName; + } +} diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs index 94f0622714..30b0495658 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLogInfoToAuditLogConverter.cs @@ -19,12 +19,19 @@ public class AuditLogInfoToAuditLogConverter : IAuditLogInfoToAuditLogConverter, protected IExceptionToErrorInfoConverter ExceptionToErrorInfoConverter { get; } protected IJsonSerializer JsonSerializer { get; } protected AbpExceptionHandlingOptions ExceptionHandlingOptions { get; } + protected AuditLogEntityTypeFullNameConverter AuditLogEntityTypeFullNameConverter { get; } - public AuditLogInfoToAuditLogConverter(IGuidGenerator guidGenerator, IExceptionToErrorInfoConverter exceptionToErrorInfoConverter, IJsonSerializer jsonSerializer, IOptions exceptionHandlingOptions) + public AuditLogInfoToAuditLogConverter( + IGuidGenerator guidGenerator, + IExceptionToErrorInfoConverter exceptionToErrorInfoConverter, + IJsonSerializer jsonSerializer, + IOptions exceptionHandlingOptions, + AuditLogEntityTypeFullNameConverter auditLogEntityTypeFullNameConverter) { GuidGenerator = guidGenerator; ExceptionToErrorInfoConverter = exceptionToErrorInfoConverter; JsonSerializer = jsonSerializer; + AuditLogEntityTypeFullNameConverter = auditLogEntityTypeFullNameConverter; ExceptionHandlingOptions = exceptionHandlingOptions.Value; } @@ -41,6 +48,15 @@ public class AuditLogInfoToAuditLogConverter : IAuditLogInfoToAuditLogConverter, } } + foreach (var entityChange in auditLogInfo.EntityChanges ?? Enumerable.Empty()) + { + entityChange.EntityTypeFullName = AuditLogEntityTypeFullNameConverter.Convert(entityChange.EntityTypeFullName); + foreach (var propertyChange in entityChange.PropertyChanges ?? Enumerable.Empty()) + { + propertyChange.PropertyTypeFullName = AuditLogEntityTypeFullNameConverter.Convert(propertyChange.PropertyTypeFullName); + } + } + var entityChanges = auditLogInfo .EntityChanges? .Select(entityChangeInfo => new EntityChange(GuidGenerator, auditLogId, entityChangeInfo, tenantId: auditLogInfo.TenantId)) diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Installer/InstallationNotes.md b/modules/audit-logging/src/Volo.Abp.AuditLogging.Installer/InstallationNotes.md new file mode 100644 index 0000000000..35bd77d32d --- /dev/null +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Installer/InstallationNotes.md @@ -0,0 +1,9 @@ +# Installation Notes for Audit Logging Module + +The ABP Audit Logging module provides automatic audit logging for web requests, service methods, and entity changes. It helps you track user activities and changes in your application. + +This module is part of the ABP Framework and provides comprehensive audit logging capabilities including entity history tracking, exception logging, and user activity monitoring. + +## Documentation + +For detailed information and usage instructions, please visit the [Audit Logging documentation](https://abp.io/docs/latest/framework/infrastructure/audit-logging). \ No newline at end of file diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs index b406e83d5c..92416174ae 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs @@ -64,8 +64,7 @@ public class MongoAuditLogRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -104,8 +103,7 @@ public class MongoAuditLogRepository : MongoDbRepository>() - .LongCountAsync(GetCancellationToken(cancellationToken)); + var count = await query.LongCountAsync(GetCancellationToken(cancellationToken)); return count; } @@ -128,7 +126,7 @@ public class MongoAuditLogRepository : MongoDbRepository auditLog.ExecutionTime >= startTime) .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime) .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "") @@ -151,7 +149,7 @@ public class MongoAuditLogRepository : MongoDbRepository a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate) .OrderBy(t => t.ExecutionTime) .GroupBy(t => new { @@ -169,7 +167,7 @@ public class MongoAuditLogRepository : MongoDbRepository x.EntityChanges.Any(y => y.Id == entityChangeId)) .OrderBy(x => x.Id) .FirstAsync(GetCancellationToken(cancellationToken))).EntityChanges.FirstOrDefault(x => x.Id == entityChangeId); @@ -199,8 +197,7 @@ public class MongoAuditLogRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -215,7 +212,7 @@ public class MongoAuditLogRepository : MongoDbRepository>().LongCountAsync(GetCancellationToken(cancellationToken)); + var count = await query.LongCountAsync(GetCancellationToken(cancellationToken)); return count; } @@ -224,7 +221,7 @@ public class MongoAuditLogRepository : MongoDbRepository x.EntityChanges.Any(y => y.Id == entityChangeId)) .FirstAsync(GetCancellationToken(cancellationToken)); @@ -240,9 +237,8 @@ public class MongoAuditLogRepository : MongoDbRepository x.EntityChanges.Any(y => y.EntityId == entityId && y.EntityTypeFullName == entityTypeFullName)) - .As>() .OrderByDescending(x => x.ExecutionTime) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -263,7 +259,7 @@ public class MongoAuditLogRepository : MongoDbRepository x.EntityChanges) .WhereIf(auditLogId.HasValue, e => e.Id == auditLogId) .WhereIf(startTime.HasValue, e => e.ChangeTime >= startTime) diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogEntityTypeFullNameConverter_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogEntityTypeFullNameConverter_Tests.cs new file mode 100644 index 0000000000..db57347815 --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogEntityTypeFullNameConverter_Tests.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.AuditLogging.EntityFrameworkCore; + +public class AuditLogEntityTypeFullNameConverter_Tests : AuditLogEntityTypeFullNameConverter_Tests +{ + +} diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj index 41718fda4e..a33c1c74f8 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj @@ -14,10 +14,10 @@ - - - - + + + + diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogEntityTypeFullNameConverter_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogEntityTypeFullNameConverter_Tests.cs new file mode 100644 index 0000000000..5c803a2a44 --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogEntityTypeFullNameConverter_Tests.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace Volo.Abp.AuditLogging.MongoDB; + +[Collection(MongoTestCollection.Name)] +public class AuditLogEntityTypeFullNameConverter_Tests : AuditLogEntityTypeFullNameConverter_Tests +{ + +} diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs index a68f246c78..569bf3ad2d 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.AuditLogging.MongoDB; diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter_Tests.cs new file mode 100644 index 0000000000..2aac19cd42 --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogEntityTypeFullNameConverter_Tests.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Shouldly; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.AuditLogging; + +public abstract class AuditLogEntityTypeFullNameConverter_Tests : AuditLoggingTestBase + where TStartupModule : IAbpModule +{ + private readonly AuditLogEntityTypeFullNameConverter _typeFullNameConverter; + + protected AuditLogEntityTypeFullNameConverter_Tests() + { + _typeFullNameConverter = GetRequiredService(); + } + + [Fact] + public void AuditLogEntityTypeFullNameConverter_Test() + { + _typeFullNameConverter.Convert("MyType").ShouldBe("MyType"); + + _typeFullNameConverter.Convert(typeof(string).FullName!).ShouldBe("System.String"); + _typeFullNameConverter.Convert(typeof(Guid).FullName!).ShouldBe("System.Guid"); + _typeFullNameConverter.Convert(typeof(Guid?).FullName!).ShouldBe("System.Guid?"); + _typeFullNameConverter.Convert(typeof(int).FullName!).ShouldBe("System.Int32"); + _typeFullNameConverter.Convert(typeof(long?).FullName!).ShouldBe("System.Int64?"); + _typeFullNameConverter.Convert(typeof(MyClass).FullName!).ShouldBe("Volo.Abp.AuditLogging.AuditLogEntityTypeFullNameConverter_Tests.MyClass"); + + _typeFullNameConverter.Convert(typeof(ICollection).FullName!).ShouldBe($"System.Collections.Generic.ICollection"); + _typeFullNameConverter.Convert(typeof(Collection).FullName!).ShouldBe($"System.Collections.ObjectModel.Collection"); + _typeFullNameConverter.Convert(typeof(List).FullName!).ShouldBe($"System.Collections.Generic.List"); + _typeFullNameConverter.Convert(typeof(List).FullName!).ShouldBe($"System.Collections.Generic.List"); + + _typeFullNameConverter.Convert(typeof(ICollection).FullName!).ShouldBe($"System.Collections.Generic.ICollection"); + _typeFullNameConverter.Convert(typeof(Collection).FullName!).ShouldBe($"System.Collections.ObjectModel.Collection"); + _typeFullNameConverter.Convert(typeof(List).FullName!).ShouldBe($"System.Collections.Generic.List"); + } + + public class MyClass + { + + } +} diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo/Abp/BackgroundJobs/BackgroundJobRecordConsts.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo/Abp/BackgroundJobs/BackgroundJobRecordConsts.cs index 4369bfcece..7cf4e651fe 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo/Abp/BackgroundJobs/BackgroundJobRecordConsts.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo/Abp/BackgroundJobs/BackgroundJobRecordConsts.cs @@ -2,6 +2,11 @@ public static class BackgroundJobRecordConsts { + /// + /// Default value: 96 + /// + public static int MaxApplicationNameLength { get; set; } = 96; + /// /// Default value: 128 /// diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs index 66714af6d6..c01f933781 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs @@ -6,6 +6,11 @@ namespace Volo.Abp.BackgroundJobs; public class BackgroundJobRecord : AggregateRoot, IHasCreationTime { + /// + /// Application name that scheduled this job. + /// + public virtual string ApplicationName { get; set; } + /// /// Type of the job. /// It's AssemblyQualifiedName of job type. diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobStore.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobStore.cs index e29948cc95..c7dbd6fbef 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobStore.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobStore.cs @@ -34,10 +34,10 @@ public class BackgroundJobStore : IBackgroundJobStore, ITransientDependency ); } - public virtual async Task> GetWaitingJobsAsync(int maxResultCount) + public virtual async Task> GetWaitingJobsAsync(string applicationName, int maxResultCount) { return ObjectMapper.Map, List>( - await BackgroundJobRepository.GetWaitingListAsync(maxResultCount) + await BackgroundJobRepository.GetWaitingListAsync(applicationName, maxResultCount) ); } diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/IBackgroundJobRepository.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/IBackgroundJobRepository.cs index b3c552c974..7e189df5c8 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/IBackgroundJobRepository.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/IBackgroundJobRepository.cs @@ -2,11 +2,12 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Volo.Abp.Domain.Repositories; namespace Volo.Abp.BackgroundJobs; public interface IBackgroundJobRepository : IBasicRepository { - Task> GetWaitingListAsync(int maxResultCount, CancellationToken cancellationToken = default); + Task> GetWaitingListAsync([CanBeNull] string applicationName, int maxResultCount, CancellationToken cancellationToken = default); } diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs index 5b51c8809d..53a2c53843 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs @@ -22,6 +22,7 @@ public static class BackgroundJobsDbContextModelCreatingExtensions b.ConfigureByConvention(); + b.Property(x => x.ApplicationName).IsRequired(false).HasMaxLength(BackgroundJobRecordConsts.MaxApplicationNameLength); b.Property(x => x.JobName).IsRequired().HasMaxLength(BackgroundJobRecordConsts.MaxJobNameLength); b.Property(x => x.JobArgs).IsRequired().HasMaxLength(BackgroundJobRecordConsts.MaxJobArgsLength); b.Property(x => x.TryCount).HasDefaultValue(0); diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs index a2be3c6e1e..a81de3cdfb 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; @@ -22,17 +23,16 @@ public class EfCoreBackgroundJobRepository : EfCoreRepository> GetWaitingListAsync( - int maxResultCount, - CancellationToken cancellationToken = default) + public virtual async Task> GetWaitingListAsync([CanBeNull] string applicationName, int maxResultCount, CancellationToken cancellationToken = default) { - return await (await GetWaitingListQueryAsync(maxResultCount)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetWaitingListQueryAsync(applicationName, maxResultCount)).ToListAsync(GetCancellationToken(cancellationToken)); } - protected virtual async Task> GetWaitingListQueryAsync(int maxResultCount) + protected virtual async Task> GetWaitingListQueryAsync([CanBeNull] string applicationName, int maxResultCount) { var now = Clock.Now; return (await GetDbSetAsync()) + .Where(t => t.ApplicationName == applicationName) .Where(t => !t.IsAbandoned && t.NextTryTime <= now) .OrderByDescending(t => t.Priority) .ThenBy(t => t.TryCount) diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Installer/InstallationNotes.md b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Installer/InstallationNotes.md new file mode 100644 index 0000000000..953695c647 --- /dev/null +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Installer/InstallationNotes.md @@ -0,0 +1,12 @@ +# Installation Notes for Background Jobs Module + +Background jobs are used to queue some tasks to be executed in the background. You may need background jobs for several reasons. Here are some examples: + +- To perform **long-running tasks** without having the users wait. For example, a user presses a 'report' button to start a long-running reporting job. You add this job to the **queue** and send the report's result to your user via email when it's completed. +- To create **re-trying** and **persistent tasks** to **guarantee** that a code will be **successfully executed**. For example, you can send emails in a background job to overcome **temporary failures** and **guarantee** that it eventually will be sent. That way users do not wait while sending emails. + +Background jobs are **persistent** that means they will be **re-tried** and **executed** later even if your application crashes. + +## Documentation + +For detailed information and usage instructions, please visit the [Background Jobs documentation](https://abp.io/docs/latest/framework/infrastructure/background-jobs). \ No newline at end of file diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs index 5993fdf9ba..71a5680524 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Linq; +using JetBrains.Annotations; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; @@ -22,17 +24,16 @@ public class MongoBackgroundJobRepository : MongoDbRepository> GetWaitingListAsync( - int maxResultCount, - CancellationToken cancellationToken = default) + public virtual async Task> GetWaitingListAsync([CanBeNull] string applicationName, int maxResultCount, CancellationToken cancellationToken = default) { - return await (await GetWaitingListQuery(maxResultCount)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetWaitingListQuery(applicationName, maxResultCount, cancellationToken)).ToListAsync(GetCancellationToken(cancellationToken)); } - protected virtual async Task> GetWaitingListQuery(int maxResultCount, CancellationToken cancellationToken = default) + protected virtual async Task> GetWaitingListQuery([CanBeNull] string applicationName, int maxResultCount, CancellationToken cancellationToken = default) { var now = Clock.Now; - return (await GetMongoQueryableAsync(cancellationToken)) + return (await GetQueryableAsync(cancellationToken)) + .Where(t => t.ApplicationName == applicationName) .Where(t => !t.IsAbandoned && t.NextTryTime <= now) .OrderByDescending(t => t.Priority) .ThenBy(t => t.TryCount) diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj index c6a4b35a66..a3f84bb18a 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj @@ -14,10 +14,10 @@ - - - - + + + + diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs index 97bd35c6fa..b41e255cb8 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo/Abp/BackgroundJobs/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.BackgroundJobs.MongoDB; diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobRepository_Tests.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobRepository_Tests.cs index 02e4fa9d60..c62cb43309 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobRepository_Tests.cs +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobRepository_Tests.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Threading.Tasks; using Shouldly; using Volo.Abp.Modularity; using Volo.Abp.Timing; @@ -23,12 +24,16 @@ public abstract class BackgroundJobRepository_Tests : Background [InlineData(5)] public async Task GetWaitingListAsync(int maxResultCount) { - var backgroundJobs = await _backgroundJobRepository.GetWaitingListAsync(maxResultCount); + var backgroundJobs = await _backgroundJobRepository.GetWaitingListAsync("App1", maxResultCount); backgroundJobs.Count.ShouldBeGreaterThan(0); backgroundJobs.Count.ShouldBeLessThanOrEqualTo(maxResultCount); backgroundJobs.ForEach(j => j.IsAbandoned.ShouldBeFalse()); backgroundJobs.ForEach(j => j.NextTryTime.ShouldBeLessThanOrEqualTo(_clock.Now.AddSeconds(1))); //1 second tolerance + + backgroundJobs.All(j => j.ApplicationName == "App1").ShouldBeTrue(); + backgroundJobs.Any(j => j.ApplicationName == "App2").ShouldBeFalse(); + backgroundJobs.Any(j => j.ApplicationName == null).ShouldBeFalse(); } } diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs index 079a0ab3ea..f6f4c37e12 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs @@ -26,6 +26,7 @@ public class BackgroundJobsTestDataBuilder : ITransientDependency await _backgroundJobRepository.InsertAsync( new BackgroundJobRecord(_testData.JobId1) { + ApplicationName = "App1", JobName = "TestJobName", JobArgs = "{ value: 1 }", NextTryTime = _clock.Now.Subtract(TimeSpan.FromMinutes(1)), @@ -40,6 +41,7 @@ public class BackgroundJobsTestDataBuilder : ITransientDependency await _backgroundJobRepository.InsertAsync( new BackgroundJobRecord(_testData.JobId2) { + ApplicationName = "App2", JobName = "TestJobName", JobArgs = "{ value: 2 }", NextTryTime = _clock.Now.AddMinutes(42), @@ -54,6 +56,7 @@ public class BackgroundJobsTestDataBuilder : ITransientDependency await _backgroundJobRepository.InsertAsync( new BackgroundJobRecord(_testData.JobId3) { + ApplicationName = "App1", JobName = "TestJobName", JobArgs = "{ value: 3 }", NextTryTime = _clock.Now, diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Installer/InstallationNotes.md b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Installer/InstallationNotes.md new file mode 100644 index 0000000000..dc655f430f --- /dev/null +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Installer/InstallationNotes.md @@ -0,0 +1,13 @@ +# Installation Notes for Basic Theme Module (MVC) + +The Basic Theme is a theme implementation for the ASP.NET Core MVC / Razor Pages UI. It is a minimalist theme that doesn't add any styling on top of the plain [Bootstrap](https://getbootstrap.com/). You can take the Basic Theme as the base theme and build your own theme or styling on top of it. See the Customization section. + +The Basic Theme has RTL (Right-to-Left language) support. + +If you are looking for a professional, enterprise ready theme, you can check the [Lepton Theme](https://abp.io/themes), which is a part of the ABP. + +See the [Theming document](https://github.com/abpframework/abp/blob/rel-9.1/docs/en/framework/ui/mvc-razor-pages/theming.md) to learn about themes. + +## Documentation + +For detailed information and usage instructions, please visit the [Basic Theme documentation](https://abp.io/docs/latest/framework/ui/mvc-razor-pages/basic-theme). \ No newline at end of file diff --git a/modules/basic-theme/src/Volo.Abp.BasicTheme.Installer/InstallationNotes.md b/modules/basic-theme/src/Volo.Abp.BasicTheme.Installer/InstallationNotes.md new file mode 100644 index 0000000000..088628d830 --- /dev/null +++ b/modules/basic-theme/src/Volo.Abp.BasicTheme.Installer/InstallationNotes.md @@ -0,0 +1,7 @@ +# Installation Notes for Basic Theme Module (Blazor) + +The Basic Theme is a theme implementation for the Blazor UI. It is a minimalist theme that doesn't add any styling on top of the plain [Bootstrap](https://getbootstrap.com/). You can take the Basic Theme as the base theme and build your own theme or styling on top of it. See the Customization section. + +## Documentation + +For detailed information and usage instructions, please visit the [Blazor UI Basic Theme documentation](https://abp.io/docs/latest/framework/ui/blazor/basic-theme?UI=BlazorServer). \ No newline at end of file diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Installer/InstallationNotes.md b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Installer/InstallationNotes.md new file mode 100644 index 0000000000..dcd9293ef3 --- /dev/null +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Installer/InstallationNotes.md @@ -0,0 +1,16 @@ +# Installation Notes for Blob Storing Database Module + +It is typical to store file contents in an application and read these file contents on need. Not only files, but you may also need to save various types of large binary objects, a.k.a. [BLOBs](https://en.wikipedia.org/wiki/Binary_large_object), into a storage. For example, you may want to save user profile pictures. + +A BLOB is a typically byte array. There are various places to store a BLOB item; storing in the local file system, in a shared database or on the [Azure BLOB storage](https://azure.microsoft.com/en-us/products/storage/blobs/) can be options. + +The ABP provides an abstraction to work with BLOBs and provides some pre-built storage providers that you can easily integrate to. Having such an abstraction has some benefits; + +You can easily integrate to your favorite BLOB storage provides with a few lines of configuration. +You can then easily change your BLOB storage without changing your application code. +If you want to create reusable application modules, you don't need to make assumption about how the BLOBs are stored. +ABP BLOB Storage system is also compatible to other ABP features like multi-tenancy. + +## Documentation + +For detailed information and usage instructions, please visit the [BLOB Storing documentation](https://abp.io/docs/latest/framework/infrastructure/blob-storing). \ No newline at end of file diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs index 4610043405..6b2663013d 100644 --- a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo/Abp/BlobStoring/Database/MongoDB/MongoDbDatabaseBlobRepository.cs @@ -17,7 +17,7 @@ public class MongoDbDatabaseBlobRepository : MongoDbRepository x.ContainerId == containerId && x.Name == name, cancellationToken @@ -28,7 +28,7 @@ public class MongoDbDatabaseBlobRepository : MongoDbRepository x.ContainerId == containerId && x.Name == name, cancellationToken diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/MongoDB/MongoDbFixture.cs b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/MongoDB/MongoDbFixture.cs index 8952236f43..7c086e0bb4 100644 --- a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/MongoDB/MongoDbFixture.cs +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.BlobStoring.Database.MongoDB; diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj index 1bd05f4357..61c0d81d02 100644 --- a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/modules/blogging/src/Volo.Blogging.Installer/InstallationNotes.md b/modules/blogging/src/Volo.Blogging.Installer/InstallationNotes.md new file mode 100644 index 0000000000..9ef0de0d04 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Installer/InstallationNotes.md @@ -0,0 +1,28 @@ +# Installation Notes for Blogging Module + +The ABP Blogging module provides a simple blogging system for ABP applications. It allows you to create and manage blogs, posts, tags, and comments. The module includes both a public interface for readers and an admin interface for content management. + +Key features of the Blogging module: +- Multiple blog support +- Post management with rich text editing +- Commenting functionality +- Social media sharing +- Admin interface for content management + +## Required Configurations + +The Blogging module requires **permission** settings to be configured after installation. Ensure that the necessary roles have the appropriate access rights for managing blogs, posts, comments and others. + +### Update Database + +The Blogging module requires database migrations to be applied. Following installation, you must update the database to create the necessary tables. + +### Permissions + +Enable the following permissions for the roles that require access to the Blogging module: + +![Blogging Permissions](blogging-permissions.png) + +## Documentation + +For detailed information and usage instructions, please visit the [Blogging Module documentation](https://abp.io/docs/latest/Modules/Cms-Kit/Blogging). \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Installer/blogging-permissions.png b/modules/blogging/src/Volo.Blogging.Installer/blogging-permissions.png new file mode 100644 index 0000000000..733f3c668f Binary files /dev/null and b/modules/blogging/src/Volo.Blogging.Installer/blogging-permissions.png differ diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs index 42c8bb467a..c15ef4d0cb 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs @@ -16,7 +16,7 @@ namespace Volo.Blogging.Blogs public virtual async Task FindByShortNameAsync(string shortName, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.ShortName == shortName, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.ShortName == shortName, GetCancellationToken(cancellationToken)); } } } diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs index 89e5b6b575..77c443e485 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Comments/MongoCommentRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; @@ -18,7 +19,7 @@ namespace Volo.Blogging.Comments public virtual async Task> GetListOfPostAsync(Guid postId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(a => a.PostId == postId) .OrderBy(a => a.CreationTime) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -26,19 +27,19 @@ namespace Volo.Blogging.Comments public virtual async Task GetCommentCountOfPostAsync(Guid postId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .CountAsync(a => a.PostId == postId, GetCancellationToken(cancellationToken)); } public virtual async Task> GetRepliesOfComment(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(a => a.RepliedCommentId == id).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task DeleteOfPost(Guid id, CancellationToken cancellationToken = default) { - var recordsToDelete = (await GetMongoQueryableAsync(cancellationToken)).Where(pt => pt.PostId == id); + var recordsToDelete = (await GetQueryableAsync(cancellationToken)).Where(pt => pt.PostId == id); foreach (var record in recordsToDelete) { diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs index 3cdcccc5fd..b3083cbd5f 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver; using MongoDB.Driver.Linq; using Nito.AsyncEx; @@ -20,13 +21,13 @@ namespace Volo.Blogging.Posts public virtual async Task> GetPostsByBlogId(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(p => p.BlogId == id).OrderByDescending(p => p.CreationTime).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(p => p.BlogId == id).OrderByDescending(p => p.CreationTime).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task IsPostUrlInUseAsync(Guid blogId, string url, Guid? excludingPostId = null, CancellationToken cancellationToken = default) { - var query = (await GetMongoQueryableAsync(cancellationToken)).Where(p => blogId == p.BlogId && p.Url == url); + var query = (await GetQueryableAsync(cancellationToken)).Where(p => blogId == p.BlogId && p.Url == url); if (excludingPostId != null) { @@ -38,7 +39,7 @@ namespace Volo.Blogging.Posts public virtual async Task GetPostByUrl(Guid blogId, string url, CancellationToken cancellationToken = default) { - var post = await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url, GetCancellationToken(cancellationToken)); + var post = await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.BlogId == blogId && p.Url == url, GetCancellationToken(cancellationToken)); if (post == null) { @@ -50,7 +51,7 @@ namespace Volo.Blogging.Posts public virtual async Task> GetOrderedList(Guid blogId, bool @descending = false, CancellationToken cancellationToken = default) { - var query = (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.BlogId == blogId); + var query = (await GetQueryableAsync(cancellationToken)).Where(x => x.BlogId == blogId); if (!descending) { @@ -62,7 +63,7 @@ namespace Volo.Blogging.Posts public virtual async Task> GetListByUserIdAsync(Guid userId, CancellationToken cancellationToken = default) { - var query = (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.CreatorId == userId) + var query = (await GetQueryableAsync(cancellationToken)).Where(x => x.CreatorId == userId) .OrderByDescending(x => x.CreationTime); return await query.ToListAsync(GetCancellationToken(cancellationToken)); @@ -70,7 +71,7 @@ namespace Volo.Blogging.Posts public virtual async Task> GetLatestBlogPostsAsync(Guid blogId, int count, CancellationToken cancellationToken = default) { - var query = (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.BlogId == blogId) + var query = (await GetQueryableAsync(cancellationToken)).Where(x => x.BlogId == blogId) .OrderByDescending(x => x.CreationTime) .Take(count); diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs index bfa0c9fb4d..2e60faaccc 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs @@ -20,27 +20,27 @@ namespace Volo.Blogging.Tagging public virtual async Task> GetListAsync(Guid blogId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetByNameAsync(Guid blogId, string name, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId && t.Name == name).FirstAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId && t.Name == name).FirstAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByNameAsync(Guid blogId, string name, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId && t.Name == name).FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(t => t.BlogId == blogId && t.Name == name).FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task DecreaseUsageCountOfTagsAsync(List ids, CancellationToken cancellationToken = default) { - var tags = await (await GetMongoQueryableAsync(cancellationToken)) + var tags = await (await GetQueryableAsync(cancellationToken)) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs index 3595620f54..b68e77c9fd 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Users/MongoBlogUserRepository.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Linq; using Volo.Abp.MongoDB; using Volo.Abp.Users.MongoDB; using Volo.Blogging.MongoDB; @@ -17,7 +18,7 @@ namespace Volo.Blogging.Users public virtual async Task> GetUsersAsync(int maxCount, string filter, CancellationToken cancellationToken = default) { - var query = await GetMongoQueryableAsync(cancellationToken); + var query = await GetQueryableAsync(cancellationToken); if (!string.IsNullOrWhiteSpace(filter)) { diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj index 88cd171a55..7dcac50e69 100644 --- a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs index ad1fce80e5..e1a4d00ce3 100644 --- a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; public class MongoDbFixture : IDisposable { diff --git a/modules/cms-kit/src/Volo.CmsKit.Installer/InstallationNotes.md b/modules/cms-kit/src/Volo.CmsKit.Installer/InstallationNotes.md new file mode 100644 index 0000000000..1a037cf1e3 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Installer/InstallationNotes.md @@ -0,0 +1,48 @@ +# Installation Notes for CMS Kit Module + +The ABP CMS Kit module provides a set of reusable Content Management System (CMS) features for your ABP-based applications. It offers ready-to-use UI components and APIs for common content management requirements. + +This module is part of the ABP Framework and provides features like comments, ratings, tags, blogs, and more to help you build content-rich applications. + +## Required Configurations + +The CmsKit module requires **permission** settings to be configured after installation. Ensure that the necessary roles have the appropriate access rights for managing blogs, posts, comments and others. + +### Enable CmsKit + +To enable the CmsKit module, add the following line to the `GlobalFeatureConfigurator` class of your module: + +```csharp +public static void Configure() +{ + OneTimeRunner.Run(() => + { + /* You can configure (enable/disable) global features of the used modules here. + * Please refer to the documentation to learn more about the Global Features System: + * https://docs.abp.io/en/abp/latest/Global-Features + */ + + GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit => + { + cmsKit.EnableAll(); + // or + // cmsKit.Tags.Enable(); + // cmsKit.Comments.Enable(); + }); + }); +} +``` + +### Database Migrations + +The CmsKit module requires database migrations to be applied. After enable **CmsKit**, Add a new migration and update the database to create the necessary tables. + +### Permissions + +Enable the following permissions for the roles that require access to the CmsKit module: + +![CmsKit Permissions](cmskit-permissions.png) + +## Documentation + +For detailed information and usage instructions, please visit the [CMS Kit documentation](https://abp.io/docs/latest/modules/cms-kit). \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Installer/cmskit-permissions.png b/modules/cms-kit/src/Volo.CmsKit.Installer/cmskit-permissions.png new file mode 100644 index 0000000000..a095dc8140 Binary files /dev/null and b/modules/cms-kit/src/Volo.CmsKit.Installer/cmskit-permissions.png differ diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogFeatureRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogFeatureRepository.cs index 334debe8c8..606c3e28ff 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogFeatureRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogFeatureRepository.cs @@ -25,14 +25,14 @@ public class MongoBlogFeatureRepository : MongoDbRepository> GetListAsync(Guid blogId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.BlogId == blogId) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetListAsync(Guid blogId, List featureNames, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.BlogId == blogId && featureNames.Contains(x.FeatureName)) .ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs index bb7ee21b17..78afc5a871 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs @@ -44,7 +44,7 @@ public class MongoBlogPostRepository : MongoDbRepository(token)).FirstOrDefaultAsync(x => x.Id == blogPost.AuthorId, token); + blogPost.Author = await (await GetQueryableAsync(token)).FirstOrDefaultAsync(x => x.Id == blogPost.AuthorId, token); return blogPost; } @@ -63,13 +63,13 @@ public class MongoBlogPostRepository : MongoDbRepository>(tagFilteredEntityIds.Any(), x => tagFilteredEntityIds.Contains(x.Id)) - .WhereIf>(favoriteUserFilteredEntityIds.Any(), x => favoriteUserFilteredEntityIds.Contains(x.Id)) - .WhereIf>(!string.IsNullOrWhiteSpace(filter), x => x.Title.Contains(filter) || x.Slug.Contains(filter)) - .WhereIf>(blogId.HasValue, x => x.BlogId == blogId) - .WhereIf>(authorId.HasValue, x => x.AuthorId == authorId) - .WhereIf>(statusFilter.HasValue, x => x.Status == statusFilter) + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf(tagFilteredEntityIds.Any(), x => tagFilteredEntityIds.Contains(x.Id)) + .WhereIf(favoriteUserFilteredEntityIds.Any(), x => favoriteUserFilteredEntityIds.Contains(x.Id)) + .WhereIf(!string.IsNullOrWhiteSpace(filter), x => x.Title.Contains(filter) || x.Slug.Contains(filter)) + .WhereIf(blogId.HasValue, x => x.BlogId == blogId) + .WhereIf(authorId.HasValue, x => x.AuthorId == authorId) + .WhereIf(statusFilter.HasValue, x => x.Status == statusFilter) .CountAsync(cancellationToken); } @@ -173,7 +173,7 @@ public class MongoBlogPostRepository : MongoDbRepository x.BlogId == blogId && x.Slug.ToLower() == slug, cancellationToken); } @@ -224,14 +224,14 @@ public class MongoBlogPostRepository : MongoDbRepository x.Status == BlogPostStatus.WaitingForReview, cancellationToken); } public virtual async Task UpdateBlogAsync(Guid sourceBlogId, Guid? targetBlogId, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - var blogPosts = await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.BlogId == sourceBlogId).ToListAsync(cancellationToken); + var blogPosts = await (await GetQueryableAsync(cancellationToken)).Where(x => x.BlogId == sourceBlogId).ToListAsync(cancellationToken); if (targetBlogId.HasValue) { foreach (var blogPost in blogPosts) diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs index 98567899e5..c25bc688b7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs @@ -23,13 +23,13 @@ public class MongoBlogRepository : MongoDbRepository ExistsAsync(Guid id, CancellationToken cancellationToken = default) { var token = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(token)).AnyAsync(x => x.Id == id, token); + return await (await GetQueryableAsync(token)).AnyAsync(x => x.Id == id, token); } public virtual async Task SlugExistsAsync(string slug, CancellationToken cancellationToken = default) { var token = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(token)).AnyAsync(x => x.Slug == slug, token); + return await (await GetQueryableAsync(token)).AnyAsync(x => x.Slug == slug, token); } public virtual async Task> GetListAsync( @@ -44,8 +44,7 @@ public class MongoBlogRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(token); } @@ -63,7 +62,7 @@ public class MongoBlogRepository : MongoDbRepository x.Id).ToList(); - var blogPostCount = await (await GetMongoQueryableAsync(token)) + var blogPostCount = await (await GetQueryableAsync(token)) .Where(blogPost => blogIds.Contains(blogPost.Id)) .GroupBy(blogPost => blogPost.BlogId) .Select(x => new @@ -82,7 +81,7 @@ public class MongoBlogRepository : MongoDbRepository>().LongCountAsync(token); + return await query.LongCountAsync(token); } public virtual Task GetBySlugAsync([NotNull] string slug, CancellationToken cancellationToken = default) @@ -93,7 +92,7 @@ public class MongoBlogRepository : MongoDbRepository> GetListQueryAsync(string filter = null, CancellationToken cancellationToken = default) { - return (await GetMongoQueryableAsync(cancellationToken)) + return (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), b => b.Name.Contains(filter)); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs index fab729fcd2..5b4566ecb8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs @@ -61,19 +61,18 @@ public class MongoCommentRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(token); var commentIds = comments.Select(x => x.Id).ToList(); - var authorsQuery = from comment in (await GetMongoQueryableAsync(token)) + var authorsQuery = from comment in (await GetQueryableAsync(token)) join user in (await GetDbContextAsync(token)).CmsUsers on comment.CreatorId equals user.Id where commentIds.Contains(comment.Id) orderby comment.CreationTime select user; - var authors = await ApplyDataFilters, CmsUser>(authorsQuery).ToListAsync(token); + var authors = await ApplyDataFilters, CmsUser>(authorsQuery).ToListAsync(token); return comments .Select( @@ -104,8 +103,7 @@ public class MongoCommentRepository : MongoDbRepository>() - .LongCountAsync(GetCancellationToken(cancellationToken)); + return await query.LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetListWithAuthorsAsync( @@ -117,15 +115,15 @@ public class MongoCommentRepository : MongoDbRepository, CmsUser>(authorsQuery).ToListAsync(GetCancellationToken(cancellationToken)); + var authors = await ApplyDataFilters, CmsUser>(authorsQuery).ToListAsync(GetCancellationToken(cancellationToken)); - var commentsQuery = (await GetMongoQueryableAsync(cancellationToken)) + var commentsQuery = (await GetQueryableAsync(cancellationToken)) .Where(c => c.EntityId == entityId && c.EntityType == entityType); commentsQuery = commentApproveState switch { @@ -152,7 +150,7 @@ public class MongoCommentRepository : MongoDbRepository x.RepliedCommentId == comment.Id) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -172,7 +170,7 @@ public class MongoCommentRepository : MongoDbRepository ExistsAsync(string idempotencyToken, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .AnyAsync(x => x.IdempotencyToken == idempotencyToken, GetCancellationToken(cancellationToken)); } @@ -187,11 +185,11 @@ public class MongoCommentRepository : MongoDbRepository(cancellationToken)).FirstOrDefaultAsync(x => x.UserName == authorUsername, cancellationToken: cancellationToken); + var author = await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.UserName == authorUsername, cancellationToken: cancellationToken); var authorId = author?.Id ?? Guid.Empty; diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/MarkedItems/MongoUserMarkedItemRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/MarkedItems/MongoUserMarkedItemRepository.cs index 91fbbf996e..ea81fe03ff 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/MarkedItems/MongoUserMarkedItemRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/MarkedItems/MongoUserMarkedItemRepository.cs @@ -24,7 +24,7 @@ public class MongoUserMarkedItemRepository : MongoDbRepository x.CreatorId == userId && x.EntityType == entityType && @@ -39,7 +39,7 @@ public class MongoUserMarkedItemRepository : MongoDbRepository x.CreatorId == userId && x.EntityType == entityType) @@ -49,7 +49,7 @@ public class MongoUserMarkedItemRepository : MongoDbRepository> GetEntityIdsFilteredByUserAsync([NotNull] Guid userId, [NotNull] string entityType, [CanBeNull] Guid? tenantId = null, CancellationToken cancellationToken = default) { var dbContext = await GetDbContextAsync(); - var userMarkedItemQueryable = await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)); + var userMarkedItemQueryable = await GetQueryableAsync(GetCancellationToken(cancellationToken)); var resultQueryable = userMarkedItemQueryable .Where(x => x.CreatorId == userId diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs index 1b49ac48bb..7c2f9a3891 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Pages/MongoPageRepository.cs @@ -26,8 +26,8 @@ public class MongoPageRepository : MongoDbRepository>( + return await (await GetQueryableAsync(cancellation)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Title.ToLower().Contains(filter.ToLower()) || u.Slug.Contains(filter) @@ -43,13 +43,12 @@ public class MongoPageRepository : MongoDbRepository>( + return await (await GetQueryableAsync(cancellation)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Title.ToLower().Contains(filter) || u.Slug.Contains(filter)) .OrderBy(sorting.IsNullOrEmpty() ? nameof(Page.Title) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(cancellation); } @@ -68,7 +67,7 @@ public class MongoPageRepository : MongoDbRepository ExistsAsync([NotNull] string slug, CancellationToken cancellationToken = default) { Check.NotNullOrEmpty(slug, nameof(slug)); - return await (await GetMongoQueryableAsync(cancellationToken)).AnyAsync(x => x.Slug == slug, + return await (await GetQueryableAsync(cancellationToken)).AnyAsync(x => x.Slug == slug, GetCancellationToken(cancellationToken)); } @@ -79,7 +78,7 @@ public class MongoPageRepository : MongoDbRepository FindTitleAsync(Guid pageId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.Id == pageId).Select(x => x.Title) + return await (await GetQueryableAsync(cancellationToken)).Where(x => x.Id == pageId).Select(x => x.Title) .FirstOrDefaultAsync(cancellationToken); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs index 3a18f31719..d93cad27be 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Ratings/MongoRatingRepository.cs @@ -25,7 +25,7 @@ public class MongoRatingRepository : MongoDbRepository r.EntityType == entityType && r.EntityId == entityId && r.CreatorId == userId, GetCancellationToken(cancellationToken)); @@ -39,7 +39,7 @@ public class MongoRatingRepository : MongoDbRepository x.CreatorId == userId && x.EntityType == entityType && @@ -47,7 +47,7 @@ public class MongoUserReactionRepository : MongoDbRepository x.CreatorId == userId && x.EntityType == entityType && @@ -63,7 +63,7 @@ public class MongoUserReactionRepository : MongoDbRepository x.EntityType == entityType && x.EntityId == entityId) diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs index 2e8dc96d01..1ce2319a49 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs @@ -67,7 +67,7 @@ public class MongoEntityTagRepository : MongoDbRepository x.EntityType == entityType && x.Name == name, @@ -69,12 +69,12 @@ public class MongoTagRepository : MongoDbRepository(cancellationToken)) + var entityTagIds = await (await GetQueryableAsync(cancellationToken)) .Where(q => q.EntityId == entityId) .Select(q => q.TagId) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); - var query = (await GetMongoQueryableAsync(cancellationToken)) + var query = (await GetQueryableAsync(cancellationToken)) .Where(x => x.EntityType == entityType && entityTagIds.Contains(x.Id)); @@ -86,14 +86,14 @@ public class MongoTagRepository : MongoDbRepository> GetPopularTagsAsync(string entityType, int maxCount, CancellationToken cancellationToken = default) { - var tags = await (await GetMongoQueryableAsync(cancellationToken)) + var tags = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.EntityType == entityType) .Select(x => new { x.Id, x.Name }) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); var tagIds = tags.Select(x => x.Id); - var entityTagCounts = await (await GetMongoQueryableAsync(cancellationToken)) + var entityTagCounts = await (await GetQueryableAsync(cancellationToken)) .Where(q => tagIds.Contains(q.TagId)) .GroupBy(q => q.TagId) .Select(q => new { TagId = q.Key, Count = q.Count() }) @@ -116,8 +116,7 @@ public class MongoTagRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -126,9 +125,9 @@ public class MongoTagRepository : MongoDbRepository> GetQueryableByFilterAsync(string filter, CancellationToken cancellationToken = default) + private async Task> GetQueryableByFilterAsync(string filter, CancellationToken cancellationToken = default) { - var mongoQueryable = await GetMongoQueryableAsync(cancellationToken: cancellationToken); + var mongoQueryable = await GetQueryableAsync(cancellationToken: cancellationToken); if (!filter.IsNullOrWhiteSpace()) { diff --git a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/MongoDB/MongoDbFixture.cs b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/MongoDB/MongoDbFixture.cs index 22f63a3780..53c9457a30 100644 --- a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/MongoDB/MongoDbFixture.cs +++ b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.CmsKit.MongoDB; diff --git a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj index 17c6dfe717..9c8dc44660 100644 --- a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj +++ b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/modules/docs/Volo.Docs.abpmdl b/modules/docs/Volo.Docs.abpmdl index 17b5d6fab9..77c70bddf8 100644 --- a/modules/docs/Volo.Docs.abpmdl +++ b/modules/docs/Volo.Docs.abpmdl @@ -7,18 +7,6 @@ } }, "packages": { - "VoloDocs.Web": { - "path": "app/VoloDocs.Web/VoloDocs.Web.abppkg", - "folder": "app" - }, - "VoloDocs.EntityFrameworkCore": { - "path": "app/VoloDocs.EntityFrameworkCore/VoloDocs.EntityFrameworkCore.abppkg", - "folder": "app" - }, - "VoloDocs.Migrator": { - "path": "app/VoloDocs.Migrator/VoloDocs.Migrator.abppkg", - "folder": "app" - }, "Volo.Docs.Web": { "path": "src/Volo.Docs.Web/Volo.Docs.Web.abppkg", "folder": "src" diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs index f19b9f41df..015f711850 100644 --- a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/NavigationNode.cs @@ -21,6 +21,9 @@ namespace Volo.Docs.Documents [JsonPropertyName("isIndex")] public bool IsIndex { get; set; } + + [JsonPropertyName("keywords")] + public string[] Keywords { get; set; } public bool IsLeaf => !HasChildItems; diff --git a/modules/docs/src/Volo.Docs.Installer/InstallationNotes.md b/modules/docs/src/Volo.Docs.Installer/InstallationNotes.md new file mode 100644 index 0000000000..a0c172d27c --- /dev/null +++ b/modules/docs/src/Volo.Docs.Installer/InstallationNotes.md @@ -0,0 +1,31 @@ +# Installation Notes for Docs Module + +The ABP Docs module provides a complete documentation system for ABP applications. It allows you to create, manage, and publish documentation from various sources like GitHub, GitLab, or local file system. The module includes both a public interface for readers and an admin interface for documentation management. + +Key features of the Docs module: +- Multiple documentation projects support +- Version control integration +- Markdown support +- Navigation generation +- Full-text search +- Multi-language support +- Admin interface for documentation management + + +## Required Configurations + +The Docs module requires **permission** settings to be configured after installation and database update. + +### Update Database + +The Docs module requires database migrations to be applied. Following installation, you must update the database to create the necessary tables. + +### Permissions + +Enable the following permissions for the roles that require access to the Docs module: + +![Docs Permissions](docs-permissions.png) + +## Documentation + +For detailed information and usage instructions, please visit the [Docs Module documentation](https://abp.io/docs/latest/Modules/Docs). \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Installer/docs-permissions.png b/modules/docs/src/Volo.Docs.Installer/docs-permissions.png new file mode 100644 index 0000000000..b3e478ce0a Binary files /dev/null and b/modules/docs/src/Volo.Docs.Installer/docs-permissions.png differ diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs index 7f55ef63b0..081e920cff 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs @@ -22,7 +22,7 @@ namespace Volo.Docs.Documents public virtual async Task> GetListWithoutDetailsByProjectId(Guid projectId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(d => d.ProjectId == projectId) .Select(x => new DocumentWithoutDetails { @@ -37,7 +37,7 @@ namespace Volo.Docs.Documents public virtual async Task> GetUniqueListDocumentInfoAsync(CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Select(x=> new DocumentInfo { ProjectId = x.ProjectId, Version = x.Version, @@ -51,13 +51,13 @@ namespace Volo.Docs.Documents public virtual async Task> GetListByProjectId(Guid projectId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetUniqueDocumentsByProjectIdPagedAsync(Guid projectId, int skipCount, int maxResultCount, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(d => d.ProjectId == projectId) .OrderBy(x => x.LastCachedTime) .GroupBy(x => new { x.Name, x.LanguageCode, x.Version }) @@ -69,7 +69,7 @@ namespace Volo.Docs.Documents public virtual async Task GetUniqueDocumentCountByProjectIdAsync(Guid projectId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId) + return await (await GetQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId) .GroupBy(x => new { x.Name, x.LanguageCode, x.Version }) .LongCountAsync(GetCancellationToken(cancellationToken)); } @@ -89,17 +89,18 @@ namespace Volo.Docs.Documents bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.ProjectId == projectId && - x.Name == name && - x.LanguageCode == languageCode && - x.Version == version, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => + x.ProjectId == projectId && + x.Name == name && + x.LanguageCode == languageCode && + x.Version == version, GetCancellationToken(cancellationToken)); } - + public virtual async Task FindAsync(Guid projectId, List possibleNames, string languageCode, string version, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.ProjectId == projectId && + return await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.ProjectId == projectId && possibleNames.Contains(x.Name) && x.LanguageCode == languageCode && x.Version == version, GetCancellationToken(cancellationToken)); @@ -114,11 +115,10 @@ namespace Volo.Docs.Documents public virtual async Task> GetListAsync(Guid? projectId, string version, string name, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(version != null, x => x.Version == version) .WhereIf(name != null, x => x.Name == name) .WhereIf(projectId.HasValue, x => x.ProjectId == projectId) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -142,26 +142,25 @@ namespace Volo.Docs.Documents int skipCount = 0, CancellationToken cancellationToken = default) { - return await (await ApplyFilterForGetAll( - await GetMongoQueryableAsync(cancellationToken), - projectId: projectId, - name: name, - version: version, - languageCode: languageCode, - fileName: fileName, - format: format, - creationTimeMin: creationTimeMin, - creationTimeMax: creationTimeMax, - lastUpdatedTimeMin: lastUpdatedTimeMin, - lastUpdatedTimeMax: lastUpdatedTimeMax, - lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin, - lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax, - lastCachedTimeMin: lastCachedTimeMin, lastCachedTimeMax: lastCachedTimeMax)) - .OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting).As>() - .PageBy>(skipCount, maxResultCount) - .ToListAsync(GetCancellationToken(cancellationToken)); + await GetQueryableAsync(cancellationToken), + projectId: projectId, + name: name, + version: version, + languageCode: languageCode, + fileName: fileName, + format: format, + creationTimeMin: creationTimeMin, + creationTimeMax: creationTimeMax, + lastUpdatedTimeMin: lastUpdatedTimeMin, + lastUpdatedTimeMax: lastUpdatedTimeMax, + lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin, + lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax, + lastCachedTimeMin: lastCachedTimeMin, lastCachedTimeMax: lastCachedTimeMax, cancellationToken: cancellationToken)) + .OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting) + .PageBy(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetAllCountAsync( @@ -184,36 +183,35 @@ namespace Volo.Docs.Documents int skipCount = 0, CancellationToken cancellationToken = default) { - - return await (await ApplyFilterForGetAll( - await GetMongoQueryableAsync(cancellationToken), - projectId: projectId, - name: name, - version: version, - languageCode: languageCode, - fileName: fileName, - format: format, - creationTimeMin: creationTimeMin, - creationTimeMax: creationTimeMax, - lastUpdatedTimeMin: lastUpdatedTimeMin, - lastUpdatedTimeMax: lastUpdatedTimeMax, - lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin, - lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax, - lastCachedTimeMin: lastCachedTimeMin, lastCachedTimeMax: lastCachedTimeMax)) - .OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting).As>() - .PageBy>(skipCount, maxResultCount) - .LongCountAsync(GetCancellationToken(cancellationToken)); + await GetQueryableAsync(cancellationToken), + projectId: projectId, + name: name, + version: version, + languageCode: languageCode, + fileName: fileName, + format: format, + creationTimeMin: creationTimeMin, + creationTimeMax: creationTimeMax, + lastUpdatedTimeMin: lastUpdatedTimeMin, + lastUpdatedTimeMax: lastUpdatedTimeMax, + lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin, + lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax, + lastCachedTimeMin: lastCachedTimeMin, lastCachedTimeMax: lastCachedTimeMax, + cancellationToken: cancellationToken)) + .OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting) + .PageBy(skipCount, maxResultCount) + .LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.Id == id).SingleAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(x => x.Id == id).SingleAsync(GetCancellationToken(cancellationToken)); } - - protected virtual async Task> ApplyFilterForGetAll( - IMongoQueryable query, + + protected virtual async Task> ApplyFilterForGetAll( + IQueryable query, Guid? projectId, string name, string version, @@ -254,7 +252,7 @@ namespace Volo.Docs.Documents { query = query.Where(d => d.FileName != null && d.FileName.Contains(fileName)); } - + if (format != null) { query = query.Where(d => d.Format != null && d.Format == format); diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs index 3960b07eb3..af54bd6bc5 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs @@ -22,8 +22,7 @@ namespace Volo.Docs.Projects public virtual async Task> GetListAsync(string sorting, int maxResultCount, int skipCount, CancellationToken cancellationToken = default) { - var projects = await (await GetMongoQueryableAsync(cancellationToken)).OrderBy(sorting.IsNullOrEmpty() ? "Id desc" : sorting).As>() - .PageBy>(skipCount, maxResultCount) + var projects = await (await GetQueryableAsync(cancellationToken)).OrderBy(sorting.IsNullOrEmpty() ? "Id desc" : sorting).PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); return projects; @@ -31,7 +30,7 @@ namespace Volo.Docs.Projects public virtual async Task> GetListWithoutDetailsAsync(CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Select(x=> new ProjectWithoutDetails { Id = x.Id, Name = x.Name, @@ -44,7 +43,7 @@ namespace Volo.Docs.Projects { var normalizeShortName = NormalizeShortName(shortName); - var project = await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.ShortName == normalizeShortName, GetCancellationToken(cancellationToken)); + var project = await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(p => p.ShortName == normalizeShortName, GetCancellationToken(cancellationToken)); if (project == null) { @@ -58,7 +57,7 @@ namespace Volo.Docs.Projects { var normalizeShortName = NormalizeShortName(shortName); - return await (await GetMongoQueryableAsync(cancellationToken)).AnyAsync(x => x.ShortName == normalizeShortName, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).AnyAsync(x => x.ShortName == normalizeShortName, GetCancellationToken(cancellationToken)); } private string NormalizeShortName(string shortName) diff --git a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs index e6c75d0161..3aa9b85777 100644 --- a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs +++ b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.AspNetCore.Razor.TagHelpers; @@ -23,7 +24,7 @@ namespace Volo.Docs.Areas.Documents.TagHelpers private const string LiItemTemplateWithLink = @"
    • {2}{3}
    • "; - private const string ListItemAnchor = @"{2}"; + private const string ListItemAnchor = @"{3}"; private const string ListItemSpan = @"{1}"; @@ -155,7 +156,8 @@ namespace Volo.Docs.Areas.Documents.TagHelpers sb.Clear(); - listInnerItem = string.Format(ListItemAnchor, NormalizePath(node.Path), textCss, + var additionalAttributes = node.Keywords.IsNullOrEmpty() ? "" : "data-keywords=\"" + node.Keywords.JoinAsString(",") + "\""; + listInnerItem = string.Format(ListItemAnchor, NormalizePath(node.Path), additionalAttributes ,textCss, node.Text.IsNullOrEmpty() ? "?" : sb.Append(node.Text).Append(badgeStringBuilder.ToString()).ToString()); diff --git a/modules/docs/src/Volo.Docs.Web/DocsUiOptions.cs b/modules/docs/src/Volo.Docs.Web/DocsUiOptions.cs index 702536c31d..a6b06768c3 100644 --- a/modules/docs/src/Volo.Docs.Web/DocsUiOptions.cs +++ b/modules/docs/src/Volo.Docs.Web/DocsUiOptions.cs @@ -38,6 +38,31 @@ namespace Volo.Docs public SingleProjectModeOptions SingleProjectMode { get; } = new (); public bool EnableEnlargeImage { get; set; } = true; + + public Func DocumentLinksNormalizer { get; set; } = link => + { + if (!link.EndsWith("/Index", StringComparison.OrdinalIgnoreCase)) + { + return link; + + } + return link.Substring(0, link.LastIndexOf("/Index", StringComparison.OrdinalIgnoreCase)); + }; + + public Func RedirectUrlResolver { get; set; } = url => + { + if (!url.EndsWith("/Index", StringComparison.OrdinalIgnoreCase)) + { + return null; + + } + return url.Substring(0, url.LastIndexOf("/Index", StringComparison.OrdinalIgnoreCase)); + }; + + public string? GetRedirectUrlIfNeeded(string url) + { + return RedirectUrlResolver.Invoke(url); + } private string GetFormattedRoutePrefix() { diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs index d6acd8c262..2bb7c82c21 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs @@ -131,6 +131,12 @@ namespace Volo.Docs.Pages.Documents.Project return Redirect(decodedUrl); } + var redirectUrl = _uiOptions.GetRedirectUrlIfNeeded(displayUrl); + if (redirectUrl != null) + { + return RedirectPermanent(redirectUrl); + } + return await SetPageAsync(); } diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js index 6636787f33..23eca169b5 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js @@ -29,7 +29,8 @@ var doc = doc || {}; var $ul = $(``); var $li = $(`
    • `); - $li.append(` ${node.text}`) + var dataKeywords = node.keywords ? `data-keywords="${node.keywords}"` : ""; + $li.append(` ${node.text}`) if(node.isLazyExpandable){ $li.addClass("lazy-expand"); @@ -111,12 +112,17 @@ var doc = doc || {}; var filteredItems = $navigation .find('li > a') .filter(function () { - return ( - $(this) - .text() - .toUpperCase() - .indexOf(filterText.toUpperCase()) > -1 - ); + var keywords = ($(this).data('keywords') || "").split(","); + var text = $(this).text(); + + if(text.toUpperCase().indexOf(filterText.toUpperCase()) > -1) + { + return true; + } + + return keywords.some(function(keyword){ + return keyword.toUpperCase().indexOf(filterText.toUpperCase()) > -1; + }); }); filteredItems.each(function () { diff --git a/modules/docs/src/Volo.Docs.Web/Utils/DefaultDocsLinkGenerator.cs b/modules/docs/src/Volo.Docs.Web/Utils/DefaultDocsLinkGenerator.cs index bc91e17848..c3934ec16f 100644 --- a/modules/docs/src/Volo.Docs.Web/Utils/DefaultDocsLinkGenerator.cs +++ b/modules/docs/src/Volo.Docs.Web/Utils/DefaultDocsLinkGenerator.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Net; using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Docs.Pages.Documents.Project; @@ -9,10 +10,13 @@ namespace Volo.Docs.Utils; public class DefaultDocsLinkGenerator : IDocsLinkGenerator, ITransientDependency { protected LinkGenerator LinkGenerator { get; } + + protected IOptions DocsUiOptions { get; } - public DefaultDocsLinkGenerator(LinkGenerator linkGenerator) + public DefaultDocsLinkGenerator(LinkGenerator linkGenerator, IOptions docsUiOptions) { LinkGenerator = linkGenerator; + DocsUiOptions = docsUiOptions; } @@ -26,6 +30,7 @@ public class DefaultDocsLinkGenerator : IDocsLinkGenerator, ITransientDependency }; var encodedUrl = LinkGenerator.GetPathByPage("/Documents/Project/Index", values: routeValues); - return encodedUrl?.Replace("%2F", "/"); //Document name can contain path separator(/), so we need to decode it. + var url = encodedUrl?.Replace("%2F", "/"); //Document name can contain path separator(/), so we need to decode it. + return DocsUiOptions.Value.DocumentLinksNormalizer?.Invoke(url); } } \ No newline at end of file diff --git a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj index 5c3f98c351..90df72d01d 100644 --- a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj +++ b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs index ad1fce80e5..e1a4d00ce3 100644 --- a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs +++ b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo/Docs/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; public class MongoDbFixture : IDisposable { diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor index ad5435b3c2..77f5018e10 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor @@ -3,7 +3,7 @@ @inherits AbpFeatureManagementComponentBase - + @L["Features"]@ProviderKeyDisplayName @@ -14,7 +14,7 @@ } else { - + @foreach (var group in Groups) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Installer/InstallationNotes.md b/modules/feature-management/src/Volo.Abp.FeatureManagement.Installer/InstallationNotes.md new file mode 100644 index 0000000000..10e1b121f6 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Installer/InstallationNotes.md @@ -0,0 +1,24 @@ +# Installation Notes for Feature Management Module + +The Feature Management module provides a way to define and manage features in an ABP application. Features are used to enable or disable specific functionalities of an application based on different conditions, such as tenant subscription levels or user preferences. + +Key capabilities of the Feature Management module: +- Define features with different value types (boolean, numeric, etc.) +- Group features by providers (tenant, edition, etc.) +- Manage feature values through a user interface +- Check feature status in your application code + +## NuGet Packages + +The following NuGet packages are required for the Feature Management module: +- `Volo.Abp.FeatureManagement.Application` +- `Volo.Abp.FeatureManagement.HttpApi` +- `Volo.Abp.FeatureManagement.EntityFrameworkCore` (for EF Core) +- `Volo.Abp.FeatureManagement.MongoDB` (for MongoDB) +- `Volo.Abp.FeatureManagement.Web` (for MVC UI) +- `Volo.Abp.FeatureManagement.Blazor.Server` (for Blazor Server UI) +- `Volo.Abp.FeatureManagement.Blazor.WebAssembly` (for Blazor WebAssembly UI) + +## Documentation + +For detailed information and usage instructions, please visit the [Feature Management Module documentation](https://abp.io/docs/latest/Modules/Feature-Management). \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureDefinitionRecordRepository.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureDefinitionRecordRepository.cs index cb7f48aeb4..e89a68a710 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureDefinitionRecordRepository.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureDefinitionRecordRepository.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; @@ -20,7 +21,7 @@ public class MongoFeatureDefinitionRecordRepository : public virtual async Task FindByNameAsync(string name, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync( s => s.Name == name, diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs index 3b52fe2634..0eb4f07e2f 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.MongoDB/Volo/Abp/FeatureManagement/MongoDB/MongoFeatureValueRepository.cs @@ -27,7 +27,7 @@ public class MongoFeatureValueRepository : string providerKey, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey, GetCancellationToken(cancellationToken)); } @@ -38,7 +38,7 @@ public class MongoFeatureValueRepository : string providerKey, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey).ToListAsync(GetCancellationToken(cancellationToken)); } @@ -47,7 +47,7 @@ public class MongoFeatureValueRepository : string providerKey, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey) .ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj index bfc01a429f..2f7f5ee7d0 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj @@ -14,10 +14,10 @@ - - - - + + + + diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs index 8088afee7b..23a5403281 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.FeatureManagement.MongoDB; diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityErrorCodes.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityErrorCodes.cs index aedec65862..4710c62f90 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityErrorCodes.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityErrorCodes.cs @@ -12,4 +12,6 @@ public static class IdentityErrorCodes public const string CanNotChangeTwoFactor = "Volo.Abp.Identity:010008"; public const string YouCannotDelegateYourself = "Volo.Abp.Identity:010009"; public const string ClaimNameExist = "Volo.Abp.Identity:010021"; + public const string CanNotUpdateStaticClaimType = "Volo.Abp.Identity:010022"; + public const string CanNotDeleteStaticClaimType = "Volo.Abp.Identity:010023"; } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ar.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ar.json index 074d02f00e..bfbd43a9d7 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ar.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ar.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "لا يجوز تغيير إعداد عاملين.", "Volo.Abp.Identity:010009": "لا يمكنك تفويض نفسك.", "Volo.Abp.Identity:010021": "الاسم {0} موجود بالفعل.", + "Volo.Abp.Identity:010022": "لا يمكن تحديث نوع المطابقة.", + "Volo.Abp.Identity:010023": "لا يمكن حذف نوع المطابقة.", "Identity.OrganizationUnit.MaxUserMembershipCount": "العدد الأقصى المسموح به لعضوية الوحدة التنظيمية للمستخدم", "ThisUserIsNotActiveMessage": "هذا المستخدم غير نشط.", "Permission:IdentityManagement": "إدارة الهوية", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "ممكّن للمستخدمين الجدد", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "مدة التأمين (بالثواني)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "محاولات الوصول الفاشلة", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "مطلوب بريد إلكتروني مؤكد", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "تمكين تأكيد رقم الهاتف", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "تتطلب رقم هاتف مؤكد", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "فرض التحقق من البريد الإلكتروني لتسجيل الدخول", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "السماح للمستخدمين بتأكيد رقم هواتفهم", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "فرض التحقق من رقم الهاتف لتسجيل الدخول", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "هل تم تمكين تحديث اسم المستخدم", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "هل تم تمكين تحديث البريد الإلكتروني", "Description:Abp.Identity.Password.RequiredLength": "يجب أن يكون الحد الأدنى لطول كلمة المرور.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "ما إذا كان يمكن قفل مستخدم جديد.", "Description:Abp.Identity.Lockout.LockoutDuration": "المدة التي يتم فيها حظر المستخدم عند حدوث قفل.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "عدد محاولات الوصول الفاشلة المسموح بها قبل قفل المستخدم ، بافتراض تمكين التأمين.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "ما إذا كان عنوان البريد الإلكتروني المؤكد مطلوبًا لتسجيل الدخول.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "ما إذا كان بإمكان المستخدم تأكيد رقم الهاتف.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "ما إذا كان رقم الهاتف المؤكد مطلوبًا لتسجيل الدخول.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "يمكن للمستخدمين إنشاء حسابات ولكن لا يمكنهم تسجيل الدخول حتى يتحققوا من عنوان بريدهم الإلكتروني.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "يمكن للمستخدمين التحقق من أرقام هواتفهم. مطلوب تكامل الرسائل القصيرة.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "يمكن للمستخدمين إنشاء حسابات ولكن لا يمكنهم تسجيل الدخول حتى يتحققوا من أرقام هواتفهم.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "ما إذا كان يمكن تحديث اسم المستخدم بواسطة المستخدم.", "Description:Abp.Identity.User.IsEmailUpdateEnabled": "ما إذا كان يمكن تحديث البريد الإلكتروني من قبل المستخدم.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "فرض التحقق من البريد الإلكتروني للتسجيل", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "لن يتم إنشاء حسابات المستخدمين ما لم يتحققوا من عناوين بريدهم الإلكتروني.", "Details": "تفاصيل", "CreatedBy": "انشأ من قبل", "ModifiedBy": "تم التعديل بواسطة", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/cs.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/cs.json index ea26d685f8..deea27dd17 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/cs.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/cs.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "Není povoleno měnit nastavení dvou faktorů.", "Volo.Abp.Identity:010009": "Nemůžete delegovat své vlastní oprávnění.", "Volo.Abp.Identity:010021": "Název '{0}' již existuje.", + "Volo.Abp.Identity:010022": "Nelze aktualizovat statický typ deklarace.", + "Volo.Abp.Identity:010023": "Nelze smazat statický typ deklarace.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Maximální povolený počet členů organizační jednotky pro uživatele", "ThisUserIsNotActiveMessage": "Tento uživatel není aktivní.", "Permission:IdentityManagement": "Správa identit", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Povoleno pro nové uživatele", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Délka blokování (sekundy)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Maximální počet neúspěšných pokusů o přístup", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Požadovat potvrzený email", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Povolit potvrzování telefonního čísla", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Požadovat potvrzené telefonní číslo", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Vyžadovat ověření e-mailu pro přihlášení", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Povolit uživatelům potvrdit jejich telefonní číslo", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Vyžadovat ověření telefonního čísla pro přihlášení", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Je povolena změna uživatelského jména", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Je povolena změna emailu", "Description:Abp.Identity.Password.RequiredLength": "Minimální délka hesla.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Zda může být uzamčen nový uživatel.", "Description:Abp.Identity.Lockout.LockoutDuration": "Doba, po kterou je uživatel zablokován, když dojde k zablokování.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Počet neúspěšných pokusů o přístup než je uživatel uzamčen, za předpokladu, že je uzamčení povoleno.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Zda je k přihlášení vyžadována potvrzená emailová adresa.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Zda telefonní číslo může být potvrzeno uživatelem.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Zda je pro přihlášení vyžadováno potvrzené telefonní číslo.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Uživatelé si mohou vytvořit účty, ale nemohou se přihlásit, dokud neověří svou e-mailovou adresu.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Uživatelé mohou ověřit svá telefonní čísla. Vyžaduje integraci SMS.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Uživatelé si mohou vytvořit účty, ale nemohou se přihlásit, dokud neověří své telefonní číslo.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Zda může uživatel změnit uživatelské jméno.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Zda může uživatel změnit email.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Zda může uživatel aktualizovat e-mail.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Vyžadovat ověření e-mailu pro registraci", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Uživatelské účty nebudou vytvořeny, dokud neověří své e-mailové adresy.", "Details": "Podrobnosti", "CreatedBy": "Vytvořil", "ModifiedBy": "Upraven", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/de.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/de.json index 56bb75d104..5987f215d7 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/de.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/de.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "Die Zwei-Faktor-Einstellung dürfen nicht geändert werden.", "Volo.Abp.Identity:010009": "Sie können sich nicht selbst delegieren.", "Volo.Abp.Identity:010021": "Der Name existiert bereits {0}", + "Volo.Abp.Identity:010022": "Der Name kann nicht aktualisiert werden.", + "Volo.Abp.Identity:010023": "Der Name kann nicht gelöscht werden.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Maximal zulässige Anzahl an Mitgliedschaften in Organisationseinheiten für einen Benutzer", "ThisUserIsNotActiveMessage": "Dieser Benutzer ist nicht aktiv.", "Permission:IdentityManagement": "Identitätsverwaltung", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Für neue Benutzer aktiviert", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Sperrdauer (Sekunden)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Max. Fehlgeschlagene Zugriffsversuche", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Bestätigte E-Mail-Adresse erforderlich", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Ermöglichen Sie Benutzern, ihre Telefonnummer zu bestätigen", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Bestätigte Telefonnummer erforderlich", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "E-Mail-Verifizierung für die Anmeldung erzwingen", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Benutzer können ihre Telefonnummer bestätigen", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Telefonverifizierung für die Anmeldung erzwingen", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Ermöglichen Sie Benutzern, ihre Benutzernamen zu ändern", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Ermöglichen Sie Benutzern, ihre E-Mail-Adressen zu ändern", "Description:Abp.Identity.Password.RequiredLength": "Die Mindestlänge, die ein Passworts aufweisen muss.", @@ -115,17 +117,19 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Gibt an, ob ein neuer Benutzer gesperrt werden kann.", "Description:Abp.Identity.Lockout.LockoutDuration": "Die Dauer, für die ein Benutzer gesperrt ist, wenn eine Sperre auftritt.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Die Anzahl der fehlgeschlagenen Zugriffsversuche, die zulässig sind, bevor ein Benutzer gesperrt wird, sofern die Sperre aktiviert ist.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Gibt an, ob eine bestätigte E-Mail-Adresse erforderlich ist, um sich anzumelden.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Gibt an, ob die Telefonnummer vom Benutzer bestätigt werden kann.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Gibt an, ob eine bestätigte Telefonnummer erforderlich ist, um sich anzumelden.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Benutzer können Konten erstellen, sich aber erst anmelden, wenn sie ihre E-Mail-Adresse verifiziert haben.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Benutzer können ihre Telefonnummern verifizieren. SMS-Integration erforderlich.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Benutzer können Konten erstellen, sich aber erst anmelden, wenn sie ihre Telefonnummer verifiziert haben.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Gibt an, ob der Benutzername vom Benutzer aktualisiert werden kann.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Gibt an, ob die E-Mail-Adresse vom Benutzer aktualisiert werden kann.", - "Details": "Einzelheiten", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Ob die E-Mail vom Benutzer aktualisiert werden kann.", + "Details": "Details", "CreatedBy": "Erstellt von", "ModifiedBy": "Angepasst von", "ModificationTime": "Änderungszeit", "PasswordUpdateTime": "Zeit der Passwortaktualisierung", "LockoutEndTime": "Endzeit der Sperrung", - "FailedAccessCount": "Anzahl der fehlgeschlagenen Zugriffe" + "FailedAccessCount": "Anzahl der fehlgeschlagenen Zugriffe", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "E-Mail-Verifizierung für die Registrierung erzwingen", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Benutzerkonten werden nicht erstellt, es sei denn, sie verifizieren ihre E-Mail-Adressen." } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/el.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/el.json index c75e1f2ce9..b3b040cb91 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/el.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/el.json @@ -76,6 +76,8 @@ "Volo.Abp.Identity:010008": "Δεν επιτρέπεται η αλλαγή της ρύθμισης δύο παραγόντων.", "Volo.Abp.Identity:010009": "Δεν μπορείτε να αναθέσετε την εξουσιοδότησή σας σε εσάς ίδιο.", "Volo.Abp.Identity:010021": "Το όνομα '{0}' υπάρχει ήδη.", + "Volo.Abp.Identity:010022": "Δεν μπορείτε να ενημερώσετε ένα στατικό τύπο δήλωσης.", + "Volo.Abp.Identity:010023": "Δεν μπορείτε να διαγράψετε ένα στατικό τύπο δήλωσης.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Μέγιστος επιτρεπόμενος αριθμός μελών μονάδας οργανισμού για έναν χρήστη", "ThisUserIsNotActiveMessage": "Αυτός ο χρήστης δεν είναι ενεργός.", "Permission:IdentityManagement": "Διαχείριση ταυτότητας", @@ -98,9 +100,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Ενεργοποιήθηκε για νέους χρήστες", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Διάρκεια κλειδώματος (δευτερόλεπτα)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Μέγιστες αποτυχημένες προσπάθειες πρόσβασης", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Απαιτείται επιβεβαιωμένο email", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Επιβολή επαλήθευσης email για σύνδεση", "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Επιτρέψτε στους χρήστες να επιβεβαιώσουν τον αριθμό τηλεφώνου τους", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Απαιτείται επιβεβαιωμένος αριθμός τηλεφώνου", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Επιβολή επαλήθευσης αριθμού τηλεφώνου για σύνδεση", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Επιτρέψτε στους χρήστες να αλλάξουν τα ονόματα χρήστη τους", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Επιτρέψτε στους χρήστες να αλλάξουν τις διευθύνσεις email τους", "Description:Abp.Identity.Password.RequiredLength": "Το ελάχιστο μήκος ενός κωδικού πρόσβασης πρέπει να είναι.", @@ -114,10 +116,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Εάν ένας νέος χρήστης μπορεί να κλειδωθεί.", "Description:Abp.Identity.Lockout.LockoutDuration": "Η διάρκεια για την οποία ένας χρήστης είναι κλειδωμένος όταν εμφανίζεται ένα κλείδωμα.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Ο αριθμός των αποτυχημένων προσπαθειών πρόσβασης που επιτρέπονται πριν από το κλείδωμα ενός χρήστη, με την προϋπόθεση ότι το κλείδωμα είναι ενεργοποιημένο.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Εάν απαιτείται επιβεβαιωμένη διεύθυνση ηλεκτρονικού ταχυδρομείου για τη σύνδεση.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Εάν ο αριθμός τηλεφώνου μπορεί να επιβεβαιωθεί από τον χρήστη.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Εάν απαιτείται επιβεβαιωμένος αριθμός τηλεφώνου για τη σύνδεση.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Οι χρήστες μπορούν να δημιουργήσουν λογαριασμούς αλλά δεν μπορούν να συνδεθούν μέχρι να επαληθεύσουν τη διεύθυνση email τους.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Οι χρήστες μπορούν να επαληθεύσουν τους αριθμούς τηλεφώνου τους. Απαιτείται ενσωμάτωση SMS.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Οι χρήστες μπορούν να δημιουργήσουν λογαριασμούς αλλά δεν μπορούν να συνδεθούν μέχρι να επαληθεύσουν τον αριθμό τηλεφώνου τους.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Εάν το όνομα χρήστη μπορεί να ενημερωθεί από τον χρήστη.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Εάν το email μπορεί να ενημερωθεί από τον χρήστη." + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Εάν το email μπορεί να ενημερωθεί από τον χρήστη.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Επιβολή επαλήθευσης email για εγγραφή", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Οι λογαριασμοί χρηστών δεν θα δημιουργηθούν εκτός αν επαληθεύσουν τις διευθύνσεις email τους.", + "Details": "Λεπτομέρειες" } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json index caa7c8691f..b7d30bb30a 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json @@ -76,6 +76,8 @@ "Volo.Abp.Identity:010008": "Changing the two factor setting is not allowed.", "Volo.Abp.Identity:010009": "You cannot delegate yourself!", "Volo.Abp.Identity:010021": "Name exist: '{0}'", + "Volo.Abp.Identity:010022": "Can not update a static ClaimType.", + "Volo.Abp.Identity:010023": "Can not delete a static ClaimType.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Maximum allowed organisation unit membership count for a user", "Permission:IdentityManagement": "Identity management", "Permission:RoleManagement": "Role management", @@ -103,9 +105,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Enabled for new users", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Lockout duration(in seconds)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Max failed access attempts", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Require confirmed email", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Require email verification for sign in", "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Allow users to confirm their phone number", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Require confirmed phone number", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Require phone number verification for sign in", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Allow users to change their usernames", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Allow users to change their email addresses", "Description:Abp.Identity.Password.RequiredLength": "The minimum length a password must be.", @@ -119,14 +121,17 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Whether a new user can be locked out.", "Description:Abp.Identity.Lockout.LockoutDuration": "The duration a user is locked out for when a lockout occurs.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "The number of failed access attempts allowed before a user is locked out, assuming lock out is enabled.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Whether a confirmed email address is required to sign in.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Whether the phoneNumber can be confirmed by the user.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Whether a confirmed telephone number is required to sign in.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Users can create accounts but cannot sign in until they verify their email address.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Users can verify their phone numbers. SMS integration required.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Users can create accounts but cannot sign in until they verify their phone number.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Whether the username can be updated by the user.", "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Whether the email can be updated by the user.", "DisplayName:Abp.Identity.TwoFactorBehaviour": "Two Factor behaviour", "Description:Abp.Identity.TwoFactorBehaviour": "Two Factor behaviour", "DisplayName:Abp.Identity.UsersCanChange": "Allow users to change their Two Factor.", - "Description:Abp.Identity.UsersCanChange": "Allow users to change their Two Factor." + "Description:Abp.Identity.UsersCanChange": "Allow users to change their Two Factor.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Enforce email verification to register", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "User accounts will not be created unless they verify their email addresses.", + "Details": "Details" } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json index ff8d8aec80..266ce50b5a 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "It's not allowed to change two factor setting.", "Volo.Abp.Identity:010009": "You can not delegate yourself.", "Volo.Abp.Identity:010021": "Name exist: '{0}'.", + "Volo.Abp.Identity:010022": "Can not update a static ClaimType.", + "Volo.Abp.Identity:010023": "Can not delete a static ClaimType.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Maximum allowed organization unit membership count for a user", "ThisUserIsNotActiveMessage": "This user is not active.", "Permission:IdentityManagement": "Identity management", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Enabled for new users", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Lockout duration(seconds)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Max failed access attempts", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Require confirmed email", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Enforce email verification to sign in", "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Allow users to confirm their phone number", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Require confirmed phone number", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Enforce phone number verification to sign in", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Allow users to change their usernames", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Allow users to change their email addresses", "Description:Abp.Identity.Password.RequiredLength": "The minimum length a password must be.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Whether a new user can be locked out.", "Description:Abp.Identity.Lockout.LockoutDuration": "The duration a user is locked out for when a lockout occurs.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "The number of failed access attempts allowed before a user is locked out, assuming lock out is enabled.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Whether a confirmed email address is required to sign in.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Whether the phoneNumber can be confirmed by the user.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Whether a confirmed telephone number is required to sign in.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Users can create accounts but cannot sign in until they verify their email address.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Users can verify their phone numbers. SMS integration required.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Users can create accounts but cannot sign in until they verify their phone numbers.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Whether the username can be updated by the user.", "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Whether the email can be updated by the user.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Enforce email verification to register", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "User accounts will not be created unless they verify their email addresses.", "Details": "Details", "CreatedBy": "Created by", "ModifiedBy": "Modified by", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json index 198e08e287..861ffe10b0 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "No está permitido cambiar la configuración de autenticación de dos pasos.", "Volo.Abp.Identity:010009": "No puedes delegar tu propia cuenta!", "Volo.Abp.Identity:010021": "Ya existe un con el nombre '{0}'", + "Volo.Abp.Identity:010022": "No se puede actualizar un tipo de reclamación estática.", + "Volo.Abp.Identity:010023": "No se puede borrar un tipo de reclamación estática.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Número máximo de unidades organizativas por usuario", "ThisUserIsNotActiveMessage": "Este usuario no está activo.", "Permission:IdentityManagement": "Gestión de identidades", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Habilitado para nuevos usuarios", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Duración del bloqueo (segundos)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Número máximo de accesos fallidos", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Confirmación de e-mail requerida", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Permitir usuarios confirmar su número de teléfono", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Requerir confirmación de número de teléfono", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Exigir verificación de correo electrónico para iniciar sesión", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Permitir a los usuarios confirmar su número de teléfono", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Exigir verificación de número de teléfono para iniciar sesión", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Permitir a los usuarios cambiar su nombre de usuario.", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Permitir usuarios cambiar sus direcciones de e-mail", "Description:Abp.Identity.Password.RequiredLength": "La mínima longitud de una contraseña debe ser.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Si un nuevo usuario puede ser bloqueado.", "Description:Abp.Identity.Lockout.LockoutDuration": "La duración del bloqueo de un usuario cuando el bloqueo ocurre.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "El número de accessos fallidos permitidos antes de que un usuario sea bloqueado, el bloqueo de usuario debe estar habilitado.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Si la confirmación de dirección de e-mail es requerida para iniciar sesión.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Si el número de teléfono puede ser confirmado por el usuario. ", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Sí un número de teléfono confirmado es requerido para iniciar sesión.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Los usuarios pueden crear cuentas pero no pueden iniciar sesión hasta que verifiquen su dirección de correo electrónico.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Los usuarios pueden verificar sus números de teléfono. Se requiere integración SMS.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Los usuarios pueden crear cuentas pero no pueden iniciar sesión hasta que verifiquen su número de teléfono.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Si el nombre de usuario puede ser actualizado por el usuario.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Si el e-mail puede ser actualizado por el usuario.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Si el correo electrónico puede ser actualizado por el usuario.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Exigir verificación de correo electrónico para registrarse", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Las cuentas de usuario no se crearán a menos que verifiquen sus direcciones de correo electrónico.", "Details": "Detalles", "CreatedBy": "Creado por", "ModifiedBy": "Modificado por", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fa.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fa.json index 187f13a210..b733dbd4eb 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fa.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fa.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "تغییر دادن تنظیمات دو مرحله ای مجاز نمی باشد.", "Volo.Abp.Identity:010009": "شما نمی توانید خودتان را معرفی کنید.", "Volo.Abp.Identity:010021": "نام {0} قبلاً استفاده گردیده است.", + "Volo.Abp.Identity:010022": "نمی توان نام نقش/وظیفه را تغییر داد.", + "Volo.Abp.Identity:010023": "نمی توان نقش/وظیفه را حذف کرد.", "Identity.OrganizationUnit.MaxUserMembershipCount": "حداکثر تعداد مجاز عضویت در یک واحد سازمان برای یک کاربر", "ThisUserIsNotActiveMessage": "این کاربر غیرفعال میباشد.", "Permission:IdentityManagement": "مدیریت هویت", @@ -126,6 +128,14 @@ "ModificationTime": "زمان اصلاح", "PasswordUpdateTime": "زمان ویرایش رمز", "LockoutEndTime": "زمان اتمام قفل", - "FailedAccessCount": "تعداد دسترسی ناموفق" + "FailedAccessCount": "تعداد دسترسی ناموفق", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "اجباری کردن تایید ایمیل برای ورود", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "به کاربران اجازه تایید شماره تلفن خود را بدهید", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "اجباری کردن تایید شماره تلفن برای ورود", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "کاربران می‌توانند حساب ایجاد کنند اما تا زمانی که آدرس ایمیل خود را تایید نکنند نمی‌توانند وارد شوند.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "کاربران می‌توانند شماره تلفن خود را تایید کنند. نیاز به یکپارچه‌سازی پیامک دارد.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "کاربران می‌توانند حساب ایجاد کنند اما تا زمانی که شماره تلفن خود را تایید نکنند نمی‌توانند وارد شوند.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "اجباری کردن تایید ایمیل برای ثبت‌نام", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "حساب‌های کاربری ایجاد نخواهند شد مگر اینکه آدرس ایمیل خود را تایید کنند." } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fi.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fi.json index f212e0d9fc..1ad2950b8e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fi.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fi.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "Kahden tekijän asetusta ei saa muuttaa.", "Volo.Abp.Identity:010009": "Et voi delegoida itseäsi.", "Volo.Abp.Identity:010021": "{0} on jo olemassa.", + "Volo.Abp.Identity:010022": "Staattista väittämätunnusta ei voi päivittää.", + "Volo.Abp.Identity:010023": "Staattista väittämätunnusta ei voi poistaa.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Suurin sallittu organisaatioyksikön jäsenmäärä käyttäjälle", "ThisUserIsNotActiveMessage": "Tämä käyttäjä ei ole aktiivinen.", "Permission:IdentityManagement": "Identiteetin hallinta", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Käytössä uusille käyttäjille", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Lukituksen kesto (sekuntia)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Max epäonnistui pääsyyrityksiä", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Vaadi vahvistettu sähköposti", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Vaadi sähköpostin vahvistus kirjautumiseen", "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Salli käyttäjien vahvistaa puhelinnumeronsa", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Vaadi vahvistettu puhelinnumero", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Vaadi puhelinnumeron vahvistus kirjautumiseen", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Salli käyttäjien vaihtaa käyttäjänimeään", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Salli käyttäjien muuttaa sähköpostiosoitteitaan", "Description:Abp.Identity.Password.RequiredLength": "Salasanan on oltava vähimmäispituus.", @@ -115,12 +117,14 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Voiko uusi käyttäjä lukita.", "Description:Abp.Identity.Lockout.LockoutDuration": "Kesto, jonka käyttäjä lukitaan, kun lukitus tapahtuu.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Ennen käyttäjän lukitsemista sallittujen epäonnistuneiden pääsyyritysten lukumäärä, olettaen, että lukitus on käytössä.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Tarvitaanko sisäänkirjautumisen yhteydessä vahvistettu sähköpostiosoite.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Voiko käyttäjä vahvistaa puhelinnumeron.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Tarvitaanko sisäänkirjautumisen yhteydessä vahvistettu puhelinnumero.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Käyttäjät voivat luoda tilejä mutta eivät voi kirjautua sisään ennen sähköpostiosoitteensa vahvistamista.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Käyttäjät voivat vahvistaa puhelinnumeronsa. SMS-integraatio vaaditaan.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Käyttäjät voivat luoda tilejä mutta eivät voi kirjautua sisään ennen puhelinnumeronsa vahvistamista.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Voiko käyttäjä päivittää käyttäjänimen?", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Voiko käyttäjä päivittää sähköpostin.", - "Details": "Yksityiskohdat", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Voiko käyttäjä päivittää sähköpostiosoitteen.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Vaadi sähköpostin vahvistus rekisteröitymiseen", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Käyttäjätilejä ei luoda, elleivät he vahvista sähköpostiosoitteitaan.", + "Details": "Tiedot", "CreatedBy": "Luonut", "ModifiedBy": "Muokannut", "ModificationTime": "Muutosaika", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fr.json index 2dc00005fd..39c5a3a71d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fr.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "Il n’est pas permis de changer deux facteurs de réglage.", "Volo.Abp.Identity:010009": "Vous ne pouvez pas vous déléguer vous-même.", "Volo.Abp.Identity:010021" : "Le nom '{0}' existe déjà.", + "Volo.Abp.Identity:010022": "Vous ne pouvez pas modifier un type de revendication statique.", + "Volo.Abp.Identity:010023": "Vous ne pouvez pas supprimer un type de revendication statique.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Nombre maximal d’adhésions autorisées à l’unité d’organisation pour un utilisateur", "ThisUserIsNotActiveMessage": "Cet utilisateur n'est pas actif.", "Permission:IdentityManagement": "Gestion de l’identité", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Activé pour les nouveaux utilisateurs", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Durée(secondes) du lock-out", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Max a échoué tentatives d’accès", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Exiger un e-mail confirmé", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Exiger la vérification de l'e-mail pour se connecter", "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Permettre aux utilisateurs de confirmer leur numéro de téléphone", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Exiger un numéro de téléphone confirmé", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Exiger la vérification du numéro de téléphone pour se connecter", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Permettre aux utilisateurs de modifier leurs noms d’utilisateur", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Permettre aux utilisateurs de modifier leurs adresses e-mail", "Description:Abp.Identity.Password.RequiredLength": "La longueur minimale d’un mot de passe doit être.", @@ -115,17 +117,19 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Si un nouvel utilisateur peut être verrouillé.", "Description:Abp.Identity.Lockout.LockoutDuration": "Durée pendant laquelle un utilisateur est verrouillé lorsqu’un lock-out se produit.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Nombre de tentatives d’accès échouées avant qu’un utilisateur ne soit verrouillé, en supposant que le verrouillage est activé.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Si une adresse e-mail confirmée est nécessaire pour se connecter.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Si le téléphoneNumber peut être confirmé par l’utilisateur.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Si un numéro de téléphone confirmé est nécessaire pour se connecter.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Les utilisateurs peuvent créer des comptes mais ne peuvent pas se connecter tant qu'ils n'ont pas vérifié leur adresse e-mail.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Les utilisateurs peuvent vérifier leurs numéros de téléphone. Intégration SMS requise.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Les utilisateurs peuvent créer des comptes mais ne peuvent pas se connecter tant qu'ils n'ont pas vérifié leur numéro de téléphone.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Si le nom d’utilisateur peut être mis à jour par l’utilisateur.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Si l’e-mail peut être mis à jour par l’utilisateur.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Si l'e-mail peut être mis à jour par l'utilisateur.", "Details": "Détails", "CreatedBy": "Créé par", "ModifiedBy": "Modifié par", "ModificationTime": "Temps de modification", "PasswordUpdateTime": "Temps de mise à jour du mot de passe", "LockoutEndTime": "Heure de fin du verrouillage", - "FailedAccessCount": "Nombre d'accès ayant échoué" + "FailedAccessCount": "Nombre d'accès ayant échoué", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Exiger la vérification de l'e-mail pour s'inscrire", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Les comptes d’utilisateurs ne seront pas créés à moins qu’ils ne vérifient leurs adresses e-mail." } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hi.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hi.json index 8f35089f94..760ae275de 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hi.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hi.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "इसे दो कारक सेटिंग बदलने की अनुमति नहीं है।", "Volo.Abp.Identity:010009": "आप अपने आप को अधिकृत नहीं कर सकते हैं!", "Volo.Abp.Identity:010021" : "नाम '{0}' पहले से ही लिया गया है।", + "Volo.Abp.Identity:010022": "स्थैतिक भूमिकाओं का नाम नहीं बदला जा सकता है।", + "Volo.Abp.Identity:010023": "स्थैतिक भूमिकाओं को हटाया नहीं जा सकता।", "Identity.OrganizationUnit.MaxUserMembershipCount": "उपयोगकर्ता के लिए अधिकतम अनुमत संगठन इकाई सदस्यता गणना", "ThisUserIsNotActiveMessage": "यह उपयोगकर्ता सक्रिय नहीं है।", "Permission:IdentityManagement": "पहचान प्रबंधन", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "नए उपयोगकर्ताओं के लिए सक्षम है", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "तालाबंदी अवधि (सेकंड)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "अधिकतम पहुँच प्रयास विफल", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "पुष्टिकरण ईमेल की आवश्यकता है", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "उपयोगकर्ताओं को अपने फ़ोन नंबर की पुष्टि करने की अनुमति दें", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "पुष्टि किए गए फ़ोन नंबर की आवश्यकता है", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "साइन इन करने के लिए ईमेल सत्यापन आवश्यक है", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "उपयोगकर्ताओं को अपना फ़ोन नंबर सत्यापित करने की अनुमति दें", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "साइन इन करने के लिए फ़ोन नंबर सत्यापन आवश्यक है", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "उपयोगकर्ताओं को अपने उपयोगकर्ता नाम बदलने की अनुमति दें", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "उपयोगकर्ताओं को अपने ईमेल पते बदलने की अनुमति दें", "Description:Abp.Identity.Password.RequiredLength": "एक पासवर्ड की लंबाई न्यूनतम होनी चाहिए।", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "क्या कोई नया उपयोगकर्ता लॉक किया जा सकता है।", "Description:Abp.Identity.Lockout.LockoutDuration": "जब लॉकआउट होता है, तो उपयोगकर्ता की अवधि लॉक हो जाती है।", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "उपयोगकर्ता द्वारा लॉक किए जाने से पहले अनुमति प्राप्त विफल प्रयासों की संख्या, यह मानकर कि लॉक आउट सक्षम है।", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "क्या साइन इन करने के लिए किसी पुष्टिकृत ईमेल पते की आवश्यकता है।", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "क्या उपयोगकर्ता द्वारा फोननंबर की पुष्टि की जा सकती है।", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "साइन इन करने के लिए एक पुष्टिकरण टेलीफोन नंबर की आवश्यकता है या नहीं।", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "उपयोगकर्ता खाते बना सकते हैं लेकिन अपना ईमेल पता सत्यापित करने तक साइन इन नहीं कर सकते।", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "उपयोगकर्ता अपने फ़ोन नंबर सत्यापित कर सकते हैं। एसएमएस एकीकरण आवश्यक है।", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "उपयोगकर्ता खाते बना सकते हैं लेकिन अपना फ़ोन नंबर सत्यापित करने तक साइन इन नहीं कर सकते।", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "उपयोगकर्ता द्वारा उपयोगकर्ता नाम अपडेट किया जा सकता है या नहीं।", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "क्या उपयोगकर्ता द्वारा ईमेल को अपडेट किया जा सकता है।", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "क्या उपयोगकर्ता द्वारा ईमेल अपडेट किया जा सकता है.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "पंजीकरण के लिए ईमेल सत्यापन अनिवार्य करें", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "उपयोगकर्ता खाते तब तक नहीं बनाए जाएंगे जब तक वे अपने ईमेल पते की पुष्टि नहीं करते हैं।", "Details": "विवरण", "CreatedBy": "के द्वारा बनाई गई", "ModifiedBy": "द्वारा संशोधित", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json index c18404d51d..5af46488f3 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json @@ -39,7 +39,7 @@ "PasswordChangedMessage": "Vaša lozinka je uspješno promijenjena.", "PersonalSettingsSavedMessage": "Vaše osobne postavke su uspješno spremljene.", "Volo.Abp.Identity:DefaultError": "Došlo je do neočekivane greške.", - "Volo.Abp.Identity:ConcurrencyFailure": "Provjera optimisti�ne paralelnosti nije uspjela. Entitet na kojem radite izmijenio je drugi korisnik. Molimo odbacite promjene i pokušajte ponovno.", + "Volo.Abp.Identity:ConcurrencyFailure": "Provjera optimistične paralelnosti nije uspjela. Entitet na kojem radite izmijenio je drugi korisnik. Molimo odbacite promjene i pokušajte ponovno.", "Volo.Abp.Identity:DuplicateEmail": "Email '{0}' je već zauzet.", "Volo.Abp.Identity:DuplicateRoleName": "Naziv uloge '{0}' već je zauzet.", "Volo.Abp.Identity:DuplicateUserName": "Korisničko ime '{0}' je već zauzeto.", @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "Ne možete promijeniti postavku dva faktora.", "Volo.Abp.Identity:010008": "Nije dopušteno mijenjati postavke dvofaktorske autentifikacije.", "Volo.Abp.Identity:010009": "Ne možete delegirati sami sebi.", - "Volo.Abp.Identity:010021" : "Naziv '{0}' već postoji.", + "Volo.Abp.Identity:010021": "Naziv '{0}' već postoji.", + "Volo.Abp.Identity:010022": "Ne možete ažurirati statički tip deklaracije.", + "Volo.Abp.Identity:010023": "Ne možete izbrisati statički tip deklaracije.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Maksimalni dopušteni broj članstva u organizacijskoj jedinici za korisnika", "ThisUserIsNotActiveMessage": "Ovaj korisnik nije aktivan.", "Permission:IdentityManagement": "Upravljanje identitetom", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Omogućeno za nove korisnike", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Trajanje zaključavanja (sekunde)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Maksimalan broj neuspjelih pokušaja pristupa", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Zahtijeva potvrđenu e-poštu", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Dopusti korisnicima da potvrde svoj telefonski broj", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Zahtijeva potvrđen telefonski broj", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Potrebna provjera e-pošte za prijavu", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Dopusti korisnicima potvrdu njihovog telefonskog broja", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Potrebna provjera telefonskog broja za prijavu", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Dopusti korisnicima promjenu korisničkih imena", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Dopustite korisnicima da mijenjaju svoje adrese e-pošte", "Description:Abp.Identity.Password.RequiredLength": "Minimalna duljina lozinke.", @@ -115,12 +117,14 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Može li se novi korisnik zaključati.", "Description:Abp.Identity.Lockout.LockoutDuration": "Trajanje koliko je korisnik zaključan kada dođe do zaključavanja.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Broj dopuštenih neuspjelih pokušaja pristupa prije nego što se korisnik zaključa, pod pretpostavkom da je zaključavanje omogućeno.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Je li za prijavu potrebna potvrđena adresa e-pošte.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Može li korisnik potvrditi telefonski broj.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Je li za prijavu potreban potvrđeni telefonski broj.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Korisnici mogu stvoriti račune, ali se ne mogu prijaviti dok ne potvrde svoju e-mail adresu.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Korisnici mogu potvrditi svoje telefonske brojeve. Potrebna je SMS integracija.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Korisnici mogu stvoriti račune, ali se ne mogu prijaviti dok ne potvrde svoj telefonski broj.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Može li korisnik ažurirati korisničko ime.", "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Može li korisnik ažurirati e-poštu.", - "Details": "pojedinosti", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Zahtijevaj verifikaciju e-pošte za registraciju", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Računi korisnika neće se stvarati ako ne potvrde svoje e-mail adrese.", + "Details": "Detalji", "CreatedBy": "Napravio", "ModifiedBy": "Izmijenio", "ModificationTime": "Vrijeme izmjene", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hu.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hu.json index 58440d13f1..4c9ee448eb 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hu.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hu.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "Nem változtathatja meg a kétlépcsős bejelentkezés beállítását.", "Volo.Abp.Identity:010008": "Kétlépcsős bejelentkezés beállítás megváltoztatása nem megengedett.", "Volo.Abp.Identity:010009": "Nem adhatja át a saját jogosultságait.", - "Volo.Abp.Identity:010021" : "'{0}' nevű már létezik.", + "Volo.Abp.Identity:010021": "'{0}' nevű már létezik.", + "Volo.Abp.Identity:010022": "Nem lehet frissíteni a statikus jogosultság típusát.", + "Volo.Abp.Identity:010023": "Nem lehet törölni a statikus jogosultság típusát.", "Identity.OrganizationUnit.MaxUserMembershipCount": "A maximálisan megengedett szervezeti egység tagsági szám egy felhasználó számára", "ThisUserIsNotActiveMessage": "Ez a felhasználó nem aktív.", "Permission:IdentityManagement": "Identitáskezelés", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Engedélyezve az új felhasználók számára", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "A zárolás időtartama (másodpercben)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Max sikertelen hozzáférési kísérlet", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Megerősített e-mail megkövetelése", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Engedje meg a felhasználóknak, hogy erősítsék meg telefonszámukat", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Meg kell erősíteni a telefonszámot", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "E-mail ellenőrzés megkövetelése a bejelentkezéshez", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Felhasználók telefonszámának megerősítésének engedélyezése", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Telefonszám ellenőrzés megkövetelése a bejelentkezéshez", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Engedje meg a felhasználóknak a felhasználónevük megváltoztatását", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Engedje meg a felhasználóknak, hogy megváltoztassák e-mail címüket", "Description:Abp.Identity.Password.RequiredLength": "A jelszó minimális hosszának meg kell lennie.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Egy új felhasználó zárolható-e.", "Description:Abp.Identity.Lockout.LockoutDuration": "Az az időtartam, amelyre a felhasználó zárolva van, amikor zárolás történik.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "A felhasználó zárolása előtt megengedett sikertelen hozzáférési kísérletek száma, feltéve, hogy a zárolás engedélyezve van.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Szükség van-e megerősített e-mail címre a bejelentkezéshez.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Meg tudja-e erősíteni a telefonszámot a felhasználó.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Szükség van-e megerősített telefonszámra a bejelentkezéshez.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "A felhasználók létrehozhatnak fiókokat, de nem jelentkezhetnek be, amíg nem erősítik meg e-mail címüket.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "A felhasználók ellenőrizhetik telefonszámukat. SMS integráció szükséges.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "A felhasználók létrehozhatnak fiókokat, de nem jelentkezhetnek be, amíg nem erősítik meg telefonszámukat.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Meg tudja e módosítani a felhasználónevet a felhasználó?.", "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Meg tudja-e módosítani az e-mail címét a felhasználó.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "E-mail ellenőrzés megkövetelése a regisztrációhoz", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Felhasználói fiókok nem lesznek létrehozva, amíg nem ellenőrzik e-mail címüket.", "Details": "Részletek", "CreatedBy": "Készítette", "ModifiedBy": "Módosította", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/is.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/is.json index 6436d4b7ed..013bce103e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/is.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/is.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "Þú getur ekki breytt tveggja þátta stillingu þinni.", "Volo.Abp.Identity:010008": "Það er ekki leyfilegt að breyta tvíþátta stillingu.", "Volo.Abp.Identity:010009": "Þú getur ekki delegað þér sjálfum.", - "Volo.Abp.Identity:010021" : "Nafnið '{0}' er þegar í notkun.", + "Volo.Abp.Identity:010021": "Nafnið '{0}' er þegar í notkun.", + "Volo.Abp.Identity:010022": "Ekki er hægt að breyta static hlutverk.", + "Volo.Abp.Identity:010023": "Ekki er hægt að eyða static hlutverkum.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Hámarks leyfileg fjöldi aðildar að skipulagseiningu fyrir notanda", "ThisUserIsNotActiveMessage": "Þessi notandi er ekki virkur.", "Permission:IdentityManagement": "Auðkenninga umsjón", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Virkt fyrir nýja notendur", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Lengd lokunar (sekúndur)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Hámarks misheppnaðra aðgangsstilrauna", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Krefjast staðfests tölvupósts", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Leyfa notendum að staðfesta símanúmerið sitt", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Krefjast staðfests símanúmers", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Krefjast staðfestingar á tölvupósti fyrir innskráningu", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Leyfa notendum að staðfesta símanúmer sitt", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Krefjast staðfestingar á símanúmeri fyrir innskráningu", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Leyfa notendum að breyta notendanöfnum sínum", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Leyfa notendum að breyta netföngum sínum", "Description:Abp.Identity.Password.RequiredLength": "Lágmarkslengd lykilorðs verður að vera.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Hvort hægt sé að læsa nýjum notanda.", "Description:Abp.Identity.Lockout.LockoutDuration": "Tímalengd þess að notandi er læstur úti þegar lokun á sér stað.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Fjöldi misheppnaðra aðgangstilrauna sem leyfður er áður en notandi er læstur út, að því gefnu að útilokun sé virk.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Hvort nauðsynlegt sé að staðfesta netfang með pósti til að geta skráð þig inn.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Hvort notandinn getur staðfest símanúmerið.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Hvort nauðsynlegt sé að staðfesta símanúmer til að geta skrá sig inn.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Notendur geta búið til reikninga en geta ekki skráð sig inn fyrr en þeir staðfesta netfangið sitt.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Notendur geta staðfest símanúmer sín. SMS samþætting nauðsynleg.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Notendur geta búið til reikninga en geta ekki skráð sig inn fyrr en þeir staðfesta símanúmerið sitt.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Hvort notandi geti uppfært notanda nafnið sitt.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Hvort notandinn getur uppfært tölvupóstfangið sitt.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Hvort notandi geti uppfært netfangið.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Krefjast staðfestingar á netfangi fyrir skráningu", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Notendareikningar verða ekki búnir til nema þeir staðfesti netfangið sitt.", "Details": "Upplýsingar", "CreatedBy": "Búið til af", "ModifiedBy": "Breytt af", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/it.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/it.json index af8dc46329..00d5c139b9 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/it.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/it.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "Non puoi modificare l'impostazione dei due fattori.", "Volo.Abp.Identity:010008": "Non è consentito modificare l'impostazione a due fattori.", "Volo.Abp.Identity:010009": "Non puoi delegare te stesso.", - "Volo.Abp.Identity:010021" : "Il nome '{0}' è già in uso.", + "Volo.Abp.Identity:010021": "Il nome '{0}' è già in uso.", + "Volo.Abp.Identity:010022": "Non puoi modificare il tipo di richiesta statica.", + "Volo.Abp.Identity:010023": "Non puoi eliminare il tipo di richiesta statica.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Numero massimo consentito di membri dell'unità organizzativa per un utente", "ThisUserIsNotActiveMessage": "Questo utente non è attivo.", "Permission:IdentityManagement": "Gestione identità", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Abilitato per i nuovi utenti", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Durata blocco (secondi)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Numero massimo di tentativi di accesso non riusciti", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Richiedi email confermata", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Consenti agli utenti di confermare il proprio numero di telefono", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Richiedi un numero di telefono confermato", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Richiedi verifica email per accedere", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Consenti agli utenti di confermare il loro numero di telefono", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Richiedi verifica numero di telefono per accedere", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Consenti agli utenti di Modifica i propri nomi utente", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Consenti agli utenti di Modifica i propri indirizzi email", "Description:Abp.Identity.Password.RequiredLength": "La lunghezza minima di caratteri della password.", @@ -115,9 +117,9 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Se un nuovo utente può essere bloccato.", "Description:Abp.Identity.Lockout.LockoutDuration": "La durata per cui un utente viene bloccato quando si verifica un blocco.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Il numero di tentativi di accesso non riusciti consentiti prima che un utente venga bloccato, a condizione che il blocco sia abilitato.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Indica se è necessario un indirizzo email confermato per accedere.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Se il numero di telefono può essere confermato dall'utente.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Indica se è necessario un numero di telefono confermato per accedere.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Gli utenti possono creare account ma non possono accedere finché non verificano il loro indirizzo email.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Gli utenti possono verificare i loro numeri di telefono. Richiesta integrazione SMS.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Gli utenti possono creare account ma non possono accedere finché non verificano il loro numero di telefono.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Se il nome utente può essere aggiornato dall'utente.", "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Se l'email può essere aggiornata dall'utente.", "Details": "Dettagli", @@ -126,6 +128,8 @@ "ModificationTime": "Tempo di modifica", "PasswordUpdateTime": "Orario di aggiornamento della password", "LockoutEndTime": "Ora di fine del blocco", - "FailedAccessCount": "Conteggio accessi non riusciti" + "FailedAccessCount": "Conteggio accessi non riusciti", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Richiedi verifica email per la registrazione", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Gli account utente non verranno creati a meno che non verifichino i loro indirizzi email." } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/nl.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/nl.json index 9304c85fbf..f7fab35933 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/nl.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/nl.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "U kunt uw instelling voor tweefactor authenticatie niet wijzigen.", "Volo.Abp.Identity:010008": "Het is niet toegestaan om de instelling van tweefactor authenticatie te wijzigen.", "Volo.Abp.Identity:010009": "U kunt uzelf niet delegeren.", - "Volo.Abp.Identity:010021" : "Er bestaat al een met de naam '{0}'.", + "Volo.Abp.Identity:010021": "Er bestaat al een met de naam '{0}'.", + "Volo.Abp.Identity:010022": "Kan de naam van een statische claim niet wijzigen.", + "Volo.Abp.Identity:010023": "Kan de naam van een statische claim niet verwijderen.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Maximaal toegestande aantal lidmaatschappen van organisatie-eenheden voor een gebruiker", "ThisUserIsNotActiveMessage": "Deze gebruiker is niet actief.", "Permission:IdentityManagement": "Identiteitsbeheer", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Ingeschakeld voor nieuwe gebruikers", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Blokkeringsduur (seconden)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Max mislukte toegangspogingen", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Vereist bevestigde e-mail", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Schakel telefoonnummerbevestiging in", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Vereist bevestigd telefoonnummer", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "E-mailverificatie vereist voor inloggen", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Sta gebruikers toe hun telefoonnummer te bevestigen", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Telefoonnummerverificatie vereist voor inloggen", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Is gebruikersnaam aktualisering ingeschakeld", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Is e-mail aktualisering ingeschakeld", "Description:Abp.Identity.Password.RequiredLength": "De minimale lengte die een wachtwoord moet hebben.", @@ -115,17 +117,19 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Of een nieuwe gebruiker kan worden geblokkeerd.", "Description:Abp.Identity.Lockout.LockoutDuration": "De duur dat een gebruiker wordt geblokkeerd wanneer een blokkering optreedt.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Het aantal mislukte toegangspogingen dat is toegestaan voordat een gebruiker wordt geblokkeerd, ervan uitgaande dat blokkering is ingeschakeld.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Of een bevestigd e-mail adres vereist is om in te loggen.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Of het telefoonnummer kan worden bevestigd door de gebruiker.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Of een bevestigd telefoonnummer vereist is om in te loggen.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Gebruikers kunnen accounts aanmaken maar kunnen niet inloggen totdat ze hun e-mailadres hebben geverifieerd.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Gebruikers kunnen hun telefoonnummers verifiëren. SMS-integratie vereist.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Gebruikers kunnen accounts aanmaken maar kunnen niet inloggen totdat ze hun telefoonnummer hebben geverifieerd.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Of de gebruikersnaam kan worden bijgewerkt door de gebruiker.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Of de e-mail door de gebruiker kan worden veranderd.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Of het e-mailadres door de gebruiker kan worden bijgewerkt.", "Details": "Details", "CreatedBy": "Gemaakt door", "ModifiedBy": "Aangepast door", "ModificationTime": "Wijzigingstijd", "PasswordUpdateTime": "Tijd voor het bijwerken van het wachtwoord", "LockoutEndTime": "Eindtijd uitsluiting", - "FailedAccessCount": "Aantal mislukte toegangen" + "FailedAccessCount": "Aantal mislukte toegangen", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "E-mailverificatie vereisen voor registratie", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Gebruikersaccounts worden niet aangemaakt tenzij ze hun e-mailadressen verifiëren." } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pl-PL.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pl-PL.json index 54984c8656..8d794777ee 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pl-PL.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pl-PL.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "Nie możesz zmienić ustawienia dwóch czynników.", "Volo.Abp.Identity:010008": "Nie wolno zmieniać ustawienia dwuczynnikowego.", "Volo.Abp.Identity:010009": "Nie możesz delegować swoich uprawnień.", - "Volo.Abp.Identity:010021" : "Nazwa '{0}' już istnieje.", + "Volo.Abp.Identity:010021": "Nazwa '{0}' już istnieje.", + "Volo.Abp.Identity:010022": "Nie można zmienić typu statycznej deklaracji.", + "Volo.Abp.Identity:010023": "Nie można usunąć typu statycznej deklaracji.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Maksymalna dozwolona liczba członków jednostki organizacyjnej dla użytkownika", "ThisUserIsNotActiveMessage": "Ten użytkownik nie jest aktywny.", "Permission:IdentityManagement": "Zarządzanie tożsamością", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Włączone dla nowych użytkowników", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Czas trwania blokady (sekundy)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Maksymalna liczba nieudanych prób dostępu", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Wymagaj potwierdzonego adresu e-mail", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Zezwalaj użytkownikom na potwierdzanie ich numeru telefonu", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Wymagaj potwierdzonego numeru telefonu", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Wymagaj weryfikacji e-mail do logowania", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Pozwól użytkownikom potwierdzić ich numer telefonu", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Wymagaj weryfikacji numeru telefonu do logowania", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Zezwalaj użytkownikom na zmianę nazwy użytkownika", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Zezwalaj użytkownikom na zmianę ich adresów e-mail", "Description:Abp.Identity.Password.RequiredLength": "Minimalna długość hasła.", @@ -115,17 +117,19 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Czy można zablokować nowego użytkownika.", "Description:Abp.Identity.Lockout.LockoutDuration": "Czas, na jaki użytkownik jest zablokowany, gdy nastąpi blokada.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Liczba nieudanych prób dostępu dopuszczonych przed zablokowaniem użytkownika, przy założeniu, że blokada jest włączona.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Czy do zalogowania jest wymagany potwierdzony adres e-mail.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Czy numer telefonu może być potwierdzony przez użytkownika.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Czy do zalogowania jest wymagany potwierdzony numer telefonu.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Użytkownicy mogą tworzyć konta, ale nie mogą się zalogować, dopóki nie zweryfikują swojego adresu e-mail.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Użytkownicy mogą weryfikować swoje numery telefonów. Wymagana integracja SMS.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Użytkownicy mogą tworzyć konta, ale nie mogą się zalogować, dopóki nie zweryfikują swojego numeru telefonu.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Czy nazwa użytkownika może być aktualizowana przez użytkownika.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Czy wiadomość e-mail może zostać zaktualizowana przez użytkownika.", - "Details": "Detale", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Czy adres e-mail może być aktualizowany przez użytkownika.", + "Details": "Szczegóły", "CreatedBy": "Stworzone przez", "ModifiedBy": "Modyfikowane przez", "ModificationTime": "Czas modyfikacji", "PasswordUpdateTime": "Czas aktualizacji hasła", "LockoutEndTime": "Czas zakończenia blokady", - "FailedAccessCount": "Liczba nieudanych dostępów" + "FailedAccessCount": "Liczba nieudanych dostępów", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Wymagaj weryfikacji e-mail do rejestracji", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Konta użytkowników nie zostaną utworzone, dopóki nie zweryfikują swoich adresów e-mail." } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json index fedeeab54c..b8c4a0fdb7 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "Você não pode alterar sua configuração de dois fatores.", "Volo.Abp.Identity:010008": "Não é permitido alterar a configuração de dois fatores.", "Volo.Abp.Identity:010009": "Você não pode delegar a si mesmo.", - "Volo.Abp.Identity:010021" : "Já existe um(a) {0} com o nome.", + "Volo.Abp.Identity:010021": "Já existe um(a) {0} com o nome.", + "Volo.Abp.Identity:010022": "Não é possível alterar o tipo de declaração estática.", + "Volo.Abp.Identity:010023": "Não é possível excluir o tipo de declaração estática.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Contagem máxima permitida de membros da unidade organizacional para um usuário", "ThisUserIsNotActiveMessage": "Este usuário não está ativo.", "Permission:IdentityManagement": "Acessos", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Habilitado para novos usuários", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Duração do bloqueio (segundos)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Máximo de tentativas de acesso malsucedidas", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Exigir e-mail confirmado", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Exigir verificação de e-mail para fazer login", "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Permitir que os usuários confirmem seu número de telefone", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Exigir número de telefone confirmado", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Exigir verificação de número de telefone para fazer login", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Permitir que os usuários alterem seus nomes de usuário", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Permitir que os usuários alterem seus endereços de e-mail", "Description:Abp.Identity.Password.RequiredLength": "O comprimento mínimo que uma senha deve ter.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Se um novo usuário pode ser bloqueado.", "Description:Abp.Identity.Lockout.LockoutDuration": "A duração que um usuário fica bloqueado quando ocorre um bloqueio.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "O número de tentativas de acesso malsucedidas permitidas antes que um usuário seja bloqueado, assumindo que o bloqueio esteja habilitado.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Se um endereço de e-mail confirmado é necessário para fazer login.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Se o número de telefone pode ser confirmado pelo usuário.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Se um número de telefone confirmado é necessário para fazer login.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Os usuários podem criar contas mas não podem fazer login até verificarem seu endereço de e-mail.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Os usuários podem verificar seus números de telefone. Integração SMS necessária.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Os usuários podem criar contas mas não podem fazer login até verificarem seu número de telefone.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Se o nome de usuário pode ser atualizado pelo usuário.", "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Se o e-mail pode ser atualizado pelo usuário.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Exigir verificação de e-mail para registro", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "As contas de usuário não serão criadas a menos que verifiquem seus endereços de e-mail.", "Details": "Detalhes", "CreatedBy": "Criado por", "ModifiedBy": "Modificado por", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json index d3fdce6f0a..2cde7af570 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "Nu vă puteţi schimba setările de autentificare în doi paşi.", "Volo.Abp.Identity:010008": "Nu este permisă modificarea setărilor autentificării în doi paşi.", "Volo.Abp.Identity:010009": "Nu vă puteţi delega singur.", - "Volo.Abp.Identity:010021" : "Numele '{0}' este deja luat.", + "Volo.Abp.Identity:010021": "Numele '{0}' este deja luat.", + "Volo.Abp.Identity:010022": "Nu poate fi schimbată tipul de declaraţie statică.", + "Volo.Abp.Identity:010023": "Nu poate fi ştersă declaraţia statică.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Numărul maxim de unităţi organizaţionale permise pentru un utilizator", "ThisUserIsNotActiveMessage": "Acest utilizator nu este activ.", "Permission:IdentityManagement": "Administrare identităţii", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Activat pentru noi utilizatori", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Durata blocării (secunde)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Numărul maxim de încercări de acces eşuate", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Solicită email confirmat", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Permite utilizatorilor să îşi confirme numărul de telefon", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Solicită număr de telefon confirmat", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Solicită verificarea e-mailului pentru autentificare", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Permite utilizatorilor să confirme numărul lor de telefon", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Solicită verificarea numărului de telefon pentru autentificare", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Permite utilizatorilor să îşi schimbe numele de utilizator", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Permite utilizatorilor să îşi schimbe adresa de email", "Description:Abp.Identity.Password.RequiredLength": "Lungimea minimă a parolei.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Dacă un utilizator nou poate fi blocat.", "Description:Abp.Identity.Lockout.LockoutDuration": "Durata blocării unui utilizator când intervine blocarea.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Numărul de accesări eşuate permise înainte de a bloca un utilizator, presupunând că blocarea este activată.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Dacă o adresă de email confirmată este obligatorie pentru autentificare.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Dacă numărul de telefon poate fi confirmată de către utilizator.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Dacă un număr de telefon confirmat este oblicatoriu pentru autentificare.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Utilizatorii pot crea conturi dar nu se pot autentifica până nu își verifică adresa de e-mail.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Utilizatorii își pot verifica numerele de telefon. Este necesară integrarea SMS.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Utilizatorii pot crea conturi dar nu se pot autentifica până nu își verifică numărul de telefon.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Dacă numele de utilizator poate fi actualizat de către utilizator.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Dacă emailul poate fi actualizat de către utilizator.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Dacă e-mailul poate fi actualizat de către utilizator.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Impune verificarea e-mailului pentru înregistrare", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Conturile de utilizator nu vor fi create decât dacă își verifică adresele de e-mail.", "Details": "Detalii", "CreatedBy": "Creat de", "ModifiedBy": "Modificat de", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json index 1120c67d35..8345df27b8 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "Вы не можете изменить настройку двух факторов.", "Volo.Abp.Identity:010008": "Изменение двухфакторной настройки не допускается.", "Volo.Abp.Identity:010009": "Вы не можете делегировать свои собственные права.", - "Volo.Abp.Identity:010021" : "Имя '{0}' уже существует.", + "Volo.Abp.Identity:010021": "Имя '{0}' уже существует.", + "Volo.Abp.Identity:010022": "Невозможно изменить тип статической декларации.", + "Volo.Abp.Identity:010023": "Невозможно удалить тип статической декларации.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Максимально допустимое количество членов организационного подразделения для пользователя", "ThisUserIsNotActiveMessage": "Этот пользователь не активен.", "Permission:IdentityManagement": "Управление идентификацией", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Включено для новых пользователей", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Длительность блокировки (секунды)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Максимальное количество неудачных попыток доступа", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Требуется подтверждение электронной почты", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Требовать подтверждение электронной почты для входа", "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Разрешить пользователям подтверждать свой номер телефона", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Требуется подтверждение номера телефона", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Требовать подтверждение номера телефона для входа", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Пользователь может изменять имя", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Электронная почта может быть изменена", "Description:Abp.Identity.Password.RequiredLength": "Минимальная длина пароля.", @@ -115,17 +117,19 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Может ли новый пользователь быть заблокирован.", "Description:Abp.Identity.Lockout.LockoutDuration": "Длительность блокировки пользователя.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Число неудачных попыток доступа, после которых пользователь будет заблокирован.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Требуется ли для входа подтвержденный адрес электронной почты.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Может ли пользователь подтвердить phoneNumber.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Требуется ли для входа в систему подтвержденный номер телефона.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Пользователи могут создавать учетные записи, но не могут войти в систему, пока не подтвердят свой адрес электронной почты.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Пользователи могут подтверждать свои номера телефонов. Требуется интеграция SMS.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Пользователи могут создавать учетные записи, но не могут войти в систему, пока не подтвердят свой номер телефона.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Может ли пользователь обновить имя пользователя.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Может ли электронная почта быть обновлена пользователем.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Может ли пользователь обновить адрес электронной почты.", "Details": "Подробности", "CreatedBy": "Сделано", "ModifiedBy": "Модифицирован", "ModificationTime": "Время модификации", "PasswordUpdateTime": "Время обновления пароля", "LockoutEndTime": "Время окончания блокировки", - "FailedAccessCount": "Количество неудачных попыток доступа" + "FailedAccessCount": "Количество неудачных попыток доступа", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Требовать подтверждение электронной почты для регистрации", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Учетные записи пользователей не будут созданы, пока они не подтвердят свои адреса электронной почты." } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sk.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sk.json index 7e5eb79096..d9fa8dbf61 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sk.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sk.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "Dvojfaktorové nastavenie nie je možné zmeniť.", "Volo.Abp.Identity:010008": "Dvojfaktorové nastavenie nie je povolené zmeniť.", "Volo.Abp.Identity:010009": "Nemôžete delegovať svoje vlastné oprávnenia.", - "Volo.Abp.Identity:010021" : "Názov '{0}' sa už používa.", + "Volo.Abp.Identity:010021": "Názov '{0}' sa už používa.", + "Volo.Abp.Identity:010022": "Nie je možné zmeniť typ statického oprávnenia.", + "Volo.Abp.Identity:010023": "Nie je možné odstrániť typ statického oprávnenia.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Maximálny povolený počet členov organizačnej jednotky pre používateľa", "ThisUserIsNotActiveMessage": "Tento používateľ nie je aktívny.", "Permission:IdentityManagement": "Správa identít", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Povolené pre nových používateľov", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Trvanie uzamknutia (v sekundách)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Maximálny počet neúspešných pokusov o prístup", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Vyžadovať potvrdenie emailu", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Umožniť používateľom potvrdiť svoje telefónne číslo", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Vyžadovať potvrdenie telefónneho čísla", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Vyžadovať overenie e-mailu pre prihlásenie", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Povoliť používateľom potvrdiť ich telefónne číslo", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Vyžadovať overenie telefónneho čísla pre prihlásenie", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Umožniť používateľom zmeniť svoje používateľské meno", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Umožniť používateľom zmeniť emailovú adresu", "Description:Abp.Identity.Password.RequiredLength": "Minimálna dĺžka, ktorú musí mať heslo.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Či môže byť nový používateľ uzamknutý.", "Description:Abp.Identity.Lockout.LockoutDuration": "Doba, počas ktorej je používateľ uzamknutý, keď dôjde k uzamknutiu.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Počet neúspešných pokusov o prístup pred tým, ako bol používateľ uzamknutý za predpokladu, že je uzamknutie povolené.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Či sa na prihlásenie vyžaduje potvrdená emailová adresa.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Či môže používateľ potvrdiť telefónne číslo.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Či sa na prihlásenie vyžaduje potvrdené telefónne číslo.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Používatelia môžu vytvárať účty, ale nemôžu sa prihlásiť, kým neoveria svoju e-mailovú adresu.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Používatelia môžu overiť svoje telefónne čísla. Vyžaduje sa SMS integrácia.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Používatelia môžu vytvárať účty, ale nemôžu sa prihlásiť, kým neoveria svoje telefónne číslo.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Či môže používateľ aktualizovať používateľské meno.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Či môže používateľ aktualizovať email.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Či používateľ môže aktualizovať e-mail.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Vyžadovať overenie e-mailu pre registráciu", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Používateľské účty nebudú vytvorené, pokiaľ neoveria svoje e-mailové adresy.", "Details": "Podrobnosti", "CreatedBy": "Vytvoril", "ModifiedBy": "Upravené používateľom", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sl.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sl.json index 17ad0dd8db..b6d505c1c3 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sl.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sl.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "Ni dovoljeno spreminjati nastavitve dveh faktorjev.", "Volo.Abp.Identity:010009": "Ne morete delegirati svojih pravic.", "Volo.Abp.Identity:010021" : "Naziv '{0}' že obstaja.", + "Volo.Abp.Identity:010022": "Ne morete spremeniti tipa statične deklaracije.", + "Volo.Abp.Identity:010023": "Ne morete izbrisati tipa statične deklaracije.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Največje dovoljeno število članov v organizacijski enoti za uporabnika", "ThisUserIsNotActiveMessage": "Ta uporabnik ni aktiven.", "Permission:IdentityManagement": "Upravljanje identitet", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Omogočeno za nove uporabnike", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Trajanje zaklepa(sekund)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Največje število neuspešnih poskusov dostopa", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Zahtevan potrjen e-poštni naslov", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Dovoli uporabnikom, da potrdijo svojo telefonsko številko", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Zahtevana potrjena telefonska številka", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Zahtevaj preverjanje e-pošte za prijavo", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Dovoli uporabnikom potrditi njihovo telefonsko številko", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Zahtevaj preverjanje telefonske številke za prijavo", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Omogočena posodobitev uporabniškega imena", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Omogočena posodobitev e-poštnega naslova", "Description:Abp.Identity.Password.RequiredLength": "Najkrajša dolžina gesla mora biti.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Ali se nov uporabnik lahko zaklene.", "Description:Abp.Identity.Lockout.LockoutDuration": "Trajanje zaklepa uporabnika, ko pride do zaklepa.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Število neuspelih poskusov dostopa ki so dovoljeni, preden se uporabnik zaklene, ob predpostavki, da je zaklepanje omogočeno.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Ali je za prijavo potreben potrjeni e-poštni naslov.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Ali lahko uporabnik potrdi telefonsko številko.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Ali je za prijavo potrebna potrjena telefonska številka.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Uporabniki lahko ustvarijo račune, vendar se ne morejo prijaviti, dokler ne preverijo svojega e-poštnega naslova.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Uporabniki lahko preverijo svoje telefonske številke. Potrebna je integracija SMS.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Uporabniki lahko ustvarijo račune, vendar se ne morejo prijaviti, dokler ne preverijo svoje telefonske številke.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Ali lahko uporabnik posodobi uporabniško ime.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Ali lahko uporabnik posodobi e-poštni naslov.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Ali lahko uporabnik posodobi e-pošto.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Zahtevaj preverjanje e-pošte za registracijo", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Uporabniški računi ne bodo ustvarjeni, dokler ne preverijo svojih e-poštnih naslovov.", "Details": "Podrobnosti", "CreatedBy": "Ustvaril", "ModifiedBy": "Spremenil", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sv.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sv.json index e6acc9d7dd..e664adbbfe 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sv.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sv.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "Det är inte tillåtet att ändra inställningen för två faktorer.", "Volo.Abp.Identity:010009": "Du kan inte delegera dig själv.", "Volo.Abp.Identity:010021": "Namn finns: '{0}'.", + "Volo.Abp.Identity:010022": "Kan inte ändra statiskt område.", + "Volo.Abp.Identity:010023": "Kan inte ta bort statiskt område.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Högsta tillåtna antal medlemskap i organisationsenheter för en användare", "ThisUserIsNotActiveMessage": "Den här användaren är inte aktiv.", "Permission:IdentityManagement": "Identitetshantering", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Aktiverad för nya användare", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Varaktighet för låsning (sekunder)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Max misslyckade åtkomstförsök", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Kräver bekräftad e-post", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Kräv e-postverifiering för inloggning", "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Tillåt användare att bekräfta sitt telefonnummer", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Kräver bekräftat telefonnummer", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Kräv telefonverifiering för inloggning", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Tillåt användare att ändra sina användarnamn", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Tillåt användare att ändra sina e-postadresser", "Description:Abp.Identity.Password.RequiredLength": "Den minsta längd som ett lösenord måste ha.", @@ -115,11 +117,13 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Om en ny användare kan låsas ute.", "Description:Abp.Identity.Lockout.LockoutDuration": "Den tid som en användare är utelåst när en utelåsning inträffar.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Det antal misslyckade åtkomstförsök som tillåts innan en användare låses ut, förutsatt att låsning är aktiverad.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Om det krävs en bekräftad e-postadress för att logga in.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Huruvida phoneNumber kan bekräftas av användaren.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Om det krävs ett bekräftat telefonnummer för att logga in.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Användare kan skapa konton men kan inte logga in förrän de verifierar sin e-postadress.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Användare kan verifiera sina telefonnummer. SMS-integration krävs.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Användare kan skapa konton men kan inte logga in förrän de verifierar sitt telefonnummer.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Om användarnamnet kan uppdateras av användaren.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Om e-postmeddelandet kan uppdateras av användaren.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Om e-postadressen kan uppdateras av användaren.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Kräv e-postverifiering för registrering", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Användarkonton kommer inte att skapas om de inte verifierar sina e-postadresser.", "Details": "Detaljer", "CreatedBy": "Skapad av", "ModifiedBy": "Ändrad av", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json index b2e08d2b4c..72b232de4e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "İki faktörlü ayarınızı değiştiremezsiniz.", "Volo.Abp.Identity:010008": "İki faktörlü ayarın değiştirilmesine izin verilmez.", "Volo.Abp.Identity:010009": "Kendinizi yetkilendiremezsiniz.", - "Volo.Abp.Identity:010021" : "{0} isminde bir birim zaten var.", + "Volo.Abp.Identity:010021": "{0} isminde bir birim zaten var.", + "Volo.Abp.Identity:010022": "Bir statik izin tipi değiştirilemez.", + "Volo.Abp.Identity:010023": "Bir statik izin tipi silinemez.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Bir kullanıcı için izin verilen en fazla organizasyon birimi sayısı", "ThisUserIsNotActiveMessage": "Bu kullanıcı aktif değil.", "Permission:IdentityManagement": "Kimlik yönetimi", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Yeni kullanıcılar için aktif", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Kilitli kalma süresi (saniye)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Maksimum başarısız giriş denemesi", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Onaylı e-posta gerekli", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Telefon numarası onayını etkin", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Onaylı telefon numarası gerekli", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Giriş için e-posta doğrulaması gerekli", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Kullanıcıların telefon numaralarını doğrulamasına izin ver", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Giriş için telefon numarası doğrulaması gerekli", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Kullanıcı adı güncellenebilir", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "E-posta güncellenebilir", "Description:Abp.Identity.Password.RequiredLength": "Minimum parola uzunluğu.", @@ -115,17 +117,19 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Yeni kullanıcılar kilitlenebilir.", "Description:Abp.Identity.Lockout.LockoutDuration": "Kilitlenme olduğunda, ne kadar kilitli kalacağı.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Kilitleme etkin olduğunda, kullanıcıya kilitlenmeden önce izin verilen başarısız giriş sayısı.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Oturum açmak için onaylanmış bir e-posta adresinin gerekli olup olmadığı.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Oturum açmak için telefon numarası gerekli", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Oturum açmak için onaylanmış bir telefon numarasının gerekli olup olmadığı.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Kullanıcılar hesap oluşturabilir ancak e-posta adreslerini doğrulayana kadar giriş yapamazlar.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Kullanıcılar telefon numaralarını doğrulayabilir. SMS entegrasyonu gereklidir.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Kullanıcılar hesap oluşturabilir ancak telefon numaralarını doğrulayana kadar giriş yapamazlar.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Kullanıcı adının, kullanıcının kendisi tarafından güncellenebilirliği.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "E-posta alanının, kullanıcının kendisi tarafından güncellenebilirliği", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "E-posta kullanıcı tarafından güncellenebilir mi.", "Details": "Detaylar", "CreatedBy": "Oluşturan", "ModifiedBy": "Düzenleyen", "ModificationTime": "Düzenleme zamanı", "PasswordUpdateTime": "Şifre güncelleme zamanı", "LockoutEndTime": "Kilitlenme bitiş zamanı", - "FailedAccessCount": "Başarısız giriş denemesi sayısı" + "FailedAccessCount": "Başarısız giriş denemesi sayısı", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Kayıt için e-posta doğrulaması zorunlu kıl", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Kullanıcı hesapları, e-posta adreslerini doğrulamadıkça oluşturulmayacaktır." } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/vi.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/vi.json index ba9a8365f9..39f9940090 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/vi.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/vi.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "Không được phép thay đổi cài đặt hai yếu tố.", "Volo.Abp.Identity:010009": "Bạn không thể ủy quyền cho chính mình.", "Volo.Abp.Identity:010021": "Tên '{0}' đã tồn tại.", + "Volo.Abp.Identity:010022": "Không thể thay đổi kiểu của phát biểu tĩnh.", + "Volo.Abp.Identity:010023": "Không thể xóa phát biểu tĩnh.", "Identity.OrganizationUnit.MaxUserMembershipCount": "Số lượng thành viên đơn vị tổ chức tối đa được phép cho một người dùng", "ThisUserIsNotActiveMessage": "Người dùng này không hoạt động.", "Permission:IdentityManagement": "Quản lý danh tính", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Đã bật cho người dùng mới", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Thời gian khóa (giây)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Số lần truy cập không thành công tối đa", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Yêu cầu email đã xác nhận", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Yêu cầu xác minh email để đăng nhập", "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Cho phép người dùng xác nhận số điện thoại của họ", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Yêu cầu số điện thoại đã xác nhận", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Yêu cầu xác minh số điện thoại để đăng nhập", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Cho phép người dùng thay đổi tên người dùng của họ", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Cho phép người dùng thay đổi địa chỉ email của họ", "Description:Abp.Identity.Password.RequiredLength": "Độ dài tối thiểu của mật khẩu phải là.", @@ -115,17 +117,19 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Người dùng mới có thể bị khóa hay không.", "Description:Abp.Identity.Lockout.LockoutDuration": "Khoảng thời gian người dùng bị khóa khi xảy ra quá trình khóa.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Số lần truy cập không thành công được phép trước khi người dùng bị khóa, giả sử tính năng khóa được bật.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Địa chỉ email được xác nhận có được yêu cầu để đăng nhập hay không.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Người dùng có thể xác nhận số điện thoại hay không.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Liệu một số điện thoại được xác nhận có được yêu cầu để đăng nhập hay không.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Người dùng có thể tạo tài khoản nhưng không thể đăng nhập cho đến khi xác minh địa chỉ email của họ.", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Người dùng có thể xác minh số điện thoại của họ. Yêu cầu tích hợp SMS.", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Người dùng có thể tạo tài khoản nhưng không thể đăng nhập cho đến khi xác minh số điện thoại của họ.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Người dùng có thể cập nhật tên người dùng hay không.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Người dùng có thể cập nhật email hay không.", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Liệu email có thể được cập nhật bởi người dùng hay không.", "Details": "Chi tiết", "CreatedBy": "Được tạo bởi", "ModifiedBy": "Được sửa đổi bởi", "ModificationTime": "Thời gian sửa đổi", "PasswordUpdateTime": "Thời gian cập nhật mật khẩu", "LockoutEndTime": "Thời gian kết thúc khóa", - "FailedAccessCount": "Số lượt truy cập không thành công" + "FailedAccessCount": "Số lượt truy cập không thành công", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Yêu cầu xác minh email để đăng ký", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "Tài khoản người dùng sẽ không được tạo ra trừ khi họ xác minh địa chỉ email của mình." } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json index f9f9f77607..cfbe6bd279 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json @@ -77,6 +77,8 @@ "Volo.Abp.Identity:010008": "不允许修改双因素身份验证设置。", "Volo.Abp.Identity:010009": "你不能委托给自己。", "Volo.Abp.Identity:010021": "名称:'{0}' 已存在", + "Volo.Abp.Identity:010022": "不能更改静态声明的类型。", + "Volo.Abp.Identity:010023": "不能删除静态声明的类型。", "Identity.OrganizationUnit.MaxUserMembershipCount": "组织单位最大允许的成员资格计数", "ThisUserIsNotActiveMessage": "该用户不可用。", "Permission:IdentityManagement": "身份标识管理", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "允许新用户", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "锁定时间(秒)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "最大失败访问尝试次数", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "要求验证的电子邮箱", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "允许用户确认他们的电话号码", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "要求验证的手机号码", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "登录需要验证邮箱", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "允许用户验证手机号码", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "登录需要验证手机号码", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "启用用户名更新", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "启用电子邮箱更新", "Description:Abp.Identity.Password.RequiredLength": "密码的最小长度。", @@ -115,12 +117,14 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "允许新用户被锁定。", "Description:Abp.Identity.Lockout.LockoutDuration": "当锁定发生时用户被的锁定的时间(秒)。", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "如果启用锁定, 当用户被锁定前失败的访问尝试次数。", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "登录时是否需要验证的电子邮箱。", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "用户是否可以确认电话号码", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "登录时是否需要验证的手机号码。", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "用户可以创建账户但在验证邮箱地址之前无法登录。", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "用户可以验证他们的手机号码。需要短信集成。", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "用户可以创建账户但在验证手机号码之前无法登录。", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "是否允许用户更新用户名。", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "是否允许用户更新电子邮箱。", - "Details": "详情", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "用户是否可以更新电子邮件.", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "强制要求验证电子邮件才能注册", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "用户帐户将不会被创建,除非他们验证他们的电子邮件地址。", + "Details": "详细信息", "CreatedBy": "创建者", "ModifiedBy": "修改者", "ModificationTime": "修改时间", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json index 676e871e0b..b3899de248 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json @@ -76,7 +76,9 @@ "Volo.Abp.Identity:010007": "你不能修改你的雙因素身份驗證設置", "Volo.Abp.Identity:010008": "不允許修改雙因素身份驗證設置.", "Volo.Abp.Identity:010009": "你不能委派給自己", - "Volo.Abp.Identity:010021" : "名稱 '{0}' 已存在.", + "Volo.Abp.Identity:010021": "名稱 '{0}' 已存在.", + "Volo.Abp.Identity:010022": "無法更改靜態宣告的類型.", + "Volo.Abp.Identity:010023": "無法刪除靜態宣告的類型.", "Identity.OrganizationUnit.MaxUserMembershipCount": "允許一個使用者至多可隸屬在幾個組織單位", "ThisUserIsNotActiveMessage": "該用戶不可用.", "Permission:IdentityManagement": "身份識別管理", @@ -99,9 +101,9 @@ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "允許新的使用者", "DisplayName:Abp.Identity.Lockout.LockoutDuration": "被鎖定期間(秒)", "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "最大登入次數嘗試", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "信箱需被確認", - "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "允許使用者確認電話號碼", - "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "電話號碼需認證", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "登入需要驗證電子郵件", + "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "允許使用者驗證手機號碼", + "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "登入需要驗證手機號碼", "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "允許使用者更新帳號名稱", "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "允許使用者更新信箱", "Description:Abp.Identity.Password.RequiredLength": "密碼須符合最小長度.", @@ -115,17 +117,19 @@ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "使用者是否會被鎖定.", "Description:Abp.Identity.Lockout.LockoutDuration": "使用者被鎖定後的時間.", "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "當啟用鎖定功能,設定最大嘗試輸入次數,超過後就被鎖定.", - "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "決定使用者是否需信箱驗證後才能登入.", - "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "是否啟用電話認證.", - "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "決定使用者是否需電話認證後才能登入.", + "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "使用者可以建立帳戶但在驗證電子郵件地址之前無法登入。", + "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "使用者可以驗證他們的手機號碼。需要簡訊整合。", + "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "使用者可以建立帳戶但在驗證手機號碼之前無法登入。", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "決定使用者是否能更新帳號.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "決定使用者是否能更新信箱.", - "Details": "詳情", + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "使用者是否可以更新電子郵件.", + "Details": "詳細資訊", "CreatedBy": "創建者", "ModifiedBy": "修改者", "ModificationTime": "修改時間", "PasswordUpdateTime": "密碼更新時間", "LockoutEndTime": "鎖定結束時間", - "FailedAccessCount": "訪問失敗次數" + "FailedAccessCount": "訪問失敗次數", + "DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "強制要求驗證電子郵件才能註冊", + "Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister": "除非驗證他們的電子郵件地址,否則不會創建用戶帳戶。" } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Settings/IdentitySettingNames.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Settings/IdentitySettingNames.cs index 9c2b44cb4b..b36995aa3b 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Settings/IdentitySettingNames.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Settings/IdentitySettingNames.cs @@ -32,6 +32,7 @@ public static class IdentitySettingNames private const string SignInPrefix = Prefix + ".SignIn"; public const string RequireConfirmedEmail = SignInPrefix + ".RequireConfirmedEmail"; + public const string RequireEmailVerificationToRegister = SignInPrefix + ".RequireEmailVerificationToRegister"; public const string EnablePhoneNumberConfirmation = SignInPrefix + ".EnablePhoneNumberConfirmation"; public const string RequireConfirmedPhoneNumber = SignInPrefix + ".RequireConfirmedPhoneNumber"; } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs index eb01525e15..7448593c77 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs @@ -99,6 +99,12 @@ public class AbpIdentitySettingDefinitionProvider : SettingDefinitionProvider L("DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation"), L("Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation"), true), + new SettingDefinition( + IdentitySettingNames.SignIn.RequireEmailVerificationToRegister, + false.ToString(), + L("DisplayName:Abp.Identity.SignIn.RequireEmailVerificationToRegister"), + L("Description:Abp.Identity.SignIn.RequireEmailVerificationToRegister"), + false), new SettingDefinition( IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, false.ToString(), diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs index f17f74b602..8da3237f83 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs @@ -69,6 +69,7 @@ public interface IIdentityUserRepository : IBasicRepository bool includeDetails = false, Guid? roleId = null, Guid? organizationUnitId = null, + Guid? id = null, string userName = null, string phoneNumber = null, string emailAddress = null, @@ -114,6 +115,7 @@ public interface IIdentityUserRepository : IBasicRepository string filter = null, Guid? roleId = null, Guid? organizationUnitId = null, + Guid? id = null, string userName = null, string phoneNumber = null, string emailAddress = null, diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimTypeManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimTypeManager.cs index bc8ab16d9f..f821f81d35 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimTypeManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimTypeManager.cs @@ -35,12 +35,12 @@ public class IdentityClaimTypeManager : DomainService { if (await IdentityClaimTypeRepository.AnyAsync(claimType.Name, claimType.Id)) { - throw new AbpException($"Name Exist: {claimType.Name}"); + throw new BusinessException(IdentityErrorCodes.ClaimNameExist).WithData("0", claimType.Name); } if (claimType.IsStatic) { - throw new AbpException($"Can not update a static ClaimType."); + throw new BusinessException(IdentityErrorCodes.CanNotUpdateStaticClaimType); } return await IdentityClaimTypeRepository.UpdateAsync(claimType); @@ -51,7 +51,7 @@ public class IdentityClaimTypeManager : DomainService var claimType = await IdentityClaimTypeRepository.GetAsync(id); if (claimType.IsStatic) { - throw new AbpException($"Can not delete a static ClaimType."); + throw new BusinessException(IdentityErrorCodes.CanNotDeleteStaticClaimType); } //Remove claim of this type from all users and roles diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs index 4ca6d9fab3..74cb486f15 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs @@ -107,6 +107,31 @@ public class IdentityUserManager : UserManager, IDomainService return result; } + /// + /// This is to call the protection method ValidateUserAsync + /// Should return if validation is successful. This is + /// called before saving the user via Create or Update. + /// + /// The user + /// A representing whether validation was successful. + public virtual async Task CallValidateUserAsync(IdentityUser user) + { + return await base.ValidateUserAsync(user); + } + + /// + /// This is to call the protection method ValidatePasswordAsync + /// Should return if validation is successful. This is + /// called before updating the password hash. + /// + /// The user. + /// The password. + /// A representing whether validation was successful. + public virtual async Task CallValidatePasswordAsync(IdentityUser user, string password) + { + return await base.ValidatePasswordAsync(user, password); + } + public virtual async Task GetByIdAsync(Guid id) { var user = await Store.FindByIdAsync(id.ToString(), CancellationToken); diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs index 86682b85db..a623894625 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs @@ -62,35 +62,35 @@ public class EfCoreIdentityUserRepository : EfCoreRepository() - join role in dbContext.Roles on userRole.RoleId equals role.Id - where userIds.Contains(userRole.UserId) - group new - { - userRole.UserId, - role.Name - } by userRole.UserId + join role in dbContext.Roles on userRole.RoleId equals role.Id + where userIds.Contains(userRole.UserId) + group new { + userRole.UserId, + role.Name + } by userRole.UserId into gp - select new IdentityUserIdWithRoleNames - { - Id = gp.Key, RoleNames = gp.Select(x => x.Name).ToArray() - }).ToListAsync(cancellationToken: cancellationToken); + select new IdentityUserIdWithRoleNames + { + Id = gp.Key, + RoleNames = gp.Select(x => x.Name).ToArray() + }).ToListAsync(cancellationToken: cancellationToken); var orgUnitRoles = await (from userOu in dbContext.Set() - join roleOu in dbContext.Set() on userOu.OrganizationUnitId equals roleOu.OrganizationUnitId - join role in dbContext.Roles on roleOu.RoleId equals role.Id - where userIds.Contains(userOu.UserId) - group new - { - userOu.UserId, - role.Name - } by userOu.UserId + join roleOu in dbContext.Set() on userOu.OrganizationUnitId equals roleOu.OrganizationUnitId + join role in dbContext.Roles on roleOu.RoleId equals role.Id + where userIds.Contains(userOu.UserId) + group new { + userOu.UserId, + role.Name + } by userOu.UserId into gp - select new IdentityUserIdWithRoleNames - { - Id = gp.Key, RoleNames = gp.Select(x => x.Name).ToArray() - }).ToListAsync(cancellationToken: cancellationToken); + select new IdentityUserIdWithRoleNames + { + Id = gp.Key, + RoleNames = gp.Select(x => x.Name).ToArray() + }).ToListAsync(cancellationToken: cancellationToken); - return userRoles.Concat(orgUnitRoles).GroupBy(x => x.Id).Select(x => new IdentityUserIdWithRoleNames {Id = x.Key, RoleNames = x.SelectMany(y => y.RoleNames).Distinct().ToArray()}).ToList(); + return userRoles.Concat(orgUnitRoles).GroupBy(x => x.Id).Select(x => new IdentityUserIdWithRoleNames { Id = x.Key, RoleNames = x.SelectMany(y => y.RoleNames).Distinct().ToArray() }).ToList(); } public virtual async Task> GetRoleNamesInOrganizationUnitAsync( @@ -196,6 +196,7 @@ public class EfCoreIdentityUserRepository : EfCoreRepository x.Id == id); + } if (roleId.HasValue) { diff --git a/modules/identity/src/Volo.Abp.Identity.Installer/InstallationNotes.md b/modules/identity/src/Volo.Abp.Identity.Installer/InstallationNotes.md new file mode 100644 index 0000000000..09950e5bdb --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Installer/InstallationNotes.md @@ -0,0 +1,9 @@ +# Installation Notes for Identity Module + +The ABP Identity module provides user and role management functionality for your ABP-based applications. It is built on Microsoft's Identity library and extends it with additional features like organization units and claims management. + +This module is part of the ABP Framework and provides the core identity management capabilities needed by most business applications. + +## Documentation + +For detailed information and usage instructions, please visit the [Identity module documentation](https://abp.io/docs/latest/modules/identity). diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs index ac0b86dee9..6a24fd8ed9 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs @@ -24,13 +24,13 @@ public class MongoIdentityClaimTypeRepository : MongoDbRepository ct.Name == name) .AnyAsync(GetCancellationToken(cancellationToken)); } else { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ct => ct.Id != ignoredId && ct.Name == name) .AnyAsync(GetCancellationToken(cancellationToken)); } @@ -43,15 +43,14 @@ public class MongoIdentityClaimTypeRepository : MongoDbRepository>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Name.Contains(filter) ) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityClaimType.CreationTime) + " desc" : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -59,19 +58,18 @@ public class MongoIdentityClaimTypeRepository : MongoDbRepository>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Name.Contains(filter) ) - .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetListByNamesAsync(IEnumerable names, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => names.Contains(x.Name)) .ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs index 20116fdd0b..46cfc60eb3 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs @@ -18,7 +18,7 @@ public class MongoIdentityLinkUserRepository : MongoDbRepository FindAsync(IdentityLinkUserInfo sourceLinkUserInfo, IdentityLinkUserInfo targetLinkUserInfo, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.SourceUserId == sourceLinkUserInfo.UserId && x.SourceTenantId == sourceLinkUserInfo.TenantId && x.TargetUserId == targetLinkUserInfo.UserId && x.TargetTenantId == targetLinkUserInfo.TenantId || @@ -30,7 +30,7 @@ public class MongoIdentityLinkUserRepository : MongoDbRepository> GetListAsync(IdentityLinkUserInfo linkUserInfo, List excludes = null, CancellationToken cancellationToken = default) { - var query = (await GetMongoQueryableAsync(cancellationToken)).Where(x => + var query = (await GetQueryableAsync(cancellationToken)).Where(x => x.SourceUserId == linkUserInfo.UserId && x.SourceTenantId == linkUserInfo.TenantId || x.TargetUserId == linkUserInfo.UserId && x.TargetTenantId == linkUserInfo.TenantId); @@ -49,7 +49,7 @@ public class MongoIdentityLinkUserRepository : MongoDbRepository + var linkUsers = await (await GetQueryableAsync(cancellationToken)).Where(x => x.SourceUserId == linkUserInfo.UserId && x.SourceTenantId == linkUserInfo.TenantId || x.TargetUserId == linkUserInfo.UserId && x.TargetTenantId == linkUserInfo.TenantId) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs index 3a57f69902..f977572a04 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs @@ -23,7 +23,7 @@ public class MongoIdentityRoleRepository : MongoDbRepository x.Id) .FirstOrDefaultAsync(r => r.NormalizedName == normalizedRoleName, GetCancellationToken(cancellationToken)); } @@ -38,7 +38,7 @@ public class MongoIdentityRoleRepository : MongoDbRepository x.Id).ToList(); - var userCount = await (await GetMongoQueryableAsync(cancellationToken)) + var userCount = await (await GetQueryableAsync(cancellationToken)) .Where(user => user.Roles.Any(role => roleIds.Contains(role.RoleId))) .SelectMany(user => user.Roles) .GroupBy(userRole => userRole.RoleId) @@ -73,7 +73,7 @@ public class MongoIdentityRoleRepository : MongoDbRepository ids, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -82,7 +82,7 @@ public class MongoIdentityRoleRepository : MongoDbRepository r.IsDefault) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -91,17 +91,16 @@ public class MongoIdentityRoleRepository : MongoDbRepository x.Name.Contains(filter) || x.NormalizedName.Contains(filter)) - .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task RemoveClaimFromAllRolesAsync(string claimType, bool autoSave = false, CancellationToken cancellationToken = default) { - var roles = await (await GetMongoQueryableAsync(cancellationToken)) + var roles = await (await GetQueryableAsync(cancellationToken)) .Where(r => r.Claims.Any(c => c.ClaimType == claimType)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -121,13 +120,12 @@ public class MongoIdentityRoleRepository : MongoDbRepository x.Name.Contains(filter) || x.NormalizedName.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityRole.CreationTime) + " desc" : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs index f173272009..388c059f1f 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs @@ -51,8 +51,7 @@ public class MongoIdentitySecurityLogRepository : ); return await query.OrderBy(sorting.IsNullOrWhiteSpace() ? $"{nameof(IdentitySecurityLog.CreationTime)} desc" : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -83,15 +82,14 @@ public class MongoIdentitySecurityLogRepository : cancellationToken ); - return await query.As>() - .LongCountAsync(GetCancellationToken(cancellationToken)); + return await query.LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetByUserIdAsync(Guid id, Guid userId, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.Id == id && x.UserId == userId, + return await (await GetQueryableAsync(cancellationToken)).OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.Id == id && x.UserId == userId, GetCancellationToken(cancellationToken)); } @@ -108,7 +106,7 @@ public class MongoIdentitySecurityLogRepository : string clientIpAddress = null, CancellationToken cancellationToken = default) { - return (await GetMongoQueryableAsync(cancellationToken)) + return (await GetQueryableAsync(cancellationToken)) .WhereIf(startTime.HasValue, securityLog => securityLog.CreationTime >= startTime.Value) .WhereIf(endTime.HasValue, securityLog => securityLog.CreationTime < endTime.Value.AddDays(1).Date) .WhereIf(!applicationName.IsNullOrWhiteSpace(), securityLog => securityLog.ApplicationName == applicationName) diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySessionRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySessionRepository.cs index a1a8f94c49..eb3f99e688 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySessionRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySessionRepository.cs @@ -23,8 +23,7 @@ public class MongoIdentitySessionRepository : MongoDbRepository FindAsync(string sessionId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) - .As>() + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .FirstOrDefaultAsync(x => x.SessionId == sessionId, GetCancellationToken(cancellationToken)); } @@ -41,15 +40,13 @@ public class MongoIdentitySessionRepository : MongoDbRepository ExistAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) - .As>() + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .AnyAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } public virtual async Task ExistAsync(string sessionId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) - .As>() + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .AnyAsync(x => x.SessionId == sessionId, GetCancellationToken(cancellationToken)); } @@ -62,13 +59,12 @@ public class MongoIdentitySessionRepository : MongoDbRepository x.UserId == userId) .WhereIf(!device.IsNullOrWhiteSpace(), x => x.Device == device) .WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId) .OrderBy(sorting.IsNullOrWhiteSpace() ? $"{nameof(IdentitySession.LastAccessed)} desc" : sorting) .PageBy(skipCount, maxResultCount) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -78,11 +74,10 @@ public class MongoIdentitySessionRepository : MongoDbRepository x.UserId == userId) .WhereIf(!device.IsNullOrWhiteSpace(), x => x.Device == device) .WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId) - .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserDelegationRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserDelegationRepository.cs index 56cc48121e..1855069b4a 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserDelegationRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserDelegationRepository.cs @@ -24,25 +24,23 @@ public class MongoIdentityUserDelegationRepository : MongoDbRepository> GetListAsync(Guid? sourceUserId, Guid? targetUserId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(sourceUserId.HasValue, x => x.SourceUserId == sourceUserId) .WhereIf(targetUserId.HasValue, x => x.TargetUserId == targetUserId) - .As>() .ToListAsync(cancellationToken: cancellationToken); } public virtual async Task> GetActiveDelegationsAsync(Guid targetUserId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.TargetUserId == targetUserId) .Where(x => x.StartTime <= Clock.Now && x.EndTime >= Clock.Now) - .As>() .ToListAsync(cancellationToken: cancellationToken); } public virtual async Task FindActiveDelegationByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .FirstOrDefaultAsync(x => x.Id == id && x.StartTime <= Clock.Now && diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs index 58486893ec..64c47f8d2c 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs @@ -25,7 +25,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Id) .FirstOrDefaultAsync( u => u.NormalizedUserName == normalizedUserName, @@ -43,13 +43,13 @@ public class MongoIdentityUserRepository : MongoDbRepository r.OrganizationUnitId) .ToArray(); - var organizationUnits = await (await GetMongoQueryableAsync(cancellationToken)) + var organizationUnits = await (await GetQueryableAsync(cancellationToken)) .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(cancellationToken: cancellationToken); var orgUnitRoleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); var roleIds = user.Roles.Select(r => r.RoleId).ToArray(); var allRoleIds = orgUnitRoleIds.Union(roleIds); - return await (await GetMongoQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(cancellationToken); + return await (await GetQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(cancellationToken); } public virtual async Task> GetRoleNamesInOrganizationUnitAsync( @@ -63,13 +63,13 @@ public class MongoIdentityUserRepository : MongoDbRepository r.OrganizationUnitId) .ToArray(); - var organizationUnits = await (await GetMongoQueryableAsync(cancellationToken)) + var organizationUnits = await (await GetQueryableAsync(cancellationToken)) .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(cancellationToken: cancellationToken); var roleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); - var queryable = await GetMongoQueryableAsync(cancellationToken); + var queryable = await GetQueryableAsync(cancellationToken); return await queryable .Where(r => roleIds.Contains(r.Id)) @@ -83,7 +83,7 @@ public class MongoIdentityUserRepository : MongoDbRepository u.Logins.Any(login => login.LoginProvider == loginProvider && login.ProviderKey == providerKey)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -94,7 +94,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Id).FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, GetCancellationToken(cancellationToken)); } @@ -103,14 +103,14 @@ public class MongoIdentityUserRepository : MongoDbRepository u.Claims.Any(c => c.ClaimType == claim.Type && c.ClaimValue == claim.Value)) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task RemoveClaimFromAllUsersAsync(string claimType, bool autoSave, CancellationToken cancellationToken = default) { - var users = await (await GetMongoQueryableAsync(cancellationToken)) + var users = await (await GetQueryableAsync(cancellationToken)) .Where(u => u.Claims.Any(c => c.ClaimType == claimType)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -129,7 +129,7 @@ public class MongoIdentityUserRepository : MongoDbRepository(cancellationToken); + var queryable = await GetQueryableAsync(cancellationToken); var role = await queryable .Where(x => x.NormalizedName == normalizedRoleName) @@ -141,7 +141,7 @@ public class MongoIdentityUserRepository : MongoDbRepository(); } - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(u => u.Roles.Any(r => r.RoleId == role.Id)) .ToListAsync(cancellationToken); } @@ -150,7 +150,7 @@ public class MongoIdentityUserRepository : MongoDbRepository u.Roles.Any(r => r.RoleId == roleId)) .Select(x => x.Id) .ToListAsync(cancellationToken); @@ -164,6 +164,7 @@ public class MongoIdentityUserRepository : MongoDbRepository>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -217,13 +218,13 @@ public class MongoIdentityUserRepository : MongoDbRepository r.OrganizationUnitId) .ToArray(); - var organizationUnits = await (await GetMongoQueryableAsync(cancellationToken)) + var organizationUnits = await (await GetQueryableAsync(cancellationToken)) .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(cancellationToken: cancellationToken); var orgUnitRoleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); var roleIds = user.Roles.Select(r => r.RoleId).ToArray(); var allRoleIds = orgUnitRoleIds.Union(roleIds); - return await (await GetMongoQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).ToListAsync(cancellationToken); + return await (await GetQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).ToListAsync(cancellationToken); } public virtual async Task> GetOrganizationUnitsAsync( @@ -235,7 +236,7 @@ public class MongoIdentityUserRepository : MongoDbRepository r.OrganizationUnitId); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(cancellationToken); } @@ -244,6 +245,7 @@ public class MongoIdentityUserRepository : MongoDbRepository u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnitId)) .ToListAsync(GetCancellationToken(cancellationToken)); return result; @@ -296,7 +299,7 @@ public class MongoIdentityUserRepository : MongoDbRepository organizationUnitIds, CancellationToken cancellationToken = default) { - var result = await (await GetMongoQueryableAsync(cancellationToken)) + var result = await (await GetQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) .ToListAsync(GetCancellationToken(cancellationToken)); return result; @@ -308,12 +311,12 @@ public class MongoIdentityUserRepository : MongoDbRepository(cancellationToken)) + var organizationUnitIds = await (await GetQueryableAsync(cancellationToken)) .Where(ou => ou.Code.StartsWith(code)) .Select(ou => ou.Id) .ToListAsync(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) .ToListAsync(cancellationToken); } @@ -324,7 +327,7 @@ public class MongoIdentityUserRepository : MongoDbRepository u.TenantId == tenantId && u.UserName == userName, GetCancellationToken(cancellationToken) @@ -333,14 +336,14 @@ public class MongoIdentityUserRepository : MongoDbRepository> GetListByIdsAsync(IEnumerable ids, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => ids.Contains(x.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task UpdateRoleAsync(Guid sourceRoleId, Guid? targetRoleId, CancellationToken cancellationToken = default) { - var users = await (await GetMongoQueryableAsync(cancellationToken)) + var users = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Roles.Any(r => r.RoleId == sourceRoleId)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -358,7 +361,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.OrganizationUnits.Any(r => r.OrganizationUnitId == sourceOrganizationId)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -390,7 +393,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Value); var roleIds = userAndRoleIds.SelectMany(x => x.Value); - var organizationUnitAndRoleIds = await (await GetMongoQueryableAsync(cancellationToken)).Where(ou => organizationUnitIds.Contains(ou.Id)) + var organizationUnitAndRoleIds = await (await GetQueryableAsync(cancellationToken)).Where(ou => organizationUnitIds.Contains(ou.Id)) .Select(userOrganizationUnit => new { userOrganizationUnit.Id, @@ -399,7 +402,8 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Roles.Select(r => r.RoleId)).ToList(); var allRoleIds = roleIds.Union(allOrganizationUnitRoleIds); - var roles = await (await GetMongoQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).Select(r => new{ r.Id, r.Name }).ToListAsync(cancellationToken); + + var roles = await (await GetQueryableAsync(cancellationToken)).Where(r => allRoleIds.Contains(r.Id)).Select(r => new{ r.Id, r.Name }).ToListAsync(cancellationToken); var userRoles = userAndRoleIds.ToDictionary(x => x.Key, x => roles.Where(r => x.Value.Contains(r.Id)).Select(r => r.Name).ToArray()); var result = userRoles.Select(x => new IdentityUserIdWithRoleNames { Id = x.Key, RoleNames = x.Value }).ToList(); @@ -413,19 +417,20 @@ public class MongoIdentityUserRepository : MongoDbRepository> GetFilteredQueryableAsync( + protected virtual async Task> GetFilteredQueryableAsync( string filter = null, Guid? roleId = null, Guid? organizationUnitId = null, + Guid? id = null, string userName = null, string phoneNumber = null, string emailAddress = null, @@ -442,11 +447,16 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Id == id); + } + if (roleId.HasValue) { - var organizationUnitIds = (await GetMongoQueryableAsync(cancellationToken)) + var organizationUnitIds = (await GetQueryableAsync(cancellationToken)) .Where(ou => ou.Roles.Any(r => r.RoleId == roleId.Value)) .Select(userOrganizationUnit => userOrganizationUnit.Id) .ToArray(); @@ -455,7 +465,7 @@ public class MongoIdentityUserRepository : MongoDbRepository>( + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.NormalizedUserName.Contains(upperFilter) || @@ -464,20 +474,20 @@ public class MongoIdentityUserRepository : MongoDbRepository>(organizationUnitId.HasValue, identityUser => identityUser.OrganizationUnits.Any(x => x.OrganizationUnitId == organizationUnitId.Value)) - .WhereIf>(!string.IsNullOrWhiteSpace(userName), x => x.UserName == userName) - .WhereIf>(!string.IsNullOrWhiteSpace(phoneNumber), x => x.PhoneNumber == phoneNumber) - .WhereIf>(!string.IsNullOrWhiteSpace(emailAddress), x => x.Email == emailAddress) - .WhereIf>(!string.IsNullOrWhiteSpace(name), x => x.Name == name) - .WhereIf>(!string.IsNullOrWhiteSpace(surname), x => x.Surname == surname) - .WhereIf>(isLockedOut.HasValue && isLockedOut.Value, x => x.LockoutEnabled && x.LockoutEnd != null && x.LockoutEnd > DateTimeOffset.UtcNow) - .WhereIf>(isLockedOut.HasValue && !isLockedOut.Value, x => !(x.LockoutEnabled && x.LockoutEnd != null && x.LockoutEnd > DateTimeOffset.UtcNow)) - .WhereIf>(notActive.HasValue, x => x.IsActive == !notActive.Value) - .WhereIf>(emailConfirmed.HasValue, x => x.EmailConfirmed == emailConfirmed.Value) - .WhereIf>(isExternal.HasValue, x => x.IsExternal == isExternal.Value) - .WhereIf>(maxCreationTime != null, p => p.CreationTime <= maxCreationTime) - .WhereIf>(minCreationTime != null, p => p.CreationTime >= minCreationTime) - .WhereIf>(maxModifitionTime != null, p => p.LastModificationTime <= maxModifitionTime) - .WhereIf>(minModifitionTime != null, p => p.LastModificationTime >= minModifitionTime); + .WhereIf(organizationUnitId.HasValue, identityUser => identityUser.OrganizationUnits.Any(x => x.OrganizationUnitId == organizationUnitId.Value)) + .WhereIf(!string.IsNullOrWhiteSpace(userName), x => x.UserName == userName) + .WhereIf(!string.IsNullOrWhiteSpace(phoneNumber), x => x.PhoneNumber == phoneNumber) + .WhereIf(!string.IsNullOrWhiteSpace(emailAddress), x => x.Email == emailAddress) + .WhereIf(!string.IsNullOrWhiteSpace(name), x => x.Name == name) + .WhereIf(!string.IsNullOrWhiteSpace(surname), x => x.Surname == surname) + .WhereIf(isLockedOut.HasValue && isLockedOut.Value, x => x.LockoutEnabled && x.LockoutEnd != null && x.LockoutEnd > DateTimeOffset.UtcNow) + .WhereIf(isLockedOut.HasValue && !isLockedOut.Value, x => !(x.LockoutEnabled && x.LockoutEnd != null && x.LockoutEnd > DateTimeOffset.UtcNow)) + .WhereIf(notActive.HasValue, x => x.IsActive == !notActive.Value) + .WhereIf(emailConfirmed.HasValue, x => x.EmailConfirmed == emailConfirmed.Value) + .WhereIf(isExternal.HasValue, x => x.IsExternal == isExternal.Value) + .WhereIf(maxCreationTime != null, p => p.CreationTime <= maxCreationTime) + .WhereIf(minCreationTime != null, p => p.CreationTime >= minCreationTime) + .WhereIf(maxModifitionTime != null, p => p.LastModificationTime <= maxModifitionTime) + .WhereIf(minModifitionTime != null, p => p.LastModificationTime >= minModifitionTime); } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs index 78838c9c6c..14514e0ab4 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs @@ -27,7 +27,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ou => ou.ParentId == parentId) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -38,7 +38,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -48,7 +48,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -58,7 +58,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Roles.Any(r => r.RoleId == roleId)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -68,7 +68,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => displayNames.Contains(x.DisplayName)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -80,10 +80,9 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(sorting.IsNullOrEmpty() ? nameof(OrganizationUnit.CreationTime) + " desc" : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -92,7 +91,7 @@ public class MongoOrganizationUnitRepository bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync( ou => ou.DisplayName == displayName, @@ -110,11 +109,10 @@ public class MongoOrganizationUnitRepository { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(r => roleIds.Contains(r.Id)) .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityRole.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -126,17 +124,16 @@ public class MongoOrganizationUnitRepository bool includeDetails = false, CancellationToken cancellationToken = default) { - var organizationUnits = await (await GetMongoQueryableAsync(cancellationToken)) + var organizationUnits = await (await GetQueryableAsync(cancellationToken)) .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); var roleIds = organizationUnits.SelectMany(ou => ou.Roles.Select(r => r.RoleId)).ToArray(); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(r => roleIds.Contains(r.Id)) .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityRole.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -146,7 +143,7 @@ public class MongoOrganizationUnitRepository { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await (await GetMongoQueryableAsync(cancellationToken)).Where(r => roleIds.Contains(r.Id)).CountAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(r => roleIds.Contains(r.Id)).CountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetUnaddedRolesAsync( @@ -160,12 +157,11 @@ public class MongoOrganizationUnitRepository { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(r => !roleIds.Contains(r.Id)) .WhereIf(!filter.IsNullOrWhiteSpace(), r => r.Name.Contains(filter)) .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityRole.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -176,10 +172,9 @@ public class MongoOrganizationUnitRepository { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(r => !roleIds.Contains(r.Id)) .WhereIf(!filter.IsNullOrWhiteSpace(), r => r.Name.Contains(filter)) - .As>() .CountAsync(GetCancellationToken(cancellationToken)); } @@ -196,15 +191,14 @@ public class MongoOrganizationUnitRepository var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, cancellationToken); return await query .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityUser.UserName) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(cancellationToken); } public virtual async Task> GetMemberIdsAsync(Guid id, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == id)).Select(x => x.Id) .ToListAsync(cancellationToken); } @@ -229,9 +223,9 @@ public class MongoOrganizationUnitRepository CancellationToken cancellationToken = default) { return await - (await GetMongoQueryableAsync(cancellationToken)) + (await GetQueryableAsync(cancellationToken)) .Where(u => !u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .WhereIf>( + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || @@ -239,24 +233,22 @@ public class MongoOrganizationUnitRepository (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) ) .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityUser.UserName) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetUnaddedUsersCountAsync(OrganizationUnit organizationUnit, string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(u => !u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .WhereIf>( + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || u.Email.Contains(filter) || (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) ) - .As>() .CountAsync(GetCancellationToken(cancellationToken)); } @@ -269,11 +261,10 @@ public class MongoOrganizationUnitRepository public virtual async Task RemoveAllMembersAsync(OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - var userQueryable = await GetMongoQueryableAsync(cancellationToken); + var userQueryable = await GetQueryableAsync(cancellationToken); var dbContext = await GetDbContextAsync(cancellationToken); var users = await userQueryable .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .As>() .ToListAsync(cancellationToken); foreach (var user in users) @@ -283,14 +274,14 @@ public class MongoOrganizationUnitRepository } } - protected virtual async Task> CreateGetMembersFilteredQueryAsync( + protected virtual async Task> CreateGetMembersFilteredQueryAsync( OrganizationUnit organizationUnit, string filter = null, CancellationToken cancellationToken = default) { - return (await GetMongoQueryableAsync(cancellationToken)) + return (await GetQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .WhereIf>( + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityClaimTypeManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityClaimTypeManager_Tests.cs index 9078040910..04f4cc6eaa 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityClaimTypeManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityClaimTypeManager_Tests.cs @@ -53,7 +53,7 @@ public class IdentityClaimTypeManager_Tests : AbpIdentityDomainTestBase [Fact] public async Task Update_Name_Exist_Should_Exception() { - await Assert.ThrowsAnyAsync(async () => await _claimTypeManager.UpdateAsync( + await Assert.ThrowsAnyAsync(async () => await _claimTypeManager.UpdateAsync( new IdentityClaimType( Guid.NewGuid(), "Age"))); } @@ -65,6 +65,6 @@ public class IdentityClaimTypeManager_Tests : AbpIdentityDomainTestBase var phoneClaim = new IdentityClaimType(Guid.NewGuid(), "Phone", true, true); await _identityClaimTypeRepository.InsertAsync(phoneClaim); - await Assert.ThrowsAnyAsync(async () => await _claimTypeManager.UpdateAsync(phoneClaim)); + await Assert.ThrowsAnyAsync(async () => await _claimTypeManager.UpdateAsync(phoneClaim)); } } diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj index cc463e1cc8..311ee9fa69 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj @@ -20,10 +20,10 @@ - - - - + + + + diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs index 732500214c..90b0f60b14 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.Identity.MongoDB; diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs index a77cb01d8a..5259c31329 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs @@ -1,7 +1,9 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Volo.Abp.BackgroundWorkers; +using Volo.Abp.DistributedLocking; using Volo.Abp.Threading; namespace Volo.Abp.IdentityServer.Tokens; @@ -9,24 +11,40 @@ namespace Volo.Abp.IdentityServer.Tokens; public class TokenCleanupBackgroundWorker : AsyncPeriodicBackgroundWorkerBase { protected TokenCleanupOptions Options { get; } + protected IAbpDistributedLock DistributedLock { get; } public TokenCleanupBackgroundWorker( AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, - IOptions options) + IOptions options, + IAbpDistributedLock distributedLock) : base( timer, serviceScopeFactory) { + DistributedLock = distributedLock; Options = options.Value; timer.Period = Options.CleanupPeriod; } protected async override Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) { - await workerContext - .ServiceProvider - .GetRequiredService() - .CleanAsync(); + await using (var handle = await DistributedLock.TryAcquireAsync(nameof(TokenCleanupBackgroundWorker))) + { + Logger.LogInformation($"Lock is acquired for {nameof(TokenCleanupBackgroundWorker)}"); + + if (handle != null) + { + await workerContext + .ServiceProvider + .GetRequiredService() + .CleanAsync(); + + Logger.LogInformation($"Lock is released for {nameof(TokenCleanupBackgroundWorker)}"); + return; + } + + Logger.LogInformation($"Handle is null because of the locking for : {nameof(TokenCleanupBackgroundWorker)}"); + } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Installer/InstallationNotes.md b/modules/identityserver/src/Volo.Abp.IdentityServer.Installer/InstallationNotes.md new file mode 100644 index 0000000000..291c4f84b1 --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Installer/InstallationNotes.md @@ -0,0 +1,9 @@ +# Installation Notes for Identity Server Module + +IdentityServer module provides a full integration with the [IdentityServer4](https://github.com/DuendeArchive/IdentityServer4) (IDS) framework, which provides advanced authentication features like single sign-on and API access control. This module persists clients, resources and other IDS-related objects to database. This module is replaced by [OpenIddict](https://abp.io/docs/latest/modules/openiddict) module after ABP v6.0 in the startup templates. + +> Note: You can not use IdentityServer and OpenIddict modules together. They are separate OpenID provider libraries for the same job. + +## Documentation + +For detailed information and usage instructions, please visit the [Identity Server Module documentation](https://abp.io/docs/latest/modules/identity-server). \ No newline at end of file diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs index 24dc519a40..42379b44f9 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiResourceRepository.cs @@ -20,7 +20,7 @@ public class MongoApiResourceRepository : MongoDbRepository FindByNameAsync(string apiResourceName, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(ar => ar.Id) .FirstOrDefaultAsync(ar => ar.Name == apiResourceName, GetCancellationToken(cancellationToken)); } @@ -28,7 +28,7 @@ public class MongoApiResourceRepository : MongoDbRepository> FindByNameAsync(string[] apiResourceNames, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ar => apiResourceNames.Contains(ar.Name)) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -36,7 +36,7 @@ public class MongoApiResourceRepository : MongoDbRepository> GetListByScopesAsync(string[] scopeNames, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ar => ar.Scopes.Any(x => scopeNames.Contains(x.Scope))) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -44,21 +44,20 @@ public class MongoApiResourceRepository : MongoDbRepository> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(ApiResource.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>(!filter.IsNullOrWhiteSpace(), + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) @@ -67,7 +66,7 @@ public class MongoApiResourceRepository : MongoDbRepository CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .AnyAsync(ar => ar.Id != expectedId && ar.Name == name, GetCancellationToken(cancellationToken)); } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs index 01c1ecad07..760bd0522c 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoApiScopeRepository.cs @@ -22,7 +22,7 @@ public class MongoApiScopeRepository : MongoDbRepository FindByNameAsync(string scopeName, bool includeDetails = true, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(x => x.Name == scopeName, GetCancellationToken(cancellationToken)); } @@ -30,7 +30,7 @@ public class MongoApiScopeRepository : MongoDbRepository> GetListByNameAsync(string[] scopeNames, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(scope => scopeNames.Contains(scope.Name)) .OrderBy(scope => scope.Id) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -39,21 +39,20 @@ public class MongoApiScopeRepository : MongoDbRepository> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(ApiScope.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>(!filter.IsNullOrWhiteSpace(), + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) @@ -62,7 +61,7 @@ public class MongoApiScopeRepository : MongoDbRepository CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .AnyAsync(x => x.Id != expectedId && x.Name == name, GetCancellationToken(cancellationToken)); } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs index c7f81f51e2..d266ac7c52 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoClientRepository.cs @@ -26,7 +26,7 @@ public class MongoClientRepository : MongoDbRepository x.Id) .FirstOrDefaultAsync(x => x.ClientId == clientId, GetCancellationToken(cancellationToken)); } @@ -39,18 +39,17 @@ public class MongoClientRepository : MongoDbRepository x.ClientId.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(Client.ClientName) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>(!filter.IsNullOrWhiteSpace(), + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.ClientId.Contains(filter)) .LongCountAsync(GetCancellationToken(cancellationToken)); } @@ -58,7 +57,7 @@ public class MongoClientRepository : MongoDbRepository> GetAllDistinctAllowedCorsOriginsAsync( CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .SelectMany(x => x.AllowedCorsOrigins) .Select(y => y.Origin) .Distinct() @@ -67,7 +66,7 @@ public class MongoClientRepository : MongoDbRepository CheckClientIdExistAsync(string clientId, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .AnyAsync(c => c.Id != expectedId && c.ClientId == clientId, GetCancellationToken(cancellationToken)); } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs index 921225a5ae..65d74b975a 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoDeviceFlowCodesRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; @@ -23,7 +24,7 @@ public class MongoDeviceFlowCodesRepository : string userCode, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(d => d.UserCode == userCode) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -31,7 +32,7 @@ public class MongoDeviceFlowCodesRepository : public virtual async Task FindByDeviceCodeAsync(string deviceCode, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(d => d.DeviceCode == deviceCode) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -42,7 +43,7 @@ public class MongoDeviceFlowCodesRepository : int maxResultCount, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Expiration != null && x.Expiration < maxExpirationDate) .OrderBy(x => x.ClientId) .Take(maxResultCount) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs index faf3d66d96..9a3ee0f815 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoIdentityResourceRepository.cs @@ -20,20 +20,19 @@ public class MongoIdentityResourceRepository : MongoDbRepository> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityResource.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>(!filter.IsNullOrWhiteSpace(), + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.Description.Contains(filter) || x.DisplayName.Contains(filter)) @@ -45,7 +44,7 @@ public class MongoIdentityResourceRepository : MongoDbRepository x.Name == name) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -54,14 +53,14 @@ public class MongoIdentityResourceRepository : MongoDbRepository> GetListByScopeNameAsync(string[] scopeNames, bool includeDetails = false, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(ar => scopeNames.Contains(ar.Name)) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task CheckNameExistAsync(string name, Guid? expectedId = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .AnyAsync(ir => ir.Id != expectedId && ir.Name == name, GetCancellationToken(cancellationToken)); } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistentGrantRepository.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistentGrantRepository.cs index e3f3cc8368..4ac0844bbe 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistentGrantRepository.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.MongoDB/Volo/Abp/IdentityServer/MongoDB/MongoPersistentGrantRepository.cs @@ -27,7 +27,7 @@ public class MongoPersistentGrantRepository : MongoDbRepository FindByKeyAsync(string key, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Key == key) .OrderBy(x => x.Id) .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); @@ -35,7 +35,7 @@ public class MongoPersistentGrantRepository : MongoDbRepository> GetListBySubjectIdAsync(string subjectId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.SubjectId == subjectId) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -43,7 +43,7 @@ public class MongoPersistentGrantRepository : MongoDbRepository> GetListByExpirationAsync(DateTime maxExpirationDate, int maxResultCount, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Expiration != null && x.Expiration < maxExpirationDate) .OrderBy(x => x.ClientId) .Take(maxResultCount) @@ -87,18 +87,17 @@ public class MongoPersistentGrantRepository : MongoDbRepository> FilterAsync( + private async Task> FilterAsync( string subjectId, string sessionId, string clientId, string type, CancellationToken cancellationToken = default) { - return (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>(!subjectId.IsNullOrWhiteSpace(), x => x.SubjectId == subjectId) - .WhereIf>(!sessionId.IsNullOrWhiteSpace(), x => x.SessionId == sessionId) - .WhereIf>(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId) - .WhereIf>(!type.IsNullOrWhiteSpace(), x => x.Type == type) - .As>(); + return (await GetQueryableAsync(cancellationToken)) + .WhereIf(!subjectId.IsNullOrWhiteSpace(), x => x.SubjectId == subjectId) + .WhereIf(!sessionId.IsNullOrWhiteSpace(), x => x.SessionId == sessionId) + .WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId) + .WhereIf(!type.IsNullOrWhiteSpace(), x => x.Type == type); } } diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj index d2d7bf8a0e..07377805af 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj @@ -20,10 +20,10 @@ - - - - + + + + diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs index 2f6d52d255..6611beb635 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.IdentityServer; diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs b/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs index 148685c1bd..c67b2977ef 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs @@ -71,6 +71,7 @@ public class ServerDataSeedContributor : IDataSeedContributor, ITransientDepende OpenIddictConstants.Permissions.Endpoints.Introspection, OpenIddictConstants.Permissions.Endpoints.Revocation, OpenIddictConstants.Permissions.Endpoints.EndSession, + OpenIddictConstants.Permissions.Endpoints.PushedAuthorization, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, OpenIddictConstants.Permissions.GrantTypes.Implicit, diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/ExtensionGrants/MyTokenExtensionGrant.cs b/modules/openiddict/app/OpenIddict.Demo.Server/ExtensionGrants/MyTokenExtensionGrant.cs index b5167621ef..12e587b65b 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/ExtensionGrants/MyTokenExtensionGrant.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/ExtensionGrants/MyTokenExtensionGrant.cs @@ -19,7 +19,17 @@ public class MyTokenExtensionGrant : ITokenExtensionGrant public const string ExtensionGrantName = "MyTokenExtensionGrant"; public string Name => ExtensionGrantName; + public async Task HandleAsync(ExtensionGrantContext context) + { + // You can get a new token using any of the following methods based on your business. + // They are just examples. You can implement your own logic here. + + return await HandleUserAccessTokenAsync(context); + return await HandleUserApiKeyAsync(context); + } + + public async Task HandleUserAccessTokenAsync(ExtensionGrantContext context) { var userToken = context.Request.GetParameter("token").ToString(); @@ -33,6 +43,9 @@ public class MyTokenExtensionGrant : ITokenExtensionGrant }!)); } + // We will validate the user token + // The Token is issued by the OpenIddict server, So we can validate it using the introspection endpoint + var transaction = await context.HttpContext.RequestServices.GetRequiredService().CreateTransactionAsync(); transaction.EndpointType = OpenIddictServerEndpointType.Introspection; transaction.Request = new OpenIddictRequest @@ -71,17 +84,92 @@ public class MyTokenExtensionGrant : ITokenExtensionGrant })); } + // We have validated the user token and got the user id + var userId = principal.FindUserId(); var userManager = context.HttpContext.RequestServices.GetRequiredService(); var user = await userManager.GetByIdAsync(userId.Value); var userClaimsPrincipalFactory = context.HttpContext.RequestServices.GetRequiredService>(); var claimsPrincipal = await userClaimsPrincipalFactory.CreateAsync(user); - claimsPrincipal.SetScopes(principal.GetScopes()); - claimsPrincipal.SetResources(await GetResourcesAsync(context, principal.GetScopes())); + + // Prepare the scopes + var scopes = GetScopes(context); + + claimsPrincipal.SetScopes(scopes); + claimsPrincipal.SetResources(await GetResourcesAsync(context, scopes)); await context.HttpContext.RequestServices.GetRequiredService().HandleAsync(context.Request, principal); return new SignInResult(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, claimsPrincipal); } + + protected async Task HandleUserApiKeyAsync(ExtensionGrantContext context) + { + var userApiKey = context.Request.GetParameter("user_api_key").ToString(); + + if (string.IsNullOrEmpty(userApiKey)) + { + return new ForbidResult( + new[] {OpenIddictServerAspNetCoreDefaults.AuthenticationScheme}, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidRequest + }!)); + } + + // Here we can validate the user API key and get the user id + if (false) // Add your own logic here + { + // If the user API key is invalid + return new ForbidResult( + new[] {OpenIddictServerAspNetCoreDefaults.AuthenticationScheme}, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidRequest + }!)); + } + + // Add your own logic to get the user by API key + var userManager = context.HttpContext.RequestServices.GetRequiredService(); + var user = await userManager.FindByNameAsync("admin"); + if (user == null) + { + return new ForbidResult( + new[] {OpenIddictServerAspNetCoreDefaults.AuthenticationScheme}, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidRequest + }!)); + } + + // Create a principal for the user + var userClaimsPrincipalFactory = context.HttpContext.RequestServices.GetRequiredService>(); + var claimsPrincipal = await userClaimsPrincipalFactory.CreateAsync(user); + + // Prepare the scopes + var scopes = GetScopes(context); + + claimsPrincipal.SetScopes(scopes); + claimsPrincipal.SetResources(await GetResourcesAsync(context, scopes)); + await context.HttpContext.RequestServices.GetRequiredService().HandleAsync(context.Request, claimsPrincipal); + return new SignInResult(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, claimsPrincipal); + } + + protected ImmutableArray GetScopes(ExtensionGrantContext context) + { + // Prepare the scopes + // The scopes must be defined in the OpenIddict server + + // If you want to get the scopes from the request, you have to add `scope` parameter in the request + // scope: AbpAPI profile roles email phone offline_access + + //var scopes = context.Request.GetScopes(); + + // If you want to set the scopes here, you can use the following code + var scopes = new[] { "AbpAPI", "profile", "roles", "email", "phone", "offline_access" }.ToImmutableArray(); + + return scopes; + } + private async Task> GetResourcesAsync(ExtensionGrantContext context, ImmutableArray scopes) { var resources = new List(); diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20241005085943_Initial.Designer.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250215074649_Initial.Designer.cs similarity index 99% rename from modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20241005085943_Initial.Designer.cs rename to modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250215074649_Initial.Designer.cs index 7fffd314e8..fec1a9f143 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20241005085943_Initial.Designer.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250215074649_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace OpenIddict.Demo.Server.Migrations { [DbContext(typeof(ServerDbContext))] - [Migration("20241005085943_Initial")] + [Migration("20250215074649_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace OpenIddict.Demo.Server.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -162,6 +162,10 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -238,6 +242,10 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); @@ -394,13 +402,6 @@ namespace OpenIddict.Demo.Server.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .IsRequired() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - b.Property("Device") .IsRequired() .HasMaxLength(64) @@ -411,7 +412,6 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(64)"); b.Property("ExtraProperties") - .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20241005085943_Initial.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250215074649_Initial.cs similarity index 99% rename from modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20241005085943_Initial.cs rename to modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250215074649_Initial.cs index 62b23276c4..fdf8dac987 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20241005085943_Initial.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20250215074649_Initial.cs @@ -23,6 +23,7 @@ namespace OpenIddict.Demo.Server.Migrations RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), ValueType = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, @@ -188,6 +189,7 @@ namespace OpenIddict.Demo.Server.Migrations IsStatic = table.Column(type: "bit", nullable: false), IsPublic = table.Column(type: "bit", nullable: false), EntityVersion = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) }, @@ -235,8 +237,7 @@ namespace OpenIddict.Demo.Server.Migrations IpAddresses = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: true), SignedIn = table.Column(type: "datetime2", nullable: false), LastAccessed = table.Column(type: "datetime2", nullable: true), - ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), - ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs index fbaf0bc710..4099fccc43 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace OpenIddict.Demo.Server.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -159,6 +159,10 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("Description") .HasMaxLength(256) .HasColumnType("nvarchar(256)"); @@ -235,6 +239,10 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + b.Property("EntityVersion") .HasColumnType("int"); @@ -391,13 +399,6 @@ namespace OpenIddict.Demo.Server.Migrations .HasMaxLength(64) .HasColumnType("nvarchar(64)"); - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .IsRequired() - .HasMaxLength(40) - .HasColumnType("nvarchar(40)") - .HasColumnName("ConcurrencyStamp"); - b.Property("Device") .IsRequired() .HasMaxLength(64) @@ -408,7 +409,6 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("nvarchar(64)"); b.Property("ExtraProperties") - .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs index 6ebb66cb6a..dddc89d515 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs @@ -65,6 +65,7 @@ public class AbpOpenIddictAspNetCoreModule : AbpModule .SetDeviceAuthorizationEndpointUris("device") .SetIntrospectionEndpointUris("connect/introspect") .SetEndSessionEndpointUris("connect/endsession") + .SetPushedAuthorizationEndpointUris("connect/par") .SetRevocationEndpointUris("connect/revocat") .SetTokenEndpointUris("connect/token") .SetUserInfoEndpointUris("connect/userinfo") diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs index 31c49807e2..416d90b3b7 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs @@ -51,8 +51,6 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase GetClientUriAsync(OpenIddictApplicationModel application, CancellationToken cancellationToken = default) diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs index 61944f7338..eb9172667d 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs @@ -53,8 +53,6 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter = null, CancellationToken cancellationToken = default) { - return await ((await GetMongoQueryableAsync(cancellationToken))) + return await ((await GetQueryableAsync(cancellationToken))) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.ClientId.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(OpenIddictApplication.CreationTime) + " desc" : sorting) .PageBy(skipCount, maxResultCount) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await ((await GetMongoQueryableAsync(cancellationToken))) + return await ((await GetQueryableAsync(cancellationToken))) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.ClientId.Contains(filter)) - .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByClientIdAsync(string clientId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .FirstOrDefaultAsync(x => x.ClientId == clientId, cancellationToken); } public virtual async Task> FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.PostLogoutRedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(x => x.PostLogoutRedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> FindByRedirectUriAsync(string address, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.RedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).Where(x => x.RedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + return await query(await GetQueryableAsync(cancellationToken), state).FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .SkipIf>(offset.HasValue, offset) .TakeIf>(count.HasValue, count) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs index f4bd5f4817..87ed933f00 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs @@ -29,53 +29,52 @@ public class MongoOpenIddictAuthorizationRepository : MongoDbRepository> FindAsync(string subject, Guid? client, string status, string type, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!subject.IsNullOrWhiteSpace(), x => x.Subject == subject) .WhereIf(client.HasValue, x => x.ApplicationId == client) .WhereIf(!status.IsNullOrWhiteSpace(), x => x.Status == status) .WhereIf(!type.IsNullOrWhiteSpace(), x => x.Type == type) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> FindByApplicationIdAsync(Guid applicationId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).Where(x => x.ApplicationId == applicationId).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))).Where(x => x.ApplicationId == applicationId).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } public virtual async Task> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).Where(x => x.Subject == subject).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))).Where(x => x.Subject == subject).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .OrderBy(authorization => authorization.Id!) .SkipIf>(offset.HasValue, offset) .TakeIf>(count.HasValue, count) - .As>().ToListAsync(GetCancellationToken(cancellationToken)); + .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task PruneAsync(DateTime date, CancellationToken cancellationToken = default) { - var tokenIds = await (await GetMongoQueryableAsync(cancellationToken)) + var tokenIds = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.AuthorizationId != null) .Select(x => x.AuthorizationId.Value) .ToListAsync(GetCancellationToken(cancellationToken)); - var authorizations = await (await GetMongoQueryableAsync(cancellationToken)) + var authorizations = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.CreationDate < date) .Where(x => x.Status != OpenIddictConstants.Statuses.Valid || (x.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && !tokenIds.Contains(x.Id))) .Select(x => x.Id) .ToListAsync(cancellationToken: cancellationToken); - var tokens = await (await GetMongoQueryableAsync(cancellationToken)) + var tokens = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.AuthorizationId != null && authorizations.Contains(x.AuthorizationId.Value)) .ToListAsync(cancellationToken: cancellationToken); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs index 3e16df4e9b..7323b3f272 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs @@ -21,61 +21,56 @@ public class MongoOpenIddictScopeRepository : MongoDbRepository> GetListAsync(string sorting, int skipCount, int maxResultCount, string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.DisplayName.Contains(filter) || x.Description.Contains(filter)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(OpenIddictScope.CreationTime) + " desc" : sorting) .PageBy(skipCount, maxResultCount) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || x.DisplayName.Contains(filter) || x.Description.Contains(filter)) - .As>() .LongCountAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } public virtual async Task FindByNameAsync(string name, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Name == name, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Name == name, GetCancellationToken(cancellationToken)); } public virtual async Task> FindByNamesAsync(string[] names, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => names.Contains(x.Name)) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> FindByResourceAsync(string resource, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.Resources.Contains(resource)) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .OrderBy(x => x.Id) .SkipIf>(offset.HasValue, offset) .TakeIf>(count.HasValue, count) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs index 175b137515..2b2a9bec12 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs @@ -21,7 +21,7 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository x.ApplicationId == applicationId) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -31,7 +31,7 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository x.AuthorizationId == authorizationId) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -40,7 +40,7 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository x.AuthorizationId != null && authorizationIds.Contains(x.AuthorizationId.Value)) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -49,67 +49,62 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository> FindAsync(string subject, Guid? client, string status, string type, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .WhereIf(!subject.IsNullOrWhiteSpace(), x => x.Subject == subject) .WhereIf(client.HasValue, x => x.ApplicationId == client) .WhereIf(!status.IsNullOrWhiteSpace(), x => x.Status == status) .WhereIf(!type.IsNullOrWhiteSpace(), x => x.Type == type) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> FindByApplicationIdAsync(Guid applicationId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.ApplicationId == applicationId) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> FindByAuthorizationIdAsync(Guid authorizationId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.AuthorizationId == authorizationId) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } public virtual async Task FindByReferenceIdAsync(string referenceId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.ReferenceId == referenceId, GetCancellationToken(cancellationToken)); + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.ReferenceId == referenceId, GetCancellationToken(cancellationToken)); } public virtual async Task> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.Subject == subject) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + return await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .OrderBy(x => x.Id) .SkipIf>(offset.HasValue, offset) .TakeIf>(count.HasValue, count) - .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task PruneAsync(DateTime date, CancellationToken cancellationToken = default) { - var authorizationIds = await (await GetMongoQueryableAsync(cancellationToken)) + var authorizationIds = await (await GetQueryableAsync(cancellationToken)) .Where(x => x.Status != OpenIddictConstants.Statuses.Valid) .Select(x => x.Id) .ToListAsync(GetCancellationToken(cancellationToken)); - var tokens = await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + var tokens = await (await GetQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.CreationDate < date) .Where(x => (x.Status != OpenIddictConstants.Statuses.Inactive && x.Status != OpenIddictConstants.Statuses.Valid) || diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj index 56512b464c..d5f8903293 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj @@ -9,10 +9,10 @@ - - - - + + + + diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoDbFixture.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoDbFixture.cs index ddceaf8104..1716d478a5 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoDbFixture.cs +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo/Abp/OpenIddict/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.OpenIddict.MongoDB; diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor index fc9884bf4e..87c2c0db91 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor @@ -5,7 +5,7 @@ @L["Permissions"] - @_entityDisplayName - + @@ -36,62 +36,65 @@ @if (_groups != null && _groups.Any()) { - - - @foreach (var group in _groups) - { - - @if (group.Permissions.Any(x => x.IsGranted)) - { - +
      + + + @foreach (var group in _groups) + { + + @if (group.Permissions.Any(x => x.IsGranted)) + { + @group.DisplayName ( @(group.Permissions.Count(x => x.IsGranted)) ) - } - else - { - + } + else + { + @group.DisplayName ( @(group.Permissions.Count(x => x.IsGranted)) ) - } - - } - - - @foreach (var group in _groups) - { - - - - - @L["SelectAllInThisTab"] - - + } + + } + + + @foreach (var group in _groups) + { + +
      + + + @L["SelectAllInThisTab"] + + - - - @foreach (var permission in group.Permissions) - { - - - @GetShownName(permission) - - - } - - - } - - + + + @foreach (var permission in group.Permissions) + { + + + @GetShownName(permission) + + + } +
      +
      + } +
      +
      +
      + } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.css b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.css index 6c827bec4a..f6870a7a16 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.css +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.css @@ -3,29 +3,29 @@ fieldset legend { width: auto; } -.lpx-scroll-pills-container ul { +::deep .lpx-scroll-pills-container ul { display: block; max-height: 500px; overflow-y: auto; } -.lpx-scroll-pills-container .tab-content { +::deep .lpx-scroll-pills-container .tab-content { padding-top: 0 !important; padding-bottom: 0 !important; } -.lpx-scroll-pills-container ul li { +::deep .lpx-scroll-pills-container ul li { border: 1px solid #e8eef3; margin-bottom: 10px; border-radius: 10px; } -.lpx-scroll-pills-container ul li a.active { +::deep .lpx-scroll-pills-container ul li a.active { color: #fff !important; border-color: #6c5dd3 !important; background-color: #6c5dd3 !important; } -.lpx-theme-dark .lpx-scroll-pills-container ul li { +::deep .lpx-theme-dark .lpx-scroll-pills-container ul li { border: 1px solid #23262a; } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Installer/InstallationNotes.md b/modules/permission-management/src/Volo.Abp.PermissionManagement.Installer/InstallationNotes.md new file mode 100644 index 0000000000..452dfc1a4c --- /dev/null +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Installer/InstallationNotes.md @@ -0,0 +1,9 @@ +# Installation Notes for Permission Management Module + +The ABP Permission Management module provides infrastructure to persist and manage permissions in your ABP-based applications. It allows you to grant permissions to users, roles, or other entities. + +This module is part of the ABP Framework and provides the core permission management functionality needed by most business applications. + +## Documentation + +For detailed information and usage instructions, please visit the [Permission Management module documentation](https://abp.io/docs/latest/modules/permission-management). \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionDefinitionRecordRepository.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionDefinitionRecordRepository.cs index 529f56511c..2f98db4f60 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionDefinitionRecordRepository.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionDefinitionRecordRepository.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; @@ -22,7 +23,7 @@ public class MongoPermissionDefinitionRecordRepository : CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync( s => s.Name == name, diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs index aa7694b7d5..d83d916890 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.MongoDB/Volo/Abp/PermissionManagement/MongoDb/MongoPermissionGrantRepository.cs @@ -27,7 +27,7 @@ public class MongoPermissionGrantRepository : CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(s => s.Name == name && @@ -43,7 +43,7 @@ public class MongoPermissionGrantRepository : CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey @@ -54,7 +54,7 @@ public class MongoPermissionGrantRepository : CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(s => names.Contains(s.Name) && s.ProviderName == providerName && diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj index 757b0f164c..0f9e0169e8 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj @@ -19,10 +19,10 @@ - - - - + + + + diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs index fc039d7ee2..05fae7288c 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo/Abp/PermissionManagement/MongoDb/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.PermissionManagement.MongoDB; diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor.cs index 9a1d36be44..885a556991 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor.cs @@ -118,7 +118,7 @@ public partial class EmailSettingGroupViewComponent await EmailSettingsAppService.SendTestEmailAsync(ObjectMapper.Map(SendTestEmailInput)); - await Notify.Success(L["SuccessfullySent"]); + await Notify.Success(L["SentSuccessfully"]); } catch (Exception ex) { diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ar.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ar.json index d25470b917..1a0a2e218a 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ar.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ar.json @@ -14,7 +14,7 @@ "Body": "جسم", "TestEmailSubject": "اختبار البريد الإلكتروني {0}", "TestEmailBody": "اختبار نص رسالة البريد الإلكتروني هنا", - "SuccessfullySent": "أرسلت بنجاح", + "SentSuccessfully": "أرسلت بنجاح", "MailSendingFailed": "فشل إرسال البريد ، يرجى التحقق من تكوين البريد الإلكتروني الخاص بك والمحاولة مرة أخرى.", "Send": "يرسل", "Menu:Emailing": "إرسال بالبريد الإلكتروني", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json index 2f6711296b..983c6718b9 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json @@ -14,7 +14,7 @@ "Body": "Tělo", "TestEmailSubject": "Testovací e-mail {0}", "TestEmailBody": "Test těla e-mailové zprávy zde", - "SuccessfullySent": "Úspěšně odesláno", + "SentSuccessfully": "Úspěšně odesláno", "MailSendingFailed": "Odesílání e-mailu se nezdařilo. Zkontrolujte konfiguraci e-mailu a zkuste to znovu.", "Send": "Poslat", "Menu:Emailing": "Zasílání e-mailem", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de-DE.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de-DE.json index a0127f127e..3f44913224 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de-DE.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de-DE.json @@ -14,7 +14,7 @@ "Body": "Nachricht", "TestEmailSubject": "Test E-Mail {0}", "TestEmailBody": "Test E-Mail Nachricht hier eingeben", - "SuccessfullySent": "Erfolgreich gesendet", + "SentSuccessfully": "Erfolgreich gesendet", "MailSendingFailed": "E-Mail-Versand fehlgeschlagen. Bitte überprüfen Sie Ihre E-Mail-Konfiguration und versuchen Sie es erneut.", "Send": "Senden", "Menu:Emailing": "E-Mail", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de.json index c9fea92a36..c5efcb1718 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de.json @@ -14,7 +14,7 @@ "Body": "Körper", "TestEmailSubject": "Test-E-Mail {0}", "TestEmailBody": "Testen Sie hier die E-Mail-Textnachricht", - "SuccessfullySent": "Erfolgreich gesendet", + "SentSuccessfully": "Erfolgreich gesendet", "MailSendingFailed": "E-Mail-Versand fehlgeschlagen. Bitte überprüfen Sie Ihre E-Mail-Konfiguration und versuchen Sie es erneut.", "Send": "Schicken", "Menu:Emailing": "E-Mail senden", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/el.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/el.json index 95132d1f67..611cfb407d 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/el.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/el.json @@ -14,7 +14,7 @@ "Body": "Κείμενο", "TestEmailSubject": "Δοκιμαστικό email {0}", "TestEmailBody": "Δοκιμαστικό κείμενο email εδώ", - "SuccessfullySent": "Στάλθηκε με επιτυχία", + "SentSuccessfully": "Στάλθηκε με επιτυχία", "MailSendingFailed": "Αποτυχία αποστολής email. Ελέγξτε τη διαμόρφωση του email σας και δοκιμάστε ξανά.", "Send": "Αποστολή", "Menu:Emailing": "Αποστολή email", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json index e81ce7718b..e7d221b4ef 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json @@ -14,7 +14,7 @@ "Body": "Body", "TestEmailSubject": "Test email {0}", "TestEmailBody": "Test email body message here", - "SuccessfullySent": "Successfully sent", + "SentSuccessfully": "Sent successfully", "MailSendingFailed": "Mail sending failed, please check your email configuration and try again.", "Send": "Send", "Menu:Emailing": "Emailing", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json index 660a7998ac..7d6bcd8236 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json @@ -14,7 +14,7 @@ "Body": "Cuerpo", "TestEmailSubject": "Correo electrónico de prueba {0}", "TestEmailBody": "Pruebe el cuerpo del mensaje de correo electrónico aquí", - "SuccessfullySent": "Enviado exitosamente", + "SentSuccessfully": "Enviado exitosamente", "MailSendingFailed": "Error al enviar el correo, por favor revise su configuración de correo y vuelva a intentarlo.", "Send": "Enviar", "Menu:Emailing": "Configuración", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fi.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fi.json index d9f853dd76..312ecf608c 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fi.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fi.json @@ -14,7 +14,7 @@ "Body": "Runko", "TestEmailSubject": "Testisähköposti {0}", "TestEmailBody": "Testaa sähköpostiviestiä täällä", - "SuccessfullySent": "Lähetetty onnistuneesti", + "SentSuccessfully": "Lähetetty onnistuneesti", "MailSendingFailed": "Sähköpostin lähetys epäonnistui. Tarkista sähköpostiasetuksesi ja yritä uudelleen.", "Send": "Lähetä", "Menu:Emailing": "Sähköpostiviestit", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json index 85a8d04f18..3ec1a598c2 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json @@ -14,7 +14,7 @@ "Body": "Corps", "TestEmailSubject": "E-mail test {0}", "TestEmailBody": "Testez le corps du message ici", - "SuccessfullySent": "Envoyé avec succès", + "SentSuccessfully": "Envoyé avec succès", "MailSendingFailed": "L'envoi de courrier a échoué, veuillez vérifier votre configuration de courrier électronique et réessayer.", "Send": "Envoyer", "Menu:Emailing": "Envoi par e-mail", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hi.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hi.json index 73e0340584..786616f901 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hi.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hi.json @@ -14,7 +14,7 @@ "Body": "शरीर", "TestEmailSubject": "परीक्षण ईमेल {0}", "TestEmailBody": "यहां ईमेल बॉडी संदेश का परीक्षण करें", - "SuccessfullySent": "सफलतापूर्वक भेजा", + "SentSuccessfully": "सफलतापूर्वक भेज दिया गया", "MailSendingFailed": "मेल भेजने में विफल, कृपया अपनी ईमेल विन्यास की जाँच करें और पुनः प्रयास करें।", "Send": "भेजना", "Menu:Emailing": "ईमेल से भेजना", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json index db40dafe47..acd0c132fa 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json @@ -14,7 +14,7 @@ "Body": "Tijelo", "TestEmailSubject": "Probna e-pošta {0}", "TestEmailBody": "Testirajte tijelo poruke e-pošte ovdje", - "SuccessfullySent": "Uspješno poslano", + "SentSuccessfully": "Poslan uspješno", "MailSendingFailed": "Slanje e-pošte nije uspjelo, provjerite konfiguraciju e-pošte i pokušajte ponovo.", "Send": "Poslati", "Menu:Emailing": "Slanje e-poštom", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hu.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hu.json index c2cc70cb5b..c47a813371 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hu.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hu.json @@ -14,7 +14,7 @@ "Body": "Test", "TestEmailSubject": "Teszt e-mail {0}", "TestEmailBody": "Itt tesztelheti az e-mail törzsüzenetét", - "SuccessfullySent": "Sikeresen elküldve", + "SentSuccessfully": "Sikeresen elküldve", "MailSendingFailed": "Az e-mail küldése sikertelen, ellenőrizze az e-mail konfigurációját, és próbálja újra.", "Send": "Küld", "Menu:Emailing": "E-mailezés", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/is.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/is.json index cd80ba6fc3..f39b10f795 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/is.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/is.json @@ -14,7 +14,7 @@ "Body": "Líkami", "TestEmailSubject": "Prófunartölvupóstur {0}", "TestEmailBody": "Prófaðu meginmál tölvupósts hér", - "SuccessfullySent": "Tókst sent", + "SentSuccessfully": "Tókst að senda", "MailSendingFailed": "Tölvupóstur sendist ekki. Athugaðu tölvupóst stillingar þínar og reyndu aftur.", "Send": "Senda", "Menu:Emailing": "Senda tölvupóst", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json index c03c678318..3de6657509 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json @@ -14,7 +14,7 @@ "Body": "Corpo", "TestEmailSubject": "Prova l'e-mail {0}", "TestEmailBody": "Prova il corpo del messaggio email qui", - "SuccessfullySent": "Inviato con successo", + "SentSuccessfully": "Inviato con successo", "MailSendingFailed": "Invio della posta fallito, controlla la tua configurazione email e riprova.", "Send": "Inviare", "Menu:Emailing": "Invio di e-mail", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/nl.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/nl.json index e68f8a0b2c..a188146d0e 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/nl.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/nl.json @@ -14,7 +14,7 @@ "Body": "Lichaam", "TestEmailSubject": "Test-e-mail {0}", "TestEmailBody": "Test hier het hoofdbericht van de e-mail", - "SuccessfullySent": "Succesvol verzonden", + "SentSuccessfully": "Succesvol verzonden", "MailSendingFailed": "E-mail verzenden mislukt. Controleer uw e-mailconfiguratie en probeer het opnieuw.", "Send": "Versturen", "Menu:Emailing": "E-mail", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json index 0e900acb36..a4bbd7238e 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json @@ -14,7 +14,7 @@ "Body": "Ciało", "TestEmailSubject": "Testowy e-mail {0}", "TestEmailBody": "Tutaj przetestuj treść wiadomości e-mail", - "SuccessfullySent": "Pomyślnie wysłane", + "SentSuccessfully": "Wysłano pomyślnie", "MailSendingFailed": "Wysyłanie e-maila nie powiodło się. Sprawdź konfigurację e-maila i spróbuj ponownie.", "Send": "Wysłać", "Menu:Emailing": "Wysyłanie e-maili", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json index 4d3719e229..c6c951c025 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json @@ -14,7 +14,7 @@ "Body": "Corpo", "TestEmailSubject": "E-mail teste {0}", "TestEmailBody": "Corpo de e-mail de teste aqui", - "SuccessfullySent": "Enviado com sucesso", + "SentSuccessfully": "Enviado com sucesso", "MailSendingFailed": "Falha no envio de e-mail, verifique sua configuração de e-mail e tente novamente.", "Send": "Enviar", "Menu:Emailing": "Enviando por e-mail", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json index dccb428a93..7e1eac80be 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json @@ -14,7 +14,7 @@ "Body": "Corp", "TestEmailSubject": "E-mail de testare {0}", "TestEmailBody": "Testați corpul mesajului de e-mail aici", - "SuccessfullySent": "Trimis cu succes", + "SentSuccessfully": "Trimis cu succes", "MailSendingFailed": "Trimiterea e-mailului a eșuat. Verificați configurația e-mailului și încercați din nou.", "Send": "Trimite", "Menu:Emailing": "Emailing", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json index c7a48b8c2e..9fde67ff61 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json @@ -14,7 +14,7 @@ "Body": "Тело", "TestEmailSubject": "Тестовое письмо {0}", "TestEmailBody": "Проверьте текст сообщения электронной почты здесь", - "SuccessfullySent": "Успешно отправлено", + "SentSuccessfully": "отправлено успешно", "MailSendingFailed": "Не удалось отправить письмо. Пожалуйста, проверьте настройки электронной почты и повторите попытку.", "Send": "Отправлять", "Menu:Emailing": "Отправка по электронной почте", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json index dfee758b09..e06c4d9d0a 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json @@ -14,7 +14,7 @@ "Body": "Telo", "TestEmailSubject": "Testovací e-mail {0}", "TestEmailBody": "Tu otestujte telo e-mailu", - "SuccessfullySent": "Úspešne odoslané", + "SentSuccessfully": "Úspešne odoslané", "MailSendingFailed": "Odoslanie emailu zlyhalo. Skontrolujte konfiguráciu emailu a skúste to znova.", "Send": "Odoslať", "Menu:Emailing": "Posielanie emailov", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json index 81af7b908c..509ce74e08 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json @@ -14,7 +14,7 @@ "Body": "Telo", "TestEmailSubject": "Preskusno e-poštno sporočilo {0}", "TestEmailBody": "Tukaj preizkusite telo e-poštnega sporočila", - "SuccessfullySent": "Uspešno poslano", + "SentSuccessfully": "Poslano uspešno", "MailSendingFailed": "Pošiljanje e-pošte ni uspelo, preverite konfiguracijo e-pošte in poskusite znova.", "Send": "Pošlji", "Menu:Emailing": "Pošiljanje po e-pošti", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sv.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sv.json index 3e66d68871..ad74a9c147 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sv.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sv.json @@ -14,7 +14,7 @@ "Body": "Kropp", "TestEmailSubject": "Testa e-post {0}", "TestEmailBody": "Testa e-postmeddelandets brödtext här", - "SuccessfullySent": "Framgångsrikt skickat", + "SentSuccessfully": "Skickat framgångsrikt", "Send": "Skicka", "Menu:Emailing": "E-post", "Menu:TimeZone": "Tidszon", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json index c91e50d716..aab8928026 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json @@ -14,7 +14,7 @@ "Body": "Gövde", "TestEmailSubject": "Test email {0}", "TestEmailBody": "E-posta gövdesi mesajını burada test edin", - "SuccessfullySent": "Başarıyla gönderildi", + "SentSuccessfully": "Gönderildi", "MailSendingFailed": "E-posta gönderme başarısız, lütfen e-posta yapılandırmanızı kontrol edin ve tekrar deneyin.", "Send": "Gönder", "Menu:Emailing": "Email", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json index 42d9af1b32..94acb63a71 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json @@ -14,7 +14,7 @@ "Body": "Thân hình", "TestEmailSubject": "Kiểm tra email {0}", "TestEmailBody": "Kiểm tra nội dung email tại đây", - "SuccessfullySent": "Đã gửi thành công", + "SentSuccessfully": "Gửi thành công", "MailSendingFailed": "Gửi email thất bại. Vui lòng kiểm tra cấu hình email của bạn và thử lại.", "Send": "Gửi", "Menu:Emailing": "Gửi email", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json index 3ad7f5efa4..339f14e292 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json @@ -14,7 +14,7 @@ "Body": "正文", "TestEmailSubject": "测试邮件 {0}", "TestEmailBody": "测试邮件内容", - "SuccessfullySent": "发送成功", + "SentSuccessfully": "发送成功", "MailSendingFailed": "邮件发送失败,请检查您的电子邮件配置并重试。", "Send": "发送", "Menu:Emailing": "邮件", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hant.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hant.json index add9d88e5c..e3a06511c2 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hant.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hant.json @@ -14,7 +14,7 @@ "Body": "內文", "TestEmailSubject": "測試郵件 {0}", "TestEmailBody": "測試郵件內容", - "SuccessfullySent": "成功發送", + "SentSuccessfully": "發送成功", "MailSendingFailed": "郵件發送失敗,請檢查你的郵件配置並重試.", "Send": "發送", "Menu:Emailing": "信箱", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Installer/InstallationNotes.md b/modules/setting-management/src/Volo.Abp.SettingManagement.Installer/InstallationNotes.md new file mode 100644 index 0000000000..dd675ae5ec --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Installer/InstallationNotes.md @@ -0,0 +1,15 @@ +# Installation Notes for Setting Management Module + +The Setting Management module provides a way to store and manage settings in an ABP application. Settings are used to store application, tenant, or user-specific configuration values that can be changed at runtime. The module includes both a UI for setting management and an API for programmatic setting management. + +Key features of the Setting Management module: +- Store and retrieve settings +- Multi-level setting management (global, tenant, user) +- Setting management UI +- Extensible setting provider system +- Multi-tenancy support +- Integration with other ABP modules + +## Documentation + +For detailed information and usage instructions, please visit the [Setting Management Module documentation](https://abp.io/docs/latest/Modules/Setting-Management). \ No newline at end of file diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingDefinitionRecordRepository.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingDefinitionRecordRepository.cs index d2500cccd2..3ea0206759 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingDefinitionRecordRepository.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingDefinitionRecordRepository.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using System.Linq; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; @@ -16,7 +17,7 @@ public class MongoSettingDefinitionRecordRepository : MongoDbRepository FindByNameAsync(string name, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(s => s.Name == name, GetCancellationToken(cancellationToken)); } diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs index 74c680e7e2..ea264b254e 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.MongoDB/Volo/Abp/SettingManagement/MongoDB/MongoSettingRepository.cs @@ -24,7 +24,7 @@ public class MongoSettingRepository : MongoDbRepository x.Id) .FirstOrDefaultAsync( s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey, @@ -36,7 +36,7 @@ public class MongoSettingRepository : MongoDbRepository s.ProviderName == providerName && s.ProviderKey == providerKey) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -47,7 +47,7 @@ public class MongoSettingRepository : MongoDbRepository names.Contains(s.Name) && s.ProviderName == providerName && s.ProviderKey == providerKey) .ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.js b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.js index ae8e694de3..6dd040ad5c 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.js +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.js @@ -40,7 +40,7 @@ }) _sendTestEmailModal.onResult(function () { - abp.notify.success(l('SuccessfullySent')); + abp.notify.success(l('SentSuccessfully')); }); $("#SendTestEmailButton").click(function (e) { diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj index 65ea9436ee..9c2c2f36a9 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj @@ -18,10 +18,10 @@ - - - - + + + + diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs index 625b66b328..bc5feb98b1 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo/Abp/SettingManagement/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace Volo.Abp.SettingManagement.MongoDB; diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/InstallationNotes.md b/modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/InstallationNotes.md new file mode 100644 index 0000000000..3a4dcd4fc6 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/InstallationNotes.md @@ -0,0 +1,9 @@ +# Installation Notes for Tenant Management Module + +The ABP Tenant Management module provides multi-tenancy features for your ABP-based applications. It implements the `ITenantStore` interface and provides UI to manage tenants and their features. + +This module is part of the ABP Framework and provides the core functionality needed to build multi-tenant (SaaS) applications. + +## Documentation + +For detailed information and usage instructions, please visit the [Tenant Management module documentation](https://abp.io/docs/latest/modules/tenant-management). \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs index 049dc5e57c..758ece4d71 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.MongoDB/Volo/Abp/TenantManagement/MongoDb/MongoTenantRepository.cs @@ -24,21 +24,21 @@ public class MongoTenantRepository : MongoDbRepository t.NormalizedName == normalizedName, GetCancellationToken(cancellationToken)); } [Obsolete("Use FindByNameAsync method.")] public virtual Tenant FindByName(string normalizedName, bool includeDetails = true) { - return GetMongoQueryable() + return GetQueryable() .FirstOrDefault(t => t.NormalizedName == normalizedName); } [Obsolete("Use FindAsync method.")] public virtual Tenant FindById(Guid id, bool includeDetails = true) { - return GetMongoQueryable() + return GetQueryable() .FirstOrDefault(t => t.Id == id); } @@ -50,22 +50,21 @@ public class MongoTenantRepository : MongoDbRepository>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Name.Contains(filter) ) .OrderBy(sorting.IsNullOrEmpty() ? nameof(Tenant.Name) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.Name.Contains(filter) diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj index c22da31998..2913a0ed53 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj @@ -18,10 +18,10 @@ - - - - + + + + diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs index 7b12dc33e7..4610234bf6 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo/Abp/TenantManagement/MongoDb/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; using MongoDB.Driver; using Volo.Abp.MongoDB; diff --git a/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs b/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs index d0e1e76873..2e657227b1 100644 --- a/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs +++ b/modules/users/src/Volo.Abp.Users.MongoDB/Volo/Abp/Users/MongoDB/MongoUserRepositoryBase.cs @@ -24,7 +24,7 @@ public abstract class MongoUserRepositoryBase : MongoDbReposi public virtual async Task FindByUserNameAsync(string userName, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) .FirstOrDefaultAsync(u => u.UserName == userName, cancellationToken); } @@ -32,7 +32,7 @@ public abstract class MongoUserRepositoryBase : MongoDbReposi public virtual async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetQueryableAsync(cancellationToken)) .Where(u => ids.Contains(u.Id)) .ToListAsync(cancellationToken); } @@ -45,8 +45,8 @@ public abstract class MongoUserRepositoryBase : MongoDbReposi CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || @@ -55,16 +55,15 @@ public abstract class MongoUserRepositoryBase : MongoDbReposi (u.Surname != null && u.Surname.Contains(filter)) ) .OrderBy(sorting.IsNullOrEmpty() ? nameof(IUserData.UserName) : sorting) - .As>() - .PageBy>(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .ToListAsync(cancellationToken); } public async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) - .WhereIf>( + return await (await GetQueryableAsync(cancellationToken)) + .WhereIf( !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || diff --git a/modules/virtual-file-explorer/.abpstudio/state.json b/modules/virtual-file-explorer/.abpstudio/state.json new file mode 100644 index 0000000000..b0ef88d2f2 --- /dev/null +++ b/modules/virtual-file-explorer/.abpstudio/state.json @@ -0,0 +1,11 @@ +{ + "selectedKubernetesProfile": null, + "solutionRunner": { + "selectedProfile": null, + "targetFrameworks": [], + "applicationsStartingWithoutBuild": [], + "applicationsWithoutAutoRefreshBrowserOnRestart": [], + "applicationBatchStartStates": [], + "folderBatchStartStates": [] + } +} \ No newline at end of file diff --git a/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.abpmdl b/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.abpmdl index 3c025e6ade..d5210d1e6b 100644 --- a/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.abpmdl +++ b/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.abpmdl @@ -7,9 +7,13 @@ }, "packages": { "Volo.Abp.VirtualFileExplorer.DemoApp": { - "path": "app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.abppkg", + "path": "app/DemoApp.abppkg", "folder": "app" }, + "Volo.Abp.VirtualFileExplorer.Contracts": { + "path": "src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg", + "folder": "src" + }, "Volo.Abp.VirtualFileExplorer.Web": { "path": "src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.abppkg", "folder": "src" diff --git a/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.abpsln b/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.abpsln index 264a302af3..73a99eb6c5 100644 --- a/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.abpsln +++ b/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.abpsln @@ -3,5 +3,6 @@ "Volo.Abp.VirtualFileExplorer": { "path": "Volo.Abp.VirtualFileExplorer.abpmdl" } - } + }, + "id": "d900c5b2-d907-4abb-bc38-b72f80006fe0" } \ No newline at end of file diff --git a/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.sln b/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.sln index 67b9741932..da8e8f67d4 100644 --- a/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.sln +++ b/modules/virtual-file-explorer/Volo.Abp.VirtualFileExplorer.sln @@ -9,10 +9,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.VirtualFileExplore EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{0489DA85-A27F-4D98-9DBD-950F5F2ECD11}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.VirtualFileExplorer.DemoApp", "app\Volo.Abp.VirtualFileExplorer.DemoApp\Volo.Abp.VirtualFileExplorer.DemoApp.csproj", "{6DAA2A8D-5422-4C3B-BA70-B54D949B1678}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.VirtualFileExplorer.Installer", "src\Volo.Abp.VirtualFileExplorer.Installer\Volo.Abp.VirtualFileExplorer.Installer.csproj", "{638DDC11-0B86-4B5D-A518-4A8158665074}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.VirtualFileExplorer.Contracts", "src\Volo.Abp.VirtualFileExplorer.Contracts\Volo.Abp.VirtualFileExplorer.Contracts.csproj", "{21FC5247-29FF-4D02-BB6A-8A739AC5640D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DemoApp", "app\DemoApp.csproj", "{C447E4F2-7FCA-49B6-8249-7E04C9E26BAD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -23,22 +25,27 @@ Global {3B7B6317-1B85-4164-8E11-75574F80AE17}.Debug|Any CPU.Build.0 = Debug|Any CPU {3B7B6317-1B85-4164-8E11-75574F80AE17}.Release|Any CPU.ActiveCfg = Release|Any CPU {3B7B6317-1B85-4164-8E11-75574F80AE17}.Release|Any CPU.Build.0 = Release|Any CPU - {6DAA2A8D-5422-4C3B-BA70-B54D949B1678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6DAA2A8D-5422-4C3B-BA70-B54D949B1678}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6DAA2A8D-5422-4C3B-BA70-B54D949B1678}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6DAA2A8D-5422-4C3B-BA70-B54D949B1678}.Release|Any CPU.Build.0 = Release|Any CPU {638DDC11-0B86-4B5D-A518-4A8158665074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {638DDC11-0B86-4B5D-A518-4A8158665074}.Debug|Any CPU.Build.0 = Debug|Any CPU {638DDC11-0B86-4B5D-A518-4A8158665074}.Release|Any CPU.ActiveCfg = Release|Any CPU {638DDC11-0B86-4B5D-A518-4A8158665074}.Release|Any CPU.Build.0 = Release|Any CPU + {21FC5247-29FF-4D02-BB6A-8A739AC5640D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21FC5247-29FF-4D02-BB6A-8A739AC5640D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21FC5247-29FF-4D02-BB6A-8A739AC5640D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21FC5247-29FF-4D02-BB6A-8A739AC5640D}.Release|Any CPU.Build.0 = Release|Any CPU + {C447E4F2-7FCA-49B6-8249-7E04C9E26BAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C447E4F2-7FCA-49B6-8249-7E04C9E26BAD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C447E4F2-7FCA-49B6-8249-7E04C9E26BAD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C447E4F2-7FCA-49B6-8249-7E04C9E26BAD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {3B7B6317-1B85-4164-8E11-75574F80AE17} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} - {6DAA2A8D-5422-4C3B-BA70-B54D949B1678} = {0489DA85-A27F-4D98-9DBD-950F5F2ECD11} {638DDC11-0B86-4B5D-A518-4A8158665074} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {21FC5247-29FF-4D02-BB6A-8A739AC5640D} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {C447E4F2-7FCA-49B6-8249-7E04C9E26BAD} = {0489DA85-A27F-4D98-9DBD-950F5F2ECD11} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD} diff --git a/modules/virtual-file-explorer/app/Data/DemoAppDbContext.cs b/modules/virtual-file-explorer/app/Data/DemoAppDbContext.cs new file mode 100644 index 0000000000..ee3ec23421 --- /dev/null +++ b/modules/virtual-file-explorer/app/Data/DemoAppDbContext.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; + +namespace DemoApp.Data; + +public class DemoAppDbContext : AbpDbContext +{ + public DemoAppDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + builder.ConfigurePermissionManagement(); + builder.ConfigureIdentity(); + } +} diff --git a/modules/virtual-file-explorer/app/Data/DemoAppDbContextFactory.cs b/modules/virtual-file-explorer/app/Data/DemoAppDbContextFactory.cs new file mode 100644 index 0000000000..1f0d7e56c4 --- /dev/null +++ b/modules/virtual-file-explorer/app/Data/DemoAppDbContextFactory.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; + +namespace DemoApp.Data; + +public class DemoAppDbContextFactory : IDesignTimeDbContextFactory +{ + public DemoAppDbContext CreateDbContext(string[] args) + { + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .UseSqlServer(configuration.GetConnectionString("Default")); + + return new DemoAppDbContext(builder.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: false); + + return builder.Build(); + } +} diff --git a/modules/virtual-file-explorer/app/DemoApp.abppkg b/modules/virtual-file-explorer/app/DemoApp.abppkg new file mode 100644 index 0000000000..48875c29cf --- /dev/null +++ b/modules/virtual-file-explorer/app/DemoApp.abppkg @@ -0,0 +1,3 @@ +{ + "role": "host.mvc" +} \ No newline at end of file diff --git a/modules/virtual-file-explorer/app/DemoApp.csproj b/modules/virtual-file-explorer/app/DemoApp.csproj new file mode 100644 index 0000000000..938e3f03b1 --- /dev/null +++ b/modules/virtual-file-explorer/app/DemoApp.csproj @@ -0,0 +1,64 @@ + + + net9.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers + compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native + + + + + + Always + + + Always + + + + diff --git a/modules/virtual-file-explorer/app/DemoAppModule.cs b/modules/virtual-file-explorer/app/DemoAppModule.cs new file mode 100644 index 0000000000..ae03d3f2ed --- /dev/null +++ b/modules/virtual-file-explorer/app/DemoAppModule.cs @@ -0,0 +1,134 @@ +using DemoApp.Data; +using Microsoft.EntityFrameworkCore; +using Volo.Abp; +using Volo.Abp.Account; +using Volo.Abp.Account.Web; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; +using Volo.Abp.AspNetCore.Serilog; +using Volo.Abp.Autofac; +using Volo.Abp.AutoMapper; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.SqlServer; +using Volo.Abp.Identity; +using Volo.Abp.Identity.EntityFrameworkCore; +using Volo.Abp.Identity.Web; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.PermissionManagement.EntityFrameworkCore; +using Volo.Abp.PermissionManagement.HttpApi; +using Volo.Abp.PermissionManagement.Identity; +using Volo.Abp.PermissionManagement.Web; +using Volo.Abp.Swashbuckle; +using Volo.Abp.VirtualFileExplorer.Web; + +namespace DemoApp; + +[DependsOn( + // ABP Framework packages + typeof(AbpAspNetCoreMvcModule), + typeof(AbpAutofacModule), + typeof(AbpAutoMapperModule), + typeof(AbpSwashbuckleModule), + typeof(AbpAspNetCoreSerilogModule), + + // basic-theme + typeof(AbpAspNetCoreMvcUiBasicThemeModule), + + // VirtualFileExplorer module packages + typeof(AbpVirtualFileExplorerWebModule), + + // Account module packages + typeof(AbpAccountWebModule), + typeof(AbpAccountHttpApiModule), + typeof(AbpAccountApplicationModule), + + // Identity module packages + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpIdentityWebModule), + typeof(AbpIdentityHttpApiModule), + typeof(AbpIdentityApplicationModule), + typeof(AbpIdentityEntityFrameworkCoreModule), + + // Permission Management module packages + typeof(AbpPermissionManagementWebModule), + typeof(AbpPermissionManagementApplicationModule), + typeof(AbpPermissionManagementHttpApiModule), + typeof(AbpPermissionManagementEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqlServerModule) +)] +public class DemoAppModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.SaveStaticPermissionsToDatabase = false; + }); + + Configure(options => + { + options.IsEnabled = true; + }); + + Configure(options => + { + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + }); + + context.Services.AddAbpDbContext(options => + { + options.AddDefaultRepositories(includeAllEntities: true); + }); + + Configure(options => + { + options.Configure(configurationContext => + { + configurationContext.UseSqlServer(); + }); + }); + } + + public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) + { + await context.ServiceProvider + .GetRequiredService() + .Database + .MigrateAsync(); + + await context.ServiceProvider + .GetRequiredService() + .SeedAsync(); + + var app = context.GetApplicationBuilder(); + var env = context.GetEnvironment(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseAbpRequestLocalization(); + + if (!env.IsDevelopment()) + { + app.UseErrorPage(); + } + + app.MapAbpStaticAssets(); + + app.UseRouting(); + app.UseUnitOfWork(); + app.UseAuthentication(); + app.UseMultiTenancy(); + app.UseAuthorization(); + app.UseConfiguredEndpoints(); + } +} diff --git a/modules/virtual-file-explorer/app/Directory.Packages.props b/modules/virtual-file-explorer/app/Directory.Packages.props new file mode 100644 index 0000000000..c416fb784b --- /dev/null +++ b/modules/virtual-file-explorer/app/Directory.Packages.props @@ -0,0 +1,5 @@ + + + false + + \ No newline at end of file diff --git a/modules/virtual-file-explorer/app/Migrations/20250315060727_Initial.Designer.cs b/modules/virtual-file-explorer/app/Migrations/20250315060727_Initial.Designer.cs new file mode 100644 index 0000000000..016aade1a7 --- /dev/null +++ b/modules/virtual-file-explorer/app/Migrations/20250315060727_Initial.Designer.cs @@ -0,0 +1,985 @@ +// +using System; +using DemoApp.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace DemoApp.Migrations +{ + [DbContext(typeof(DemoAppDbContext))] + [Migration("20250315060727_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("ProductVersion", "9.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("bit") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("bit") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("bit") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("LastAccessed") + .HasColumnType("datetime2"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("SignedIn") + .HasColumnType("datetime2"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("datetimeoffset"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("bit"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("nvarchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("bit"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[TenantId] IS NOT NULL"); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/virtual-file-explorer/app/Migrations/20250315060727_Initial.cs b/modules/virtual-file-explorer/app/Migrations/20250315060727_Initial.cs new file mode 100644 index 0000000000..1fc66a9503 --- /dev/null +++ b/modules/virtual-file-explorer/app/Migrations/20250315060727_Initial.cs @@ -0,0 +1,606 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace DemoApp.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Required = table.Column(type: "bit", nullable: false), + IsStatic = table.Column(type: "bit", nullable: false), + Regex = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + RegexDescription = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + Description = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ValueType = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpLinkUsers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + SourceUserId = table.Column(type: "uniqueidentifier", nullable: false), + SourceTenantId = table.Column(type: "uniqueidentifier", nullable: true), + TargetUserId = table.Column(type: "uniqueidentifier", nullable: false), + TargetTenantId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLinkUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ParentId = table.Column(type: "uniqueidentifier", nullable: true), + Code = table.Column(type: "nvarchar(95)", maxLength: 95, nullable: false), + DisplayName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGrants", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + ProviderKey = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGrants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissionGroups", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpPermissions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + GroupName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ParentName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + IsEnabled = table.Column(type: "bit", nullable: false), + MultiTenancySide = table.Column(type: "tinyint", nullable: false), + Providers = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + StateCheckers = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpRoles", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + IsDefault = table.Column(type: "bit", nullable: false), + IsStatic = table.Column(type: "bit", nullable: false), + IsPublic = table.Column(type: "bit", nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSecurityLogs", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ApplicationName = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + Identity = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + Action = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), + UserId = table.Column(type: "uniqueidentifier", nullable: true), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + TenantName = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ClientId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + CorrelationId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + ClientIpAddress = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + BrowserInfo = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpSessions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + SessionId = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Device = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + DeviceInfo = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + UserId = table.Column(type: "uniqueidentifier", nullable: false), + ClientId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + IpAddresses = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: true), + SignedIn = table.Column(type: "datetime2", nullable: false), + LastAccessed = table.Column(type: "datetime2", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSessions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUserDelegations", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + SourceUserId = table.Column(type: "uniqueidentifier", nullable: false), + TargetUserId = table.Column(type: "uniqueidentifier", nullable: false), + StartTime = table.Column(type: "datetime2", nullable: false), + EndTime = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserDelegations", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpUsers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Name = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + Surname = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + EmailConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + PasswordHash = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + IsExternal = table.Column(type: "bit", nullable: false, defaultValue: false), + PhoneNumber = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false, defaultValue: false), + IsActive = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false, defaultValue: false), + AccessFailedCount = table.Column(type: "int", nullable: false, defaultValue: 0), + ShouldChangePasswordOnNextLogin = table.Column(type: "bit", nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), + LastPasswordChangeTime = table.Column(type: "datetimeoffset", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + OrganizationUnitId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpRoleClaims", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ClaimType = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpRoleClaims_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserClaims", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ClaimType = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + ClaimValue = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpUserClaims_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserLogins", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + LoginProvider = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + ProviderKey = table.Column(type: "nvarchar(196)", maxLength: 196, nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); + table.ForeignKey( + name: "FK_AbpUserLogins_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + OrganizationUnitId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUnitId", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserRoles", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AbpUserTokens", + columns: table => new + { + UserId = table.Column(type: "uniqueidentifier", nullable: false), + LoginProvider = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Value = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AbpUserTokens_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpLinkUsers_SourceUserId_SourceTenantId_TargetUserId_TargetTenantId", + table: "AbpLinkUsers", + columns: new[] { "SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId" }, + unique: true, + filter: "[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGrants_TenantId_Name_ProviderName_ProviderKey", + table: "AbpPermissionGrants", + columns: new[] { "TenantId", "Name", "ProviderName", "ProviderKey" }, + unique: true, + filter: "[TenantId] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGroups_Name", + table: "AbpPermissionGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_GroupName", + table: "AbpPermissions", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_Name", + table: "AbpPermissions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoleClaims_RoleId", + table: "AbpRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoles_NormalizedName", + table: "AbpRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Action", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Action" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_ApplicationName", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "ApplicationName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Identity", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Identity" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_UserId", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_Device", + table: "AbpSessions", + column: "Device"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_SessionId", + table: "AbpSessions", + column: "SessionId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_TenantId_UserId", + table: "AbpSessions", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserClaims_UserId", + table: "AbpUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserLogins_LoginProvider_ProviderKey", + table: "AbpUserLogins", + columns: new[] { "LoginProvider", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserRoles_RoleId_UserId", + table: "AbpUserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_Email", + table: "AbpUsers", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedEmail", + table: "AbpUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedUserName", + table: "AbpUsers", + column: "NormalizedUserName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_UserName", + table: "AbpUsers", + column: "UserName"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropTable( + name: "AbpLinkUsers"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpPermissionGrants"); + + migrationBuilder.DropTable( + name: "AbpPermissionGroups"); + + migrationBuilder.DropTable( + name: "AbpPermissions"); + + migrationBuilder.DropTable( + name: "AbpRoleClaims"); + + migrationBuilder.DropTable( + name: "AbpSecurityLogs"); + + migrationBuilder.DropTable( + name: "AbpSessions"); + + migrationBuilder.DropTable( + name: "AbpUserClaims"); + + migrationBuilder.DropTable( + name: "AbpUserDelegations"); + + migrationBuilder.DropTable( + name: "AbpUserLogins"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpUserRoles"); + + migrationBuilder.DropTable( + name: "AbpUserTokens"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpRoles"); + + migrationBuilder.DropTable( + name: "AbpUsers"); + } + } +} diff --git a/modules/virtual-file-explorer/app/Migrations/DemoAppDbContextModelSnapshot.cs b/modules/virtual-file-explorer/app/Migrations/DemoAppDbContextModelSnapshot.cs new file mode 100644 index 0000000000..2dc39f2526 --- /dev/null +++ b/modules/virtual-file-explorer/app/Migrations/DemoAppDbContextModelSnapshot.cs @@ -0,0 +1,982 @@ +// +using System; +using DemoApp.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace DemoApp.Migrations +{ + [DbContext(typeof(DemoAppDbContext))] + partial class DemoAppDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("ProductVersion", "9.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("bit") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("bit") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("bit") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("LastAccessed") + .HasColumnType("datetime2"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("SignedIn") + .HasColumnType("datetime2"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("datetimeoffset"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("bit"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("nvarchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("bit"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[TenantId] IS NOT NULL"); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/virtual-file-explorer/app/Pages/Index.cshtml b/modules/virtual-file-explorer/app/Pages/Index.cshtml new file mode 100644 index 0000000000..2b4fd37270 --- /dev/null +++ b/modules/virtual-file-explorer/app/Pages/Index.cshtml @@ -0,0 +1,4 @@ +@page +@using Volo.Abp.Users +@model DemoApp.Pages.IndexModel +@inject ICurrentUser CurrentUser diff --git a/modules/virtual-file-explorer/app/Pages/Index.cshtml.cs b/modules/virtual-file-explorer/app/Pages/Index.cshtml.cs new file mode 100644 index 0000000000..5f8da0f725 --- /dev/null +++ b/modules/virtual-file-explorer/app/Pages/Index.cshtml.cs @@ -0,0 +1,8 @@ +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace DemoApp.Pages; + +public class IndexModel : AbpPageModel +{ + +} \ No newline at end of file diff --git a/modules/virtual-file-explorer/app/Pages/_ViewImports.cshtml b/modules/virtual-file-explorer/app/Pages/_ViewImports.cshtml new file mode 100644 index 0000000000..6d6bdbde94 --- /dev/null +++ b/modules/virtual-file-explorer/app/Pages/_ViewImports.cshtml @@ -0,0 +1,4 @@ +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling \ No newline at end of file diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Program.cs b/modules/virtual-file-explorer/app/Program.cs similarity index 50% rename from modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Program.cs rename to modules/virtual-file-explorer/app/Program.cs index 4b2c43079c..3471652b7c 100644 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Program.cs +++ b/modules/virtual-file-explorer/app/Program.cs @@ -1,47 +1,46 @@ -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Serilog; -using Serilog.Events; - -namespace Volo.Abp.VirtualFileExplorer.DemoApp; - -public class Program -{ - public static async Task Main(string[] args) - { - Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.File("Logs/logs.txt") - .CreateLogger(); - - try - { - Log.Information("Starting web host."); +using Serilog; +using Serilog.Events; + +namespace DemoApp; + +public class Program +{ + public async static Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Debug() + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + try + { var builder = WebApplication.CreateBuilder(args); - builder.Host - .AddAppSettingsSecretsJson() - .UseSerilog() + builder.Host.AddAppSettingsSecretsJson() .UseAutofac() - ; - await builder.AddApplicationAsync(); + .UseSerilog(); + + await builder.AddApplicationAsync(); var app = builder.Build(); await app.InitializeApplicationAsync(); - await app.RunAsync(); - return 0; - } - catch (Exception ex) - { - Log.Fatal(ex, "Host terminated unexpectedly!"); - return 1; - } - finally - { - Log.CloseAndFlush(); - } - } -} + Log.Information("Starting DemoApp."); + await app.RunAsync(); + return 0; + } + catch (Exception ex) + { + if (ex is HostAbortedException) + { + throw; + } + + Log.Fatal(ex, "DemoApp terminated unexpectedly!"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } +} diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Properties/launchSettings.json b/modules/virtual-file-explorer/app/Properties/launchSettings.json similarity index 70% rename from modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Properties/launchSettings.json rename to modules/virtual-file-explorer/app/Properties/launchSettings.json index 83b0d02709..c0680d491c 100644 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Properties/launchSettings.json +++ b/modules/virtual-file-explorer/app/Properties/launchSettings.json @@ -3,8 +3,8 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:51233", - "sslPort": 44377 + "applicationUrl": "https://localhost:44391/", + "sslPort": 44391 } }, "profiles": { @@ -15,13 +15,13 @@ "ASPNETCORE_ENVIRONMENT": "Development" } }, - "Volo.Abp.VirtualFileExplorer.DemoApp": { + "DemoApp": { "commandName": "Project", "launchBrowser": true, - "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "applicationUrl": "https://localhost:44391/" } } -} +} \ No newline at end of file diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/AbpVirtualFileExplorerDemoAppModule.cs b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/AbpVirtualFileExplorerDemoAppModule.cs deleted file mode 100644 index c7cc5f4484..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/AbpVirtualFileExplorerDemoAppModule.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; -using Volo.Abp.Autofac; -using Volo.Abp.Localization; -using Volo.Abp.Modularity; -using Volo.Abp.VirtualFileExplorer.Web; - -namespace Volo.Abp.VirtualFileExplorer.DemoApp; - -[DependsOn( - typeof(AbpAutofacModule), - typeof(AbpAspNetCoreMvcUiBasicThemeModule), - typeof(AbpVirtualFileExplorerWebModule) -)] -public class AbpVirtualFileExplorerDemoAppModule : AbpModule -{ - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); - options.Languages.Add(new LanguageInfo("en", "en", "English")); - options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); - options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); - options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi")); - options.Languages.Add(new LanguageInfo("is", "is", "Icelandic")); - options.Languages.Add(new LanguageInfo("it", "it", "Italiano")); - options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar")); - options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română")); - options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); - options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); - options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); - options.Languages.Add(new LanguageInfo("el", "el", "Ελληνικά")); - }); - } - - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var app = context.GetApplicationBuilder(); - - app.MapAbpStaticAssets(); - app.UseRouting(); - app.UseAbpRequestLocalization(); - app.UseConfiguredEndpoints(); - } -} diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Branding/AbpVirtualFileExplorerDemoAppBrandingProvider.cs b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Branding/AbpVirtualFileExplorerDemoAppBrandingProvider.cs deleted file mode 100644 index 89659be15c..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Branding/AbpVirtualFileExplorerDemoAppBrandingProvider.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Volo.Abp.Ui.Branding; -using Volo.Abp.DependencyInjection; - -namespace Volo.Abp.VirtualFileExplorer.DemoApp.Branding; - -[Dependency(ReplaceServices = true)] -public class AbpVirtualFileExplorerDemoAppBrandingProvider : DefaultBrandingProvider -{ - public AbpVirtualFileExplorerDemoAppBrandingProvider() - { - AppName = "Virtual file explorer demo app"; - - - } - - public override string AppName { get; } - - public override string LogoUrl { get; } -} diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Pages/Index.cshtml b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Pages/Index.cshtml deleted file mode 100644 index fb6ccb3305..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Pages/Index.cshtml +++ /dev/null @@ -1,14 +0,0 @@ -@page - -@model Volo.Abp.VirtualFileExplorer.DemoApp.Pages.IndexModel - -
      -
      -
      -

      Virtual file explprer demo application

      -
      -
      -
      - abp.io - -
      diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Pages/Index.cshtml.cs b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Pages/Index.cshtml.cs deleted file mode 100644 index 779bdd97e8..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Pages/Index.cshtml.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.Extensions.Logging; - -namespace Volo.Abp.VirtualFileExplorer.DemoApp.Pages; - -public class IndexModel : PageModel -{ - private readonly ILogger _logger; - - public IndexModel(ILogger logger) - { - _logger = logger; - } - - public void OnGet() - { - } -} diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Pages/_ViewImports.cshtml b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Pages/_ViewImports.cshtml deleted file mode 100644 index 231948b339..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Pages/_ViewImports.cshtml +++ /dev/null @@ -1,4 +0,0 @@ -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI -@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap -@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.abppkg b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.abppkg deleted file mode 100644 index 9e26dfeeb6..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.abppkg +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.csproj b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.csproj deleted file mode 100644 index 683766e077..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Volo.Abp.VirtualFileExplorer.DemoApp.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - net9.0 - aspnet-Volo.Abp.VirtualFileExplorer.DemoApp-234AF9E1-C3E0-4F8F-BD7D-840627CC8E46 - - - - - - - - - - - - - - - - - true - PreserveNewest - PreserveNewest - - - - - - - - - diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/abp.resourcemapping.js b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/abp.resourcemapping.js deleted file mode 100644 index 8c0bb53dad..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/abp.resourcemapping.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - aliases: { - "@node_modules": "./node_modules", - "@libs": "./wwwroot/libs" - }, - clean: [ - "@libs" - ], - mappings: { - - } -}; diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/gulpfile.js b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/gulpfile.js deleted file mode 100644 index f7ebc78f23..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/gulpfile.js +++ /dev/null @@ -1,9 +0,0 @@ -"use strict"; - -var gulp = require("gulp"), - path = require('path'), - copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js'); - -exports.default = function(){ - return copyResources(path.resolve('./')); -}; \ No newline at end of file diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/yarn.lock b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/yarn.lock deleted file mode 100644 index 216bbe0cb2..0000000000 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/yarn.lock +++ /dev/null @@ -1,391 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@abp/aspnetcore.mvc.ui.theme.basic@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.1.0.tgz#e9e0321037c34b43145dfc7827c422fbf79f59ab" - integrity sha512-vLkyrdFXw0/MPyU2hzqGJJk7trmIlVMdflNIe/rF77UIRmJYHWaTmPt9i5PLN/O4s0jnE9kWlaaJ/VnnFWeGsQ== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.1.0" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.1.0.tgz#35a73580b9b67a33708f2cf897243b50c9ad7100" - integrity sha512-rggTYL9poOFICsOseDX22JNhD0KWH8Oxs0YH91TZjvm/F67cPemW99eBlJc/YdJ7bN6icRiebN8m81y9MSanyg== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.1.0" - "@abp/bootstrap" "~9.1.0" - "@abp/bootstrap-datepicker" "~9.1.0" - "@abp/bootstrap-daterangepicker" "~9.1.0" - "@abp/datatables.net-bs5" "~9.1.0" - "@abp/font-awesome" "~9.1.0" - "@abp/jquery-form" "~9.1.0" - "@abp/jquery-validation-unobtrusive" "~9.1.0" - "@abp/lodash" "~9.1.0" - "@abp/luxon" "~9.1.0" - "@abp/malihu-custom-scrollbar-plugin" "~9.1.0" - "@abp/moment" "~9.1.0" - "@abp/select2" "~9.1.0" - "@abp/sweetalert2" "~9.1.0" - "@abp/timeago" "~9.1.0" - "@abp/toastr" "~9.1.0" - -"@abp/aspnetcore.mvc.ui@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.1.0.tgz#38d058ab148a36ad4d63870e8a501ca339e4a70e" - integrity sha512-lUw1ij87KJp+Rj4cz8oSQkdRuoMq76l/wIAGwtXH+EOKusVpSJTOTioAV/tPKeKZ15ubE4bO5jWcQGxZkXgH3w== - dependencies: - ansi-colors "^4.1.3" - -"@abp/bootstrap-datepicker@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.1.0.tgz#96a1875a2b92f03b8f90f7842ebf8849cf8a4d04" - integrity sha512-3FQm1SK8qmzoP7LOvXkZpq1AzrdPHKRdQJjoqK9N+lQxQjNfOxEFMxeDSg6WJKO619Cnve++jAyMidojXlCiwQ== - dependencies: - bootstrap-datepicker "^1.10.0" - -"@abp/bootstrap-daterangepicker@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.1.0.tgz#1993c539837eb31de174cba9f0bccd441a98f209" - integrity sha512-jS1jTqP6KCXQYX9xZpDAI07C94nwzXrNJD3H0pJXsXoOva3TTBQDD8khf6RDb7tiZrkrNJqmMyUiCfVTDbO7zg== - dependencies: - bootstrap-daterangepicker "^3.1.0" - -"@abp/bootstrap@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.1.0.tgz#a06c1cd4c11554c29973db70c6a383efebb10b4e" - integrity sha512-r6onkBnpqoWrdYLDVZTiqgQBvH5UZerYRrPB3Ky+RkXJhgwn7AM3LAVrB42sIvFZRNbwOlvuAL+a0+5yDOH67Q== - dependencies: - "@abp/core" "~9.1.0" - bootstrap "^5.3.3" - -"@abp/clipboard@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.1.0.tgz#5d5678ef7e8c355715c5a74e4aabd0a21d5e6cbe" - integrity sha512-1TxZbB/q5DPeLhYzrc6y0OVekxnjM+CRH/Gu8nAXQMX46XjdTboXvBtvgKHV1aCznGNsWyjd5A2O5G/XGg9NNw== - dependencies: - "@abp/core" "~9.1.0" - clipboard "^2.0.11" - -"@abp/core@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.1.0.tgz#af78fc096932d4ec45216b5e910c87a72e479b1f" - integrity sha512-6P0KGh5+IqlhQnUOyzaGaKrKzOAm1G0gg8Ay3DXyW2ksY6Zr+lyi5cxNsSi4ix1dicqfydIKvLfV+DF3mQf/dw== - dependencies: - "@abp/utils" "~9.1.0" - -"@abp/datatables.net-bs5@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.1.0.tgz#3b2e7d68e947db3d3432ab5e8bff4da89a85d05d" - integrity sha512-zBrzOrfvTPJcc6mvHZDPVdXbWesKU0lKlrb7vuBZxWjrFNwVC0d/KNJPcYVvyQ3zf9rrQB5Xg0MDgu0k5Tt7tQ== - dependencies: - "@abp/datatables.net" "~9.1.0" - datatables.net-bs5 "^2.1.8" - -"@abp/datatables.net@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.1.0.tgz#12d6e1412aac4a2e0a61437dcdfbfbe1add7fed7" - integrity sha512-lYRvEZUkntaI+dS9Xkz23Z54eDeZ1R4Wzhqcg6VIsz3iO5kYAa5GiQjcOiBssNGJSLuaet6R5Pqh1ThEUjfvvA== - dependencies: - "@abp/jquery" "~9.1.0" - datatables.net "^2.1.8" - -"@abp/font-awesome@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.1.0.tgz#af21ff2d7c332deb1df626404b53a78d790ba842" - integrity sha512-HcJzDCACGejOIvhxsorCdaesyDHnupR/sl5YFCsGikSqATyOSKQy4pw8wKsb1z+FCT5JYCTR7ROJ3lB1lTEgZw== - dependencies: - "@abp/core" "~9.1.0" - "@fortawesome/fontawesome-free" "^6.6.0" - -"@abp/jquery-form@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.1.0.tgz#bdb96436c54b2a09ac4259db97e1e577410e1fc3" - integrity sha512-xjHXWstVY6B3MPB4/8g0EJeHlVvlV010OMZKFmfCGLFi6aHAEKqqWh1rMItAiVuSmCCzL0m/208ZkpoCI++jGQ== - dependencies: - "@abp/jquery" "~9.1.0" - jquery-form "^4.3.0" - -"@abp/jquery-validation-unobtrusive@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.1.0.tgz#798551e7c14ba286a819a48804107a53e974c1ee" - integrity sha512-TggKckfbLtB7Ig2kNt2kH//GaJUns8OZbpdKdh7vCWIAGedw2FLNCABCpoGnyNp0s/dVOtdyxRl9eFRN3+a4tw== - dependencies: - "@abp/jquery-validation" "~9.1.0" - jquery-validation-unobtrusive "^4.0.0" - -"@abp/jquery-validation@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.1.0.tgz#b771652377fbfb3c92ce03b7b7c069a3bb2ae70b" - integrity sha512-bmPSOHcxjitB8NkiLv0SxxuSS3FlCq9SiTUGvsT8nOStDsm+KpyYSzZQq8LSCyqWWj54tlOARTfcD4tMK7/K3Q== - dependencies: - "@abp/jquery" "~9.1.0" - jquery-validation "^1.21.0" - -"@abp/jquery@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.1.0.tgz#952b61ea3e4a99e6551f667297dbb637d83f3c50" - integrity sha512-Ulw8ClAbqmxceNYCb76bR6dq7e9b7Hs6mjlEy05zdbsSNuZW3UoycsJ+BquXi+dUNBo6OppqEmhVeiIjAKTaFg== - dependencies: - "@abp/core" "~9.1.0" - jquery "~3.7.1" - -"@abp/lodash@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.1.0.tgz#62c784bd99c9e1ccfa82905e843375c594ef8584" - integrity sha512-cCE3ZwwWcPrh+ccKx4AS1USL1ttbrXBqci/l+ROjXhFzrs6GYnhI0+30xRZgPdPRm3U3nGPrSaDAU7UuHkRScg== - dependencies: - "@abp/core" "~9.1.0" - lodash "^4.17.21" - -"@abp/luxon@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.1.0.tgz#b246f3627bbc7ce41b7878fce1679da473b0e0ae" - integrity sha512-AouS/qEK+i69hwr4XtUOCepONLuR+1gdHFb50RpOEbUoDfTYmYpxPBdiICmZPeJ3CExErITPZxzzngCnKPPOUw== - dependencies: - "@abp/core" "~9.1.0" - luxon "^3.5.0" - -"@abp/malihu-custom-scrollbar-plugin@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.1.0.tgz#288ae1916a78100f2c728dfd05a560ee99fafae4" - integrity sha512-McdMRDtbTZBjp//3GMVjRjkc16HNYDEdPc2ar1xrY817e0tEln6/TBkItAcfOvjso0TsLcvlNL1+1bjbMjj8OA== - dependencies: - "@abp/core" "~9.1.0" - malihu-custom-scrollbar-plugin "^3.1.5" - -"@abp/moment@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.1.0.tgz#f3c0ae02209e496913cda53df752dabc5be648bd" - integrity sha512-WxR1l09vwxRhqyvAVP4m4IBOFjIC4pzLOmelloqES+gL/klw+T/AmY21Z/z+OV0p7aJ3V3Q1aQStuMCDCyGFnQ== - dependencies: - moment "^2.30.1" - -"@abp/prismjs@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.1.0.tgz#40b688c82ae808ef92516ea5731ccb38c19d2384" - integrity sha512-trSW1K6VtIEaAyxe7umQGimCTLrgdT6DwSiQ8PONvKa8WR5ZmzSDU7lK8SliorufkbWtdkjCvuXB81NGt3tAhQ== - dependencies: - "@abp/clipboard" "~9.1.0" - "@abp/core" "~9.1.0" - prismjs "^1.29.0" - -"@abp/select2@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.1.0.tgz#9c2c6751f8506fb375c9b7c42a008c168a8f4c75" - integrity sha512-n6HqsH8aFLMrqL6LJ0gsHFlaq6T1QSt/x7HkkZyhDC7CwhXajxtsJEstDnDF9naHSXX/lerPbrHEgzn2QRMBqg== - dependencies: - "@abp/core" "~9.1.0" - select2 "^4.0.13" - -"@abp/sweetalert2@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.1.0.tgz#660f9b1db60cc04bde6cadbcf3c55320d20c2f3e" - integrity sha512-z3JMeAwva2vR8qZSRJ/BisQDdAEqjDJ/6oIGu/JYXQEchO1Lnd9UMV376nc3crLJdnyRRO7Qs6zx4FfVOCH0kw== - dependencies: - "@abp/core" "~9.1.0" - sweetalert2 "^11.14.1" - -"@abp/timeago@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.1.0.tgz#496e40153241bae5d418d79cc6c65c9db6306447" - integrity sha512-a/UAYQ2GrhYFGx4p0hqr3x+teBqnjnOiWJEPq9//RTlz+EZ+OUyHbJrcUtqZRvaGJtOAsfmljD3jYnOXUlU7DA== - dependencies: - "@abp/jquery" "~9.1.0" - timeago "^1.6.7" - -"@abp/toastr@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.1.0.tgz#501cbe211164b2e7416a2d4878cb34aed3550b7c" - integrity sha512-BkTDuU0p9Qa4+HT9CYwiPQjVTrbTSNBgQ18h69S3lIadLJwdC6pXeLbL9bhe+5fiuhq2f+0Oqo3X75LNEgzHkw== - dependencies: - "@abp/jquery" "~9.1.0" - toastr "^2.1.4" - -"@abp/utils@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.1.0.tgz#a4fd37d943df18b5c11f5d4869efd5d8882b7959" - integrity sha512-+UZo0ocTEZlRO41SzzHNdinjdFUDVq8wYZSj5BA1bqCVeWYhfjI2+rl9DuogCN8UEuCACA4K/qb4XcE/untQ3g== - dependencies: - just-compare "^2.3.0" - -"@abp/virtual-file-explorer@~9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@abp/virtual-file-explorer/-/virtual-file-explorer-9.1.0.tgz#9a140afb19db28b281f91c83beeb4883cf7d78b1" - integrity sha512-6g3HOiYowLRDmjuIS8zEuauGPf5XEtP8V/D6483+NQ0ysrn/GDposToINDBNXjqGWLWYZNcRSG80APM457P4Fw== - dependencies: - "@abp/clipboard" "~9.1.0" - "@abp/prismjs" "~9.1.0" - -"@fortawesome/fontawesome-free@^6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz#0e984f0f2344ee513c185d87d77defac4c0c8224" - integrity sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow== - -ansi-colors@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - -bootstrap-datepicker@^1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.10.0.tgz#61612bbe8bf0a69a5bce32bbcdda93ebb6ccf24a" - integrity sha512-lWxtSYddAQOpbAO8UhYhHLcK6425eWoSjb5JDvZU3ePHEPF6A3eUr51WKaFy4PccU19JRxUG6wEU3KdhtKfvpg== - dependencies: - jquery ">=3.4.0 <4.0.0" - -bootstrap-daterangepicker@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz#632e6fb2de4b6360c5c0a9d5f6adb9aace051fe8" - integrity sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g== - dependencies: - jquery ">=1.10" - moment "^2.9.0" - -bootstrap@^5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.3.tgz#de35e1a765c897ac940021900fcbb831602bac38" - integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg== - -clipboard@^2.0.11: - version "2.0.11" - resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.11.tgz#62180360b97dd668b6b3a84ec226975762a70be5" - integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw== - dependencies: - good-listener "^1.2.2" - select "^1.1.2" - tiny-emitter "^2.0.0" - -datatables.net-bs5@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.1.8.tgz#860717c4ee85ecb84812ba9a73fb1204aa2a68b6" - integrity sha512-YlGws8eI3iw/1AmKJH18+YMzm/UgGb6o9s14KAC24QT1/8anolm8GnVAgGcwUcvHm3hn1i8A5QXqgbqeMRINeg== - dependencies: - datatables.net "2.1.8" - jquery ">=1.7" - -datatables.net@2.1.8, datatables.net@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.1.8.tgz#9b020f18e927cc924d72411f62dc595cc688669b" - integrity sha512-47ULt+U4bcjbuGTpTlT6SnCuSFVRBxxdWa6X3NfvTObBJ2BZU0o+JUIl05wQ6cABNIavjbAV51gpgvFsMHL9zA== - dependencies: - jquery ">=1.7" - -delegate@^3.1.2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" - integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== - -good-listener@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" - integrity sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw== - dependencies: - delegate "^3.1.2" - -jquery-form@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/jquery-form/-/jquery-form-4.3.0.tgz#7d3961c314a1f2d15298f4af1d3943f54f4149c6" - integrity sha512-q3uaVCEWdLOYUCI6dpNdwf/7cJFOsUgdpq6r0taxtGQ5NJSkOzofyWm4jpOuJ5YxdmL1FI5QR+q+HB63HHLGnQ== - dependencies: - jquery ">=1.7.2" - -jquery-mousewheel@>=3.0.6: - version "3.1.13" - resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5" - integrity sha512-GXhSjfOPyDemM005YCEHvzrEALhKDIswtxSHSR2e4K/suHVJKJxxRCGz3skPjNxjJjQa9AVSGGlYjv1M3VLIPg== - -jquery-validation-unobtrusive@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-4.0.0.tgz#dfcf25a558496a2c883db6021d10f5398d15f99d" - integrity sha512-1ervYFFv6LX/rp7ktuLnMakHNG0piNRDyROI8Ir3hL1vPIwylAehB1AY3BPrYJnzW3WmwWryZq+Bz4sazZK9iQ== - dependencies: - jquery "^3.6.0" - jquery-validation ">=1.19" - -jquery-validation@>=1.19, jquery-validation@^1.21.0: - version "1.21.0" - resolved "https://registry.yarnpkg.com/jquery-validation/-/jquery-validation-1.21.0.tgz#78fc05ab76020912a246af3661b3f54a438bca93" - integrity sha512-xNot0rlUIgu7duMcQ5qb6MGkGL/Z1PQaRJQoZAURW9+a/2PGOUxY36o/WyNeP2T9R6jvWB8Z9lUVvvQWI/Zs5w== - -jquery@>=1.10, jquery@>=1.12.0, "jquery@>=1.5.0 <4.0", jquery@>=1.7, jquery@>=1.7.2: - version "3.6.4" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.4.tgz#ba065c188142100be4833699852bf7c24dc0252f" - integrity sha512-v28EW9DWDFpzcD9O5iyJXg3R3+q+mET5JhnjJzQUZMHOv67bpSIHq81GEYpPNZHG+XXHsfSme3nxp/hndKEcsQ== - -"jquery@>=3.4.0 <4.0.0", jquery@^3.6.0, jquery@~3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" - integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== - -just-compare@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/just-compare/-/just-compare-2.3.0.tgz#a2adcc1d1940536263275f5a1ef1298bcacfeda7" - integrity sha512-6shoR7HDT+fzfL3gBahx1jZG3hWLrhPAf+l7nCwahDdT9XDtosB9kIF0ZrzUp5QY8dJWfQVr5rnsPqsbvflDzg== - -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -luxon@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.5.0.tgz#6b6f65c5cd1d61d1fd19dbf07ee87a50bf4b8e20" - integrity sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ== - -malihu-custom-scrollbar-plugin@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-3.1.5.tgz#310cecc5e59415a1c29e9dfb5d2b6e01d66a29ef" - integrity sha512-lwW3LgI+CNDMPnP4ED2la6oYxWMkCXlnhex+s2wuOLhFDFGnGmQuTQVdRK9bvDLpxs10sGlfErVufJy9ztfgJQ== - dependencies: - jquery-mousewheel ">=3.0.6" - -moment@^2.30.1: - version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" - integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== - -moment@^2.9.0: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== - -prismjs@^1.29.0: - version "1.29.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" - integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== - -select2@^4.0.13: - version "4.0.13" - resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.13.tgz#0dbe377df3f96167c4c1626033e924372d8ef44d" - integrity sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw== - -select@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" - integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA== - -sweetalert2@^11.14.1: - version "11.14.4" - resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.14.4.tgz#0186439674ea4f15991e41cea3af203ee497853c" - integrity sha512-8QMzjxCuinwm18EK5AtYvuhP+lRMRxTWVXy8om9wGlULsXSI4TD29kyih3VYrSXMMBlD4EShFvNC7slhTC7j0w== - -timeago@^1.6.7: - version "1.6.7" - resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.7.tgz#afd467c29a911e697fc22a81888c7c3022783cb5" - integrity sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ== - dependencies: - jquery ">=1.5.0 <4.0" - -tiny-emitter@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" - integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== - -toastr@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181" - integrity sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA== - dependencies: - jquery ">=1.12.0" diff --git a/modules/virtual-file-explorer/app/abp.resourcemapping.js b/modules/virtual-file-explorer/app/abp.resourcemapping.js new file mode 100644 index 0000000000..3129042151 --- /dev/null +++ b/modules/virtual-file-explorer/app/abp.resourcemapping.js @@ -0,0 +1,7 @@ +module.exports = { + aliases: { + + }, + mappings: { + } +}; diff --git a/modules/virtual-file-explorer/app/appsettings.json b/modules/virtual-file-explorer/app/appsettings.json new file mode 100644 index 0000000000..4d1712a519 --- /dev/null +++ b/modules/virtual-file-explorer/app/appsettings.json @@ -0,0 +1,14 @@ +{ + "ConnectionStrings": { + "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=VirtualFileExplorerDemoApp;Trusted_Connection=True;TrustServerCertificate=True" + }, + "Settings": { + "Abp.Identity.Password.RequireNonAlphanumeric": "false", + "Abp.Identity.Password.RequireLowercase": "false", + "Abp.Identity.Password.RequireUppercase": "false", + "Abp.Identity.Password.RequireDigit": "false" + }, + "StringEncryption": { + "DefaultPassPhrase": "Qn7xFuzxdr4NIxvE" + } +} diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/package.json b/modules/virtual-file-explorer/app/package.json similarity index 78% rename from modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/package.json rename to modules/virtual-file-explorer/app/package.json index 8f454ff41f..999c375067 100644 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/package.json +++ b/modules/virtual-file-explorer/app/package.json @@ -1,9 +1,9 @@ -{ - "name": "volo.virtualfileexplorer.dempapp", - "version": "1.0.0", - "private": true, - "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.1.0", - "@abp/virtual-file-explorer": "~9.1.0" - } -} +{ + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.1.0", + "@abp/virtual-file-explorer": "~9.1.0" + } +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/FodyWeavers.xml b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/FodyWeavers.xml new file mode 100644 index 0000000000..1715698ccd --- /dev/null +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/FodyWeavers.xsd b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/FodyWeavers.xsd new file mode 100644 index 0000000000..ffa6fc4b78 --- /dev/null +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg new file mode 100644 index 0000000000..49032794e2 --- /dev/null +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg @@ -0,0 +1,3 @@ +{ + "role": "lib.application-contracts" +} \ No newline at end of file diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg.analyze.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg.analyze.json new file mode 100644 index 0000000000..0f37f00591 --- /dev/null +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg.analyze.json @@ -0,0 +1,7 @@ +{ + "name": "Volo.Abp.VirtualFileExplorer.Contracts", + "hash": "", + "contents": [ + + ] + } \ No newline at end of file diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.csproj b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.csproj new file mode 100644 index 0000000000..2d4c3bcb28 --- /dev/null +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.csproj @@ -0,0 +1,30 @@ + + + + + + + netstandard2.0;netstandard2.1;net8.0;net9.0 + Volo.Abp.VirtualFileExplorer.Contracts + Volo.Abp.VirtualFileExplorer.Contracts + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + + + + + + + + + + diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/AbpVirtualFileExplorerContractsModule.cs b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/AbpVirtualFileExplorerContractsModule.cs new file mode 100644 index 0000000000..4a7821f379 --- /dev/null +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/AbpVirtualFileExplorerContractsModule.cs @@ -0,0 +1,24 @@ +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileExplorer.Localization; +using Volo.Abp.VirtualFileSystem; + +namespace Volo.Abp.VirtualFileExplorer; + +public class AbpVirtualFileExplorerContractsModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddVirtualJson("/Volo/Abp/VirtualFileExplorer/Localization/Resources"); + }); + } +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/AbpVirtualFileExplorerPermissionDefinitionProvider.cs b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/AbpVirtualFileExplorerPermissionDefinitionProvider.cs new file mode 100644 index 0000000000..fac144d244 --- /dev/null +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/AbpVirtualFileExplorerPermissionDefinitionProvider.cs @@ -0,0 +1,19 @@ +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; +using Volo.Abp.VirtualFileExplorer.Localization; + +namespace Volo.Abp.VirtualFileExplorer; + +public class AbpVirtualFileExplorerPermissionDefinitionProvider : PermissionDefinitionProvider +{ + public override void Define(IPermissionDefinitionContext context) + { + var virtualFileExplorer = context.AddGroup(VirtualFileExplorerPermissions.GroupName, L("Permission:AbpVirtualFileExplorer")); + virtualFileExplorer.AddPermission(VirtualFileExplorerPermissions.View, L("Permission:AbpVirtualFileExplorer:View")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ar.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/ar.json similarity index 77% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ar.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/ar.json index 643e5ff7be..7375ccafa0 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ar.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/ar.json @@ -9,6 +9,8 @@ "FileContent": "محتوى الملف", "Size": "المقاس", "BackToRoot": "العودة إلى الجذر", - "EmptyFileInfoList": "لا توجد أى ملفات افتراضية" + "EmptyFileInfoList": "لا توجد أى ملفات افتراضية", + "Permission:AbpVirtualFileExplorer": "مستكشف الملفات الافتراضي", + "Permission:AbpVirtualFileExplorer:View": "عرض" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/cs.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/cs.json similarity index 68% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/cs.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/cs.json index 44f8d06288..4cbdafcadd 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/cs.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/cs.json @@ -9,6 +9,8 @@ "FileContent": "Obsah souboru", "Size": "Velikost", "BackToRoot": "Zpět na kořen", - "EmptyFileInfoList": "Nejsou žádné virtuální soubory" + "EmptyFileInfoList": "Nejsou žádné virtuální soubory", + "Permission:AbpVirtualFileExplorer": "Prohlížeč virtuálních souborů", + "Permission:AbpVirtualFileExplorer:View": "Zobrazit" } } diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/de-DE.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/de-DE.json similarity index 68% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/de-DE.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/de-DE.json index 78e2d41ed4..a4cd4d11b6 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/de-DE.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/de-DE.json @@ -9,6 +9,8 @@ "FileContent": "Dateiinhalt", "Size": "Größe", "BackToRoot": "Zurück zum Stammverzeichnis", - "EmptyFileInfoList": "Es gibt keine virtuellen Dateien" + "EmptyFileInfoList": "Es gibt keine virtuellen Dateien", + "Permission:AbpVirtualFileExplorer": "Virtueller Dateiexplorer", + "Permission:AbpVirtualFileExplorer:View": "Ansicht" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/de.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/de.json similarity index 68% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/de.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/de.json index 6fdd864602..1b0a058adf 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/de.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/de.json @@ -9,6 +9,8 @@ "FileContent": "Dateiinhalt", "Size": "Größe", "BackToRoot": "Zurück zur Wurzel", - "EmptyFileInfoList": "Es gibt keine virtuellen Dateien" + "EmptyFileInfoList": "Es gibt keine virtuellen Dateien", + "Permission:AbpVirtualFileExplorer": "Virtueller Datei-Explorer", + "Permission:AbpVirtualFileExplorer:View": "Ansicht" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/el.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/el.json similarity index 77% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/el.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/el.json index cdfd2bb331..818af6c91f 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/el.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/el.json @@ -9,6 +9,8 @@ "FileContent": "Περιεχόμενο αρχείου", "Size": "Μέγεθος", "BackToRoot": "Επιστροφή στη ρίζα", - "EmptyFileInfoList": "Δεν υπάρχουν εικονικά αρχεία" + "EmptyFileInfoList": "Δεν υπάρχουν εικονικά αρχεία", + "Permission:AbpVirtualFileExplorer": "Εικονικός Εξερευνητής Αρχείων", + "Permission:AbpVirtualFileExplorer:View": "Προβολή" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/en-GB.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/en-GB.json similarity index 67% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/en-GB.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/en-GB.json index cd7cbf3c1a..8da17d88ba 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/en-GB.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/en-GB.json @@ -9,6 +9,8 @@ "FileContent": "File content", "Size": "Size", "BackToRoot": "Back to root", - "EmptyFileInfoList": "There are no virtual files" + "EmptyFileInfoList": "There are no virtual files", + "Permission:AbpVirtualFileExplorer": "Virtual file explorer", + "Permission:AbpVirtualFileExplorer:View": "View" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/en.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/en.json similarity index 67% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/en.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/en.json index 6b794bf791..f3563aafcf 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/en.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/en.json @@ -9,6 +9,8 @@ "FileContent": "File content", "Size": "Size", "BackToRoot": "Back to root", - "EmptyFileInfoList": "There are no virtual files" + "EmptyFileInfoList": "There are no virtual files", + "Permission:AbpVirtualFileExplorer": "Virtual file explorer", + "Permission:AbpVirtualFileExplorer:View": "View" } } diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/es.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/es.json similarity index 70% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/es.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/es.json index e45f76aab0..b4bcd16809 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/es.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/es.json @@ -9,6 +9,8 @@ "FileContent": "Contenido del fichero", "Size": "Tamaño", "BackToRoot": "Volver al raíz", - "EmptyFileInfoList": "No hay ficheros virtuales" + "EmptyFileInfoList": "No hay ficheros virtuales", + "Permission:AbpVirtualFileExplorer": "Explorador de ficheros virtual", + "Permission:AbpVirtualFileExplorer:View": "Ver" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/fa.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/fa.json similarity index 77% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/fa.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/fa.json index 3787092446..839640d6fc 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/fa.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/fa.json @@ -9,6 +9,8 @@ "FileContent": "محتوای فایل", "Size": "اندازه", "BackToRoot": "بازگشت به ریشه", - "EmptyFileInfoList": "هیچ فایل مجازی وجود ندارد" + "EmptyFileInfoList": "هیچ فایل مجازی وجود ندارد", + "Permission:AbpVirtualFileExplorer": "کاوشگر فایل مجازی", + "Permission:AbpVirtualFileExplorer:View": "مشاهده" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/fi.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/fi.json similarity index 68% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/fi.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/fi.json index 3ec395cfa0..8ed05499b9 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/fi.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/fi.json @@ -9,6 +9,8 @@ "FileContent": "Tiedoston sisältö", "Size": "Koko", "BackToRoot": "Takaisin juuriin", - "EmptyFileInfoList": "Virtuaalitiedostoja ei ole" + "EmptyFileInfoList": "Virtuaalitiedostoja ei ole", + "Permission:AbpVirtualFileExplorer": "Virtuaalinen tiedostojen selain", + "Permission:AbpVirtualFileExplorer:View": "Näytä" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/fr.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/fr.json similarity index 68% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/fr.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/fr.json index 0471341bb9..b3e76b99e6 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/fr.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/fr.json @@ -9,6 +9,8 @@ "FileContent": "Contenu du fichier", "Size": "Taille", "BackToRoot": "Retour à la racine", - "EmptyFileInfoList": "Il n’y a pas de fichiers virtuels" + "EmptyFileInfoList": "Il n'y a pas de fichiers virtuels", + "Permission:AbpVirtualFileExplorer": "Explorateur de fichiers virtuels", + "Permission:AbpVirtualFileExplorer:View": "Voir" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/hi.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/hi.json similarity index 76% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/hi.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/hi.json index 09056ed265..dec2b54e62 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/hi.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/hi.json @@ -9,6 +9,8 @@ "FileContent": "फ़ाइल सामग्री", "Size": "आकार", "BackToRoot": "वापस रूट करने के लिए", - "EmptyFileInfoList": "कोई वर्चुअल फ़ाइल नहीं हैं" + "EmptyFileInfoList": "कोई वर्चुअल फ़ाइल नहीं हैं", + "Permission:AbpVirtualFileExplorer": "आभासी फ़ाइल एक्सप्लोरर", + "Permission:AbpVirtualFileExplorer:View": "देखें" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/hr.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/hr.json similarity index 69% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/hr.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/hr.json index 81a7052642..86ca73b02b 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/hr.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/hr.json @@ -9,6 +9,8 @@ "FileContent": "Sadržaj datoteke", "Size": "Veličina", "BackToRoot": "Natrag na korijen", - "EmptyFileInfoList": "Nema virtualnih datoteka" + "EmptyFileInfoList": "Nema virtualnih datoteka", + "Permission:AbpVirtualFileExplorer": "Virtualni preglednik datoteka", + "Permission:AbpVirtualFileExplorer:View": "Pregled" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/hu.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/hu.json similarity index 67% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/hu.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/hu.json index 9a6dddb460..9f963bc9b1 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/hu.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/hu.json @@ -9,6 +9,8 @@ "FileContent": "File tartalma", "Size": "Méret", "BackToRoot": "Vissza a fő mappába", - "EmptyFileInfoList": "Nem találhatóak virtuális fileok" + "EmptyFileInfoList": "Nem találhatóak virtuális fileok", + "Permission:AbpVirtualFileExplorer": "Virtuális file böngésző", + "Permission:AbpVirtualFileExplorer:View": "Megtekintés" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/is.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/is.json similarity index 67% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/is.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/is.json index 550c678913..1382d594c1 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/is.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/is.json @@ -9,6 +9,8 @@ "FileContent": "Innihald skráar", "Size": "Stærð", "BackToRoot": "Aftur í rót", - "EmptyFileInfoList": "Það eru engar sýndar skrár" + "EmptyFileInfoList": "Það eru engar sýndar skrár", + "Permission:AbpVirtualFileExplorer": "Sýndar skráarkönnuður", + "Permission:AbpVirtualFileExplorer:View": "Skoða" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/it.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/it.json similarity index 69% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/it.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/it.json index 7f51b3ad72..555f7ea620 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/it.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/it.json @@ -9,6 +9,8 @@ "FileContent": "Contenuto del file", "Size": "Dimensione", "BackToRoot": "Torna al principale", - "EmptyFileInfoList": "Non ci sono file virtuali" + "EmptyFileInfoList": "Non ci sono file virtuali", + "Permission:AbpVirtualFileExplorer": "Esplora file virtuale", + "Permission:AbpVirtualFileExplorer:View": "Visualizza" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/nl.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/nl.json similarity index 67% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/nl.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/nl.json index 4f00849893..8999b87ed3 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/nl.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/nl.json @@ -9,6 +9,8 @@ "FileContent": "Bestandsinhoud", "Size": "Grootte", "BackToRoot": "Terug naar hoofdmap", - "EmptyFileInfoList": "Er zijn geen virtuele bestanden" + "EmptyFileInfoList": "Er zijn geen virtuele bestanden", + "Permission:AbpVirtualFileExplorer": "Virtuele bestandsverkenner", + "Permission:AbpVirtualFileExplorer:View": "Bekijken" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/pl-PL.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/pl-PL.json similarity index 69% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/pl-PL.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/pl-PL.json index 3527bfbe02..09e6adad4e 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/pl-PL.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/pl-PL.json @@ -9,6 +9,8 @@ "FileContent": "Zawartość pliku", "Size": "Rozmiar", "BackToRoot": "Powrót do korzenia", - "EmptyFileInfoList": "Nie ma wirtualnych plików" + "EmptyFileInfoList": "Nie ma wirtualnych plików", + "Permission:AbpVirtualFileExplorer": "Wirtualny eksplorator plików", + "Permission:AbpVirtualFileExplorer:View": "Podgląd" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/pt-BR.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/pt-BR.json similarity index 69% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/pt-BR.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/pt-BR.json index f4b0675210..b59d281a1e 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/pt-BR.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/pt-BR.json @@ -9,6 +9,8 @@ "FileContent": "Conteúdo do arquivo", "Size": "Tamanho", "BackToRoot": "Voltar à raiz", - "EmptyFileInfoList": "Não há arquivos virtuais" + "EmptyFileInfoList": "Não há arquivos virtuais", + "Permission:AbpVirtualFileExplorer": "Explorador de arquivo virtual", + "Permission:AbpVirtualFileExplorer:View": "Visualizar" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ro-RO.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/ro-RO.json similarity index 68% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ro-RO.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/ro-RO.json index 67abc693a4..4acbd39fd9 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ro-RO.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/ro-RO.json @@ -9,6 +9,8 @@ "FileContent" : "Conţinut fişier", "Size" : "Mărimea", "BackToRoot" : "Înapoi la rădăcină", - "EmptyFileInfoList" : "Nu există fişiere virtuale" + "EmptyFileInfoList" : "Nu există fişiere virtuale", + "Permission:AbpVirtualFileExplorer": "Explorator de fişiere virtuale", + "Permission:AbpVirtualFileExplorer:View": "Vizualizare" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ru.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/ru.json similarity index 78% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ru.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/ru.json index f616e7679b..a9ceb1e819 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ru.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/ru.json @@ -9,6 +9,8 @@ "FileContent": "Содержание файла", "Size": "Размер", "BackToRoot": "Вернуться к корню", - "EmptyFileInfoList": "Нет виртуальных файлов" + "EmptyFileInfoList": "Нет виртуальных файлов", + "Permission:AbpVirtualFileExplorer": "Виртуальный файловый менеджер", + "Permission:AbpVirtualFileExplorer:View": "Просмотр" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/sk.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/sk.json similarity index 78% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/sk.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/sk.json index eaeb989d34..56815767d2 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/sk.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/sk.json @@ -9,6 +9,8 @@ "FileContent": "Obsah súboru", "Size": "Veľkosť", "BackToRoot": "Späť na koreňový priečinok", - "EmptyFileInfoList": "Neexistujú žiadne virtuálne súbory" + "EmptyFileInfoList": "Neexistujú žiadne virtuálne súbory", + "Permission:AbpVirtualFileExplorer": "Virtuálny prieskumník súborov", + "Permission:AbpVirtualFileExplorer:View": "Zobraziť" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/sl.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/sl.json similarity index 100% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/sl.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/sl.json diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/sv.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/sv.json similarity index 100% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/sv.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/sv.json diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/tr.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/tr.json similarity index 68% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/tr.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/tr.json index 30f659ff45..cb7c655a8a 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/tr.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/tr.json @@ -9,6 +9,8 @@ "FileContent": "Dosyaa içeriği", "Size": "Boyut", "BackToRoot": "Kök'e dön", - "EmptyFileInfoList": "Sanal dosyalar yok" + "EmptyFileInfoList": "Sanal dosyalar yok", + "Permission:AbpVirtualFileExplorer": "Sanal dosya gezgini", + "Permission:AbpVirtualFileExplorer:View": "Görüntüle" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/vi.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/vi.json similarity index 69% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/vi.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/vi.json index 71ff7b26ab..19b7e32e25 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/vi.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/vi.json @@ -9,6 +9,8 @@ "FileContent": "Nội dung tệp", "Size": "Kích thước", "BackToRoot": "Quay lại thư mục gốc", - "EmptyFileInfoList": "Không có tệp ảo nào" + "EmptyFileInfoList": "Không có tệp ảo nào", + "Permission:AbpVirtualFileExplorer": "Trình khám phá tệp ảo", + "Permission:AbpVirtualFileExplorer:View": "Xem" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/zh-Hans.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/zh-Hans.json similarity index 69% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/zh-Hans.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/zh-Hans.json index 46e5e4b811..824a8813f8 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/zh-Hans.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/zh-Hans.json @@ -9,6 +9,8 @@ "FileContent": "文件内容", "Size": "文件大小", "BackToRoot": "返回根目录", - "EmptyFileInfoList": "没有虚拟文件" + "EmptyFileInfoList": "没有虚拟文件", + "Permission:AbpVirtualFileExplorer": "虚拟文件资源管理器", + "Permission:AbpVirtualFileExplorer:View": "查看" } -} \ No newline at end of file +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/zh-Hant.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/zh-Hant.json similarity index 69% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/zh-Hant.json rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/zh-Hant.json index 1fb05fc6bf..4e293a3f25 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/zh-Hant.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/Resources/zh-Hant.json @@ -9,6 +9,8 @@ "FileContent" : "檔案內容", "Size" : "檔案大小", "BackToRoot" : "返回根目錄", - "EmptyFileInfoList" : "無任何虛擬檔案" + "EmptyFileInfoList" : "無任何虛擬檔案", + "Permission:AbpVirtualFileExplorer": "虛擬檔案總管", + "Permission:AbpVirtualFileExplorer:View": "檢視" } } diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/VirtualFileExplorerResource.cs b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/VirtualFileExplorerResource.cs similarity index 70% rename from modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/VirtualFileExplorerResource.cs rename to modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/VirtualFileExplorerResource.cs index 78f1e6eb4b..95fe949bd0 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/VirtualFileExplorerResource.cs +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/Localization/VirtualFileExplorerResource.cs @@ -1,6 +1,6 @@ using Volo.Abp.Localization; -namespace Volo.Abp.VirtualFileExplorer.Web.Localization; +namespace Volo.Abp.VirtualFileExplorer.Localization; [LocalizationResourceName("AbpVirtualFileExplorer")] public class VirtualFileExplorerResource diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/VirtualFileExplorerPermissions.cs b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/VirtualFileExplorerPermissions.cs new file mode 100644 index 0000000000..214a2e5663 --- /dev/null +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo/Abp/VirtualFileExplorer/VirtualFileExplorerPermissions.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Reflection; + +namespace Volo.Abp.VirtualFileExplorer; + +public static class VirtualFileExplorerPermissions +{ + public const string GroupName = "AbpVirtualFileExplorer"; + + public const string View = GroupName + ".View"; + + public static string[] GetAll() + { + return ReflectionHelper.GetPublicConstantsRecursively(typeof(VirtualFileExplorerPermissions)); + } +} diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Installer/InstallationNotes.md b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Installer/InstallationNotes.md new file mode 100644 index 0000000000..9cc08c2ae7 --- /dev/null +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Installer/InstallationNotes.md @@ -0,0 +1,7 @@ +# Installation Notes for Virtual File Explorer Module + +The Virtual File System makes it possible to manage files that do not physically exist on the file system (disk). It's mainly used to embed (js, css, image..) files into assemblies and use them like physical files at runtime. + +## Documentation + +For detailed information and usage instructions, please visit the [Virtual File System Module documentation](https://abp.io/docs/latest/framework/infrastructure/virtual-file-system). \ No newline at end of file diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/AbpVirtualFileExplorerWebModule.cs b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/AbpVirtualFileExplorerWebModule.cs index 9bf9c7aa5d..6d2133844c 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/AbpVirtualFileExplorerWebModule.cs +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/AbpVirtualFileExplorerWebModule.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.DependencyInjection; +using Localization; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders.Physical; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; @@ -8,8 +9,8 @@ using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.UI.Navigation; using Volo.Abp.Validation.Localization; +using Volo.Abp.VirtualFileExplorer.Localization; using Volo.Abp.VirtualFileExplorer.Web.Bundling; -using Volo.Abp.VirtualFileExplorer.Web.Localization; using Volo.Abp.VirtualFileExplorer.Web.Navigation; using Volo.Abp.VirtualFileSystem; @@ -17,6 +18,7 @@ namespace Volo.Abp.VirtualFileExplorer.Web; [DependsOn(typeof(AbpAspNetCoreMvcUiBootstrapModule))] [DependsOn(typeof(AbpAspNetCoreMvcUiThemeSharedModule))] +[DependsOn(typeof(AbpVirtualFileExplorerContractsModule))] public class AbpVirtualFileExplorerWebModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) @@ -43,14 +45,6 @@ public class AbpVirtualFileExplorerWebModule : AbpModule options.FileSets.AddEmbedded("Volo.Abp.VirtualFileExplorer.Web"); }); - Configure(options => - { - options.Resources - .Add("en") - .AddBaseTypes(typeof(AbpValidationResource)) - .AddVirtualJson("/Localization/Resources"); - }); - Configure(options => { options diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Navigation/VirtualFileExplorerMenuContributor.cs b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Navigation/VirtualFileExplorerMenuContributor.cs index a47f7585ad..45b8e2089e 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Navigation/VirtualFileExplorerMenuContributor.cs +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Navigation/VirtualFileExplorerMenuContributor.cs @@ -1,8 +1,10 @@ using System.Threading.Tasks; +using Localization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; +using Volo.Abp.Authorization.Permissions; using Volo.Abp.UI.Navigation; -using Volo.Abp.VirtualFileExplorer.Web.Localization; +using Volo.Abp.VirtualFileExplorer.Localization; namespace Volo.Abp.VirtualFileExplorer.Web.Navigation; @@ -17,7 +19,12 @@ public class VirtualFileExplorerMenuContributor : IMenuContributor var l = context.GetLocalizer(); - context.Menu.Items.Add(new ApplicationMenuItem(VirtualFileExplorerMenuNames.Index, l["Menu:VirtualFileExplorer"], icon: "fa fa-file", url: "~/VirtualFileExplorer")); + context.Menu.Items.Add(new ApplicationMenuItem( + VirtualFileExplorerMenuNames.Index, + l["Menu:VirtualFileExplorer"], + icon: "fa fa-file", url: "~/VirtualFileExplorer") + .RequirePermissions(VirtualFileExplorerPermissions.View) + ); return Task.CompletedTask; } diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/FileContentModal.cshtml b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/FileContentModal.cshtml index 7db9c4ca43..f25578f06e 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/FileContentModal.cshtml +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/FileContentModal.cshtml @@ -1,8 +1,9 @@ @page +@using Localization @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs -@using Volo.Abp.VirtualFileExplorer.Web.Localization +@using Volo.Abp.VirtualFileExplorer.Localization @model Volo.Abp.VirtualFileExplorer.Web.Pages.VirtualFileExplorer.FileContentModal @inject IHtmlLocalizer L @{ diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/FileContentModal.cshtml.cs b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/FileContentModal.cshtml.cs index 181028eabd..742038b31a 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/FileContentModal.cshtml.cs +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/FileContentModal.cshtml.cs @@ -1,6 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.FileProviders; @@ -8,6 +9,7 @@ using Volo.Abp.VirtualFileSystem; namespace Volo.Abp.VirtualFileExplorer.Web.Pages.VirtualFileExplorer; +[Authorize(VirtualFileExplorerPermissions.View)] public class FileContentModal : PageModel { [Required] diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml index 83d6688252..bf5d86fa1a 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml @@ -1,8 +1,9 @@ @page +@using Localization @using Localization.Resources.AbpUi @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Layout -@using Volo.Abp.VirtualFileExplorer.Web.Localization +@using Volo.Abp.VirtualFileExplorer.Localization @using Volo.Abp.VirtualFileExplorer.Web.Navigation @using Volo.Abp.VirtualFileExplorer.Web.Pages.VirtualFileExplorer @model IndexModel diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml.cs b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml.cs index fb8fab07c0..894332be84 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml.cs +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/Index.cshtml.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.FileProviders; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination; @@ -11,6 +12,7 @@ using Volo.Abp.VirtualFileSystem.Embedded; namespace Volo.Abp.VirtualFileExplorer.Web.Pages.VirtualFileExplorer; +[Authorize(VirtualFileExplorerPermissions.View)] public class IndexModel : VirtualFileExplorerPageModel { [BindProperty(SupportsGet = true)] diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/VirtualFileExplorerPageModel.cs b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/VirtualFileExplorerPageModel.cs index d9423788b3..c9fd10a9a5 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/VirtualFileExplorerPageModel.cs +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Pages/VirtualFileExplorer/VirtualFileExplorerPageModel.cs @@ -1,5 +1,6 @@ -using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; -using Volo.Abp.VirtualFileExplorer.Web.Localization; +using Localization; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.VirtualFileExplorer.Localization; namespace Volo.Abp.VirtualFileExplorer.Web.Pages.VirtualFileExplorer; diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.csproj b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.csproj index 362207b447..47454333bf 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.csproj +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.csproj @@ -16,6 +16,7 @@ + @@ -24,17 +25,11 @@ - - - - - - diff --git a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts index 2742cedcee..c68c9afc85 100644 --- a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts +++ b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts @@ -40,27 +40,34 @@ type PermissionWithGroupName = PermissionGrantInfoDto & { exportAs: 'abpPermissionManagement', styles: [ ` - .overflow-scroll { - max-height: 70vh; - overflow-y: scroll; - } - .scroll-in-modal { overflow: auto; - max-height: calc(100vh - 15rem); - } - - fieldset legend { - float: none; - width: auto; + /* + To maintain a 28px top margin and 28px bottom margin when the modal reaches full height, the scrollable area needs to be 100vh - 23.1rem + */ + max-height: calc(100vh - 23.1rem); } .lpx-scroll-pills-container ul { display: block; - max-height: 500px; overflow-y: auto; } + /* Target mobile screens */ + @media (max-width: 768px) { + .scroll-in-modal { + max-height: calc(100vh - 15rem); + } + .lpx-scroll-pills-container ul { + max-height: 500px; + } + } + + fieldset legend { + float: none; + width: auto; + } + .lpx-scroll-pills-container .tab-content { padding-top: 0 !important; padding-bottom: 0 !important; diff --git a/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.ts b/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.ts index 282072e170..f1c8557ed1 100644 --- a/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.ts +++ b/npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.ts @@ -101,7 +101,7 @@ export class EmailSettingGroupComponent implements OnInit { } this.emailSettingsService.sendTestEmail(this.emailTestForm.value).subscribe(res => { - this.toasterService.success('AbpSettingManagement::SuccessfullySent'); + this.toasterService.success('AbpSettingManagement::SentSuccessfully'); this.isEmailTestModalOpen = false; }); } diff --git a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json index 8e2a59a4fb..c2eb417d62 100644 --- a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json +++ b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json @@ -10,22 +10,21 @@ "access": "public" }, "dependencies": { - "@abp/aspnetcore.mvc.ui": "~9.1.0", - "@abp/bootstrap": "~9.1.0", - "@abp/bootstrap-datepicker": "~9.1.0", - "@abp/bootstrap-daterangepicker": "~9.1.0", - "@abp/datatables.net-bs5": "~9.1.0", - "@abp/font-awesome": "~9.1.0", - "@abp/jquery-form": "~9.1.0", - "@abp/jquery-validation-unobtrusive": "~9.1.0", - "@abp/lodash": "~9.1.0", - "@abp/luxon": "~9.1.0", - "@abp/malihu-custom-scrollbar-plugin": "~9.1.0", - "@abp/moment": "~9.1.0", - "@abp/select2": "~9.1.0", - "@abp/sweetalert2": "~9.1.0", - "@abp/timeago": "~9.1.0", - "@abp/toastr": "~9.1.0" + "@abp/aspnetcore.mvc.ui": "~9.1.0-rc.3", + "@abp/bootstrap": "~9.1.0-rc.3", + "@abp/bootstrap-datepicker": "~9.1.0-rc.3", + "@abp/bootstrap-daterangepicker": "~9.1.0-rc.3", + "@abp/datatables.net-bs5": "~9.1.0-rc.3", + "@abp/font-awesome": "~9.1.0-rc.3", + "@abp/jquery-form": "~9.1.0-rc.3", + "@abp/jquery-validation-unobtrusive": "~9.1.0-rc.3", + "@abp/lodash": "~9.1.0-rc.3", + "@abp/luxon": "~9.1.0-rc.3", + "@abp/malihu-custom-scrollbar-plugin": "~9.1.0-rc.3", + "@abp/moment": "~9.1.0-rc.3", + "@abp/select2": "~9.1.0-rc.3", + "@abp/sweetalert2": "~9.1.0-rc.3", + "@abp/timeago": "~9.1.0-rc.3" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/nupkg/common.ps1 b/nupkg/common.ps1 index afaa62a32f..e2d65a631c 100644 --- a/nupkg/common.ps1 +++ b/nupkg/common.ps1 @@ -157,6 +157,7 @@ $projects = ( "framework/src/Volo.Abp.BlobStoring.Minio", "framework/src/Volo.Abp.BlobStoring.Aws", "framework/src/Volo.Abp.BlobStoring.Google", + "framework/src/Volo.Abp.BlobStoring.Bunny", "framework/src/Volo.Abp.Caching", "framework/src/Volo.Abp.Caching.StackExchangeRedis", "framework/src/Volo.Abp.Castle.Core", @@ -443,6 +444,7 @@ $projects = ( "source-code/Volo.Abp.Users.SourceCode", # modules/virtual-file-explorer + "modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts", "modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web", "modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Installer", "source-code/Volo.Abp.VirtualFileExplorer.SourceCode", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj index 90003189c1..32cd17a78e 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj @@ -8,8 +8,8 @@ - - + + @@ -82,7 +82,7 @@
      - + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250310031518_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250310031518_Initial.Designer.cs index 041cf03236..3fd2b00a67 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250310031518_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20241226032336_Initial")] + [Migration("20250310031518_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250310031518_Initial.cs similarity index 100% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20241226032336_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20250310031518_Initial.cs diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index c6f919612a..29da815662 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj index 1ec0a9e256..7761bbde29 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj @@ -8,8 +8,8 @@ - - + + @@ -83,11 +83,11 @@ - + - + runtime; build; native; contentfiles; analyzers compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj index ec6b540a0b..34eeb42de4 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj @@ -9,10 +9,10 @@ - - - - + + + + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.Mongo.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.Mongo.csproj index 305cf43780..c42c2e72f1 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.Mongo.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.Mongo.csproj @@ -8,7 +8,7 @@ - + @@ -79,7 +79,7 @@ - + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250310031634_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250310031634_Initial.Designer.cs index 8a28aa0c28..3d7c7ef6ac 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250310031634_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20241226032120_Initial")] + [Migration("20250310031634_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250310031634_Initial.cs similarity index 100% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20241226032120_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20250310031634_Initial.cs diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs index 032a7e08be..b81df45051 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.csproj index 6e0de5f178..8d3698cb1b 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.csproj @@ -8,7 +8,7 @@ - + @@ -80,11 +80,11 @@ - + - + runtime; build; native; contentfiles; analyzers compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Shared/MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Shared/MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj index 00ba87e384..d086ca8003 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Shared/MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Shared/MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj @@ -29,7 +29,7 @@ - + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj index 2c6330dd35..a1436f339f 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj @@ -74,7 +74,7 @@ - + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250310031445_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250310031445_Initial.Designer.cs index bbc683e8c9..7773acc68f 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250310031445_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Host.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20241226032219_Initial")] + [Migration("20250310031445_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250310031445_Initial.cs similarity index 100% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20241226032219_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20250310031445_Initial.cs diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs index 54276957a3..8b3cae9651 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj index 8bbeef97ef..d5843b5373 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj @@ -75,11 +75,11 @@ - + - + runtime; build; native; contentfiles; analyzers compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj index 3ec0c7a745..f7de34413f 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj @@ -77,7 +77,7 @@ - + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.Designer.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250310031459_Initial.Designer.cs similarity index 99% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.Designer.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250310031459_Initial.Designer.cs index 0702c60f89..d8b4cb4a48 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.Designer.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250310031459_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Mvc.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20241226032333_Initial")] + [Migration("20250310031459_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250310031459_Initial.cs similarity index 100% rename from templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20241226032333_Initial.cs rename to templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/20250310031459_Initial.cs diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs index a003e4b6cc..3699529124 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Mvc.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj index c25426d19c..ccbc44f2b8 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj @@ -78,11 +78,11 @@ - + - + runtime; build; native; contentfiles; analyzers compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj index db551782ff..b95c06305c 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj @@ -41,7 +41,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj index 47ef773a62..72840b70b4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj @@ -12,10 +12,10 @@ - - - - + + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj index 8d57516f1b..a8ff20d2ec 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj @@ -14,11 +14,11 @@ - - + + - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj index 233cc474f4..20b58b045d 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj @@ -14,9 +14,9 @@ - - - + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj index db97961869..9347651ff4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj @@ -13,10 +13,10 @@ - - - - + + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj index 8faf21b2d3..8861471b0f 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj @@ -13,10 +13,10 @@ - - - - + + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj index 0fa42f9051..f0da067b27 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj @@ -15,12 +15,12 @@ - - - + + + - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj index a98c87cdda..65d54aeb32 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj index ce661e3e32..156e1147b7 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj index 6f3cfaaec4..7fbbb92fa8 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj @@ -22,7 +22,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj index 36a39a26da..7f6b9936fa 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj @@ -26,7 +26,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.Designer.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250310031524_Initial.Designer.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.Designer.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250310031524_Initial.Designer.cs index 94f4c9722f..6f6d50b88e 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.Designer.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250310031524_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameDbContext))] - [Migration("20241226031540_Initial")] + [Migration("20250310031524_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -296,6 +296,10 @@ namespace MyCompanyName.MyProjectName.Migrations .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + b.Property("ConcurrencyStamp") .IsConcurrencyToken() .IsRequired() diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250310031524_Initial.cs similarity index 99% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.cs rename to templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250310031524_Initial.cs index 13dee16800..b22d01c83b 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20241226031540_Initial.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20250310031524_Initial.cs @@ -50,6 +50,7 @@ namespace MyCompanyName.MyProjectName.Migrations columns: table => new { Id = table.Column(type: "uniqueidentifier", nullable: false), + ApplicationName = table.Column(type: "nvarchar(96)", maxLength: 96, nullable: true), JobName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), JobArgs = table.Column(type: "nvarchar(max)", maxLength: 1048576, nullable: false), TryCount = table.Column(type: "smallint", nullable: false, defaultValue: (short)0), diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs index 860b1fc689..42f90bfc62 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/MyProjectNameDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -293,6 +293,10 @@ namespace MyCompanyName.MyProjectName.Migrations .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + b.Property("ConcurrencyStamp") .IsConcurrencyToken() .IsRequired() diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj index 258844c045..3c77133bb4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj @@ -22,7 +22,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index fe61f75815..6928fab989 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index 006c96bb42..ea2058353f 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -19,7 +19,7 @@ - + diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj index e22776c2d8..3884ee5abf 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj index dc4c43ac0c..b1061875f2 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj index 6aa0f455df..ae9b957906 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj index 006d938a8d..8cd45f7b82 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj @@ -22,8 +22,8 @@ - - + + diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbFixture.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbFixture.cs index 55387d7ba5..e69539eff8 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbFixture.cs +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/MyProjectNameMongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace MyCompanyName.MyProjectName.MongoDB; diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs index 9f51c616ec..f705959e83 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs @@ -32,7 +32,7 @@ public class SampleRepositoryTests : MyProjectNameMongoDbTestBase await WithUnitOfWorkAsync(async () => { //Act - var adminUser = await (await _appUserRepository.GetMongoQueryableAsync()) + var adminUser = await (await _appUserRepository.GetQueryableAsync()) .FirstOrDefaultAsync(u => u.UserName == "admin"); //Assert diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj index 53cc18991c..79c080216c 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj @@ -14,11 +14,11 @@ - - - - - + + + + + diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj index d2190fa5ed..426dcaca1c 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj @@ -16,7 +16,7 @@ - + all diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj index b11ac98272..3ca0425b28 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj @@ -8,7 +8,7 @@ - + diff --git a/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index 6cf91f5a09..65fee12cfc 100644 --- a/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj +++ b/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index c6a650859e..f33122e97a 100644 --- a/templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj +++ b/templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj @@ -35,7 +35,7 @@ - + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250310031550_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250310031550_Initial.Designer.cs index 35b5661fc4..412ca9d60c 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250310031550_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(AuthServerDbContext))] - [Migration("20241226032427_Initial")] + [Migration("20250310031550_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250310031550_Initial.cs similarity index 100% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20241226032427_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/20250310031550_Initial.cs diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs index 74d8f6d802..f47250a204 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/Migrations/AuthServerDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj index 996b557a55..7efc0aae71 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj index 518bf4589b..3fe2b0415b 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj @@ -10,10 +10,10 @@ - - - - + + + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj index a567757f08..589c0fced6 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250310031538_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250310031538_Initial.Designer.cs index b0eb5d07ff..1ac2d12df8 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250310031538_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20241226032535_Initial")] + [Migration("20250310031538_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250310031538_Initial.cs similarity index 100% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20241226032535_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/20250310031538_Initial.cs diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs index 87d089ac54..4f14e8dec0 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Migrations/UnifiedDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj index 2298178199..d05d66c666 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj @@ -13,11 +13,11 @@ - - + + - + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20241010091847_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250310031557_Initial.Designer.cs similarity index 89% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20241010091847_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250310031557_Initial.Designer.cs index 0cc3e26a91..53e5e56a03 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20241010091847_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250310031557_Initial.Designer.cs @@ -12,7 +12,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(MyProjectNameHttpApiHostMigrationsDbContext))] - [Migration("20241010091847_Initial")] + [Migration("20250310031557_Initial")] partial class Initial { /// @@ -21,7 +21,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20241010091847_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250310031557_Initial.cs similarity index 100% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20241010091847_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/20250310031557_Initial.cs diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/MyProjectNameHttpApiHostMigrationsDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/MyProjectNameHttpApiHostMigrationsDbContextModelSnapshot.cs index 8f18778ba3..73a8d2db0a 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/MyProjectNameHttpApiHostMigrationsDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/Migrations/MyProjectNameHttpApiHostMigrationsDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0-rc.1.24451.1") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index 513e18897d..8db094e467 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -14,9 +14,9 @@ - - - + + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index 73c365a744..666658da33 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.Designer.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250310031608_Initial.Designer.cs similarity index 99% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.Designer.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250310031608_Initial.Designer.cs index f278c04955..e3239cdd3a 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.Designer.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250310031608_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace MyCompanyName.MyProjectName.Migrations { [DbContext(typeof(UnifiedDbContext))] - [Migration("20241226032624_Initial")] + [Migration("20250310031608_Initial")] partial class Initial { /// @@ -22,7 +22,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250310031608_Initial.cs similarity index 100% rename from templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20241226032624_Initial.cs rename to templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/20250310031608_Initial.cs diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs index 393f21c825..802d950dec 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace MyCompanyName.MyProjectName.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj index b67e95ebc6..bc22e1a5f6 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj index e60d536bde..20c07d94f8 100644 --- a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj +++ b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj @@ -15,7 +15,7 @@ - + diff --git a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj index d26202b3e5..b8791a1f3f 100644 --- a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj +++ b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj @@ -22,7 +22,7 @@ - + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj index eb162439aa..c79b7cf9b5 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyCompanyName.MyProjectName.Application.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj index 8e0d9ac365..48a85a1afd 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.Domain.Tests/MyCompanyName.MyProjectName.Domain.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj index 8ee4580845..7a93e9f941 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj index 0302fce20c..98abac34f3 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj @@ -23,7 +23,7 @@ - + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs index 07cfd77583..63a2f598c5 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDB/MongoDbFixture.cs @@ -1,5 +1,5 @@ using System; -using EphemeralMongo; +using MongoSandbox; namespace MyCompanyName.MyProjectName.MongoDB; diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj index fed5495bbe..f63599ff8a 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj @@ -9,11 +9,11 @@ - - - - - + + + + + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj index 772c28108c..4c004ee12a 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj @@ -9,7 +9,7 @@ - + all diff --git a/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index b36d28e406..3f3a1535bb 100644 --- a/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj +++ b/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj @@ -14,7 +14,7 @@ - +