Merge branch 'dev' into auto-merge/rel-7-2/1949

pull/16612/head
Engincan VESKE 2 years ago committed by GitHub
commit 4888839384
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,52 @@
import os
import json
from github import Github
def update_latest_versions():
version = os.environ["GITHUB_REF"].split("/")[-1]
if "rc" in version:
return False
with open("latest-versions.json", "r") as f:
latest_versions = json.load(f)
latest_versions[0]["version"] = version
with open("latest-versions.json", "w") as f:
json.dump(latest_versions, f, indent=2)
return True
def create_pr():
g = Github(os.environ["GITHUB_TOKEN"])
repo = g.get_repo("abpframework/abp")
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)
# Get the current latest-versions.json file and its sha
contents = repo.get_contents("latest-versions.json", ref="dev")
file_sha = contents.sha
# 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,
)
pr = repo.create_pull(title="Update latest-versions.json",
body="Automated PR to update the latest-versions.json file.",
head=branch_name, base="dev")
pr.create_review_request(reviewers=["ebicoglu", "gizemmutukurt", "skoc10"])
if __name__ == "__dev__":
should_create_pr = update_latest_versions()
if should_create_pr:
create_pr()

@ -41,7 +41,7 @@ permissions:
jobs:
build-test:
runs-on: windows-latest
runs-on: ubuntu-latest
if: ${{ !github.event.pull_request.draft }}
steps:
- uses: actions/checkout@v2
@ -49,15 +49,19 @@ jobs:
with:
dotnet-version: 7.0.100
- name: chown
run: |
sudo chown -R $USER:$USER /home/runneradmin
- name: Build All
run: .\build-all.ps1 -f
working-directory: .\build
shell: powershell
run: ./build-all.ps1
working-directory: ./build
shell: pwsh
- name: Test All
run: .\test-all.ps1 -f
working-directory: .\build
shell: powershell
run: ./test-all.ps1
working-directory: ./build
shell: pwsh
- name: Codecov
uses: codecov/codecov-action@v2

@ -0,0 +1,33 @@
name: Update Latest Versions
on:
release:
types:
- published
permissions:
contents: write
pull-requests: write
jobs:
update-versions:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.x
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install PyGithub
- name: Update latest-versions.json and create PR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python .github/scripts/update_versions.py

@ -0,0 +1,94 @@
# Contributor Covenant Code of Conduct
## Preamble
The ABP Framework was created to implement common generic web application features in a common code base. This approach helps developers to decouple line of business application features from their custom business logic. Besides, the ABP Framework helps create MVPs and kick-start your project as quickly as possible. All the contributors try to save valuable time by automating repetitive tasks at the framework level. This code of conduct has been adopted by many [other open source communities](http://contributor-covenant.org/adopters/) and we feel it expresses our values well.
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
- Focusing on what is best not just for us as individuals but for the overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others private information, such as a physical or email address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned with this Code of Conduct and will communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces and when an individual officially represents the community in public spaces. Examples of representing our community include:
- Using an official e-mail address.
- Posting via an official social media account.
- Acting as an appointed representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [info@abp.io](mailto:info@abp.io). All complaints will be reviewed and investigated promptly and fairly. All community leaders must to respect the privacy and security of the reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact:** Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
**Consequence:** A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact:** A violation through a single incident or series of actions.
**Consequence:** A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period. This includes avoiding interactions in community spaces and external channels like social media. Violating these terms may lead to a temporary or permanent ban.
### 3. Temporary Ban
**Community Impact:** A serious violation of community standards, including sustained inappropriate behavior.
**Consequence:** A temporary ban from any interaction or public communication with the community for a specified period. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact:** Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
**Consequence:** A permanent ban from any sort of public interaction within the community.
## Attribution
This document is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozillas code of conduct enforcement ladder](https://github.com/mozilla/diversity).
For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq.
Translations are available at https://www.contributor-covenant.org/translations.

@ -6,7 +6,8 @@
[![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://docs.abp.io/en/abp/latest/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)
[![ABP Discord server](https://img.shields.io/discord/951497912645476422?label=Discord)](https://discord.gg/abp)
ABP Framework is a complete **infrastructure** based on **ASP.NET Core** to create **modern web applications** and **APIs** by following the software development **best practices** and the **latest technologies**. Check out https://abp.io

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>

@ -455,8 +455,11 @@
"InterestedLicenseType": "Interested License Type",
"MoveWaitList": "Move to wait list",
"CommunityLinkTitle": "Open on the community website",
"CommunityLink": "Community Link",
"CommunityLink": "Community link",
"ReloadFromSource": "Reload From the Source",
"ReloadFromSourceConfirmationMessage": "This post will be refreshed from \"{0}\". Do you want to continue?"
"ReloadFromSourceConfirmationMessage": "This post will be refreshed from \"{0}\". Do you want to continue?",
"UnitPrice": "Unit Price",
"OverallDiscountAmount": "Overall Discount Amount",
"DiscountAmount": "Discount Amount"
}
}

@ -26,7 +26,7 @@
"ContributionGuide": "Contribution Guide",
"Blog": "Blog",
"Commercial": "Commercial",
"MyAccount": "My account",
"MyAccount": "My Account",
"Permission:License": "License",
"Permission:UserInfo": "User info",
"SeeDocuments": "See Documents",

@ -43,9 +43,9 @@
"ContributionGuide": "Contribution Guide",
"Blog": "Blog",
"Commercial": "Commercial",
"MyAccount": "My account",
"MyAccount": "My Account",
"Permission:License": "License",
"Permission:UserInfo": "Usere info",
"Permission:UserInfo": "User info",
"SeeDocuments": "See Documents",
"Samples": "Samples",
"Framework": "Framework",
@ -210,6 +210,7 @@
"Icon": "Icon",
"RecentActivities": "Recent Activities",
"SpringCampaign": "Welcome <br>Spring Sale!",
"SpringCampaign2": "<span>Limited <br> Time Offer!</span>"
"SpringCampaign2": "<span>Limited <br> Time Offer!</span>",
"AboutUs": "About Us"
}
}

@ -208,6 +208,7 @@
"Icon": "图标",
"RecentActivities": "最近的活动",
"SpringCampaign": "欢迎 <br>春季促销!",
"SpringCampaign2": "<span>限时优惠!<br></span>"
"SpringCampaign2": "<span>限时优惠!<br></span>",
"AboutUs": "关于我们"
}
}

@ -41,6 +41,7 @@
"TrialLicensePeriodExpireToday": "您的試用許可期將於今天到期。",
"PurchaseNow": "現在買!",
"WelcomeFallCampaign": "欢迎秋季活动!",
"GiveAwayForNewPurchases": "新购买将赠送应用程序开发课堂培训!"
"GiveAwayForNewPurchases": "新购买将赠送应用程序开发课堂培训!",
"AboutUs": "關於我們"
}
}

@ -516,6 +516,7 @@
"Pricing_Page_Testimonial_4": "ABP التجاري منتج رائع يوصى به. تسويق المنتجات التجارية لعملائنا في منصة واحدة قابلة للتكوين. البداية السريعة التي يوفرها إطار العمل والأدوات لأي فريق تستحق كل سنت. كانت ABP هي الأنسب لاحتياجاتنا.",
"Pricing_Page_Testimonial_5": "إطار عمل ABP ليس مجرد إطار عمل ، ولكنه أيضًا دليل لتطوير / إدارة المشروع ، لأنه يوفر تدريب DDD و GenericRepository و DI و Microservice و Modularity. حتى إذا كنت لن تستخدم الإطار نفسه ، يمكنك تطوير نفسك باستخدام docs.abp.io المُعد جيدًا ومهنيًا (OpenIdict و Redis و Quartz وما إلى ذلك). نظرًا لأن العديد من الأشياء مبنية مسبقًا ، فإنها تقصر وقت تطوير المشروع بشكل كبير (مثل صفحة تسجيل الدخول ، ومعالجة الاستثناءات ، وتصفية البيانات ، والبذر ، وتسجيل التدقيق ، والترجمة ، ووحدة التحكم في واجهة برمجة التطبيقات التلقائية ، وما إلى ذلك). كمثال من تطبيقنا ، لقد استخدمت Local Event Bus للتحكم في المخزون. لذلك ، أنا قادر على إدارة حركات الأوامر عن طريق كتابة معالج الأسهم. إنه لأمر رائع ألا تضيع الوقت من أجل CreationTime ، CreatorId. يتم ملؤها تلقائيًا.",
"Pricing_Page_Testimonial_6": "إطار عمل ABP هو إطار عمل جيد ولكنه يحتاج إلى وقت لفهم الطبقات والفئات والمكتبات المختلفة التي يستخدمها (خاصة ABP). قضيت الكثير من الوقت في قراءة قاعدة الكود ، لكن ABP Commercial توفر لنا الوقت لإنشاء كيانات تخصص المشروع (AR) والمستودع المرتبط بكل منها. أعجبني أيضًا أن النهج المستخدم في ABP ناضج جدًا ، ونعلم أنه يعتمد على DDD و monolith.",
"Pricing_Page_Testimonial_7": "كشركة ناشئة ، نحتاج إلى التكرار بسرعة وقضاء أقل وقت في استخدام الميزات المعيارية وغير الأساسية.\nتتراوح مهندسينا من ذوي الخبرة العالية إلى المهندسين المبتدئين ، فنحن بحاجة إلى فهم مشترك وطريقة لمشاركة المعرفة الفنية والمعرفة بالمجال ، وقد سمح لنا ABP بالقيام بذلك بسبب أدلةهم ووثائقهم الرائعة.\nهناك أشياء لا داعي للقلق بشأنها لأنها تعمل خارج الصندوق مع ABP.\nساعدتنا ABP في تبسيط النماذج الأولية السريعة والتطوير ، أقل من 4 أسابيع من بداية الميزة إلى الإنتاج. مع كل ميزاتها المتميزة المضمنة في الترخيص ، منحتنا ABP \"Startup in a Box\" في جانب هندسة البرمجيات.",
"AbpBookDownloadArea_ClaimYourEBook": "احصل على كتاب <span class='gradient-framework'>إتقان إطار عمل ABP</span> الالكتروني الخاص بك",
"AddMemberModal_Warning_1": "اذا كان <strong>المستخدم</strong> الذي تحاول اضافته لا يوجد في النظام, يرجى مطالبة عضو فريقك بالتسجيل في <a href='{0}/Account/Register'>{0}</a> ومشاركة اسم المستخدم الخاص بحسابه معك.",
"MyOrganizations_Detail_WelcomeMessage": "مرحبًا بك في مؤسستك، {0}",

@ -247,7 +247,7 @@
"FastEasy": "Fast & Easy",
"AbpSuiteExplanation3": "ABP Suite allows you to easily create CRUD pages. You just need to define your entity and its properties, let the rest to ABP Suite for you! ABP Suite generates all the necessary code for your CRUD page in a few seconds. It supports Angular, MVC and Blazor user interfaces.",
"RichOptions": "Rich Options",
"AbpSuiteExplanation4": "ABP Suite supports multiple UI options like <a href=\"https://docs.microsoft.com/en-us/aspnet/core/razor-pages\">Razor Pages</a> and <a href=\"https://angular.io\">Angular</a>.It also supports multiple databases like <a href=\"https://www.mongodb.com\">MongoDB</a> and all databases supported by <strong>EntityFramework Core</strong> (MS SQL Server, Oracle, MySql, PostgreSQL and <a href=\"https://docs.microsoft.com/en-us/ef/core/providers/?tabs=dotnet-core-cli\">more</a>).",
"AbpSuiteExplanation4": "ABP Suite supports multiple UI options like <a href=\"https://docs.microsoft.com/en-us/aspnet/core/razor-pages\">Razor Pages</a> and <a href=\"https://angular.io\">Angular</a>.It also supports multiple databases like <a href=\"https://www.mongodb.com\">MongoDB</a> and all databases supported by <strong>EntityFramework Core</strong> (MS SQL Server, Oracle, MySql, PostgreSQL, and <a href=\"https://docs.microsoft.com/en-us/ef/core/providers/?tabs=dotnet-core-cli\">other providers...</a>).",
"AbpSuiteExplanation5": "Good thing is that, you don't have to worry about those options. ABP Suite understands your project type and generates the code for your project and places the generated code in correct place in your project.",
"SourceCode": "Source Code",
"AbpSuiteExplanation6": "ABP Suite generates the source code for you! It doesn't generate magic files to generate the web page. ABP Suite generates the source code for <strong>Entity, Repository, Application Service, Code First Migration, JavaScript/TypeScript and CSHTML/HTML</strong> and necessary Interfaces as well. ABP Suite also generates the code according to the <strong>Best Practices</strong> of software development, so you don't have to worry about the generated code's quality.",
@ -538,6 +538,9 @@
"Pricing_Page_Testimonial_4": "ABP Commercial is a fantastic product would recommend. Commercial products to market for our customers in a single configurable platform. The jump start that the framework and tooling provide any team is worth every cent. ABP Commercial was the best fit for our needs.",
"Pricing_Page_Testimonial_5": "ABP Framework is not only a framework, but it is also a guide for project development/management, because it provides DDD, GenericRepository, DI, Microservice, and Modularity training. Even if you are not going to use the framework itself, you can develop yourself with docs.abp.io which is well and professionally prepared (OpenIddict, Redis, Quartz etc.). Because many things are pre-built, it shortens project development time significantly (Such as login page, exception handling, data filtering, seeding, audit logging, localization, auto API controller etc.). As an example from our application, I have used Local Event Bus for stock control. So, I am able to manage order movements by writing stock handler. It is wonderful not to lose time for CreationTime, CreatorId. They are being filled automatically.",
"Pricing_Page_Testimonial_6": "ABP Framework is a good framework but it needs time to understand the different layers, classes, and libraries it used (specially ABP). I spent a lot of time reading the code base, but ABP Commercial save us time to create the project specialty entities (AR) and the repository linked to each of them. I liked also the approach used in ABP is very mature, we know is based on DDD and monolith.",
"Pricing_Page_Testimonial_7": "As a startup we need to iterate quickly and spend minimal time on boilerplate and non-core features.\nOur engineers range from highly experienced to junior engineers, we needed a common understanding and a way to share technical and domain knowledge, ABP allowed us to do this due to their great guides and documentation. \nThere are things we haven't had to worry about since they work out of the box with ABP. \nABP helped us streamline rapid prototyping and development, less than 4 weeks from feature inception to production. With all its premium features included in the license, ABP has given us, \"Startup in a Box\" on the Software Engineering Side.",
"Pricing_Page_Testimonial_8": "I would recommend ABP commercial to all those who want to expand the range of products available to their customers. It's fantastic when need to use a distributed enterprise enviroment (Angualr, WPF, Win&Linux). In addition to their products, we love their support, which makes our job faster and easier. We already know that we have found a great partner for the future who will support us in expanding our business.",
"Pricing_Page_Testimonial_9": "We are a company of 2 employees that's been in business for over 20 years.\nIn terms of our experience with ABP Commercial, we were approached by a client who requested that we develop a new human resources application in a modern environment to replace their 25-year-old Access application. We decided to transition from a desktop solution to a web-based one.\n\nAt the time, we had very little knowledge of web applications and .NET but we stumbled upon ABP Commercial, and with the help of ABP Framework, technical documentation, and ABP Suite, we were able to not only develop the application to the client's specifications but also successfully work within a .NET environment within a year.",
"AbpBookDownloadArea_ClaimYourEBook": "Claim your <span class='gradient-framework'>Mastering ABP Framework</span> E-Book",
"AddMemberModal_Warning_1": "If the <strong>username</strong> you are trying to add doesn't exist in the system, please ask your team member to register on <a href='{0}/Account/Register'>{0}</a> and share the username of his/her account with you.",
"MyOrganizations_Detail_WelcomeMessage": "Welcome to your organization, {0}",
@ -831,6 +834,14 @@
"Volo.AbpIo.Commercial:040001": "API Access Key is incorrect.",
"GetLepton": "Get Lepton Now",
"MyOrganizations_Detail_LicenseStartDate": "License Start Date",
"MyOrganizations_Detail_LicenseExpiryDate": "Expiry Date"
"MyOrganizations_Detail_LicenseExpiryDate": "Expiry Date",
"BlazoriseSupport": "How do I get the Blazorise license key and support from the Blazorise team?",
"BlazoriseSupportExplanation": "Follow the steps below to get support from the Blazorise team and get your Blazorise license key:",
"BlazoriseSupportExplanation1": "Sign up for a new account at <a href=\"https://blazorise.com/support/register\">blazorise.com/support/register</a> with the same email address as your abp.io account. Leave the \"License Key\" entry blank. <strong>It must be the same email address as your email account on abp.io</strong>.",
"BlazoriseSupportExplanation2": "Verify your email address by checking your email box. Check your spam box if you don't see an email in your inbox!",
"BlazoriseSupportExplanation3": "Log into the Blazorise support website at <a href=\"https://blazorise.com/support/login\">blazorise.com/support/login</a>.",
"BlazoriseSupportExplanation4": "If you have an active ABP Commercial license, you will also have a Blazorise PRO license. You can get your Blazorise license key at <a href=\"https://blazorise.com/support/user/manage/license\">blazorise.com/support/user/manage/license</a>.",
"BlazoriseSupportExplanation5": "You can post your questions on the support website and generate a product token for your application.",
"AbpLiveTrainingPackages": "ABP Live Training Packages"
}
}

@ -538,6 +538,7 @@
"Pricing_Page_Testimonial_4": "ABP Commercial on loistava tuote, jota suosittelen. Kaupalliset tuotteet markkinoille asiakkaillemme yhdellä konfiguroitavalla alustalla. Kehyksen ja työkalujen tarjoama aloitus jokaiselle joukkueelle on jokaisen sentin arvoinen. ABP Commercial sopi parhaiten tarpeisiimme.",
"Pricing_Page_Testimonial_5": "ABP Framework ei ole vain viitekehys, vaan se on myös opas projektin kehittämiseen/hallintaan, koska se tarjoaa DDD-, GenericRepository-, DI-, Microservice- ja Modularity-koulutusta. Vaikka et itse käyttäisikään kehystä, voit kehittää itseäsi docs.abp.io:lla, joka on hyvin ja ammattimaisesti valmisteltu (OpenIddict, Redis, Quartz jne.). Koska monet asiat on rakennettu valmiiksi, se lyhentää projektin kehitysaikaa merkittävästi (kuten kirjautumissivu, poikkeusten käsittely, tietojen suodatus, kylvö, tarkastusloki, lokalisointi, automaattinen API-ohjain jne.). Esimerkkinä sovelluksestamme olen käyttänyt paikallista tapahtumaväylää varastonhallintaan. Pystyn siis hallitsemaan tilausliikkeitä kirjoittamalla varastokäsittelijäksi. On hienoa olla hukkaamatta aikaa CreationTimelle, CreatorId:lle. Ne täytetään automaattisesti.",
"Pricing_Page_Testimonial_6": "ABP Framework on hyvä kehys, mutta sen käyttämien eri kerrosten, luokkien ja kirjastojen (erityisesti ABP:n) ymmärtäminen vaatii aikaa. Käytin paljon aikaa koodikannan lukemiseen, mutta ABP Commercial säästää aikaa projektin erityiskokonaisuuksien (AR) ja kuhunkin niistä linkitetyn arkiston luomiseen. Pidin myös ABP:ssä käytetystä lähestymistavasta, joka on hyvin kypsä, sillä se perustuu DDD:hen ja monoliittisuuteen.",
"Pricing_Page_Testimonial_7": "Aloittajana meidän on iteroitava nopeasti ja käytettävä mahdollisimman vähän aikaa perusominaisuuksiin ja muihin kuin ydinominaisuuksiin.\nInsinöörimme vaihtelevat erittäin kokeneista nuorempiin insinööreihin, tarvitsimme yhteisymmärryksen ja tavan jakaa teknistä ja aluetietoa. ABP antoi meille mahdollisuuden tehdä tämä heidän loistavien oppaidensa ja dokumentointinsa ansiosta.\nOn asioita, joista meidän ei ole tarvinnut huolehtia, koska ne toimivat suoraan ABP:n kanssa.\nABP auttoi meitä virtaviivaistamaan nopeaa prototyyppien valmistusta ja kehitystä, alle 4 viikkoa ominaisuuden käyttöönotosta tuotantoon. Kaikkien lisenssiin sisältyvien ensiluokkaisten ominaisuuksiensa ansiosta ABP on antanut meille \"Startup in a Box\" -ohjelman ohjelmistosuunnittelun puolella.",
"AbpBookDownloadArea_ClaimYourEBook": "Lunasta <span class='gradient-framework'>Mastering ABP Framework</span> -e-kirja",
"AddMemberModal_Warning_1": "Jos <strong>käyttäjätunnusta</strong>, jota yrität lisätä, ei ole järjestelmässä, pyydä tiimisi jäsentä rekisteröitymään osoitteessa <a href='{0}/Account/Register'>{0}</ a> ja jakaa hänen tilinsä käyttäjätunnus kanssasi.",
"MyOrganizations_Detail_WelcomeMessage": "Tervetuloa organisaatioosi, {0}",

@ -539,6 +539,7 @@
"Pricing_Page_Testimonial_4": "Az ABP Commercial egy fantasztikus termék, amelyet ajánlunk. Kereskedelmi termékek, amelyeket ügyfeleink számára egyetlen konfigurálható platformon értékesíthetnek. Az ugrásszerű indítás, amelyet a keret és az eszközök biztosítanak bármely csapat számára, minden centet megér. Az ABP Commercial volt a legjobban megfelelő az igényeinknek.",
"Pricing_Page_Testimonial_5": "Az ABP Framework nem csak keretrendszer, hanem útmutató is a projektfejlesztéshez/menedzsmenthez, mert DDD, GenericRepository, DI, Microservice és Modularity képzést biztosít. Ha magát a keretrendszert nem is használja, fejlesztheti magát a docs.abp.io-val, amely jól és professzionálisan elkészített (OpenIddict, Redis, Quartz stb.) leírás. Mivel sok minden előre be van építve, jelentősen lerövidíti a projektfejlesztési időt (például bejelentkezési oldal, kivételkezelés, adatszűrés, aéapadatok, audit naplózás, lokalizáció, automatikus API vezérlő stb.). Alkalmazásunkból példaként a Helyi Event Bus-t használtam az állomány karbantartására. Így a rendelési mozgásokat eseményekkel tudom a készlethez igazítani. Csodálatos, hogy nem veszítünk időt a CreationTime-ra, a CreatorId-re. Automatikusan feltöltődnek.",
"Pricing_Page_Testimonial_6": "Az ABP Framework egy jó keretrendszer, de időre van szükség a különböző rétegek, osztályok és könyvtárak (különösen az ABP) megértéséhez. Sok időt töltöttem a kódbázis elolvasásával, de az ABP Commercial időt takarít meg nekünk a projekt speciális entitások (AR) és a mindegyikhez kapcsolódó tároló létrehozására. Tetszett az ABP-ben használt megközelítés is nagyon érett, tudjuk, hogy a DDD-n és a monoliton alapul.",
"Pricing_Page_Testimonial_7": "Indításként gyorsan ismételgetnünk kell, és minimális időt kell töltenünk az alapjellemzőkkel és a nem alapvető funkciókkal.\nMérnökeink a nagy tapasztalattal rendelkező mérnököktől a fiatal mérnökökig terjednek, közös megértésre volt szükségünk, és egy módra volt szükségünk a műszaki és területi ismeretek megosztására, az ABP ezt nagyszerű útmutatóik és dokumentációik révén tette lehetővé.\nVannak dolgok, amelyek miatt nem kellett aggódnunk, mióta az ABP-vel már a dobozból működnek.\nAz ABP segített nekünk a gyors prototípus-készítés és fejlesztés egyszerűsítésében, kevesebb mint 4 héttel a funkció kezdetétől a gyártásig. A licencben szereplő összes prémium funkcióval együtt az ABP a szoftverfejlesztési oldalon a „Startup in a Box”-t adta nekünk.",
"AbpBookDownloadArea_ClaimYourEBook": "Igényelje <span class='gradient-framework'>Mastering ABP Framework</span> e-könyvét",
"AddMemberModal_Warning_1": "Ha a hozzáadni kívánt <strong>felhasználónév</strong> nem létezik a rendszerben, kérje meg csapattagját, hogy regisztráljon a <a href='{0}/Account/Register'>(z) {0}</a> webhelyen, és ossza meg fiókja felhasználónevét Önnel.",
"MyOrganizations_Detail_WelcomeMessage": "Üdvözöljük szervezetében, {0}",

@ -548,6 +548,7 @@
"Pricing_Page_Testimonial_4": "ABP Commercial harika bir ürün, tavsiye ederim. Müşterilerimiz için ticari ürünleri tek bir yapılandırılabilir platformda pazara sunuyor. Çerçeve ve araçların herhangi bir ekibe sağladığı hızlı başlangıç her kuruşa değer. ABP Commercial ihtiyaçlarımız için en uygun üründü.",
"Pricing_Page_Testimonial_5": "ABP Framework sadece bir framework değil, aynı zamanda bir proje geliştirme/yönetme rehberi, çünkü DDD, GenericRepository, DI, Microservice ve Modularity eğitimleri veriyor. Framework'ün kendisini kullanmayacak olsanız bile, iyi ve profesyonelce hazırlanmış docs.abp.io ile kendinizi geliştirebilirsiniz (OpenIddict, Redis, Quartz vb.). Birçok şey önceden hazır olduğu için proje geliştirme süresini önemli ölçüde kısaltıyor (Giriş sayfası, istisna işleme, veri filtreleme, tohumlama, denetim günlüğü, yerelleştirme, otomatik API denetleyicisi vb.) Uygulamamızdan bir örnek olarak, stok kontrolü için Local Event Bus kullandım. Böylece stok işleyicisi yazarak sipariş hareketlerini yönetebiliyorum. CreationTime, CreatorId için zaman kaybetmemek harika. Bunlar otomatik olarak dolduruluyor.",
"Pricing_Page_Testimonial_6": "ABP Framework iyi bir çerçeve ancak kullandığı farklı katmanları, sınıfları ve kütüphaneleri (özellikle ABP) anlamak için zaman gerekiyor. Kod tabanını okumak için çok zaman harcadım, ancak ABP Commercial, proje özel varlıklarını (AR) ve her birine bağlı depoyu oluşturmak için bize zaman kazandırdı. ABP'de kullanılan yaklaşımın çok olgun olduğunu da beğendim, DDD ve monolith'e dayandığını biliyoruz.",
"Pricing_Page_Testimonial_7": "Bir başlangıç olarak hızlı bir şekilde yineleme yapmamız ve temel olmayan özellikler için minimum zaman harcamamız gerekiyor.\nMühendislerimiz son derece deneyimli mühendislerden genç mühendislere kadar çeşitlilik gösteriyor, ortak bir anlayışa ve teknik ve alan bilgisini paylaşmanın bir yoluna ihtiyacımız vardı, ABP harika kılavuzları ve belgeleri sayesinde bunu yapmamızı sağladı. \nABP ile kutudan çıkar çıkmaz çalıştıkları için endişelenmemize gerek kalmayan şeyler var. \nABP, hızlı prototip oluşturma ve geliştirmeyi kolaylaştırmamıza yardımcı oldu, özelliğin başlangıcından üretime kadar 4 haftadan kısa bir süre geçti. Lisansa dahil olan tüm premium özellikleriyle ABP, Yazılım Mühendisliği tarafında bize \"Startup in a Box\" sağladı.",
"AbpBookDownloadArea_ClaimYourEBook": "<span class='gradient-framework'>Mastering ABP Framework</span> E-Kitabınızı talep edin",
"AddMemberModal_Warning_1": "Eklemeye çalıştığınız <strong>kullanıcı adı</strong> sistemde yoksa, lütfen ekip üyenizden <a href='{0}/Account/Register'>{0}</a> adresine kaydolmasını ve hesabının kullanıcı adını sizinle paylaşmasını isteyin.",
"MyOrganizations_Detail_WelcomeMessage": "Organizasyonunuza hoş geldiniz, {0}",

@ -538,6 +538,7 @@
"Pricing_Page_Testimonial_4": "ABP 商业版 是一款很值得推荐的出色产品。 是在一个可配置的平台上为我们的客户推向市场的商业产品。 其框架和工具为任何团队提供的快速启动值得每一分钱。 ABP 商业版 最适合我们的需求。",
"Pricing_Page_Testimonial_5": "ABP Framework 不仅是一个框架,它还是项目开发/管理的指南,因为它提供了 DDD、GenericRepository、DI、微服务和模块化培训。 即使你不打算使用框架本身,你也可以通过 docs.abp.io 进行自己的开发该文档已经做好了专业的准备OpenIddict、Redis、Quartz 等)。 因为很多东西都是预先构建的,它大大缩短了项目开发时间(例如登录页面、异常处理、数据过滤、种子、审计日志、本地化、自动 API 控制器等)。 作为我们应用程序的一个示例,我使用本地事件总线进行库存控制。 因此我可以通过编写库存处理程序来管理订单移动。 不为 CreationTimeCreatorId 浪费时间真是太好了。 它们正在自动填充。",
"Pricing_Page_Testimonial_6": "ABP Framework 是一个很好的框架,但它需要时间来理解它使用的不同层、类和库(特别是 ABP。 我花了很多时间阅读代码库,但是 ABP Commercial 为我们节省了创建项目专业实体 (AR) 和链接到每个实体的存储库的时间。 我也喜欢 ABP 中使用的方法非常成熟,我们知道它基于 DDD 和单体。",
"Pricing_Page_Testimonial_7": "作为一家初创公司,我们需要快速迭代并在样板和非核心功能上花费最少的时间。\n我们的工程师从经验丰富的工程师到初级工程师我们需要一个共同的理解和一种分享技术和领域知识的方式ABP 允许我们这样做是因为他们提供了很好的指南和文档。\n有些事情我们不必担心因为它们与 ABP 一起开箱即用。\nABP 帮助我们简化了快速原型设计和开发,从功能开始到生产不到 4 周。凭借许可证中包含的所有高级功能ABP 在软件工程方面为我们提供了“盒子里的启动”。",
"AbpBookDownloadArea_ClaimYourEBook": "领取您的<span class='gradient-framework'>掌握ABP框架</span>电子书",
"AddMemberModal_Warning_1": "如果您尝试添加的<strong>用户名</strong>在系统中不存在,请让您的团队成员在 <a href='{0}/账户/注册'>{0}</ 上注册 a> 并与您分享他/她帐户的用户名。",
"MyOrganizations_Detail_WelcomeMessage": "欢迎加入您的组织,{0}",

@ -187,6 +187,7 @@
"IConsentToMedium": "I consent to the publication of this post at https://medium.com/volosoft.",
"SearchResultsFor": "Search results for <span class=\"fw-bold\">\"{0}\"</span>",
"SeeMoreVideos": "See more videos",
"DiscordPageTitle": "ABP Discord Community"
"DiscordPageTitle": "ABP Discord Community",
"ViewVideo": "View Video"
}
}

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

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

@ -58,3 +58,22 @@ Here you can see them in table with the GitHub stars, GitHub release counts, rec
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.
---
### 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!**
---
> 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)

@ -0,0 +1,211 @@
# ABP.IO Platform 7.2 RC Has Been Released
Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **7.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<CmsKitCommentOptions>(options =>
{
options.AllowedExternalUrls = new Dictionary<string, List<string>>
{
{
"Product",
new List<string>
{
"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
<abp-card cardClass="mt-4 mb-5">
<abp-card-body>
<div>...</div>
</abp-card-body>
</abp-card>
```
> 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)
### 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](force-password-change.png)
After the first successful login, a password change page will open and force the user to change their password:
![password change form](password-change-form.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](password-aging.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-menu-render](leptonx-group-render.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](suite-property.png)
## Community News
### ABP - DOTNET CONF'23
![abp-conf](abp-conf.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:
* [Whats 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!

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

@ -0,0 +1,118 @@
# 💻 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
<picture>
<source media="(min-width: 650px)" data-srcset="image.webp">
<source media="(min-width: 465px)" data-srcset="image_small.webp">
<img src="placeholder.png" data-src="image.webp" alt="Image" width="100" height="100" class="lazy" />
</picture>
```
```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
<div id="placeholder" data-url="/slow-loading-content">
<p>Loading...</p>
</div>
```
```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
<a href="https://example.com/" aria-label="Go to Example">Example</a>
<a href="https://example.com/" aria-label="Go to Another Example">Another Example</a>
```
## 🌐 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.
## What is 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 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, try [abp.io](https://abp.io/) now...
**IT IS FREE AND OPEN-SOURCE!**

@ -0,0 +1,86 @@
# ABP.IO Platform 7.2 Final Has Been Released!
[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 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 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.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](abp-conf.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)
* [Whats 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)
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 Conf23! 📣](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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

@ -41,6 +41,7 @@ Here, is the list of all available commands before explaining their details:
* **`switch-to-preview`**: Switches to the latest preview version of the ABP Framework.
* **`switch-to-nightly`**: Switches to the latest [nightly builds](Nightly-Builds.md) of the ABP related packages on a solution.
* **`switch-to-stable`**: Switches to the latest stable versions of the ABP related packages on a solution.
* **`switch-to-local`**: Changes NuGet package references on a solution to local project references.
* **`translate`**: Simplifies to translate localization files when you have multiple JSON [localization](Localization.md) files in a source control repository.
* **`login`**: Authenticates on your computer with your [abp.io](https://abp.io/) username and password.
* **`login-info`**: Shows the current user's login information.
@ -453,6 +454,27 @@ abp switch-to-stable [options]
* `--solution-directory` or `-sd`: Specifies the directory. The solution should be in that directory or in any of its sub directories. If not specified, default is the current directory.
### switch-to-local
Changes all NuGet package references to local project references for all the .csproj files in the specified folder (and all its subfolders with any deep). It is not limited to ABP Framework or Module packages.
Usage:
````bash
abp switch-to-local [options]
````
#### Options
* `--solution` or `-s`: Specifies the solution directory. The solution should be in that directory or in any of its sub directories. If not specified, default is the current directory.
* `--paths` or `-p`: Specifies the local paths that the projects are inside. You can use `|` character to separate the paths.
Example:
````bash
abp switch-to-local --paths "D:\Github\abp|D:\Github\my-repo"
````
### translate
Simplifies to translate [localization](Localization.md) files when you have multiple JSON [localization](Localization.md) files in a source control repository.

@ -241,3 +241,24 @@ That's all! We created a passwordless login with 7 steps.
## Source Code
The completed sample is available on [GitHub repository](https://github.com/abpframework/abp-samples/tree/master/PasswordlessAuthentication).
〰️〰️〰️
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)
---

@ -258,8 +258,19 @@ Not all the changes are here, but you can check out the following PR of the .NET
* [github.com/abpframework/abp/pull/13626/files](https://github.com/abpframework/abp/pull/13626/files)
...
Happy coding with .NET 7 🤗
〰️〰️〰️
...
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)https://medium.com/@alperonline)\

@ -71,7 +71,13 @@ public class MyTokenExtensionGrant : ITokenExtensionGrant
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<AbpOpenIddictClaimDestinationsManager>().SetAsync(principal);
//For abp version >= 7.3
await context.HttpContext.RequestServices.GetRequiredService<AbpOpenIddictClaimsPrincipalManager>().HandleAsync(context.Request, principal);
return new SignInResult(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, claimsPrincipal);
}

@ -220,7 +220,17 @@ Become a pioneer and try the new features of .NET 8 now.
Adapt it to your project or start a new .NET 8 project.
[Claim your copy of .NET 8](https://dotnet.microsoft.com/next) today 🏎️ !
〰️〰️〰️
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)

@ -0,0 +1,325 @@
# Convert Create/Edit Modals to Page
In this document we will explain how to convert the BookStore's Books create & edit modals to regular Angular component pages.
## Before
![bookstore-crud-before](images/old.gif)
## After
![bookstore-crud-after](images/new.gif)
# BooksComponent
This is the main component of the books management. The create & update operations are done in this page. So we'll remove the create & update operations from this page and move a separate angular component for each operation. Each component will be a page.
- Remove the Create & Update modal on template
![remove-modal](images/books-remove-modals.png)
- Modify the **NewBook** button with a link to the **CreateBookComponent** page.
```html
<button
*abpPermission="'BookStore.Books.Create'"
id="create"
class="btn btn-primary"
type="button"
[routerLink]="['create']"
>
<i class="fa fa-plus me-1"></i>
<span>{{ '::NewBook' | abpLocalization }}</span>
</button>
```
- Modify the **Edit** button with a link to the **EditBookComponent** page.
```html
<button
*abpPermission="'BookStore.Books.Edit'"
ngbDropdownItem
[routerLink]="['edit', row.id]"
>
{{ '::Edit' | abpLocalization }}
</button>
```
- Remove all unused methods and variables in the `BookComponent` except the **book** variable, the **ngOnInit** and **delete** methods.
![bookstore-remove-unsued](images/books-remove-unused.png)
- Also we can clear unncessary imports
![bookstore-remove-unsued-imports](images/books-remove-unused-imports.png)
# CreateBookComponent Page
Create a new component by the name `create-book` in your project.
```bash
yarn ng g c book/create-book --skip-tests --style=none
```
- `create-book.component.html`
```html
<div class="card">
<div class="card-body">
<form [formGroup]="form" (ngSubmit)="save()">
<div class="form-group">
<label for="author-id">Author</label><span> * </span>
<select class="form-control" id="author-id" formControlName="authorId">
<option [ngValue]="null">Select author</option>
<option [ngValue]="author.id" *ngFor="let author of authors$ | async">
{{ author.name }}
</option>
</select>
</div>
<div class="mt-2">
<label for="book-name">Name</label><span> * </span>
<input type="text" id="book-name" class="form-control" formControlName="name" autofocus />
</div>
<div class="mt-2">
<label for="book-price">Price</label><span> * </span>
<input type="number" id="book-price" class="form-control" formControlName="price" />
</div>
<div class="mt-2">
<label for="book-type">Type</label><span> * </span>
<select class="form-control" id="book-type" formControlName="type">
<option [ngValue]="null">Select a book type</option>
<option [ngValue]="type.value" *ngFor="let type of bookTypes">
{{ '::Enum:BookType.' + type.value | abpLocalization }}
</option>
</select>
</div>
<div class="mt-2">
<label>Publish date</label><span> * </span>
<input
#datepicker="ngbDatepicker"
class="form-control"
name="datepicker"
formControlName="publishDate"
ngbDatepicker
(click)="datepicker.toggle()"
/>
</div>
<div class="pt-2">
<button type="button" class="btn btn-secondary m-1" [routerLink]="['/books']">
{{ '::Cancel' | abpLocalization }}
</button>
<button class="btn btn-primary">
<i class="fa fa-check mr-1"></i>
{{ '::Save' | abpLocalization }}
</button>
</div>
</form>
</div>
</div>
```
- `create-book.component.ts`
```ts
import { Component, inject } from '@angular/core';
import { Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { map } from 'rxjs';
import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap';
import { BookService, bookTypeOptions } from '@proxy/books';
const { required } = Validators;
@Component({
selector: 'app-create-book',
templateUrl: './create-book.component.html',
providers: [{ provide: NgbDateAdapter, useClass: NgbDateNativeAdapter }],
})
export class CreateBookComponent {
//inject() function came with Angular v14, detail: https://angular.io/api/core/inject
private readonly router = inject(Router);
private readonly fb = inject(FormBuilder);
private readonly bookService = inject(BookService);
form: FormGroup;
authors$ = this.bookService.getAuthorLookup().pipe(map(({ items }) => items));
bookTypes = bookTypeOptions;
private buildForm() {
this.form = this.fb.group({
authorId: [null, required],
name: [null, required],
type: [null, required],
publishDate: [undefined, required],
price: [null, required],
});
}
constructor() {
this.buildForm();
}
save() {
if (this.form.invalid) return;
this.bookService.create(this.form.value).subscribe(() => {
this.router.navigate(['/books']);
});
}
}
```
# EditBookComponent Page
Create a new component by the name **edit-book** in your project.
```bash
yarn ng g c book/edit-book --skip-tests --style=none
```
- `edit-book.component.html`
```html
<div class="card">
<div class="card-body">
<form *ngIf="form" [formGroup]="form" (ngSubmit)="save()">
<div class="form-group">
<label for="author-id">Author</label><span> * </span>
<select class="form-control" id="author-id" formControlName="authorId">
<option [ngValue]="null">Select author</option>
<option [ngValue]="author.id" *ngFor="let author of authors$ | async">
{{ author.name }}
</option>
</select>
</div>
<div class="mt-2">
<label for="book-name">Name</label><span> * </span>
<input type="text" id="book-name" class="form-control" formControlName="name" autofocus />
</div>
<div class="mt-2">
<label for="book-price">Price</label><span> * </span>
<input type="number" id="book-price" class="form-control" formControlName="price" />
</div>
<div class="mt-2">
<label for="book-type">Type</label><span> * </span>
<select class="form-control" id="book-type" formControlName="type">
<option [ngValue]="null">Select a book type</option>
<option [ngValue]="type.value" *ngFor="let type of bookTypes">
{{ '::Enum:BookType.' + type.value | abpLocalization }}
</option>
</select>
</div>
<div class="mt-2">
<label>Publish date</label><span> * </span>
<input
#datepicker="ngbDatepicker"
class="form-control"
name="datepicker"
formControlName="publishDate"
ngbDatepicker
(click)="datepicker.toggle()"
/>
</div>
<div class="pt-2">
<button type="button" class="btn btn-secondary m-1" [routerLink]="['/books']">
{{ '::Cancel' | abpLocalization }}
</button>
<button class="btn btn-primary">
<i class="fa fa-check mr-1"></i>
{{ '::Save' | abpLocalization }}
</button>
</div>
</form>
</div>
</div>
```
- `edit-book.component.ts`
```ts
import { Component, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { filter, map, switchMap, tap } from 'rxjs';
import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap';
import { BookDto, BookService, bookTypeOptions } from '@proxy/books';
const { required } = Validators;
@Component({
selector: 'app-edit-book',
templateUrl: './edit-book.component.html',
providers: [{ provide: NgbDateAdapter, useClass: NgbDateNativeAdapter }],
})
export class EditBookComponent {
//inject() function came with Angular v14, detail: https://angular.io/api/core/inject
private readonly router = inject(Router);
private readonly activatedRoute = inject(ActivatedRoute);
private readonly fb = inject(FormBuilder);
private readonly bookService = inject(BookService);
id: string;
form: FormGroup;
authors$ = this.bookService.getAuthorLookup().pipe(map(({ items }) => items));
bookTypes = bookTypeOptions;
private buildForm(book: BookDto): void {
this.form = this.fb.group({
authorId: [book.authorId, required],
name: [book.name, required],
type: [book.type, required],
publishDate: [new Date(book.publishDate), required],
price: [book.price, required],
});
}
constructor() {
this.activatedRoute.params
.pipe(
filter(params => params.id),
tap(({ id }) => (this.id = id)),
switchMap(({ id }) => this.bookService.get(id)),
tap(book => this.buildForm(book))
)
.subscribe();
}
save(): void {
if (this.form.invalid) return;
this.bookService.update(this.id, this.form.value).subscribe(() => {
this.router.navigate(['/books']);
});
}
}
```
# Update BookRoutingModule
Finally add 2 items to the routes array in the `book-routing.module.ts`
```ts
import { CreateBookComponent } from './create-book/create-book.component';
import { EditBookComponent } from './edit-book/edit-book.component';
const routes: Routes = [
{ path: '', component: BookComponent, canActivate: [AuthGuard, PermissionGuard] },
{ path: 'create', component: CreateBookComponent },
{ path: 'edit/:id', component: EditBookComponent },
];
```
You can check the following commit for more details: https://github.com/abpframework/abp-samples/commit/351ad5e093036702edbb15169968935496afea0e

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 KiB

@ -0,0 +1,36 @@
# Authority Delegation in ABP Commercial
In this post, I'll explain a new feature that comes with the ABP Commercial `v7.2.0`. It's called **Authority Delegation**.
## 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, the user can switch to the delegated user's account and perform actions on their behalf.
> This feature is part of the [Account Pro module](https://commercial.abp.io/modules/Volo.Account.Pro), which is one of the application PRO modules of [ABP Commercial](https://commercial.abp.io/).
### Delegating a new user
After logging into the application, you can see the `Authority Delegation` menu item under the user menu. When you click the menu, a modal will open, and in the first tab of the modal, you will see the list of delegated users.
![delegated-users](images/delegated-users.jpg)
You can click the `Delegate New User` button to delegate a new user:
![delegate-new-user](images/delegate-new-user.jpg)
* You can specify a time range to ensure the delegation is only available within the time range.
* You can make multiple delegates to the same user and set different delegate time ranges.
> The delegation has three states: `Expired`, `Active`, and `Future`. These states are set automatically by checking the specified time interval.
### My delegated users
A list of users who delegated me to log in on behalf of them can be seen in the figure:
![my-delegated-users](images/my-delegated-users.jpg)
You can click the `Login` button to log in to the application as a delegated user and go back to your account by clicking the `Back to my account` icon.
![delegated-impersonate](images/delegated-impersonate.jpg)
> The **Authority Delegation** feature uses the [impersonation system](https://docs.abp.io/en/commercial/latest/modules/account/impersonation) internally.

@ -3,4 +3,5 @@
You may want to override a page, a component, a JavaScript, CSS or an image file of your depended module. Overriding the UI completely depends on the UI framework you're using. Select the UI framework to continue:
* [ASP.NET Core (MVC / Razor Pages)](UI/AspNetCore/Customization-User-Interface.md)
* [Angular](UI/Angular/Customization-User-Interface.md)
* [Angular](UI/Angular/Customization-User-Interface.md)
* [Blazor](UI/Blazor/Customization-Overriding-Components.md)

@ -1,11 +1,11 @@
# Getting Started with the React Native
````json
```json
//[doc-params]
{
"Tiered": ["No", "Yes"]
"Tiered": ["No", "Yes"]
}
````
```
ABP platform provide basic [React Native](https://reactnative.dev/) startup template to develop mobile applications **integrated to your ABP based backends**.
@ -20,7 +20,6 @@ Please follow the steps below to prepare your development environment for React
3. **[Optional] Install VS Code:** [VS Code](https://code.visualstudio.com/) is a free, open-source IDE which works seamlessly with TypeScript. Although you can use any IDE including Visual Studio or Rider, VS Code will most likely deliver the best developer experience when it comes to React Native projects.
4. **Install an Emulator:** React Native applications need an Android emulator or an iOS simulator to run on your OS. See the [Android Studio Emulator](https://docs.expo.io/workflow/android-simulator/) or [iOS Simulator](https://docs.expo.io/workflow/ios-simulator/) on expo.io documentation to learn how to set up an emulator.
## How to Start a New React Native Project
You have multiple options to initiate a new React Native project that works with ABP:
@ -56,6 +55,7 @@ Please do the following:
> When you are using OpenIddict, You should remove 'clientSecret' on Environment.js (if exists) and disable "HTTPS-only" settings. (Openiddict has default since Version 6.0)
### How to disable Https-only in Openiddict.
You should add this code on {{ if Tiered == "No" }}`MyProjectNameHttpApiHostModule`{{ else if Tiered == "Yes" }}`MyProjectNameAuthServerModule`{{ end }}.
```csharp
@ -79,26 +79,27 @@ A React Native application running on an Android emulator or a physical phone **
{{ if Tiered == "No"}}
![React Native host project local IP entry](images/rn-host-local-ip.png)
* Open the `appsettings.json` in the `.HttpApi.Host` folder. Replace the `localhost` address on the `SelfUrl` and `Authority` properties with your local IP address.
* Open the `launchSettings.json` in the `.HttpApi.Host/Properties` folder. Replace the `localhost` address on the `applicationUrl` properties with your local IP address.
- Open the `appsettings.json` file in the `.HttpApi.Host` folder. Replace the `localhost` address on the `SelfUrl` and `Authority` properties with your local IP address.
- Open the `launchSettings.json` file in the `.HttpApi.Host/Properties` folder. Replace the `localhost` address on the `applicationUrl` properties with your local IP address.
{{ else if Tiered == "Yes" }}
![React Native tiered project local IP entry](images/rn-tiered-local-ip.png)
* Open the `appsettings.json` in the `.AuthServer` folder. Replace the `localhost` address on the `SelfUrl` property with your local IP address.
* Open the `launchSettings.json` in the `.AuthServer/Properties` folder. Replace the `localhost` address on the `applicationUrl` properties with your local IP address.
* Open the `appsettings.json` in the `.HttpApi.Host` folder. Replace the `localhost` address on the `Authority` property with your local IP address.
* Open the `launchSettings.json` in the `.HttpApi.Host/Properties` folder. Replace the `localhost` address on the `applicationUrl` properties with your local IP address.
- Open the `appsettings.json` file in the `.AuthServer` folder. Replace the `localhost` address on the `SelfUrl` property with your local IP address.
- Open the `launchSettings.json` file in the `.AuthServer/Properties` folder. Replace the `localhost` address on the `applicationUrl` properties with your local IP address.
- Open the `appsettings.json` file in the `.HttpApi.Host` folder. Replace the `localhost` address on the `Authority` property with your local IP address.
- Open the `launchSettings.json` file in the `.HttpApi.Host/Properties` folder. Replace the `localhost` address on the `applicationUrl` properties with your local IP address.
{{ end }}
Run the backend application as described in the [getting started document](Getting-Started.md).
> You should turn off the "Https Restriction" if you're using OpenIddict as a central identity management solution. Because the IOS Simulator doesn't support self-signed certificates and OpenIddict is set to only work with HTTPS by default.
## How to disable the Https-only settings of OpenIddict
Go to MyProjectNameHttpApiHostModule.cs under the host project. Add put these codes under the `PreConfigureServices` function.
Go to MyProjectNameHttpApiHostModule.cs under the host project. And put these codes under the `PreConfigureServices` function.
```csharp
#if DEBUG
@ -109,7 +110,6 @@ Run the backend application as described in the [getting started document](Getti
#endif
```
## How to Configure & Run the React Native Application
1. Make sure the [database migration is complete](./Getting-Started?UI=NG&DB=EF&Tiered=No#create-the-database) and the [API is up and running](./Getting-Started?UI=NG&DB=EF&Tiered=No#run-the-application).
@ -128,21 +128,20 @@ Run the backend application as described in the [getting started document](Getti
{{ end }}
4. Run `yarn start` or `npm start`. Wait Expo CLI to start. Expo CLI opens the management interface on the `http://localhost:19002/` address.
4. Run `yarn start` or `npm start`. Wait for the Expo CLI to print the opitons.
> The React Native application was generated with [Expo](https://expo.io/). Expo is a set of tools built around React Native to help you quickly start an app and, while it has many features.
![expo-interface](images/rn-expo-interface.png)
![expo-cli-options](images/rn-options.png)
In the above management interface, you can start the application with an Android emulator, an iOS simulator or a physical phone by the scan the QR code with the [Expo Client](https://expo.io/tools#client).
In the above image, you can start the application with an Android emulator, an iOS simulator or a physical phone by scanning the QR code with the [Expo Client](https://expo.io/tools#client) or choosing the option.
![React Native login screen on iPhone 11](images/rn-login-iphone.png)
Enter **admin** as the username and **1q2w3E*** as the password to login to the application.
Enter **admin** as the username and **1q2w3E\*** as the password to login to the application.
The application is up and running. You can continue to develop your application based on this startup template.
## See Also
* [React Native project structure](./Startup-Templates/Application#react-native)
- [React Native project structure](./Startup-Templates/Application#react-native)

@ -323,16 +323,16 @@ Configure<TokenCleanupOptions>(options =>
[Claims Principal Factory](https://docs.abp.io/en/abp/latest/Authorization#claims-principal-factory) can be used to add/remove claims to the `ClaimsPrincipal`.
The `AbpDefaultOpenIddictClaimDestinationsProvider` service will add `Name`, `Email,` and `Role` types of Claims to `access_token` and `id_token`, other claims are only added to `access_token` by default, and remove the `SecurityStampClaimType` secret claim of `Identity`.
The `AbpDefaultOpenIddictClaimsPrincipalHandler` service will add `Name`, `Email,` and `Role` types of Claims to `access_token` and `id_token`, other claims are only added to `access_token` by default, and remove the `SecurityStampClaimType` secret claim of `Identity`.
Create a service that inherits from `IAbpOpenIddictClaimDestinationsProvider` and add it to DI to fully control the destinations of claims.
Create a service that inherits from `IAbpOpenIddictClaimsPrincipalHandler` and add it to DI to fully control the destinations of claims.
```cs
public class MyClaimDestinationsProvider : IAbpOpenIddictClaimDestinationsProvider, ITransientDependency
public class MyClaimDestinationsHandler : IAbpOpenIddictClaimsPrincipalHandler, ITransientDependency
{
public virtual Task SetDestinationsAsync(AbpOpenIddictClaimDestinationsProviderContext context)
public virtual Task HandleAsync(AbpOpenIddictClaimsPrincipalHandlerContext context)
{
foreach (var claim in context.Claims)
foreach (var claim in context.Principal.Claims)
{
if (claim.Type == MyClaims.MyClaimsType)
{
@ -351,7 +351,7 @@ public class MyClaimDestinationsProvider : IAbpOpenIddictClaimDestinationsProvid
Configure<AbpOpenIddictClaimDestinationsOptions>(options =>
{
options.ClaimDestinationsProvider.Add<MyClaimDestinationsProvider>();
options.ClaimsPrincipalHandlers.Add<MyClaimDestinationsHandler>();
});
```

@ -120,6 +120,8 @@ Build the project, open the build folder, find the `MyPlugIn.dll`:
Copy `MyPlugIn.dll` into the plug-in folder (`D:\Temp\MyPlugIns` for this example).
> Please delete the `MyPlugIn.deps.json` file if you use `build folder` folder as `PlugInSources`.
If you have configured the main application like described above (see Basic Usage section), you should see the `MyService has been initialized` log in the application startup.
## Example: Creating a Plug-In With Razor Pages
@ -227,4 +229,4 @@ If your module uses a relational database and [Entity Framework Core](Entity-Fra
1. The Plugin may check if the database tables does exists and create the tables on the application startup or migrate them if the plug-in has been updated and requires some schema changes. You can use EF Core's migration API to do that.
2. You can improve the `DbMigrator` application to find migrations of the plug-ins and execute them.
There may be other solutions. For example, if your DB admin doesn't allow you to change the database schema in the application code, you may need to manually send a SQL file to the database admin to apply it to the database.
There may be other solutions. For example, if your DB admin doesn't allow you to change the database schema in the application code, you may need to manually send a SQL file to the database admin to apply it to the database.

@ -238,7 +238,7 @@ context.Menu.AddItem(
"BooksStore.Authors",
l["Menu:Authors"],
url: "/Authors"
).RequirePermissions(BookStorePermissions.Books.Default)
).RequirePermissions(BookStorePermissions.Authors.Default)
)
);
````

@ -29,7 +29,7 @@ ABP Card Component is a part of the `ThemeSharedModule` module. If you've import
// my-feature.module.ts
import { ThemeSharedModule } from '@abp/ng.theme.shared';
import { CardDemoComponent } from './chart-demo.component';
import { CardDemoComponent } from './card-demo.component';
@NgModule({
imports: [

@ -0,0 +1,51 @@
# Checkbox Component
The ABP Checkbox Component is a reusable form input component for the checkbox type.
# Inputs
- `label`
- `labelClass (default form-check-label)`
- `checkboxId`
- `checkboxReadonly`
- `checkboxReadonly (default form-check-input)`
- `checkboxStyle`
# Outputs
- `checkboxBlur`
- `checkboxFocus`
# Usage
The ABP Checkbox component is a part of the `ThemeSharedModule` module. If you've imported that module into your module, there's no need to import it again. If not, then first import it as shown below:
```ts
// my-feature.module.ts
import { ThemeSharedModule } from "@abp/ng.theme.shared";
import { CheckboxDemoComponent } from "./CheckboxDemoComponent.component";
@NgModule({
imports: [
ThemeSharedModule,
// ...
],
declarations: [CheckboxDemoComponent],
// ...
})
export class MyFeatureModule {}
```
Then, the `abp-checkbox` component can be used. See the example below:
```html
<div class="form-check">
<abp-checkbox label="Yes,I Agree" checkboxId="checkbox-input">
</abp-checkbox>
</div>
```
See the checkbox input result below:
![abp-checkbox](./images/form-checkbox.png)

@ -0,0 +1,49 @@
# Form Input Component
The ABP FormInput Component is a reusable form input component for the text type.
# Inputs
* `label`
* `labelClass (default form-label)`
* `inputPlaceholder`
* `inputReadonly`
* `inputClass (default form-control)`
# Outputs
* `formBlur`
* `formFocus`
# Usage
The ABP FormInput component is a part of the `ThemeSharedModule` module. If you've imported that module into your module, there's no need to import it again. If not, then first import it as shown below:
```ts
import { ThemeSharedModule } from "@abp/ng.theme.shared";
import { FormInputDemoComponent } from "./FomrInputDemoComponent.component";
@NgModule({
imports: [
ThemeSharedModule,
// ...
],
declarations: [FormInputDemoComponent],
})
export class MyFeatureModule {}
```
Then, the `abp-form-input` component can be used. See the example below:
```html
<div class="row">
<div class="col-4">
<abp-form-input
label="AbpAccount::UserNameOrEmailAddress"
inputId="login-input-user-name-or-email-address"
></abp-form-input>
</div>
</div>
```
See the form input result below:
![abp-form-input](./images/form-input.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

@ -0,0 +1,45 @@
# Security Headers
ABP Framework allows you to add frequently used security headers into your application. The following security headers will be added as response headers to your application if you use the `UseAbpSecurityHeaders` middleware:
* `X-Content-Type-Options`: Tells the browser to not try and guess what a mime-type of a resource might be, and to just take what mime-type the server has returned.
* `X-XSS-Protection`: This is a feature of Internet Explorer, Chrome, and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks.
* `X-Frame-Options`: This header can be used to indicate whether or not a browser should be allowed to render a page in a `<iframe>` tag. By specifying this header value as *SAMEORIGIN*, you can make it displayed in a frame on the same origin as the page itself.
* `Content-Security-Policy`: This response header allows you to restrict which resources (such as JavaScript, CSS, images, manifests, etc.) can be loaded, and the URLs that they can be loaded from. This security header will only be added if you configure the `AbpSecurityHeadersOptions` class and enable it.
## Configuration
### AbpSecurityHeadersOptions
`AbpSecurityHeadersOptions` is the main class to enable the `Content-Security-Policy` header, define its value and set other security headers that you want to add to your application.
**Example:**
```csharp
Configure<AbpSecurityHeadersOptions>(options =>
{
options.UseContentSecurityPolicyHeader = true; //false by default
options.ContentSecurityPolicyValue = "object-src 'none'; form-action 'self'; frame-ancestors 'none'";
//adding additional security headers
options.Headers["Referrer-Policy"] = "no-referrer";
});
```
> If the header is the same, the additional security headers you defined take precedence over the default security headers. In other words, it overrides the default security headers' values.
## Security Headers Middleware
Security Headers middleware is an ASP.NET Core request pipeline [middleware](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware) that adds pre-defined security headers to your application, including `X-Content-Type-Options`, `X-XSS-Protection`, and `X-Frame-Options`. Additionally, this middleware also includes those unique security headers in your application if you configure the `AbpSecurityHeadersOptions` as mentioned above.
**Example:**
```csharp
app.UseAbpSecurityHeaders();
```
> You can add this middleware into the `OnApplicationInitialization` method of your module class to register it to the request pipeline. This middleware is already configured in the [ABP Commercial Startup Templates](https://docs.abp.io/en/commercial/latest/startup-templates/index), so you don't need to manually add it if you are using one of these startup templates.
After that, you have registered the `UseAbpSecurityHeaders` middleware into the request pipeline, the defined security headers will be shown in the response headers as in the figure below:
![](../../images/security-response-headers.png)

@ -845,6 +845,15 @@
"path": "UI/AspNetCore/Page-Toolbar-Extensions.md"
}
]
},
{
"text": "Security",
"items": [
{
"text": "Security Headers",
"path": "UI/AspNetCore/Security-Headers.md"
}
]
}
]
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@ -437,6 +437,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Compone
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Ldap.Abstractions", "src\Volo.Abp.Ldap.Abstractions\Volo.Abp.Ldap.Abstractions.csproj", "{0F80E95C-41E6-4F23-94FF-FC9D0B8D5D71}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Ddd.Domain.Shared", "src\Volo.Abp.Ddd.Domain.Shared\Volo.Abp.Ddd.Domain.Shared.csproj", "{0858571B-CE73-4AD6-BD06-EC9F0714D8E9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -1303,6 +1305,10 @@ Global
{0F80E95C-41E6-4F23-94FF-FC9D0B8D5D71}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F80E95C-41E6-4F23-94FF-FC9D0B8D5D71}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F80E95C-41E6-4F23-94FF-FC9D0B8D5D71}.Release|Any CPU.Build.0 = Release|Any CPU
{0858571B-CE73-4AD6-BD06-EC9F0714D8E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0858571B-CE73-4AD6-BD06-EC9F0714D8E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0858571B-CE73-4AD6-BD06-EC9F0714D8E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0858571B-CE73-4AD6-BD06-EC9F0714D8E9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1523,6 +1529,7 @@ Global
{E9492F9F-47E0-45A6-A51D-9949FEAA8543} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{8764DFAF-D13D-449A-9A5E-5D7F0B2D7FEF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{0F80E95C-41E6-4F23-94FF-FC9D0B8D5D71} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{0858571B-CE73-4AD6-BD06-EC9F0714D8E9} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<AssemblyName>Volo.Abp.ApiVersioning.Abstractions</AssemblyName>
<PackageId>Volo.Abp.ApiVersioning.Abstractions</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

@ -1,14 +1,23 @@
using System;
using System.Globalization;
using System.Net;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Http.Json;
using Microsoft.AspNetCore.Internal;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
using Volo.Abp.Http;
using Volo.Abp.Json;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy;
@ -58,14 +67,70 @@ public class AbpAspNetCoreMultiTenancyOptions
}
}
context.Response.Headers.Add("Abp-Tenant-Resolve-Error", HtmlEncoder.Default.Encode(exception.Message));
if (isCookieAuthentication && context.Request.Method.Equals("Get", StringComparison.OrdinalIgnoreCase) && !context.Request.IsAjax())
{
context.Response.Headers.Add("Abp-Tenant-Resolve-Error", HtmlEncoder.Default.Encode(exception.Message));
context.Response.Redirect(context.Request.GetEncodedUrl());
}
else if (context.Request.IsAjax())
{
var error = new RemoteServiceErrorResponse(new RemoteServiceErrorInfo(exception.Message, exception is BusinessException businessException ? businessException.Details : string.Empty));
var jsonSerializerOptions = context.RequestServices.GetRequiredService<IOptions<JsonOptions>>().Value.SerializerOptions;
ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
null,
context.Response.ContentType,
(new MediaTypeHeaderValue("application/json")
{
Encoding = Encoding.UTF8
}.ToString(), Encoding.UTF8),
MediaType.GetEncoding,
out var resolvedContentType,
out var resolvedContentTypeEncoding);
context.Response.ContentType = resolvedContentType;
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
var responseStream = context.Response.Body;
if (resolvedContentTypeEncoding.CodePage == Encoding.UTF8.CodePage)
{
try
{
await JsonSerializer.SerializeAsync(responseStream, error, error.GetType(), jsonSerializerOptions, context.RequestAborted);
await responseStream.FlushAsync(context.RequestAborted);
}
catch (OperationCanceledException) when (context.RequestAborted.IsCancellationRequested) { }
}
else
{
var transcodingStream = Encoding.CreateTranscodingStream(context.Response.Body, resolvedContentTypeEncoding, Encoding.UTF8, leaveOpen: true);
ExceptionDispatchInfo exceptionDispatchInfo = null;
try
{
await JsonSerializer.SerializeAsync(transcodingStream, error, error.GetType(), jsonSerializerOptions, context.RequestAborted);
await transcodingStream.FlushAsync(context.RequestAborted);
}
catch (OperationCanceledException) when (context.RequestAborted.IsCancellationRequested) { }
catch (Exception ex)
{
exceptionDispatchInfo = ExceptionDispatchInfo.Capture(ex);
}
finally
{
try
{
await transcodingStream.DisposeAsync();
}
catch when (exceptionDispatchInfo != null)
{
}
exceptionDispatchInfo?.Throw();
}
}
}
else
{
context.Response.Headers.Add("Abp-Tenant-Resolve-Error", HtmlEncoder.Default.Encode(exception.Message));
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
context.Response.ContentType = "text/html";

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.Client.Common</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.Client.Common</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<AssemblyName>Volo.Abp.AspNetCore.Mvc.Contracts</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Mvc.Contracts</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

@ -21,6 +21,7 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController
var daprSerializer = HttpContext.RequestServices.GetRequiredService<IDaprSerializer>();
var body = (await JsonDocument.ParseAsync(HttpContext.Request.Body));
var id = body.RootElement.GetProperty("id").GetString();
var pubSubName = body.RootElement.GetProperty("pubsubname").GetString();
var topic = body.RootElement.GetProperty("topic").GetString();
var data = body.RootElement.GetProperty("data").GetRawText();
@ -32,7 +33,7 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController
var distributedEventBus = HttpContext.RequestServices.GetRequiredService<DaprDistributedEventBus>();
var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic));
await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(topic), eventData);
await distributedEventBus.TriggerHandlersAsync(id, distributedEventBus.GetEventType(topic), eventData);
return Ok();
}
}

@ -46,6 +46,10 @@ public class AbpInputTagHelper : AbpTagHelper<AbpInputTagHelper, AbpInputTagHelp
public bool SuppressLabel { get; set; }
[HtmlAttributeName("floating-label")]
public bool FloatingLabel { get; set; }
public CheckBoxHiddenInputRenderMode? CheckBoxHiddenInputRenderMode { get; set; }
public AbpInputTagHelper(AbpInputTagHelperService tagHelperService)

@ -54,6 +54,10 @@ public class AbpInputTagHelperService : AbpTagHelperService<AbpInputTagHelper>
output.TagMode = TagMode.StartTagAndEndTag;
output.TagName = "div";
LeaveOnlyGroupAttributes(context, output);
if (TagHelper.FloatingLabel && !isCheckBox)
{
output.Attributes.AddClass("form-floating");
}
output.Attributes.AddClass(isCheckBox ? "mb-2" : "mb-3");
if (isCheckBox)
{

@ -44,6 +44,10 @@ public class AbpSelectTagHelper : AbpTagHelper<AbpSelectTagHelper, AbpSelectTagH
public string Placeholder { get; set; }
[HtmlAttributeName("floating-label")]
public bool FloatingLabel { get; set; }
public AbpSelectTagHelper(AbpSelectTagHelperService tagHelperService)
: base(tagHelperService)
{

@ -56,6 +56,10 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
{
output.TagName = "div";
LeaveOnlyGroupAttributes(context, output);
if (TagHelper.FloatingLabel)
{
output.Attributes.AddClass("form-floating");
}
output.Attributes.AddClass("mb-3");
output.TagMode = TagMode.StartTagAndEndTag;
output.Content.SetHtmlContent(innerHtml);

@ -3,14 +3,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers;
@ -68,7 +67,9 @@ public abstract class AbpTagHelperResourceService : ITransientDependency
if (file == null || !file.Exists)
{
throw new AbpException($"Could not find the bundle file '{bundleFile}' for the bundle '{bundleName}'!");
Logger.LogError($"Could not find the bundle file '{bundleFile}' for the bundle '{bundleName}'!");
AddErrorScript(viewContext, tagHelper, context, output, bundleFile, bundleName);
continue;
}
if (file.Length > 0)
@ -87,6 +88,11 @@ public abstract class AbpTagHelperResourceService : ITransientDependency
protected abstract void AddHtmlTag(ViewContext viewContext, TagHelper tagHelper, TagHelperContext context, TagHelperOutput output, string file);
protected virtual void AddErrorScript(ViewContext viewContext, TagHelper tagHelper, TagHelperContext context, TagHelperOutput output, string file, string bundleName)
{
output.Content.AppendHtml($"<script>console.log(\"%cCould not find the bundle file '{file}' for the bundle '{bundleName}'!\", 'background: yellow; font-size:20px;');</script>{Environment.NewLine}");
}
protected virtual string GenerateBundleName(List<BundleTagHelperItem> bundleItems)
{
return bundleItems.JoinAsString("|").ToMd5();

@ -100,6 +100,14 @@ public class FormElementsDemoModel
<abp-input asp-for="@Model.MyDetailsModel.Description" label="Description" />
</abp-component-demo-section>
<abp-component-demo-section title="Floating Labels" view-path="@FormElementsDemoViewComponent.ViewPath">
<abp-input asp-for="@Model.MyDetailsModel.EmailAddress" label="Email Address" placeholder="name@example.com" floating-label="true" />
<abp-select asp-for="@Model.MyDetailsModel.City" asp-items="@Model.CityList" label="City" floating-label="true" />
<abp-select asp-for="@Model.MyDetailsModel.Cities" asp-items="@Model.CityList" label="Cities" floating-label="true" />
<abp-input asp-for="@Model.MyDetailsModel.Description" label="Description" floating-label="true" />
</abp-component-demo-section>
<abp-component-demo-section title="Sizing" view-path="@FormElementsDemoViewComponent.ViewPath">
<abp-input asp-for="@Model.MyInformMeModel.Name" size="Large" />
<abp-input asp-for="@Model.MyInformMeModel.Name" size="Small" />

@ -0,0 +1,78 @@
using System;
using System.Net.Mime;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Internal;
/// <summary>
/// https://github.com/dotnet/aspnetcore/blob/release/7.0/src/Shared/ResponseContentTypeHelper.cs
/// </summary>
public static class ResponseContentTypeHelper
{
/// <summary>
/// Gets the content type and encoding that need to be used for the response.
/// The priority for selecting the content type is:
/// 1. ContentType property set on the action result
/// 2. <see cref="ContentType"/> property set on <see cref="HttpResponse"/>
/// 3. Default content type set on the action result
/// </summary>
/// <remarks>
/// The user supplied content type is not modified and is used as is. For example, if user
/// sets the content type to be "text/plain" without any encoding, then the default content type's
/// encoding is used to write the response and the ContentType header is set to be "text/plain" without any
/// "charset" information.
/// </remarks>
public static void ResolveContentTypeAndEncoding(
string? actionResultContentType,
string? httpResponseContentType,
(string defaultContentType, Encoding defaultEncoding) @default,
Func<string, Encoding> getEncoding,
out string resolvedContentType,
out Encoding resolvedContentTypeEncoding)
{
var (defaultContentType, defaultContentTypeEncoding) = @default;
// 1. User sets the ContentType property on the action result
if (actionResultContentType != null)
{
resolvedContentType = actionResultContentType;
var actionResultEncoding = getEncoding(actionResultContentType);
resolvedContentTypeEncoding = actionResultEncoding ?? defaultContentTypeEncoding;
return;
}
// 2. User sets the ContentType property on the http response directly
if (!string.IsNullOrEmpty(httpResponseContentType))
{
var mediaTypeEncoding = getEncoding(httpResponseContentType);
if (mediaTypeEncoding != null)
{
resolvedContentType = httpResponseContentType;
resolvedContentTypeEncoding = mediaTypeEncoding;
}
else
{
resolvedContentType = httpResponseContentType;
resolvedContentTypeEncoding = defaultContentTypeEncoding;
}
return;
}
// 3. Fall-back to the default content type
resolvedContentType = defaultContentType;
resolvedContentTypeEncoding = defaultContentTypeEncoding;
}
public static Encoding GetEncoding(string mediaType)
{
if (MediaTypeHeaderValue.TryParse(mediaType, out var parsed))
{
return parsed.Encoding;
}
return default;
}
}

@ -20,27 +20,38 @@ public class AbpSecurityHeadersMiddleware : IMiddleware, ITransientDependency
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
/*X-Content-Type-Options header tells the browser to not try and “guess” what a mimetype of a resource might be, and to just take what mimetype the server has returned as fact.*/
AddHeaderIfNotExists(context, "X-Content-Type-Options", "nosniff");
AddHeader(context, "X-Content-Type-Options", "nosniff");
/*X-XSS-Protection is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks*/
AddHeaderIfNotExists(context, "X-XSS-Protection", "1; mode=block");
AddHeader(context, "X-XSS-Protection", "1; mode=block");
/*The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe> or <object>. SAMEORIGIN makes it being displayed in a frame on the same origin as the page itself. The spec leaves it up to browser vendors to decide whether this option applies to the top level, the parent, or the whole chain*/
AddHeaderIfNotExists(context, "X-Frame-Options", "SAMEORIGIN");
AddHeader(context, "X-Frame-Options", "SAMEORIGIN");
if (Options.Value.UseContentSecurityPolicyHeader)
{
AddHeaderIfNotExists(context, "Content-Security-Policy",
AddHeader(context, "Content-Security-Policy",
Options.Value.ContentSecurityPolicyValue.IsNullOrEmpty()
? "object-src 'none'; form-action 'self'; frame-ancestors 'none'"
: Options.Value.ContentSecurityPolicyValue);
}
foreach (var (key, value) in Options.Value.Headers)
{
AddHeader(context, key, value, true);
}
await next.Invoke(context);
}
protected virtual void AddHeaderIfNotExists(HttpContext context, string key, string value)
protected virtual void AddHeader(HttpContext context, string key, string value, bool overrideIfExists = false)
{
if (overrideIfExists && context.Response.Headers.TryGetValue(key, out _))
{
context.Response.Headers[key] = value;
return;
}
context.Response.Headers.AddIfNotContains(new KeyValuePair<string, StringValues>(key, value));
}
}

@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Security;
public class AbpSecurityHeadersOptions
@ -5,4 +7,11 @@ public class AbpSecurityHeadersOptions
public bool UseContentSecurityPolicyHeader { get; set; }
public string ContentSecurityPolicyValue { get; set; }
public Dictionary<string, string> Headers { get; }
public AbpSecurityHeadersOptions()
{
Headers = new Dictionary<string, string>();
}
}

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<AssemblyName>Volo.Abp.Auditing.Contracts</AssemblyName>
<PackageId>Volo.Abp.Auditing.Contracts</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<AssemblyName>Volo.Abp.Auditing</AssemblyName>
<PackageId>Volo.Abp.Auditing</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<AssemblyName>Volo.Abp.Authorization.Abstractions</AssemblyName>
<PackageId>Volo.Abp.Authorization.Abstractions</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<AssemblyName>Volo.Abp.Authorization</AssemblyName>
<PackageId>Volo.Abp.Authorization</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

@ -4,7 +4,7 @@
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net7.0</TargetFrameworks>
<AssemblyName>Volo.Abp.Autofac</AssemblyName>
<PackageId>Volo.Abp.Autofac</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

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

Loading…
Cancel
Save