diff --git a/.github/scripts/update_versions.py b/.github/scripts/update_versions.py index 48f312b561..dcbd749796 100644 --- a/.github/scripts/update_versions.py +++ b/.github/scripts/update_versions.py @@ -51,5 +51,4 @@ def create_pr(): if __name__ == "__main__": should_create_pr = update_latest_versions() if should_create_pr: - create_pr() - + create_pr() \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 43a884f556..2b04bcc025 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -42,6 +42,9 @@ true + + 4.5.0 + diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 341056fae9..34092c44ee 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -463,6 +463,7 @@ "DiscountAmount": "Discount Amount", "FullChangeHistory": "Full Change History", "Permission:RefreshReleaseLogs": "Refresh Release Logs", - "ReleaseLogs": "Release Logs" + "ReleaseLogs": "Release Logs", + "AuthorUserName": "Author User Name" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json index 82cc7724bf..4a7e64125f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json @@ -137,6 +137,7 @@ "Address": "العنوان", "Homepage": "الصفحة الرئيسية", "Year": "السنة", + "Year_Plural": "سنوات", "Copyright": "حقوق النشر © {1}", "DomainDrivenDesign": "التصميم المُقاد بالنطاق DDD", "CrossCuttingConcerns": "اهتمامات مشتركة", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json index d228bed40c..6788a4d224 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json @@ -141,6 +141,7 @@ "Address": "Address", "Homepage": "Homepage", "Year": "Year", + "Year_Plural": "Years", "Copyright": "Copyright © {1}", "DomainDrivenDesign": "Domain Driven Design", "CrossCuttingConcerns": "Cross Cutting Concerns", @@ -211,6 +212,11 @@ "RecentActivities": "Recent Activities", "SpringCampaign": "Welcome
Spring Sale!", "SpringCampaign2": "Limited
Time Offer!
", - "AboutUs": "About Us" + "AboutUs": "About Us", + "HowItWorks": "How it works?", + "ReleaseNotes": "Release Notes", + "DetailedChangeNotes" : "Detailed Change Notes", + "SeeTrainings": "See Trainings", + "NoContent": "No content" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json index cd2802fef4..16437480ef 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json @@ -140,6 +140,7 @@ "Address": "Osoite", "Homepage": "Kotisivu", "Year": "vuosi", + "Year_Plural": "vuotta", "Copyright": "Tekijänoikeus © {1}", "DomainDrivenDesign": "Domain Driven Design", "CrossCuttingConcerns": "Cross Cutting Concerns", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json index 21eb33ac23..b9ccddecf4 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json @@ -138,6 +138,7 @@ "Address": "Cím", "Homepage": "Kezdőlap", "Year": "Év", + "Year_Plural": "Év", "Copyright": "Copyright © {1}", "DomainDrivenDesign": "Domainvezérelt tervezés", "CrossCuttingConcerns": "Cross Cutting Concerns", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json index 4275bb3771..c57cd13b7f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json @@ -132,6 +132,7 @@ "Address": "Adres", "Homepage": "Anasayfa", "Year": "Yıl", + "Year_Plural": "Yıl", "Copyright": "Telif hakkı © {1}", "DomainDrivenDesign": "Alan Odaklı Tasarım", "CrossCuttingConcerns": "Cross Cutting Concerns", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json index 89f156c473..d1a0db7176 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json @@ -140,6 +140,7 @@ "Address": "地址", "Homepage": "主页", "Year": "年份", + "Year_Plural": "年份", "Copyright": "版权所有 © {1}", "DomainDrivenDesign": "领域驱动设计", "CrossCuttingConcerns": "横切关注点", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json index d875bffc2b..a7cfc334a9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json @@ -454,7 +454,7 @@ "MultipleUIOptionsExplanation": "نحن نحب طرقًا مختلفة لإنشاء واجهة المستخدم. يوفر حل بدء التشغيل هذا ثلاثة خيارات مختلفة لإطار عمل واجهة المستخدم لتطبيق عملك.", "MultipleDatabaseOptions": "خيارات قاعدة بيانات متعددة", "MultipleDatabaseOptionsExplanation": "لديك خياران لموفر قاعدة البيانات (بالإضافة إلى استخدام كليهما في تطبيق واحد). استخدم Entity Framework Core للعمل مع أي قاعدة بيانات علائقية واستخدم Dapper اختياريًا عندما تحتاج إلى كتابة استعلامات منخفضة المستوى للحصول على أداء أفضل. يعد MongoDB خيارًا آخر إذا كنت بحاجة إلى استخدام قاعدة بيانات NoSQL قائمة على المستندات. في حين أن هؤلاء الموفرين مدمجون جيدًا وملخصون ومهيئون مسبقًا ، يمكنك في الواقع التفاعل مع أي نظام قاعدة بيانات يمكنك استخدامه مع .NET.", - "ModularArchitectureExplanation2": "النمطية هي مواطن من الدرجة الأولى في منصة ABP.IO. يتم تقسيم جميع وظائف التطبيق إلى وحدات اختيارية معزولة جيدًا. يأتي حل بدء التشغيل بالفعل مع وحدات ABP Commercial الأساسية المثبتة مسبقًا. يمكنك أيضًا إنشاء الوحدات النمطية الخاصة بك لبناء نظام معياري لتطبيقك الخاص.", + "ModularArchitectureExplanation2": "النمطية هي مواطن من الدرجة الأولى في منصة ABP.IO. يتم تقسيم جميع وظائف التطبيق إلى وحدات اختيارية معزولة جيدًا. يأتي حل بدء التشغيل بالفعل مع وحدات ABP Commercial الأساسية المثبتة مسبقًا. يمكنك أيضًا إنشاء الوحدات النمطية الخاصة بك لبناء نظام معياري لتطبيقك الخاص.", "MultiTenancyForSaasBusiness": "متعدد الإيجارات لأعمال SaaS الخاصة بك", "MultiTenancyForSaasBusinessExplanation": "توفر ABP Commercial نظامًا كاملاً ومتعدد الإيجارات لإنشاء أنظمة SaaS (البرمجيات كخدمة). يسمح للمستأجرين بمشاركة قواعد البيانات الخاصة بهم أو الحصول عليها من خلال إنشاء قاعدة بيانات سريعة ونظام الهجرة.", "MicroserviceStartupSolution": "حل بدء تشغيل الخدمات المصغرة", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 450cd69ae3..b6a1e3299f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -476,7 +476,7 @@ "MultipleUIOptionsExplanation": "We love different ways to create the User Interface. This startup solution provides three different UI framework options for your business application.", "MultipleDatabaseOptions": "Multiple Database Options", "MultipleDatabaseOptionsExplanation": "You have two database provider options (in addition to use both in a single application). Use Entity Framework Core to work with any relational database and optionally use Dapper when you need to write low-level queries for a better performance. MongoDB is another option if you need to use a document based NoSQL database. While these providers are well-integrated, abstracted and pre-configured, you can actually interact to any database system that you can use with .NET.", - "ModularArchitectureExplanation2": "Modularity is a first-class citizen in the ABP.IO platform. All the application functionalities are split into well-isolated optional modules. The startup solution already comes with the fundamental ABP Commercial modules pre-installed. You can also create your own modules to build a modular system for your own application.", + "ModularArchitectureExplanation2": "Modularity is a first-class citizen in the ABP.IO platform. All the application functionalities are split into well-isolated optional modules. The startup solution already comes with the fundamental ABP Commercial modules pre-installed. You can also create your own modules to build a modular system for your own application.", "MultiTenancyForSaasBusiness": "Multi-Tenancy for your SaaS Business", "MultiTenancyForSaasBusinessExplanation": "ABP Commercial provides a complete, end-to-end multi-tenancy system to create your SaaS (Software-as-a-Service) systems. It allows the tenants to share or have their own databases with on-the-fly database creation and migration system.", "MicroserviceStartupSolution": "Microservice Startup Solution", @@ -844,7 +844,7 @@ "BlazoriseSupportExplanation5": "You can post your questions on the support website and generate a product token for your application.", "AbpLiveTrainingPackages": "ABP Live Training Packages", "Releases": "Releases", - "ReleasesDescription": "ABP Commercial releases and their changelogs.", + "ReleasesDescription": "Release logs of ABP Commercial.", "ReleaseDate": "Release Date", "Labels": "Labels", "PreRelease": "Pre-release", @@ -852,7 +852,56 @@ "Enhancement": "Enhancement", "Bug": "Bug", "Feature": "Feature", - "AllUIs": "All UI's", - "MVC": "MVC" + "AllUIs": "All UIs", + "MVC": "MVC", + "BlazorServer": "Blazor Server", + "MAUI": "MAUI", + "HowItWorks_Page_Title": "How it works?", + "HowItWorks_Page_Description": "ABP Framework extends the .NET platform. So, anything you can do with a plain .NET solution is already possible with the ABP Framework. That makes it easy to get started with a low learning curve.", + "HowItWorks_Description1": "ABP Framework extends the .NET platform. So, anything you can do with a plain .NET solution is already possible with the ABP Framework. That makes it easy to get started with a low learning curve.", + "HowItWorks_Description2": "Once you start learning and using the ABP Framework features, developing your software will be much more enjoyable than ever.", + "HowItWorks_Description3": "This page basically explains how you use the ABP.IO Platform as a .NET developer.", + "CreateANewSolution": "Create a New .NET Solution", + "CreateANewSolution_Description1": "Everything starts by creating a new ABP integrated .NET solution.", + "StartWithStartupTemplates": "Start one of the pre-built startup solution templates", + "SimpleMonolithApplicationTemplate": "Simple monolith application template", + "LayeredApplicationTemplate": "Layered application template", + "MicroserviceSolutionTemplate": "Microservice solution template", + "CreateEmptySolutionAndUseAbp": "Or create a new empty .NET solution and install ABP NuGet & NPM packages yourself.", + "CreatingSolutionWithMultipleOptions": "There are multiple User Interface and Database options while creating a new solution.", + "UIFrameworkOptions": "UI Framework Options", + "DotnetSolutionWithoutDependency": "Now, you have a regular .NET solution in your local computer that has no dependency to a cloud platform or external service.", + "CheckTheDocumentForDetails": "You can check the {1} document for details.", + "UIAndDatabaseIndependent": "ABP can work with any UI and any database provider supported by .NET. \n However, these UI and database providers are pre-integrated and well documented.", + "InstallAbpModules": "Install ABP Modules", + "DevelopYourSolution": "Develop Your Solution", + "DeployAnywhere": "Deploy Anywhere", + "InstallAbpModule_Description1": "ABP is a modular application development framework. Startup solution templates already come with the essential modules installed. \n But there are more application modules you may want to use in your solution.", + "InstallAbpModule_Description2": "Every module consists of a few NuGet and NPM packages and has an installation document. ABP Suite does most of the work automatically, then you manually configure or fine tune the module based on its documentation.", + "DevelopYourSolution_Description1": "ABP’s infrastructure makes you focus on your own business code by automating the repetitive work and providing pre-built infrastructure and application features.", + "DevelopYourSolution_Description2": "In the following code block, you can see how the ABP Framework seamlessly integrates into your code and automates the repetitive tasks for you.", + "DevelopYourSolution_Description3": "Even in this short code block, ABP does a lot of things for you.", + "DevelopYourSolution_Description4": "It provides base classes to apply conventions, like \n dependency injection. Generic \n repository services provide a convenient \n way to interact with the database. Declarative \n authorization works with a fine-tuned permission system.", + "DevelopYourSolution_Description5": "ABP completely automates \n unit of work (for database connection and transaction management), \n exception handling, \n validation\n and audit logging. It provides many more building blocks to simplify your daily development tasks and focus on your own code while creating production ready \n applications.", + "DevelopYourSolution_Description6": "You can imagine how much that code block can be long and complicated if you would do it all manually.", + "SuiteCrudGenerationInFewSeconds": "In addition to hand coding your solution, you can create fully working advanced CRUD pages in a few minutes using the ABP Suite tooling. It generates the code into your solution, so you can fine tune it based on your custom requirements.", + "DeployAnywhere_Description1": "At the end of the day, you have a pure .NET solution. You can deploy your solution to your own server, to a cloud platform, kubernetes or anywhere you want. You can deploy to as many servers as you want. ABP is a deployment environment agnostic tool.", + "ExpertiseAbpFramework": "Expertise the ABP Framework", + "ExpertiseAbpFramework_Description1": "Want to go beyond basics and get expertise with the ABP.IO Platform?", + "FreeDownload": "Free Download", + "Read": "Read", + "HavingTrouble": "Having Trouble?", + "HavingTrouble_Description1": "Do you have problems with developing your solution? We are here! Use the ABP Support platform \n or send an email to get help directly from the Core ABP Framework team members.", + "WeAreHereToHelp_Description1": "You can browse our help topics or search in the frequently asked questions, \n or you can ask us a question by using the contact form.", + "OtherModules": "Other Modules", + "OtherModules_Description1": "Account, Audit Logging, Chat , CMS Kit,File Management , Forms, GDPR, Identity, Language Management, Payment , Saas and more...", + "HowItWorks_DatabaseProviderOptions": "Database provider options", + "SeeFAQ" : "See FAQ", + "ReleaseLogs": "Release Logs", + "ReleaseLogs_Tag": "{0} Release Logs", + "ReleaseLogs_Pr": "Pull Request #{0} - {1}", + "NoLabels": "No labels", + "DoesTheSubscriptionRenewAutomatically": "Does the subscription renew automatically?", + "DoesTheSubscriptionRenewAutomaticallyExplanation": "The ABP Commercial does not have an auto-renewal billing model. Therefore your subscription will not be automatically renewed at the end of your license period. If you want to continue to have the benefits of ABP Commercial, you can manually renew it at the organization management page. If you have multiple organizations, click the \"Manage\" button at your expiring organization and then click the \"Extend Now\" button to renew your license. You may also want to take a look at the What Happens When My License Ends? section." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json index 885f43c70b..a4b3ac3a80 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json @@ -476,7 +476,7 @@ "MultipleUIOptionsExplanation": "Rakastamme erilaisia tapoja luoda käyttöliittymä. Tämä käynnistysratkaisu tarjoaa kolme erilaista käyttöliittymäkehysvaihtoehtoa yrityssovelluksellesi.", "MultipleDatabaseOptions": "Useita tietokantavaihtoehtoja", "MultipleDatabaseOptionsExplanation": "Sinulla on kaksi tietokannan tarjoajavaihtoehtoa (sen lisäksi, että voit käyttää molempia yhdessä sovelluksessa). Käytä Entity Framework Corea työskennelläksesi minkä tahansa relaatiotietokannan kanssa ja käytä valinnaisesti Dapperia, kun sinun on kirjoitettava matalan tason kyselyitä parantaaksesi suorituskykyä. MongoDB on toinen vaihtoehto, jos haluat käyttää dokumenttipohjaista NoSQL-tietokantaa. Vaikka nämä palveluntarjoajat ovat hyvin integroituja, abstrakteja ja esikonfiguroituja, voit itse asiassa olla vuorovaikutuksessa minkä tahansa tietokantajärjestelmän kanssa, jota voit käyttää .NET:n kanssa.", - "ModularArchitectureExplanation2": "Modulaarisuus on ensiluokkainen kansalainen ABP.IO-alustalla. Kaikki sovelluksen toiminnot on jaettu hyvin eristettyihin valinnaisiin moduuleihin. Käynnistysratkaisussa on valmiiksi asennettuna perus ABP Commercial -moduulit. Voit myös luoda omia moduuleita rakentaaksesi modulaarisen järjestelmän omalle sovelluksellesi.", + "ModularArchitectureExplanation2": "Modulaarisuus on ensiluokkainen kansalainen ABP.IO-alustalla. Kaikki sovelluksen toiminnot on jaettu hyvin eristettyihin valinnaisiin moduuleihin. Käynnistysratkaisussa on valmiiksi asennettuna perus ABP Commercial -moduulit. Voit myös luoda omia moduuleita rakentaaksesi modulaarisen järjestelmän omalle sovelluksellesi.", "MultiTenancyForSaasBusiness": "Monivuokraus SaaS-yrityksellesi", "MultiTenancyForSaasBusinessExplanation": "ABP Commercial tarjoaa täydellisen, päästä-päähän usean vuokrausjärjestelmän SaaS-järjestelmien (Software-as-a-Service) luomiseen. Sen avulla vuokralaiset voivat jakaa tai käyttää omia tietokantojaan tietokantojen luonti- ja siirtojärjestelmässä.", "MicroserviceStartupSolution": "Mikropalvelun käynnistysratkaisu", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json index 65f7a66c2d..8b9fb041b7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json @@ -477,7 +477,7 @@ "MultipleUIOptionsExplanation": "Szeretjük a felhasználói felület létrehozásának különböző módjait. Ez az indítási megoldás három különböző felhasználói felületi keretrendszert biztosít az üzleti alkalmazás számára.", "MultipleDatabaseOptions": "Több adatbázis-beállítás", "MultipleDatabaseOptionsExplanation": "Két adatbázis-szolgáltató lehetősége van (amellett, hogy mindkettőt egyetlen alkalmazásban használhatja). Az Entity Framework Core segítségével bármilyen relációs adatbázissal dolgozhat, és opcionálisan használja a Dappert, ha alacsony szintű lekérdezéseket kell írnia a jobb teljesítmény érdekében. A MongoDB egy másik lehetőség, ha dokumentum alapú NoSQL adatbázist kell használnia. Noha ezek a szolgáltatók jól integráltak, absztraktáltak és előre konfiguráltak, valójában bármilyen adatbázis-rendszerrel kapcsolatba léphet, amelyet a .NET-tel használhat.", - "ModularArchitectureExplanation2": "A a legfőbb szempont az ABP.IO platformon. Az alkalmazás összes funkciója jól elkülönített opcionális modulokra van felosztva. Az indítási megoldás már előre telepítve tartalmazza az alapvető ABP Commercial modulokat . Saját modulokat is létrehozhat, hogy moduláris rendszert építsen fel saját alkalmazásához.", + "ModularArchitectureExplanation2": "A a legfőbb szempont az ABP.IO platformon. Az alkalmazás összes funkciója jól elkülönített opcionális modulokra van felosztva. Az indítási megoldás már előre telepítve tartalmazza az alapvető ABP Commercial modulokat . Saját modulokat is létrehozhat, hogy moduláris rendszert építsen fel saját alkalmazásához.", "MultiTenancyForSaasBusiness": "Többérlős felépítés az Ön SaaS-üzleteihez", "MultiTenancyForSaasBusinessExplanation": "Az ABP Commercial teljes körű, többbérlős rendszert biztosít SaaS (Software-as-a-Service) rendszereinek létrehozásához. Lehetővé teszi a bérlők számára, hogy megosszák vagy rendelkezzenek saját adatbázisokkal az on-the-fly adatbázis-létrehozó és migrációs rendszerrel.", "MicroserviceStartupSolution": "Mikroszolgáltatás indítási megoldás", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json index 9623aba8bf..3b58578d41 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json @@ -21,7 +21,7 @@ "SetDefault": "Varsayılan olarak ayarla", "DefaultOrganization": "Varsayılan", "StartDate": "Başlangıç tarihi", - "EndDate": "bitiş tarihi", + "EndDate": "Bitiş tarihi", "Modules": "Modüller", "LicenseExtendMessage": "Lisans bitiş tarihiniz {0} tarihine kadar uzatıldı", "LicenseUpgradeMessage": "Lisansınız {0} lisansa yükseltildi", @@ -129,8 +129,8 @@ "TellUsWhatYouNeed": "Bize neye ihtiyacın olduğunu söyle.", "YourMessage": "Mesajın", "YourFullName": "Tam adınız", - "EmailField": "E", - "YourEmailAddress": "E", + "EmailField": "E-posta Adresi", + "YourEmailAddress": "E-posta adresiniz", "HowMayWeHelpYou": "Size nasıl yardımcı olabiliriz?", "SendMessage": "Mesaj gönder", "Success": "Başarı", @@ -486,7 +486,7 @@ "MultipleUIOptionsExplanation": "Kullanıcı Arayüzü oluşturmanın farklı yollarını seviyoruz. Bu başlangıç çözümü, iş uygulamanız için üç farklı UI çerçeve seçeneği sunuyor.", "MultipleDatabaseOptions": "Çoklu Veritabanı Seçenekleri", "MultipleDatabaseOptionsExplanation": "İki veritabanı sağlayıcısı seçeneğiniz var (her ikisini de tek bir uygulamada kullanmanın yanı sıra). Herhangi bir ilişkisel veritabanıyla çalışmak için Entity Framework Core'u kullanın ve daha iyi bir performans için düşük seviyeli sorgular yazmanız gerektiğinde isteğe bağlı olarak Dapper'ı kullanın. Belge tabanlı bir NoSQL veritabanı kullanmanız gerekiyorsa MongoDB başka bir seçenektir. Bu sağlayıcılar iyi entegre edilmiş, soyutlanmış ve önceden yapılandırılmış olsa da, .NET ile kullanabileceğiniz herhangi bir veritabanı sistemiyle etkileşime girebilirsiniz. ", - "ModularArchitectureExplanation2": "Modülerlik, ABP.IO platformunda birinci sınıf bir vatandaştır. Uygulamalardaki tüm işlevler iyi izole edilmiş opsiyonel modüllere ayrılmıştır. Başlangıç çözümü zaten temel ABP Ticari modülleri önceden yüklenmiş olarak gelir. Kendi uygulamanız için modüler bir sistem oluşturmak üzere kendi modüllerinizi de oluşturabilirsiniz.", + "ModularArchitectureExplanation2": "Modülerlik, ABP.IO platformunda birinci sınıf bir vatandaştır. Uygulamalardaki tüm işlevler iyi izole edilmiş opsiyonel modüllere ayrılmıştır. Başlangıç çözümü zaten temel ABP Ticari modülleri önceden yüklenmiş olarak gelir. Kendi uygulamanız için modüler bir sistem oluşturmak üzere kendi modüllerinizi de oluşturabilirsiniz.", "MultiTenancyForSaasBusiness": "Saas İşletmeleri için Çoklu Kiralama", "MultiTenancyForSaasBusinessExplanation": "ABP Commercial, SaaS (Hizmet Olarak Yazılım) sistemlerinizi oluşturmak için eksiksiz, uçtan uca çoklu kiracılık sistemi sağlar. Anında veritabanı oluşturma ve taşıma sistemi ile kiracıların kendi veritabanlarını paylaşmalarına veya sahip olmalarına olanak tanır.", "MicroserviceStartupSolution": "Mikro Hizmet Başlangıç Çözümü", @@ -808,4 +808,4 @@ "BlazoriseLicense": "Blazorise lisansı satın almamız gerekiyor mu?", "BlazoriseLicenseExplanation": "Volosoft ve Megabit arasında bir anlaşmamız var, bu anlaşma ile Blazorise lisansı ABP Ticari ürünleri ile birlikte geliyor, bu nedenle müşterilerimizin ekstra bir Blazorise lisansı satın almasına gerek kalmıyor." } -} \ No newline at end of file +} diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json index c6ed352d1e..f815f1051b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json @@ -476,7 +476,7 @@ "MultipleUIOptionsExplanation": "我们喜欢不同的方式来创建用户界面。 此启动解决方案为您的业务应用程序提供了三种不同的 UI 框架选项。", "MultipleDatabaseOptions": "多个数据库选项", "MultipleDatabaseOptionsExplanation": "您有两个数据库提供程序选项(除了在单个应用程序中使用两者)。 使用 Entity Framework Core 处理任何关系数据库,当您需要编写低级查询以获得更好的性能时,可以选择使用 Dapper。 如果您需要使用基于文档的 NoSQL 数据库,MongoDB 是另一种选择。 虽然这些提供程序是良好集成、抽象和预配置的,但您实际上可以与任何可与 .NET 一起使用的数据库系统进行交互。", - "ModularArchitectureExplanation2": "模块化是 ABP.IO 平台的一等公民。 所有应用程序功能都被拆分为隔离良好的可选模块。 启动解决方案已经预装了基本的 ABP 商业模块。 您还可以创建自己的模块来为自己的应用程序构建模块化系统。", + "ModularArchitectureExplanation2": "模块化是 ABP.IO 平台的一等公民。 所有应用程序功能都被拆分为隔离良好的可选模块。 启动解决方案已经预装了基本的 ABP 商业模块。 您还可以创建自己的模块来为自己的应用程序构建模块化系统。", "MultiTenancyForSaasBusiness": "SaaS 业务的多租户", "MultiTenancyForSaasBusinessExplanation": "ABP 商业版 提供完整的端到端多租户系统来创建您的 SaaS(软件即服务)系统。 它允许租户通过动态数据库创建和迁移系统共享或拥有自己的数据库。", "MicroserviceStartupSolution": "微服务启动解决方案", @@ -827,6 +827,15 @@ "PrivacyPolicyPageTitle": "隐私政策 - Cookies政策", "TermsConditionsPageTitle": "条款和条件", "TrainingsPageTitle": "ABP培训套餐", - "ModulesPageTitle": "ABP内置的应用模块" + "ModulesPageTitle": "ABP内置的应用模块", + "DoesTheSubscriptionRenewAutomatically": "订阅会自动续订吗?", + "DoesTheSubscriptionRenewAutomaticallyExplanation": "ABP 商业版没有自动续订计费模式。因此,在您的许可期结束时,您的订阅将不会自动续订。如果您希望继续享受 ABP 商业版的好处,您可以在组织管理页面手动续订。如果您有多个组织,请点击即将到期的组织上的“管理”按钮,然后点击“立即续订”按钮来续订您的许可证。您还可以查看许可证到期后会发生什么?部分。", + "BlazoriseSupport": "如何获取Blazorise许可密钥并获得Blazorise团队的支持?", + "BlazoriseSupportExplanation": "请按照以下步骤获取Blazorise团队的支持并获得您的Blazorise许可密钥:", + "BlazoriseSupportExplanation1": "使用与您的abp.io账户相同的电子邮件地址在blazorise.com/support/register上注册一个新账户。请将“许可密钥”一栏留空,并确保该电子邮件地址与您在abp.io上的电子邮件账户相同。", + "BlazoriseSupportExplanation2": "通过查看您的电子邮件信箱来验证您的电子邮件地址。如果在收件箱中没有看到电子邮件,请检查您的垃圾邮件箱!", + "BlazoriseSupportExplanation3": "在blazorise.com/support/login上登录Blazorise支持网站。", + "BlazoriseSupportExplanation4": "如果您有有效的ABP商业版许可证,您还将拥有Blazorise PRO许可证。您可以在blazorise.com/support/user/manage/license获取您的Blazorise许可密钥。", + "BlazoriseSupportExplanation5": "您可以在support网站上发布您的问题,并为您的应用程序生成一个产品令牌。" } } diff --git a/common.props b/common.props index eb7e9eb102..90cd1a1b4a 100644 --- a/common.props +++ b/common.props @@ -1,7 +1,7 @@ latest - 7.3.0-rc.3 + 7.4.0 $(NoWarn);CS1591;CS0436 https://abp.io/assets/abp_nupkg.png https://abp.io/ diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/POST.md b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/POST.md new file mode 100644 index 0000000000..ef5a8323c4 --- /dev/null +++ b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/POST.md @@ -0,0 +1,267 @@ +# ABP.IO Platform 7.3 RC Has Been Released + +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **7.3 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version. + +Try this version and provide feedback for a more stable version of ABP v7.3! Thanks to all of you. + +## Get Started with the 7.3 RC + +Follow the steps below to try version 7.3.0 RC today: + +1) **Upgrade** the ABP CLI to version `7.3.0-rc.1` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 7.3.0-rc.1 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 7.3.0-rc.1 +```` + +2) Create a **new application** with the `--preview` option: + +````bash +abp new BookStore --preview +```` + +See the [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all the available options. + +> You can also use the [Get Started](https://abp.io/get-started) page to generate a CLI command to create a new application. + +You can use any IDE that supports .NET 7.x, like [Visual Studio 2022](https://visualstudio.microsoft.com/downloads/). + +## Migration Guides + +There are a few breaking changes in this version that may affect your application. +Please see the following migration documents, if you are upgrading from v7.2: + +* [ABP Framework 7.2 to 7.3 Migration Guide](https://docs.abp.io/en/abp/7.3/Migration-Guides/Abp-7_3) + +> If you are using the CMS Kit or CMS Kit Pro module, please don't forget to create a new migration and apply it to your database. + +## What's New with ABP Framework 7.3? + +In this section, I will introduce some major features released in this version. Here is a brief list of the titles that will be explained in the next sections: + +* Introducing the Volo.Abp.Imaging packages +* ABP CLI: switch-to-local command +* Monitoring Distributed Events +* Ordering of the Local Event Handlers +* Nonce attribute support for Content Security Policy (CSP) +* Other News + +### Introducing the Volo.Abp.Imaging packages + +ABP Framework provides some packages to compress and resize images. Currently, there are four official packages: + +* `Volo.Abp.Imaging.Abstractions`: Provides common services for compression and resizing purposes. +* `Volo.Abp.Imaging.AspNetCore`: Provides some attributes for controller actions that can automatically compress and/or resize uploaded files. +* `Volo.Abp.Imaging.ImageSharp`: Implements the image compression & resize operations using the [ImageSharp](https://github.com/SixLabors/ImageSharp) library. +* `Volo.Abp.Imaging.MagickNet`: Implements the image compression & resize operations using the [Magick.NET](https://github.com/dlemstra/Magick.NET) library. + +You can use one of these official providers (`ImageSharp` or `Magick.NET`) or implement your own image resizer/compressor contributor and use it in your application. + +> See the [Image Manipulation](https://docs.abp.io/en/abp/7.3/Image-Manipulation) documentation to learn more and see the required configurations. + +### ABP CLI: switch-to-local command + +In this version, ABP CLI introduces a new CLI command: **"switch-to-local"**. The `switch-to-local` command changes all NuGet package references on a solution to local project references for all the `.csproj` files in the specified folder (and all its subfolders with any depth). + +**Usage:** + +```bash +abp switch-to-local --paths "C:\Github\abp" +``` + +### Monitoring Distributed Events + +ABP Framework allows you to stay informed when your application **receives** or **sends** a distributed event. This enables you to track the event flow within your application and take appropriate actions based on the received or sent distributed events. + +You just need to subscribe to one of the `DistributedEventReceived` or `DistributedEventSent` events and take additional actions according to your cases. + +**Example: Get informed when your application sends an event to the distributed event bus** + +```csharp +public class DistributedEventSentHandler : ILocalEventHandler, ITransientDependency +{ + public async Task HandleEventAsync(DistributedEventSent eventData) + { + // TODO: IMPLEMENT YOUR LOGIC... + } +} +``` + +> See the documentation to learn more: [https://docs.abp.io/en/abp/7.3/Distributed-Event-Bus](https://docs.abp.io/en/abp/7.3/Distributed-Event-Bus) + +### Ordering of the Local Event Handlers + +In this version, ABP Framework introduces the `LocalEventHandlerOrder` attribute, which can be used to set the execution order for the event handlers. This can be helpful if you want to handle your local event handlers in a specific order. + +**Example:** + +```csharp +[LocalEventHandlerOrder(-1)] +public class MyHandler + : ILocalEventHandler, + ITransientDependency +{ + public async Task HandleEventAsync(StockCountChangedEvent eventData) + { + //TODO: your implementation + } +} +``` + +By default, all event handlers have an order value of 0. Thus, if you want to take certain event handlers to be executed before other event handlers, you can set the order value as a negative value. + +> See the documentation to learn more: [https://docs.abp.io/en/abp/7.3/Local-Event-Bus](https://docs.abp.io/en/abp/7.3/Local-Event-Bus) + +### Nonce attribute support for Content Security Policy (CSP) + +ABP Framework supports adding unique value to nonce attribute for script tags which can be used by Content Security Policy to determine whether or not a given fetch will be allowed to proceed for a given element. In other words, it provides a mechanism to execute only correct script tags with the correct nonce value. + +This feature is disabled by default. You can enable it by setting the *UseContentSecurityPolicyScriptNonce* property of the `AbpSecurityHeadersOptions` class to **true**: + +```csharp +Configure(options => +{ + //adding script-src nonce + options.UseContentSecurityPolicyScriptNonce = true; //false by default +}); +``` + +> See the [Security Headers](https://docs.abp.io/en/abp/7.3/UI/AspNetCore/Security-Headers) documentation for more information. + +### Other News + +* Upgraded the [Blazorise](https://blazorise.com/) library to v1.2.3 for Blazor UI. After the upgrade, ensure that all Blazorise-related packages are using v1.2.3 in your application. +* Module Entity Extension support has been added for the CMS Kit module. See [#16572](https://github.com/abpframework/abp/issues/16572) for more information. + +If you want to see more details, you can check [the release on GitHub](https://github.com/abpframework/abp/releases/tag/5.3.0-rc.1), which contains a list of all the issues and pull requests were closed with this version. + +## What's New with ABP Commercial 7.3? + +We've also worked on [ABP Commercial](https://commercial.abp.io/) to align the features and changes made in the ABP Framework. The following sections introduce a few new features coming with ABP Commercial 7.3. + +### Account Module - Using Authenticator App for Two-Factor Authentication + +In this version, ABP Commercial provides a new **Two-Factor Authentication (2FA) provider** that allows you to log in to an application by scanning a QR Code with an Authenticator App, such as Microsoft Authenticator or Google Authenticator. + +You need to apply the following actions to configure an Authenticator and then you are free to log in by using the Authenticator App: + +**Step 1 - Enable Two Factor Authentication and Scan the QR Code:** + +![](./two-factor-auth-1.png) + +**Step 2 - Verify the QR Code with an authenticator app:** + +![](./two-factor-auth-2.png) + +**Step 3 - Save the recovery codes for later use in case of not being able to login by verifying the QR code:** + +![](./two-factor-auth-3.png) + +You can disable the two-factor authentication and reset the Authenticator App anytime you want, just by disabling the two-factor authentication or resetting the authenticator: + +![](./reset-authenticator.png) + +### Upgrade Blazorise to v1.2.3 + +Upgraded the [Blazorise](https://blazorise.com/) library to v1.2.3 for Blazor UI. If you are upgrading your project to v7.3.0, please ensure that all the Blazorise-related packages are using v1.2.3 in your application. Otherwise, you might get errors due to incompatible versions. + +### CMS Kit: Module Entity Extensions + +Module entity extension system is a high-level extension system that allows you to define new properties for existing entities of the dependent modules. ABP Framework and ABP Commercial use this system to allow developers to extend entities in different modules. + +In this version, Module Entity Extension support has been added for the CMS Kit Pro module. + +You can open the `YourProjectNameModuleExtensionConfigurator` class inside the `Domain.Shared` project of your solution and change the `ConfigureExtraProperties` method as shown below to add a new property to the `Poll` entity of the [CMS Kit Pro module](https://docs.abp.io/en/commercial/latest/modules/cms-kit/index): + +```csharp +public static void ConfigureExtraProperties() +{ + OneTimeRunner.Run(() => + { + ObjectExtensionManager.Instance.Modules() + .ConfigureCmsKitPro(cmsKitPro => + { + cmsKitPro.ConfigurePoll(poll => + { + poll.AddOrUpdateProperty( + "", + property => + { + //configuration for this property + } + ) + }); + }); + }); +} + +``` + +> See the [Module Entity Extensions documentation](https://docs.abp.io/en/abp/latest/Module-Entity-Extensions) to learn more. + +### LeptonX Account Layout + +In this version, Account Layout has been re-designed for LeptonX Theme. You can see the new account layout in the following figure: + +![](leptonx-account-layout.png) + +> To use this new account layout, ensure that your LeptonX Theme package versions are v2.3+. + +## Community News + +### ABP Community Talks 2023.4: Angular 16 and ABP v7.3 + +![](./community-talks-2023-4.png) + +In this episode, the core ABP team talked about what's new with ABP v7.3 and Angular 16. You can watch the event from [here](https://www.youtube.com/watch?v=lq6u4vQURcI). + +### ABP .NET Conference 2023 + +![](./abp-conf.png) + +We organized ABP .NET Conference 2023 on May 2023 and we are happy to share the success of the conference, which captivated overwhelmingly interested live viewers from all over the world. 13 great line up of speakers which includes .NET experts and Microsoft MVPs delivered captivating talks that resonated with the audiences. Each of the talks attracted a great amount of interest and a lot of questions, sparking curiosity in the attendees. + +Thanks to all speakers and attendees for joining our event. + +> We shared our takeaways in a blog post, which you can read at [https://blog.abp.io/abp/ABP-.NET-Conference-2023-Wrap-Up](https://blog.abp.io/abp/ABP-.NET-Conference-2023-Wrap-Up). + +### Volosoft Attendeed & Sponsored Devnot .NET Conference 2023 + +![](devnot-conference.png) + +We are thrilled to announce that the Volosoft Company proudly attended as one of the Gold Sponsors at the Devnot .NET Conference 2023! We are happy to join and be a sponsor of events and contribute to the software society, empowering developers and driving innovation with the .NET community. + +![](devnot-talk.png) + +Co-Founder of [Volosoft](https://volosoft.com/) and Lead Developer of the ABP Framework, [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan) gave a word about "Dealing with Concurrency and Multi Threading in .NET" at this event. + +> You can check [this blog post](https://volosoft.com/blog/Reflecting-on-Devnot-Dotnet-Conference-2023) if you want to learn more about the Devnot .NET Conference 2023. + +### New ABP Community Posts + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Authority Delegation in ABP Commercial](https://community.abp.io/posts/authority-delegation-in-abp-commercial-3wtljpp0) by [Liang Shiwei](https://github.com/realLiangshiwei) +* [What's new in Angular 16? New Features and Updates](https://community.abp.io/posts/whats-new-in-angular-16-new-features-and-updates-s1izi9br) by [Masum Ulu](https://twitter.com/masumulu) +* [Kubernetes Integrated Microservice Development with ABP Studio](https://community.abp.io/videos/kubernetes-integrated-microservice-development-with-abp-studio-oix9zkp8) by [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/articles/submit) to the ABP Community. + +### New ABP Blog Posts + +There are also some exciting blog posts written by the ABP team. You can see the following list for some of those articles: + +* [ABP .NET Conference 2023 Wrap Up](https://blog.abp.io/abp/ABP-.NET-Conference-2023-Wrap-Up) by [Bige Beşikçi](https://twitter.com/bigedediki) +* [Meet Volosoft at the Devnot .NET Conference 2023!](https://volosoft.com/blog/Meet-Volosoft-at-the-Devnot-.NET-Conference-2023) by [Roo Xu](https://github.com/Roo1227) + +## Conclusion + +This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://docs.abp.io/en/abp/7.3/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v7.3 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/abp-conf.png b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/abp-conf.png new file mode 100644 index 0000000000..b3add3ebc0 Binary files /dev/null and b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/abp-conf.png differ diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/community-talks-2023-4.png b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/community-talks-2023-4.png new file mode 100644 index 0000000000..7c4bef3950 Binary files /dev/null and b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/community-talks-2023-4.png differ diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/cover-image.png b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/cover-image.png new file mode 100644 index 0000000000..235642a3f8 Binary files /dev/null and b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/cover-image.png differ diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-conference.png b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-conference.png new file mode 100644 index 0000000000..9175452037 Binary files /dev/null and b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-conference.png differ diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-talk.png b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-talk.png new file mode 100644 index 0000000000..896663ae28 Binary files /dev/null and b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/devnot-talk.png differ diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/leptonx-account-layout.png b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/leptonx-account-layout.png new file mode 100644 index 0000000000..9395011060 Binary files /dev/null and b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/leptonx-account-layout.png differ diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/reset-authenticator.png b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/reset-authenticator.png new file mode 100644 index 0000000000..42651b9479 Binary files /dev/null and b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/reset-authenticator.png differ diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-1.png b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-1.png new file mode 100644 index 0000000000..00c9e12456 Binary files /dev/null and b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-1.png differ diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-2.png b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-2.png new file mode 100644 index 0000000000..4ccfbcee83 Binary files /dev/null and b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-2.png differ diff --git a/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-3.png b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-3.png new file mode 100644 index 0000000000..82a58bb479 Binary files /dev/null and b/docs/en/Blog-Posts/2023-06-05 v7_3_Preview/two-factor-auth-3.png differ diff --git a/docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/POST.md b/docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/POST.md index 7d183a7b6c..58849266eb 100644 --- a/docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/POST.md +++ b/docs/en/Community-Articles/2023-06-05-Kubernetes-Integration-Abp-Studio/POST.md @@ -163,12 +163,10 @@ The solution runner is a great way of running multiple services locally. However ### How ABP Studio Kubernetes Tunnel works -I am sure that you want to see it in action, but before that, let me explain how the solution works. No problem if you can not understand it completely. It is enough to see the big picture: +I am sure that you want to see it in action, but before that, let me explain how the solution works. ![abp-studio-kubernetes-tunnel-how-it-works](06-abp-studio-kubernetes-tunnel-how-it-works.png) -Let's explain how it works: - * **Kubernetes cluster** is shown on the right side and your **local development machine** is shown on the left side. * As you know, when a **user requests a web page** from your web application, the request is accepted by an **Ingress Controller** inside your Kubernetes cluster. * The Ingress controller forwards the request to your **web application**, which then uses an **API gateway** to consume your microservices. diff --git a/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md b/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md new file mode 100644 index 0000000000..9023417b20 --- /dev/null +++ b/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md @@ -0,0 +1,293 @@ +# Image Compression and Resize with ABP Framework + +## Introduction + +In this article, I will show how to compress and resize images easily with the ABP Framework's new [Image Manipulation System](https://docs.abp.io/en/abp/7.3/Image-Manipulation), which is introduced in v7.3.0. + +ABP Framework provides services to compress and resize images and implements these services with popular [ImageSharp](https://sixlabors.com/products/imagesharp/) and [Magick.NET](https://github.com/dlemstra/Magick.NET) libraries. Currently, only these two providers are officially supported by the ABP Framework but thanks to the system being designed extensible, you can implement your own image resizer/compressor and use it in your application. + +> Refer to the documentation for more info: [Image Manipulation](https://docs.abp.io/en/abp/7.3/Image-Manipulation) + +### Source Code + +You can find the source code of the application at [https://github.com/abpframework/abp-samples/tree/master/ImageManipulation](https://github.com/abpframework/abp-samples/tree/master/ImageManipulation). Don't hesitate to check the source code, if you are stuck on any point. + +## Demo: Image Compression and Resize + +The best way to see what ABP's Image Manipulation System is capable of is to see it in action. Thus, we can create a simple application that basically allows us to upload, search and display images. + +### Creating a New ABP Solution + +> I have created an ABP solution and you can find the [full source code of the demo application here](https://github.com/abpframework/abp-samples/tree/master/ImageManipulation). If you want to create the same solution from scratch, you can apply the following steps: + +Install the ABP CLI, if you haven't installed it before: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +Create a new solution with the ABP Framework's Application Startup Template with MVC UI and EF Core database (default options): + +```bash +abp new ImageManipulationDemo -t app --version 7.3.0-rc.2 +``` + +> As I have mentioned above, ABP introduced the Image Manipulation System in v7.3.0. So, ensure your application is v7.3.0 or higher. + +After creating the application, let's create the database and seed the initial data by running the `*.DbMigrator` project. Also, you can run the application to see if it's working as expected. + +### Configuring the BLOB Storing System + +Since we are creating an image upload application, we need to store our images somewhere and read these image contents when it's needed. [BLOB Storing System](https://docs.abp.io/en/abp/latest/Blob-Storing) is a great solution to achieve this. Let's install & configure the BLOB Storing System into our application. + +First, run the following command under the directory of your `*.HttpApi` project: + +```bash +abp add-package Volo.Abp.BlobStoring +``` + +Then, we need to select and configure a storage provider to tell the BLOB Storing System where to store the file contents. There are [multiple providers](https://docs.abp.io/en/abp/latest/Blob-Storing#blob-storage-providers) that we can choose. For the simplicity of the demo, let's continue with the **database provider** and run the following command under the directory of your solution (`*.sln`): + +```bash +abp add-module Volo.Abp.BlobStoring.Database +``` + +* This command adds all the NuGet packages to the corresponding layers of your solution. +* Also, it makes the necessary configurations, adds a new database migration, and updates the database. +* Since we are not configuring the connection string, the BLOB Storing system will use the default connection string in our application. + +That's it. We have installed and configured the BLOB Storing System in our application. + +### Configuring the Image Manipulation System + +After, configuring the BLOB Storing System, now we can install and configure the Image Manipulation System to be able to compress and resize images. + +ABP Framework provides two image resizer/compressor implementations out of the box: [ImageSharp](https://docs.abp.io/en/abp/7.3/Image-Manipulation#imagesharp-provider) and [Magick.NET](https://docs.abp.io/en/abp/7.3/Image-Manipulation#magick-net-provider). + +We can use the `Volo.Abp.Imaging.ImageSharp` as the provider for our application. To install the package, run the following command under the `*.HttpApi` project: + +```bash +abp add-package Volo.Abp.Imaging.ImageSharp +``` + +* This package will provide the required services to compress and resize images. +* You can [configure the `ImageSharpCompressOptions`](https://docs.abp.io/en/abp/7.3/Image-Manipulation#configuration-1) to define *DefaultQuality* and encoders. + + +After installing the provider, now we can use the services to compress and resize our images, such as `IImageCompression` and `IImageResizer`. But there is an easier way. The `Volo.Abp.Imaging.AspNetCore` NuGet package defines some attributes for controller actions that can automatically compress and/or resize the uploaded files. + +To be able to use these attributes, we need to install the `Volo.Abp.Imaging.AspNetCore` package. Type the following command under the `*.HttpApi` project: + +```bash +abp add-package Volo.Abp.Imaging.AspNetCore +``` + +This package provides two attributes: `[CompressImage]` and `[ResizeImage]`. Whenever we use these attributes, the Image Manipulation System will automatically compress and/or resize uploaded files. + +### Image Upload (with Compress & Resize) + +After all the required package installations and configurations are done, now we can start implementing the API and UI for the Image Upload. + +Let's start with creating the API. Create a controller in the `*.HttpApi` project named `ImageController` and perform the image upload and image display operations: + +```csharp +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp.BlobStoring; +using Volo.Abp.Imaging; + +namespace ImageManipulationDemo.Controllers +{ + [Controller] + [Route("api/image")] + public class ImageController : ImageManipulationDemoController + { + private readonly IBlobContainer _blobContainer; + + public ImageController(IBlobContainer blobContainer) + { + _blobContainer = blobContainer; + } + + [HttpPost("upload")] + [CompressImage] + [ResizeImage(width: 200, height: 200)] + public async Task UploadAsync(IFormFile file) + { + var fileBytes = await file.GetAllBytesAsync(); + var blobName = file.FileName; + + await _blobContainer.SaveAsync(blobName, fileBytes, overrideExisting: true); + + return Ok(); + } + + [HttpGet("")] + public async Task GetImageAsync(string fileName) + { + return await _blobContainer.GetAllBytesAsync(fileName); + } + } +} +``` + +* Here, we have used both `CompressImage` and `ResizeImage` attributes to automatically compress & resize the uploaded file. +* As you can see, we used the `IBlobContainer` service to save our file content. +* Since we are using the *database provider* as BLOB storing provider, the file contents will be added to our database and then we will be able to fetch them whenever it's needed like we have done in the `GetImageAsync` method above. +* We simply used the required attributes (and they do the rest on behalf of us and call the related image resize and compress services) to resize & compress images and save the new resized/compressed image into the database. + +Before implementing the UI side, as you may notice, we've injected the `IBlobContainer` as a typed service (`IBlobContainer`). A typed BLOB container system is a way of creating and managing multiple containers in an application. We haven't created the `ImageManipulationContainer` class yet. + +Let's create this class as below: + +```csharp +using Volo.Abp.BlobStoring; + +namespace ImageManipulationDemo +{ + [BlobContainerName("image-manipulation-demo")] + public class ImageManipulationContainer + { + } +} +``` + +* We have used the `BlobContainerName` attribute to define the name of the container. +* If we haven't used the `BlobContainerName` attribute, ABP Framework uses the full name of the class with its namespace. + +We have implemented the endpoints and now can start implementing the UI side. You can see the following figure to see what we are going to design for the image upload page: + +![](image-upload-ui.png) + +Let's start designing this page. Open the `Index.cshtml` file (*/Pages/Index.cshtml*) under the `*.Web` project and replace it with the following content: + +```html +@page +@using Microsoft.AspNetCore.Mvc.Localization +@using ImageManipulationDemo.Localization +@using Volo.Abp.Users +@model ImageManipulationDemo.Web.Pages.IndexModel +@inject IHtmlLocalizer L +@inject ICurrentUser CurrentUser +@section styles { + +} +@section scripts { + +} + +
+
+
+
+
+
+
+ + +
+ +
+ +
+
+
+
+
+ +
+
+
+
+
+
Search & Display Images
+ +
+
+ + +
+
+ +
+
+
+
+
+
+
+``` + +Then, open the `index.js` file and replace it with the following content: + +```js +$(function () { + + $("#upload-image").submit(function (e) { + e.preventDefault(); + + var file = document.getElementById("formFile").files[0]; + var formData = new FormData(); + formData.append("file", file); + + $.ajax( + { + url: "/api/image/upload", + data: formData, + processData: false, + contentType: false, + type: "POST", + success: function (data) { + abp.message.success("Image saved successfully!"); + }, + error: function (err) { + abp.message.error("An error occured while saving the image."); + } + } + ); + }); + + $("#search-image").submit(function (e) { + e.preventDefault(); + + var imgResult = $("#image-result"); + imgResult.removeClass("d-none"); + + imgResult.html("

Loading...

"); + + var fileName = $("#img-search-input").val(); + + imageManipulationDemo.controllers.image.getImage(fileName) + .then(function (imageFile) { + var src = "data:image/png;base64," + imageFile; + var img = ""; + + imgResult.html(img); + }) + .catch(function (err) { + imgResult.html("

Could not find the image...

"); + }); + }); +}); +``` + +Now, we can run the application and see the Image Manipulation System in action: + +![](image-manipulation.gif) + +The results are impressive for the example above: + +* The original image was 12 KB and now the compressed & resized image has been reduced to 8 KB. +* The original image was 225x225 and now resized as 200x200. + +## Conclusion + +In this article, I have shown you how to compress and/or resize images with ABP Framework's Image Manipulation System by just defining some attributes to the top of the controller actions. + +Also, I have shown that you can use the BLOB Storing System to store file contents and compress/resize images before saving them into BLOB Storages thanks to the image resizers/compressors provided by ABP Framework. + +## See Also + +* [BLOB Storing](https://docs.abp.io/en/abp/latest/Blob-Storing) +* [Image Manipulation](https://docs.abp.io/en/abp/7.3/Image-Manipulation#iimageresizer) diff --git a/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/image-manipulation.gif b/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/image-manipulation.gif new file mode 100644 index 0000000000..d8b2a10c16 Binary files /dev/null and b/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/image-manipulation.gif differ diff --git a/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/image-upload-ui.png b/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/image-upload-ui.png new file mode 100644 index 0000000000..d5fab5a945 Binary files /dev/null and b/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/image-upload-ui.png differ diff --git a/docs/en/Integration-Services.md b/docs/en/Integration-Services.md index e788c348f7..98e3e593e5 100644 --- a/docs/en/Integration-Services.md +++ b/docs/en/Integration-Services.md @@ -34,11 +34,47 @@ public interface IProductAppService : IApplicationService That's all. From now, ABP will handle your application service as integration service and implement the followings by convention: -* If you are using the [Auto API Controllers](API/Auto-API-Controllers.md) feature in your application, the URL prefix will be `/integration-api` instead of `/api` for your integration services. Thus, you can distinguish internal and external service communications and take additional actions, such as preventing REST API calls for integration services out of API Gateway. -* Audit logging is disabled by default for the integration services. See the next section if you want to enable it. +* That service is **not exposed** by default, unless you explicitly set `ExposeIntegrationServices` options (see the *Exposing Integration Services* section). +* If you are using the [Auto API Controllers](API/Auto-API-Controllers.md) feature in your application, the **URL prefix** will be `/integration-api` instead of `/api` for your integration services. Thus, you can distinguish internal and external service communications and take additional actions, such as preventing REST API calls for integration services out of API Gateway. +* **Audit logging** is disabled by default for the integration services. See the next section if you want to enable it. + +## Marking an MVC Controller as Integration Service + +In addition to application services, you can mark a regular MVC Controller as integration service, using the same `IntegrationService` attribute, or inheriting an interface that has the `IntegrationService` attribute. + +**Example:** + +````csharp +[IntegrationService] // Mark as integration service +[Route("integration-api/products")] +public class ProductController : AbpControllerBase +{ + //... +} +```` + +When you use the `IntegrationService` attribute, ABP will handle your controller as integration service and implement the followings by convention: + +* That controller is **not exposed** to clients by default, unless you explicitly set `ExposeIntegrationServices` options (see the *Exposing Integration Services* section). +* **Audit logging** is disabled by default for controller. See the next section if you want to enable it. ## Configuration +### Exposing Integration Services + +Integration services and controllers are not exposed by default for security reasons. They typically don't require authorization, so you should **carefully and explicitly** allow them to be visible and usable to client applications. + +To expose integration services and controllers, set `AbpAspNetCoreMvcOptions.ExposeIntegrationServices` to `true` in the `ConfigureServices` method of your [module class](Module-Development-Basics.md): + +````csharp +Configure(options => +{ + options.ExposeIntegrationServices = true; +}); +```` + +> Hiding integration services is useful when you are building reusable application modules, where they may be used in a monolith application or in a microservice system. In a monolith application, integration services don't need to be exposed outside since the modules may in-process communicate with each other. On the other hand, if you build a microservice solution and use that module as a service, it will be proper to expose the integration services, so other microservices can consume them remotely inside your private network (or Kubernetes cluster). In that case, be careful to not accidently expose the integration services out of your private network. Configuring your API Gateway so that it blocks requests to `integration-api` prefixed URLs from outside of your network will be a good option. + ### Enabling/Disabling the Audit Logging Audit Logging is disabled by default for integration services but it can be enabled by configuring the `AbpAuditingOptions` [options class](Options.md) in the `ConfigureServices` method of your [module class](Module-Development-Basics.md): diff --git a/docs/en/Migration-Guides/docs/en/Migration-Guides/Abp-7_4.md b/docs/en/Migration-Guides/docs/en/Migration-Guides/Abp-7_4.md new file mode 100644 index 0000000000..5ec8eb6c65 --- /dev/null +++ b/docs/en/Migration-Guides/docs/en/Migration-Guides/Abp-7_4.md @@ -0,0 +1,8 @@ +# ABP Version 7.4 Migration Guide + +This document is a guide for upgrading ABP v7.3 solutions to ABP v7.4. There are a few changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application. + +## TemplateDefinition + +The `LocalizationResource(Type)` of `TemplateDefinition` class is changed to `LocalizationResourceName(string)`. + diff --git a/docs/en/Module-Development-Basics.md b/docs/en/Module-Development-Basics.md index dfce0bf4b2..1fdd09f8b2 100644 --- a/docs/en/Module-Development-Basics.md +++ b/docs/en/Module-Development-Basics.md @@ -147,7 +147,7 @@ Lastly, you can override ``OnApplicationShutdown`` method if you want to execute ## Module Dependencies -In a modular application, it's not unusual for one module to depend upon another module(s). An Abp module must declare ``[DependsOn]`` attribute if it does have a dependency upon another module, as shown below: +In a modular application, it's not unusual for one module to depend upon another module(s). An ABP module must declare a ``[DependsOn]`` attribute if it does have a dependency upon another module, as shown below: ````C# [DependsOn(typeof(AbpAspNetCoreMvcModule))] @@ -162,6 +162,27 @@ You can use multiple ``DependsOn`` attribute or pass multiple module types to a A depended module may depend on another module, but you only need to define your direct dependencies. ABP investigates the dependency graph for the application at startup and initializes/shutdowns modules in the correct order. +## Additional Module Assemblies + +ABP automatically registers all the services of your module to the [dependency injection](Dependency-Injection.md) system. It finds the service types by scanning types in the assembly that defines your module class. That assembly is considered as the main assembly of your module. + +Typically, every assembly contains a separate module class definition. Then modules depend on each other using the `DependsOn` attribute as explained in the previous section. However, in some rare cases, your module may consist of multiple assemblies, and only one of them defines a module class, and you want to make the other assemblies parts of your module. In that case, you can use the `AdditionalAssembly` attribute as shown below: + +````csharp +[DependsOn(...)] // Your module dependencies as you normally do +[AdditionalAssembly(typeof(BlogService))] // A type in the target assembly +public class BlogModule +{ + //... +} +```` + +In this example, we assume that the `BlogService` class is inside one assembly (`csproj`) and the `BlogModule` class is inside another assembly (`csproj`). With the `AdditionalAssembly` definition, ABP will load the assembly containing the `BlogService` class as a part of the blog module. + +Notice that `BlogService` is only an arbitrary selected type in the target assembly. It is just used to indicate the related assembly. You could use any type in the assembly. + +> WARNING: If you need to use the `AdditionalAssembly`, be sure that you don't design your system in a wrong way. With this example above, the `BlogService` class' assembly should normally have its own module class and the `BlogModule` should depend on it using the `DependsOn` attribute. Do not use the `AdditionalAssembly` attribute when you can already use the `DependsOn` attribute. + ## Framework Modules vs Application Modules There are **two types of modules.** They don't have any structural difference but categorized by functionality and purpose: diff --git a/docs/en/Module-Entity-Extensions.md b/docs/en/Module-Entity-Extensions.md index 47436a7dd9..93c79120cd 100644 --- a/docs/en/Module-Entity-Extensions.md +++ b/docs/en/Module-Entity-Extensions.md @@ -255,6 +255,20 @@ property => Use `property.UI.OnCreateForm` and `property.UI.OnEditForm` to control forms too. If a property is required, but not added to the create form, you definitely get a validation exception, so use this option carefully. But a required property may not be in the edit form if that's your requirement. +### UI Order + +When you define a property, it appears on the data table, create and edit forms on the related UI page. However, you can control its order. Example: + +````csharp +property => +{ + property.UI.Order = 1; + //...other configurations +} +```` + +Use `property.UI.OnCreateForm` and `property.UI.OnEditForm` to control forms too. If a property is required, but not added to the create form, you definitely get a validation exception, so use this option carefully. But a required property may not be in the edit form if that's your requirement. + ### HTTP API Availability Even if you disable a property on UI, it can be still available through the HTTP API. By default, a property is available on all APIs. diff --git a/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo.Abp.ApiVersioning.Abstractions.csproj b/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo.Abp.ApiVersioning.Abstractions.csproj index 038e852f21..2924448609 100644 --- a/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo.Abp.ApiVersioning.Abstractions.csproj +++ b/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo.Abp.ApiVersioning.Abstractions.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.ApiVersioning.Abstractions Volo.Abp.ApiVersioning.Abstractions $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/IRequestedApiVersion.cs b/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/IRequestedApiVersion.cs index 96c2ef33cd..428f8bb6c0 100644 --- a/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/IRequestedApiVersion.cs +++ b/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/IRequestedApiVersion.cs @@ -2,5 +2,5 @@ public interface IRequestedApiVersion { - string Current { get; } + string? Current { get; } } diff --git a/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/NullRequestedApiVersion.cs b/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/NullRequestedApiVersion.cs index 0589c662ef..6099283cc4 100644 --- a/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/NullRequestedApiVersion.cs +++ b/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/NullRequestedApiVersion.cs @@ -4,7 +4,7 @@ public class NullRequestedApiVersion : IRequestedApiVersion { public static NullRequestedApiVersion Instance = new NullRequestedApiVersion(); - public string Current => null; + public string? Current => null; private NullRequestedApiVersion() { diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj index bfe8b1d37b..6deeaac7e3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj @@ -5,6 +5,8 @@ net7.0 + enable + Nullable Volo.Abp.AspNetCore.Authentication.JwtBearer Volo.Abp.AspNetCore.Authentication.JwtBearer $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj index 562e559273..f8efe3c11c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj @@ -5,6 +5,8 @@ net7.0 + enable + Nullable Volo.Abp.AspNetCore.Authentication.OAuth Volo.Abp.AspNetCore.Authentication.OAuth $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs index 1910af63d5..e058303572 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs @@ -29,7 +29,7 @@ public class MultipleClaimAction : ClaimAction switch (prop.ValueKind) { case JsonValueKind.String: - claim = new Claim(ClaimType, prop.GetString(), ValueType, issuer); + claim = new Claim(ClaimType, prop.GetString()!, ValueType, issuer); if (!identity.Claims.Any(c => c.Type == claim.Type && c.Value == claim.Value)) { identity.AddClaim(claim); @@ -38,7 +38,7 @@ public class MultipleClaimAction : ClaimAction case JsonValueKind.Array: foreach (var arramItem in prop.EnumerateArray()) { - claim = new Claim(ClaimType, arramItem.GetString(), ValueType, issuer); + claim = new Claim(ClaimType, arramItem.GetString()!, ValueType, issuer); if (!identity.Claims.Any(c => c.Type == claim.Type && c.Value == claim.Value)) { identity.AddClaim(claim); diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs index 2a2d0a712d..7d2c1fe6d6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs @@ -28,8 +28,6 @@ public static class AbpOpenIdConnectExtensions { options.ClaimActions.MapAbpClaimTypes(); - configureOptions?.Invoke(options); - options.Events ??= new OpenIdConnectEvents(); var authorizationCodeReceived = options.Events.OnAuthorizationCodeReceived ?? (_ => Task.CompletedTask); @@ -39,16 +37,7 @@ public static class AbpOpenIdConnectExtensions return authorizationCodeReceived.Invoke(receivedContext); }; - options.Events.OnRemoteFailure = remoteFailureContext => - { - if (remoteFailureContext.Failure is OpenIdConnectProtocolException && - remoteFailureContext.Failure.Message.Contains("access_denied")) - { - remoteFailureContext.HandleResponse(); - remoteFailureContext.Response.Redirect($"{remoteFailureContext.Request.PathBase}/"); - } - return Task.CompletedTask; - }; + options.AccessDeniedPath = "/"; options.Events.OnTokenValidated = async (context) => { @@ -63,6 +52,8 @@ public static class AbpOpenIdConnectExtensions logger?.LogException(ex); } }; + + configureOptions?.Invoke(options); }); } diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj index 9f1051fbd5..9fa50a203f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj @@ -5,6 +5,8 @@ net7.0 + enable + Nullable diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs index dc1923f180..47a0d570bf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs @@ -168,6 +168,11 @@ public abstract class AbpComponentBase : OwningComponentBase protected virtual async Task HandleErrorAsync(Exception exception) { + if (IsDisposed) + { + return; + } + Logger.LogException(exception); await InvokeAsync(async () => { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs index da0dad6a70..b1d5bac7fb 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprEventsController.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; @@ -21,7 +22,6 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController var daprSerializer = HttpContext.RequestServices.GetRequiredService(); 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,8 +32,31 @@ public class AbpAspNetCoreMvcDaprEventsController : AbpController } var distributedEventBus = HttpContext.RequestServices.GetRequiredService(); - var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic)); - await distributedEventBus.TriggerHandlersAsync(id, distributedEventBus.GetEventType(topic), eventData); + + if (IsAbpDaprEventData(data)) + { + var daprEventData = daprSerializer.Deserialize(data, typeof(AbpDaprEventData)).As(); + var eventData = daprSerializer.Deserialize(daprEventData.JsonData, distributedEventBus.GetEventType(daprEventData.Topic)); + await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(daprEventData.Topic), eventData, daprEventData.MessageId, daprEventData.CorrelationId); + } + else + { + var eventData = daprSerializer.Deserialize(data, distributedEventBus.GetEventType(topic)); + await distributedEventBus.TriggerHandlersAsync(distributedEventBus.GetEventType(topic), eventData); + } + return Ok(); } + + protected virtual bool IsAbpDaprEventData(string data) + { + var document = JsonDocument.Parse(data); + var objects = document.RootElement.EnumerateObject().ToList(); + return objects.Count == 5 && + objects.Any(x => x.Name.Equals("PubSubName", StringComparison.CurrentCultureIgnoreCase)) && + objects.Any(x => x.Name.Equals("Topic", StringComparison.CurrentCultureIgnoreCase)) && + objects.Any(x => x.Name.Equals("MessageId", StringComparison.CurrentCultureIgnoreCase)) && + objects.Any(x => x.Name.Equals("JsonData", StringComparison.CurrentCultureIgnoreCase)) && + objects.Any(x => x.Name.Equals("CorrelationId", StringComparison.CurrentCultureIgnoreCase)); + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index e22fef4236..c9b5984843 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -227,18 +227,16 @@ public class AbpAspNetCoreMvcModule : AbpModule return; } - //Plugin modules - var moduleAssemblies = context - .ServiceProvider - .GetRequiredService() + var moduleContainer = context.ServiceProvider.GetRequiredService(); + + var plugInModuleAssemblies = moduleContainer .Modules .Where(m => m.IsLoadedAsPlugIn) - .Select(m => m.Type.Assembly) + .SelectMany(m => m.AllAssemblies) .Distinct(); - AddToApplicationParts(partManager, moduleAssemblies); + AddToApplicationParts(partManager, plugInModuleAssemblies); - //Controllers for application services var controllerAssemblies = context .ServiceProvider .GetRequiredService>() @@ -249,6 +247,13 @@ public class AbpAspNetCoreMvcModule : AbpModule .Distinct(); AddToApplicationParts(partManager, controllerAssemblies); + + var additionalAssemblies = moduleContainer + .Modules + .SelectMany(m => m.GetAdditionalAssemblies()) + .Distinct(); + + AddToApplicationParts(partManager, additionalAssemblies); } private static void AddToApplicationParts(ApplicationPartManager partManager, IEnumerable moduleAssemblies) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs index 1cd4b88fb8..56acc2f745 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs @@ -14,6 +14,8 @@ public class AbpAspNetCoreMvcOptions public HashSet ControllersToRemove { get; } + public bool ExposeIntegrationServices { get; set; } = false; + public bool AutoModelValidation { get; set; } public bool EnableRazorRuntimeCompilationOnDevelopment { get; set; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationPartSorter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationPartSorter.cs index 9664a2005e..dc39ef5f53 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationPartSorter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationPartSorter.cs @@ -125,7 +125,7 @@ public static class ApplicationPartSorter var moduleDependedAssemblies = moduleDescriptor .Dependencies - .Select(d => d.Assembly) + .SelectMany(d => d.AllAssemblies) .ToArray(); return partManager.ApplicationParts @@ -161,6 +161,6 @@ public static class ApplicationPartSorter { return moduleContainer .Modules - .FirstOrDefault(m => m.Assembly == assembly); + .FirstOrDefault(m => m.AllAssemblies.Contains(assembly)); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs index 933f325975..19479f552d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs @@ -45,6 +45,7 @@ public class AbpServiceConvention : IAbpServiceConvention, ITransientDependency protected virtual void ApplyForControllers(ApplicationModel application) { RemoveDuplicateControllers(application); + RemoveIntegrationControllersIfNotExposed(application); foreach (var controller in GetControllers(application)) { @@ -72,6 +73,20 @@ public class AbpServiceConvention : IAbpServiceConvention, ITransientDependency } } + protected virtual void RemoveIntegrationControllersIfNotExposed(ApplicationModel application) + { + if (Options.ExposeIntegrationServices) + { + return; + } + + var integrationControllers = GetControllers(application) + .Where(c => IntegrationServiceAttribute.IsDefinedOrInherited(c.ControllerType)) + .ToArray(); + + application.Controllers.RemoveAll(integrationControllers); + } + protected virtual IList GetControllers(ApplicationModel application) { return application.Controllers; diff --git a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs index eb9504570c..c362d5074c 100644 --- a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs @@ -7,11 +7,15 @@ using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Volo.Abp.Modularity; namespace Volo.Abp.AspNetCore.TestBase; -public abstract class AbpAspNetCoreIntegratedTestBase : AbpTestBaseWithServiceProvider, IDisposable - where TStartup : class +/// +/// Can be a module type or old-style ASP.NET Core Startup class. +/// +public abstract class AbpAspNetCoreIntegratedTestBase : AbpTestBaseWithServiceProvider, IDisposable + where TStartupModule : class { protected TestServer Server { get; } @@ -39,7 +43,15 @@ public abstract class AbpAspNetCoreIntegratedTestBase : AbpTestBaseWit return Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(webBuilder => { - webBuilder.UseStartup(); + if (typeof(TStartupModule).IsAssignableTo()) + { + webBuilder.UseStartup>(); + } + else + { + webBuilder.UseStartup(); + } + webBuilder.UseAbpTestServer(); }) .UseAutofac() diff --git a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/TestStartup.cs b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/TestStartup.cs new file mode 100644 index 0000000000..be641912c7 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/TestStartup.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Threading; + +namespace Volo.Abp.AspNetCore.TestBase; + +internal class TestStartup +{ + public void ConfigureServices(IServiceCollection services) + { + AsyncHelper.RunSync(() => services.AddApplicationAsync(typeof(TStartupModule))); + } + + public void Configure(IApplicationBuilder app) + { + AsyncHelper.RunSync(app.InitializeApplicationAsync); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpAspNetCoreApplicationBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpAspNetCoreApplicationBuilderExtensions.cs index 23a73c74c7..684c948975 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpAspNetCoreApplicationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpAspNetCoreApplicationBuilderExtensions.cs @@ -23,7 +23,7 @@ public static class AbpAspNetCoreApplicationBuilderExtensions .GetRequiredService>() .Value; - if (!options.EndpointConfigureActions.Any()) + if (!options.EndpointConfigureActions.Any() && additionalConfigurationAction == null) { return app; } @@ -32,15 +32,18 @@ public static class AbpAspNetCoreApplicationBuilderExtensions { using (var scope = app.ApplicationServices.CreateScope()) { - var context = new EndpointRouteBuilderContext(endpoints, scope.ServiceProvider); - - foreach (var configureAction in options.EndpointConfigureActions) + if (options.EndpointConfigureActions.Any()) { - configureAction(context); - } + var context = new EndpointRouteBuilderContext(endpoints, scope.ServiceProvider); - additionalConfigurationAction?.Invoke(endpoints); + foreach (var configureAction in options.EndpointConfigureActions) + { + configureAction(context); + } + } } + + additionalConfigurationAction?.Invoke(endpoints); }); } } diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs index 23f1192d1c..33f5de3582 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AbpCorrelationIdMiddleware.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Http; +using System; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; @@ -20,16 +21,31 @@ public class AbpCorrelationIdMiddleware : IMiddleware, ITransientDependency public async Task InvokeAsync(HttpContext context, RequestDelegate next) { - var correlationId = _correlationIdProvider.Get(); + var correlationId = GetCorrelationIdFromRequest(context); - try + using (_correlationIdProvider.Change(correlationId)) { - await next(context); + try + { + await next(context); + } + finally + { + CheckAndSetCorrelationIdOnResponse(context, _options, correlationId); + } } - finally + } + + protected virtual string GetCorrelationIdFromRequest(HttpContext context) + { + string correlationId = context.Request.Headers[_options.HttpHeaderName]; + if (correlationId.IsNullOrEmpty()) { - CheckAndSetCorrelationIdOnResponse(context, _options, correlationId); + correlationId = Guid.NewGuid().ToString("N"); + context.Request.Headers[_options.HttpHeaderName] = correlationId; } + + return correlationId; } protected virtual void CheckAndSetCorrelationIdOnResponse( diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AspNetCoreCorrelationIdProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AspNetCoreCorrelationIdProvider.cs deleted file mode 100644 index 02e5f91596..0000000000 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Tracing/AspNetCoreCorrelationIdProvider.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Tracing; - -namespace Volo.Abp.AspNetCore.Tracing; - -[Dependency(ReplaceServices = true)] -public class AspNetCoreCorrelationIdProvider : ICorrelationIdProvider, ITransientDependency -{ - protected IHttpContextAccessor HttpContextAccessor { get; } - protected AbpCorrelationIdOptions Options { get; } - - public AspNetCoreCorrelationIdProvider( - IHttpContextAccessor httpContextAccessor, - IOptions options) - { - HttpContextAccessor = httpContextAccessor; - Options = options.Value; - } - - public virtual string Get() - { - if (HttpContextAccessor.HttpContext?.Request?.Headers == null) - { - return CreateNewCorrelationId(); - } - - string correlationId = HttpContextAccessor.HttpContext.Request.Headers[Options.HttpHeaderName]; - - if (correlationId.IsNullOrEmpty()) - { - lock (HttpContextAccessor.HttpContext.Request.Headers) - { - if (correlationId.IsNullOrEmpty()) - { - correlationId = CreateNewCorrelationId(); - HttpContextAccessor.HttpContext.Request.Headers[Options.HttpHeaderName] = correlationId; - } - } - } - - return correlationId; - } - - protected virtual string CreateNewCorrelationId() - { - return Guid.NewGuid().ToString("N"); - } -} diff --git a/framework/src/Volo.Abp.Autofac.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyApplicationCreationOptionsAutofacExtensions.cs b/framework/src/Volo.Abp.Autofac.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyApplicationCreationOptionsAutofacExtensions.cs index 62c6f92b9a..dd2ec149c5 100644 --- a/framework/src/Volo.Abp.Autofac.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyApplicationCreationOptionsAutofacExtensions.cs +++ b/framework/src/Volo.Abp.Autofac.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyApplicationCreationOptionsAutofacExtensions.cs @@ -11,7 +11,7 @@ public static class AbpWebAssemblyApplicationCreationOptionsAutofacExtensions { public static void UseAutofac( [NotNull] this AbpWebAssemblyApplicationCreationOptions options, - [CanBeNull] Action configure = null) + Action? configure = null) { options.HostBuilder.Services.AddAutofacServiceProviderFactory(); options.HostBuilder.ConfigureContainer( diff --git a/framework/src/Volo.Abp.Autofac.WebAssembly/Volo.Abp.Autofac.WebAssembly.csproj b/framework/src/Volo.Abp.Autofac.WebAssembly/Volo.Abp.Autofac.WebAssembly.csproj index 034c5c1903..1ce2a8154d 100644 --- a/framework/src/Volo.Abp.Autofac.WebAssembly/Volo.Abp.Autofac.WebAssembly.csproj +++ b/framework/src/Volo.Abp.Autofac.WebAssembly/Volo.Abp.Autofac.WebAssembly.csproj @@ -5,6 +5,8 @@ net7.0 + enable + Nullable diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs index 03084d8351..4ee9ba5916 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs @@ -69,7 +69,7 @@ public static class AbpRegistrationBuilderExtensions where TActivatorData : ReflectionActivatorData { // Enable Property Injection only for types in an assembly containing an AbpModule and without a DisablePropertyInjection attribute on class or properties. - if (moduleContainer.Modules.Any(m => m.Assembly == implementationType.Assembly) && + if (moduleContainer.Modules.Any(m => m.AllAssemblies.Contains(implementationType.Assembly)) && implementationType.GetCustomAttributes(typeof(DisablePropertyInjectionAttribute), true).IsNullOrEmpty()) { registrationBuilder = registrationBuilder.PropertiesAutowired(new AbpPropertySelector(false)); diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs index 241c3dd7a8..56a5d7480c 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Extensions/DependencyInjection/AutofacRegistration.cs @@ -87,7 +87,7 @@ public static class AutofacRegistration public static void Populate( this ContainerBuilder builder, IServiceCollection services, - object lifetimeScopeTagForSingletons) + object? lifetimeScopeTagForSingletons) { if (services == null) { @@ -134,7 +134,7 @@ public static class AutofacRegistration private static IRegistrationBuilder ConfigureLifecycle( this IRegistrationBuilder registrationBuilder, ServiceLifetime lifecycleKind, - object lifetimeScopeTagForSingleton) + object? lifetimeScopeTagForSingleton) { switch (lifecycleKind) { @@ -179,7 +179,7 @@ public static class AutofacRegistration private static void Register( ContainerBuilder builder, IServiceCollection services, - object lifetimeScopeTagForSingletons) + object? lifetimeScopeTagForSingletons) { var moduleContainer = services.GetSingletonInstance(); var registrationActionList = services.GetRegistrationActionList(); @@ -223,7 +223,7 @@ public static class AutofacRegistration else { builder - .RegisterInstance(descriptor.ImplementationInstance) + .RegisterInstance(descriptor.ImplementationInstance!) .As(descriptor.ServiceType) .ConfigureLifecycle(descriptor.Lifetime, null); } diff --git a/framework/src/Volo.Abp.Autofac/Microsoft/Extensions/DependencyInjection/AbpAutofacServiceCollectionExtensions.cs b/framework/src/Volo.Abp.Autofac/Microsoft/Extensions/DependencyInjection/AbpAutofacServiceCollectionExtensions.cs index fe6e57ade8..e249e7e5ac 100644 --- a/framework/src/Volo.Abp.Autofac/Microsoft/Extensions/DependencyInjection/AbpAutofacServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Autofac/Microsoft/Extensions/DependencyInjection/AbpAutofacServiceCollectionExtensions.cs @@ -21,7 +21,7 @@ public static class AbpAutofacServiceCollectionExtensions return builder; } - public static IServiceProvider BuildAutofacServiceProvider([NotNull] this IServiceCollection services, Action builderAction = null) + public static IServiceProvider BuildAutofacServiceProvider([NotNull] this IServiceCollection services, Action? builderAction = null) { return services.BuildServiceProviderFromFactory(builderAction); } diff --git a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj index 32c4eb4e39..cf1c18994a 100644 --- a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj +++ b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Autofac Volo.Abp.Autofac $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacServiceProviderFactory.cs b/framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacServiceProviderFactory.cs index 0cc35cbf81..dd8f383c5c 100644 --- a/framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacServiceProviderFactory.cs +++ b/framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacServiceProviderFactory.cs @@ -11,7 +11,7 @@ namespace Volo.Abp.Autofac; public class AbpAutofacServiceProviderFactory : IServiceProviderFactory { private readonly ContainerBuilder _builder; - private IServiceCollection _services; + private IServiceCollection _services = default!; public AbpAutofacServiceProviderFactory(ContainerBuilder builder) { diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index 3bcc507e39..f476ecad89 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -215,9 +215,9 @@ public abstract class AbpCrudPageBase< protected async override Task OnInitializedAsync() { - await SetPermissionsAsync(); - await SetEntityActionsAsync(); - await SetTableColumnsAsync(); + await TrySetPermissionsAsync(); + await TrySetEntityActionsAsync(); + await TrySetTableColumnsAsync(); await InvokeAsync(StateHasChanged); } @@ -231,7 +231,15 @@ public abstract class AbpCrudPageBase< await base.OnAfterRenderAsync(firstRender); } + private async Task TrySetPermissionsAsync() + { + if (IsDisposed) + { + return; + } + await SetPermissionsAsync(); + } protected virtual async Task SetPermissionsAsync() { @@ -579,13 +587,34 @@ public abstract class AbpCrudPageBase< return ValueTask.CompletedTask; } + private async ValueTask TrySetEntityActionsAsync() + { + if (IsDisposed) + { + return; + } + + await SetEntityActionsAsync(); + } + protected virtual ValueTask SetEntityActionsAsync() { return ValueTask.CompletedTask; } + + private async ValueTask TrySetTableColumnsAsync() + { + if (IsDisposed) + { + return; + } + + await SetTableColumnsAsync(); + } protected virtual ValueTask SetTableColumnsAsync() { + return ValueTask.CompletedTask; } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/CheckExtensionProperty.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/CheckExtensionProperty.razor index eebff3970d..b9ef1e0f8e 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/CheckExtensionProperty.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/CheckExtensionProperty.razor @@ -8,7 +8,7 @@ { - + @PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory) diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/DateTimeExtensionProperty.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/DateTimeExtensionProperty.razor index 8fa7f0d777..0500d29c32 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/DateTimeExtensionProperty.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/DateTimeExtensionProperty.razor @@ -13,6 +13,7 @@ diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor index 9fe96c7a20..aa546793b9 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor @@ -25,6 +25,7 @@ __builder.AddAttribute(1, "PropertyInfo", propertyInfo); __builder.AddAttribute(2, "Entity", Entity); __builder.AddAttribute(3, "LH", LH); + __builder.AddAttribute(4, "ModalType", ModalType); __builder.CloseComponent(); } } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor.cs index 947069a7ee..d9a1a42d85 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Components.Web; using Volo.Abp.Data; +using Volo.Abp.ObjectExtending; namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending; @@ -16,4 +17,7 @@ public partial class ExtensionProperties : Component [Parameter] public TEntityType Entity { get; set; } + + [Parameter] + public ExtensionPropertyModalType? ModalType { get; set; } } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyComponentBase.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyComponentBase.cs index b2a5c1e48d..46f4bd7f51 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyComponentBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyComponentBase.cs @@ -33,6 +33,9 @@ public abstract class ExtensionPropertyComponentBase : O [Parameter] public AbpBlazorMessageLocalizerHelper LH { get; set; } + [Parameter] + public ExtensionPropertyModalType? ModalType { get; set; } + protected virtual void Validate(ValidatorEventArgs e) { e.Status = ValidationStatus.Success; @@ -65,12 +68,14 @@ public abstract class ExtensionPropertyComponentBase : O } e.MemberNames = result.MemberNames; - e.Status = ValidationStatus.Error; + e.Status = ValidationStatus.Error; e.ErrorText = errorMessage; break; } } + protected bool IsReadonlyField => ModalType is ExtensionPropertyModalType.EditModal && PropertyInfo.UI.EditModal.IsReadOnly; + private static string GetDefaultErrorMessage(ValidationAttribute validationAttribute) { if (validationAttribute is StringLengthAttribute stringLengthAttribute && stringLengthAttribute.MinimumLength != 0) diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyModalType.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyModalType.cs new file mode 100644 index 0000000000..67cf8d5bb8 --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionPropertyModalType.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending; + +public enum ExtensionPropertyModalType : byte +{ + CreateModal = 0, + EditModal = 1 +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/LookupExtensionProperty.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/LookupExtensionProperty.razor index 2ea468f1f4..7c32549d51 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/LookupExtensionProperty.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/LookupExtensionProperty.razor @@ -15,6 +15,7 @@ SelectedValueChanged="@SelectedValueChanged" SearchChanged="@SearchFilterChangedAsync" Validator="@Validate" - MinLength="0"> + MinLength="0" + Disabled="IsReadonlyField"> diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/SelectExtensionProperty.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/SelectExtensionProperty.razor index cc1735c26a..605158aec0 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/SelectExtensionProperty.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/SelectExtensionProperty.razor @@ -10,7 +10,7 @@ @foreach (var item in SelectItems) { - @item.Text + @item.Text } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextExtensionProperty.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextExtensionProperty.razor index fc8b7b5398..e9d3d7031e 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextExtensionProperty.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextExtensionProperty.razor @@ -9,7 +9,7 @@ @PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory) - + diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TimeExtensionProperty.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TimeExtensionProperty.razor index 6ad15b2cb5..5d3f1f26af 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TimeExtensionProperty.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TimeExtensionProperty.razor @@ -9,7 +9,7 @@ @PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)--> - + diff --git a/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj b/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj index 7125519bb0..d840a3bf69 100644 --- a/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj +++ b/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Castle.Core Volo.Abp.Castle.Core $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs index 1a96e20320..138a35c8b0 100644 --- a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs +++ b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterBase.cs @@ -20,7 +20,7 @@ public abstract class CastleAbpMethodInvocationAdapterBase : IAbpMethodInvocatio public MethodInfo Method => Invocation.MethodInvocationTarget ?? Invocation.Method; - public object ReturnValue { get; set; } + public object ReturnValue { get; set; } = default!; protected IInvocation Invocation { get; } @@ -39,7 +39,7 @@ public abstract class CastleAbpMethodInvocationAdapterBase : IAbpMethodInvocatio var methodParameters = Method.GetParameters(); for (int i = 0; i < methodParameters.Length; i++) { - dict[methodParameters[i].Name] = Invocation.Arguments[i]; + dict[methodParameters[i].Name!] = Invocation.Arguments[i]; } return dict; diff --git a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs index 6bebcf531e..5e6e2b3e3b 100644 --- a/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs +++ b/framework/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapterWithReturnValue.cs @@ -21,6 +21,6 @@ public class CastleAbpMethodInvocationAdapterWithReturnValue : CastleAb public override async Task ProceedAsync() { - ReturnValue = await Proceed(Invocation, ProceedInfo); + ReturnValue = (await Proceed(Invocation, ProceedInfo))!; } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs index 0d5b3b31e5..66519a2275 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs @@ -17,7 +17,7 @@ namespace Volo.Abp.Cli.Commands; public class LoginCommand : IConsoleCommand, ITransientDependency { public const string Name = "login"; - + public ILogger Logger { get; set; } protected AuthService AuthService { get; } @@ -122,6 +122,12 @@ public class LoginCommand : IConsoleCommand, ITransientDependency return; } + if (ex.Message.Contains("RequiresTwoFactor")) + { + Logger.LogError("Two factor authentication is enabled for your account. Please use `abp login --device` command to login."); + return; + } + if (TryGetErrorMessageFromHtmlPage(ex.Message, out var errorMsg)) { Logger.LogError(errorMsg); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs index d274234ded..7d2a61858a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs @@ -46,6 +46,34 @@ public class SuiteAppSettingsService : ITransientDependency return Convert.ToInt32(url.Split(":").Last()); } + + public int GetSuitePort() + { + return GetSuitePort(GetCurrentSuiteVersion()); + } + + public int GetSuitePort(string version) + { + var filePath = GetFilePathOrNull(version); + + if (filePath == null) + { + return DefaultPort; + } + + var content = File.ReadAllText(filePath); + + var contentAsJson = JObject.Parse(content); + + var url = contentAsJson["AbpSuite"]?["ApplicationUrl"]?.ToString(); + + if (url == null) + { + return DefaultPort; + } + + return Convert.ToInt32(url.Split(":").Last()); + } private string GetFilePathOrNull(string version) { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ConnectionStringRenameStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ConnectionStringRenameStep.cs new file mode 100644 index 0000000000..ea71eb1c51 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ConnectionStringRenameStep.cs @@ -0,0 +1,21 @@ +using System; +using System.Linq; +using Volo.Abp.Cli.ProjectBuilding.Files; + +namespace Volo.Abp.Cli.ProjectBuilding.Building; + +public class ConnectionStringRenameStep : ProjectBuildPipelineStep +{ + public override void Execute(ProjectBuildContext context) + { + foreach (var fileEntry in context.Files.Where(file => file.Name.EndsWith(CliConsts.AppSettingsJsonFileName, StringComparison.OrdinalIgnoreCase))) + { + RenameDatabaseName(fileEntry); + } + } + + private void RenameDatabaseName(FileEntry fileEntry) + { + fileEntry.SetContent(fileEntry.Content.Replace("MyProjectNamePro", "MyProjectName")); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs index 8777291c24..5bd0614206 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs @@ -645,6 +645,11 @@ public abstract class AppTemplateBase : TemplateInfo { steps.Add(new ConnectionStringChangeStep()); } + + if (IsPro()) + { + steps.Add(new ConnectionStringRenameStep()); + } } protected void CleanupFolderHierarchy(ProjectBuildContext context, List steps) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs index 3e396e8113..13674458ee 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs @@ -39,7 +39,8 @@ public abstract class MicroserviceServiceTemplateBase : TemplateInfo SetRandomPortForHostProject(context, steps); RandomizeStringEncryption(context, steps); RandomizeAuthServerPassPhrase(context, steps); - + ChangeConnectionString(context, steps); + return steps; } @@ -75,4 +76,9 @@ public abstract class MicroserviceServiceTemplateBase : TemplateInfo { steps.Add(new RandomizeAuthServerPassPhraseStep()); } + + private static void ChangeConnectionString(ProjectBuildContext context, List steps) + { + steps.Add(new ConnectionStringRenameStep()); + } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs index 5fc263afc3..5229bb167f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs @@ -102,12 +102,17 @@ public abstract class ModuleTemplateBase : TemplateInfo steps.Add(new UpdateNuGetConfigStep("/NuGet.Config")); } - private static void ChangeConnectionString(ProjectBuildContext context, List steps) + private void ChangeConnectionString(ProjectBuildContext context, List steps) { if (context.BuildArgs.ConnectionString != null) { steps.Add(new ConnectionStringChangeStep()); } + + if (IsPro()) + { + steps.Add(new ConnectionStringRenameStep()); + } } private void CleanupFolderHierarchy(ProjectBuildContext context, List steps) diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj index bf8c9a209d..c250d07eee 100644 --- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj +++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj @@ -28,7 +28,7 @@ - + diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs index 0ccff2db23..ec20467ac9 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs @@ -188,11 +188,13 @@ public abstract class AbpApplicationBase : IAbpApplication { if (!abpModule.SkipAutoServiceRegistration) { - var assembly = module.Type.Assembly; - if (!assemblies.Contains(assembly)) + foreach (var assembly in module.AllAssemblies) { - Services.AddAssembly(assembly); - assemblies.Add(assembly); + if (!assemblies.Contains(assembly)) + { + Services.AddAssembly(assembly); + assemblies.Add(assembly); + } } } } @@ -279,11 +281,13 @@ public abstract class AbpApplicationBase : IAbpApplication { if (!abpModule.SkipAutoServiceRegistration) { - var assembly = module.Type.Assembly; - if (!assemblies.Contains(assembly)) + foreach (var assembly in module.AllAssemblies) { - Services.AddAssembly(assembly); - assemblies.Add(assembly); + if (!assemblies.Contains(assembly)) + { + Services.AddAssembly(assembly); + assemblies.Add(assembly); + } } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs index cf779ff7e0..906d3a7fcb 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs @@ -13,13 +13,13 @@ public class AbpException : Exception } - public AbpException(string message) + public AbpException(string? message) : base(message) { } - public AbpException(string message, Exception innerException) + public AbpException(string? message, Exception? innerException) : base(message, innerException) { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptor.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptor.cs index dcb9cfc817..9bcb7d6a06 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptor.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptor.cs @@ -11,6 +11,8 @@ public class AbpModuleDescriptor : IAbpModuleDescriptor public Type Type { get; } public Assembly Assembly { get; } + + public Assembly[] AllAssemblies { get; } public IAbpModule Instance { get; } @@ -26,6 +28,7 @@ public class AbpModuleDescriptor : IAbpModuleDescriptor { Check.NotNull(type, nameof(type)); Check.NotNull(instance, nameof(instance)); + AbpModule.CheckAbpModuleType(type); if (!type.GetTypeInfo().IsAssignableFrom(instance.GetType())) { @@ -34,6 +37,7 @@ public class AbpModuleDescriptor : IAbpModuleDescriptor Type = type; Assembly = type.Assembly; + AllAssemblies = AbpModuleHelper.GetAllAssemblies(type); Instance = instance; IsLoadedAsPlugIn = isLoadedAsPlugIn; diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptorExtensions.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptorExtensions.cs new file mode 100644 index 0000000000..d2e719efb0 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleDescriptorExtensions.cs @@ -0,0 +1,15 @@ +using System; +using System.Linq; +using System.Reflection; + +namespace Volo.Abp.Modularity; + +public static class AbpModuleDescriptorExtensions +{ + public static Assembly[] GetAdditionalAssemblies(this IAbpModuleDescriptor module) + { + return module.AllAssemblies.Length <= 1 + ? Array.Empty() + : module.AllAssemblies.Where(x => x != module.Assembly).ToArray(); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs index 697543409e..eb72664444 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs @@ -36,6 +36,27 @@ internal static class AbpModuleHelper return dependencies; } + + public static Assembly[] GetAllAssemblies(Type moduleType) + { + var assemblies = new List(); + + var additionalAssemblyDescriptors = moduleType + .GetCustomAttributes() + .OfType(); + + foreach (var descriptor in additionalAssemblyDescriptors) + { + foreach (var assembly in descriptor.GetAssemblies()) + { + assemblies.AddIfNotContains(assembly); + } + } + + assemblies.Add(moduleType.Assembly); + + return assemblies.ToArray(); + } private static void AddModuleAndDependenciesRecursively( List moduleTypes, diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalAssemblyAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalAssemblyAttribute.cs new file mode 100644 index 0000000000..ac4165f85e --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AdditionalAssemblyAttribute.cs @@ -0,0 +1,24 @@ +using System; +using System.Linq; +using System.Reflection; + +namespace Volo.Abp.Modularity; + +/// +/// Used to define additional assemblies for a module. +/// +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] +public class AdditionalAssemblyAttribute : Attribute, IAdditionalModuleAssemblyProvider +{ + public Type[] TypesInAssemblies { get; } + + public AdditionalAssemblyAttribute(params Type[]? typesInAssemblies) + { + TypesInAssemblies = typesInAssemblies ?? Type.EmptyTypes; + } + + public virtual Assembly[] GetAssemblies() + { + return TypesInAssemblies.Select(t => t.Assembly).Distinct().ToArray(); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/DependsOnAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/DependsOnAttribute.cs index 89970859e8..8792d146d9 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/DependsOnAttribute.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/DependsOnAttribute.cs @@ -1,5 +1,4 @@ using System; -using JetBrains.Annotations; namespace Volo.Abp.Modularity; @@ -9,12 +8,11 @@ namespace Volo.Abp.Modularity; [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class DependsOnAttribute : Attribute, IDependedTypesProvider { - [NotNull] public Type[] DependedTypes { get; } public DependsOnAttribute(params Type[]? dependedTypes) { - DependedTypes = dependedTypes ?? new Type[0]; + DependedTypes = dependedTypes ?? Type.EmptyTypes; } public virtual Type[] GetDependedTypes() diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs index 8a4fb1e270..8690baa33d 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModuleDescriptor.cs @@ -6,13 +6,36 @@ namespace Volo.Abp.Modularity; public interface IAbpModuleDescriptor { + /// + /// Type of the module class. + /// Type Type { get; } + /// + /// Main assembly that defines the module . + /// Assembly Assembly { get; } + + /// + /// All the assemblies of the module. + /// Includes the main and other assemblies defined + /// on the module using the attribute. + /// + Assembly[] AllAssemblies { get; } + /// + /// The instance of the module class (singleton). + /// IAbpModule Instance { get; } + /// + /// Is this module loaded as a plug-in? + /// bool IsLoadedAsPlugIn { get; } + /// + /// Modules on which this module depends on. + /// A module can depend on another module using the attribute. + /// IReadOnlyList Dependencies { get; } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAdditionalModuleAssemblyProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAdditionalModuleAssemblyProvider.cs new file mode 100644 index 0000000000..3a26d8e918 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAdditionalModuleAssemblyProvider.cs @@ -0,0 +1,8 @@ +using System.Reflection; + +namespace Volo.Abp.Modularity; + +public interface IAdditionalModuleAssemblyProvider +{ + Assembly[] GetAssemblies(); +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/AssemblyFinder.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/AssemblyFinder.cs index 4e9a37db1a..602c577050 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/AssemblyFinder.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Reflection/AssemblyFinder.cs @@ -29,7 +29,7 @@ public class AssemblyFinder : IAssemblyFinder foreach (var module in _moduleContainer.Modules) { - assemblies.Add(module.Type.Assembly); + assemblies.AddRange(module.AllAssemblies); } return assemblies.Distinct().ToImmutableList(); diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Tracing/DefaultCorrelationIdProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Tracing/DefaultCorrelationIdProvider.cs index e24e81ca21..578587f449 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Tracing/DefaultCorrelationIdProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Tracing/DefaultCorrelationIdProvider.cs @@ -1,17 +1,27 @@ using System; +using System.Threading; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Tracing; public class DefaultCorrelationIdProvider : ICorrelationIdProvider, ISingletonDependency { - public string Get() + private readonly AsyncLocal _currentCorrelationId = new AsyncLocal(); + + private string? CorrelationId => _currentCorrelationId.Value; + + public virtual string? Get() { - return CreateNewCorrelationId(); + return CorrelationId; } - protected virtual string CreateNewCorrelationId() + public virtual IDisposable Change(string? correlationId) { - return Guid.NewGuid().ToString("N"); + var parent = CorrelationId; + _currentCorrelationId.Value = correlationId; + return new DisposeAction(() => + { + _currentCorrelationId.Value = parent; + }); } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Tracing/ICorrelationIdProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Tracing/ICorrelationIdProvider.cs index dd94ccb93d..06c3200877 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Tracing/ICorrelationIdProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Tracing/ICorrelationIdProvider.cs @@ -1,9 +1,10 @@ -using JetBrains.Annotations; +using System; namespace Volo.Abp.Tracing; public interface ICorrelationIdProvider { - [NotNull] - string Get(); + string? Get(); + + IDisposable Change(string? correlationId); } diff --git a/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs index 9a8b4c9520..1d1861cd97 100644 --- a/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs +++ b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/IDaprSerializer.cs @@ -6,6 +6,8 @@ public interface IDaprSerializer { byte[] Serialize(object obj); + string SerializeToString(object obj); + object Deserialize(byte[] value, Type type); object Deserialize(string value, Type type); diff --git a/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs index c0924f775b..a1a8324598 100644 --- a/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs +++ b/framework/src/Volo.Abp.Dapr/Volo/Abp/Dapr/Utf8JsonDaprSerializer.cs @@ -19,6 +19,11 @@ public class Utf8JsonDaprSerializer : IDaprSerializer, ITransientDependency return Encoding.UTF8.GetBytes(_jsonSerializer.Serialize(obj)); } + public string SerializeToString(object obj) + { + return _jsonSerializer.Serialize(obj); + } + public object Deserialize(byte[] value, Type type) { return _jsonSerializer.Deserialize(type, Encoding.UTF8.GetString(value)); diff --git a/framework/src/Volo.Abp.Data/Volo.Abp.Data.csproj b/framework/src/Volo.Abp.Data/Volo.Abp.Data.csproj index b5d2589b19..751042e62c 100644 --- a/framework/src/Volo.Abp.Data/Volo.Abp.Data.csproj +++ b/framework/src/Volo.Abp.Data/Volo.Abp.Data.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Data Volo.Abp.Data $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpCommonDbProperties.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpCommonDbProperties.cs index eacedc2408..16236a4e10 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpCommonDbProperties.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpCommonDbProperties.cs @@ -13,5 +13,5 @@ public static class AbpCommonDbProperties /// /// Default value: null. /// - public static string DbSchema { get; set; } = null; + public static string? DbSchema { get; set; } = null; } diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDataMigrationEnvironmentExtensions.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDataMigrationEnvironmentExtensions.cs index 796b547164..18b990ce73 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDataMigrationEnvironmentExtensions.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDataMigrationEnvironmentExtensions.cs @@ -6,17 +6,17 @@ namespace Volo.Abp.Data; public static class AbpDataMigrationEnvironmentExtensions { - public static void AddDataMigrationEnvironment(this AbpApplicationCreationOptions options, AbpDataMigrationEnvironment environment = null) + public static void AddDataMigrationEnvironment(this AbpApplicationCreationOptions options, AbpDataMigrationEnvironment? environment = null) { options.Services.AddDataMigrationEnvironment(environment ?? new AbpDataMigrationEnvironment()); } - public static void AddDataMigrationEnvironment(this IServiceCollection services, AbpDataMigrationEnvironment environment = null) + public static void AddDataMigrationEnvironment(this IServiceCollection services, AbpDataMigrationEnvironment? environment = null) { services.AddObjectAccessor(environment ?? new AbpDataMigrationEnvironment()); } - public static AbpDataMigrationEnvironment GetDataMigrationEnvironment(this IServiceCollection services) + public static AbpDataMigrationEnvironment? GetDataMigrationEnvironment(this IServiceCollection services) { return services.GetObjectOrNull(); } @@ -26,7 +26,7 @@ public static class AbpDataMigrationEnvironmentExtensions return services.GetDataMigrationEnvironment() != null; } - public static AbpDataMigrationEnvironment GetDataMigrationEnvironment(this IServiceProvider serviceProvider) + public static AbpDataMigrationEnvironment? GetDataMigrationEnvironment(this IServiceProvider serviceProvider) { return serviceProvider.GetService>()?.Value; } diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfo.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfo.cs index c4f8d9674b..069b7bb85b 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfo.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfo.cs @@ -24,4 +24,16 @@ public class AbpDatabaseInfo DatabaseName = databaseName; MappedConnections = new HashSet(); } + + /// + /// Shortcut method to add one or multiple connections to the collection. + /// + /// + public void MapConnection(params string[] connectionNames) + { + foreach (var connectionName in connectionNames) + { + MappedConnections.AddIfNotContains(connectionName); + } + } } diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfoDictionary.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfoDictionary.cs index 2f17b320dd..06334be6db 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfoDictionary.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfoDictionary.cs @@ -13,8 +13,7 @@ public class AbpDatabaseInfoDictionary : Dictionary ConnectionIndex = new Dictionary(); } - [CanBeNull] - public AbpDatabaseInfo GetMappedDatabaseOrNull(string connectionStringName) + public AbpDatabaseInfo? GetMappedDatabaseOrNull(string connectionStringName) { return ConnectionIndex.GetOrDefault(connectionStringName); } diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDbConnectionOptions.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDbConnectionOptions.cs index a8101e2f7c..3e27ae97ae 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDbConnectionOptions.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDbConnectionOptions.cs @@ -15,7 +15,7 @@ public class AbpDbConnectionOptions Databases = new AbpDatabaseInfoDictionary(); } - public string GetConnectionStringOrNull( + public string? GetConnectionStringOrNull( string connectionStringName, bool fallbackToDatabaseMappings = true, bool fallbackToDefault = true) diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AppliedDatabaseMigrationsEto.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AppliedDatabaseMigrationsEto.cs new file mode 100644 index 0000000000..53fae25737 --- /dev/null +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AppliedDatabaseMigrationsEto.cs @@ -0,0 +1,12 @@ +using System; +using Volo.Abp.EventBus; + +namespace Volo.Abp.Data; + +[Serializable] +[EventName("abp.data.applied_database_migrations")] +public class AppliedDatabaseMigrationsEto +{ + public string DatabaseName { get; set; } = default!; + public Guid? TenantId { get; set; } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/ApplyDatabaseMigrationsEto.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/ApplyDatabaseMigrationsEto.cs index 061ce94a79..8ac1290fad 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/ApplyDatabaseMigrationsEto.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/ApplyDatabaseMigrationsEto.cs @@ -10,5 +10,5 @@ public class ApplyDatabaseMigrationsEto : EtoBase { public Guid? TenantId { get; set; } - public string DatabaseName { get; set; } + public string DatabaseName { get; set; } = default!; } diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConcurrencyStampExtensions.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConcurrencyStampExtensions.cs index 4b0cd87252..84232a7a88 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConcurrencyStampExtensions.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConcurrencyStampExtensions.cs @@ -7,11 +7,11 @@ namespace Volo.Abp.Data; public static class ConcurrencyStampExtensions { - public static void SetConcurrencyStampIfNotNull(this IHasConcurrencyStamp entity, [CanBeNull] string concurrencyStamp) + public static void SetConcurrencyStampIfNotNull(this IHasConcurrencyStamp entity, string? concurrencyStamp) { if (!concurrencyStamp.IsNullOrEmpty()) { - entity.ConcurrencyStamp = concurrencyStamp; + entity.ConcurrencyStamp = concurrencyStamp!; } } } diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConnectionStringNameAttribute.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConnectionStringNameAttribute.cs index 9e028eef12..e5936ab932 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConnectionStringNameAttribute.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConnectionStringNameAttribute.cs @@ -27,7 +27,7 @@ public class ConnectionStringNameAttribute : Attribute if (nameAttribute == null) { - return type.FullName; + return type.FullName!; } return nameAttribute.Name; diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConnectionStrings.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConnectionStrings.cs index ca84675c10..22354defc4 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConnectionStrings.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/ConnectionStrings.cs @@ -4,11 +4,11 @@ using System.Collections.Generic; namespace Volo.Abp.Data; [Serializable] -public class ConnectionStrings : Dictionary +public class ConnectionStrings : Dictionary { public const string DefaultConnectionStringName = "Default"; - public string Default { + public string? Default { get => this.GetOrDefault(DefaultConnectionStringName); set => this[DefaultConnectionStringName] = value; } diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataFilter.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataFilter.cs index cca494bb07..40ff5cdf70 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataFilter.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataFilter.cs @@ -42,10 +42,10 @@ public class DataFilter : IDataFilter, ISingletonDependency private IDataFilter GetFilter() where TFilter : class { - return _filters.GetOrAdd( + return (_filters.GetOrAdd( typeof(TFilter), - factory: () => _serviceProvider.GetRequiredService>() - ) as IDataFilter; + factory: () => _serviceProvider.GetRequiredService>() + ) as IDataFilter)!; } } @@ -55,7 +55,7 @@ public class DataFilter : IDataFilter public bool IsEnabled { get { EnsureInitialized(); - return _filter.Value.IsEnabled; + return _filter.Value!.IsEnabled; } } @@ -76,7 +76,7 @@ public class DataFilter : IDataFilter return NullDisposable.Instance; } - _filter.Value.IsEnabled = true; + _filter.Value!.IsEnabled = true; return new DisposeAction(() => Disable()); } @@ -88,7 +88,7 @@ public class DataFilter : IDataFilter return NullDisposable.Instance; } - _filter.Value.IsEnabled = false; + _filter.Value!.IsEnabled = false; return new DisposeAction(() => Enable()); } diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs index 783fddecb3..3a4aa1c0d7 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeedContext.cs @@ -16,8 +16,7 @@ public class DataSeedContext /// Returns the value in the dictionary by given . /// Returns null if given is not present in the dictionary. /// - [CanBeNull] - public object this[string name] { + public object? this[string name] { get => Properties.GetOrDefault(name); set => Properties[name] = value; } @@ -26,19 +25,19 @@ public class DataSeedContext /// Can be used to get/set custom properties. /// [NotNull] - public Dictionary Properties { get; } + public Dictionary Properties { get; } public DataSeedContext(Guid? tenantId = null) { TenantId = tenantId; - Properties = new Dictionary(); + Properties = new Dictionary(); } /// /// Sets a property in the dictionary. /// This is a shortcut for nested calls on this object. /// - public virtual DataSeedContext WithProperty(string key, object value) + public virtual DataSeedContext WithProperty(string key, object? value) { Properties[key] = value; return this; diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeeder.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeeder.cs index 45729fcb86..83586e8e70 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeeder.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeeder.cs @@ -33,9 +33,9 @@ public class DataSeeder : IDataSeeder, ITransientDependency foreach (var contributorType in Options.Contributors) { var options = context.Properties.TryGetValue(DataSeederExtensions.SeedInSeparateUowOptions, out var uowOptions) - ? (AbpUnitOfWorkOptions) uowOptions + ? (AbpUnitOfWorkOptions) uowOptions! : new AbpUnitOfWorkOptions(); - var requiresNew = context.Properties.TryGetValue(DataSeederExtensions.SeedInSeparateUowRequiresNew, out var obj) && (bool) obj; + var requiresNew = context.Properties.TryGetValue(DataSeederExtensions.SeedInSeparateUowRequiresNew, out var obj) && (bool) obj!; using (var uow = manager.Begin(options, requiresNew)) { diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeederExtensions.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeederExtensions.cs index bd17736b46..f8f3cf8dc5 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeederExtensions.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DataSeederExtensions.cs @@ -15,7 +15,7 @@ public static class DataSeederExtensions return seeder.SeedAsync(new DataSeedContext(tenantId)); } - public static Task SeedInSeparateUowAsync(this IDataSeeder seeder, Guid? tenantId = null, AbpUnitOfWorkOptions options = null, bool requiresNew = false) + public static Task SeedInSeparateUowAsync(this IDataSeeder seeder, Guid? tenantId = null, AbpUnitOfWorkOptions? options = null, bool requiresNew = false) { var context = new DataSeedContext(tenantId); context.WithProperty(SeedInSeparateUow, true); diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringResolver.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringResolver.cs index d3edbd30b0..257c0be663 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringResolver.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringResolver.cs @@ -16,17 +16,17 @@ public class DefaultConnectionStringResolver : IConnectionStringResolver, ITrans } [Obsolete("Use ResolveAsync method.")] - public virtual string Resolve(string connectionStringName = null) + public virtual string Resolve(string? connectionStringName = null) { - return ResolveInternal(connectionStringName); + return ResolveInternal(connectionStringName)!; } - public virtual Task ResolveAsync(string connectionStringName = null) + public virtual Task ResolveAsync(string? connectionStringName = null) { - return Task.FromResult(ResolveInternal(connectionStringName)); + return Task.FromResult(ResolveInternal(connectionStringName))!; } - private string ResolveInternal(string connectionStringName) + private string? ResolveInternal(string? connectionStringName) { if (connectionStringName == null) { diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolver.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolver.cs index 793fb309cb..8ef7df4e60 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolver.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolver.cs @@ -8,8 +8,8 @@ public interface IConnectionStringResolver { [NotNull] [Obsolete("Use ResolveAsync method.")] - string Resolve(string connectionStringName = null); + string Resolve(string? connectionStringName = null); [NotNull] - Task ResolveAsync(string connectionStringName = null); + Task ResolveAsync(string? connectionStringName = null); } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqliteExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqliteExtensions.cs index 395cc4de7e..6dea2a336b 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqliteExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqliteExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Data.Common; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -29,4 +30,27 @@ public static class AbpDbContextConfigurationContextSqliteExtensions }); } } + + public static DbContextOptionsBuilder UseSqlite( + [NotNull] this AbpDbContextConfigurationContext context, + DbConnection connection, + [CanBeNull] Action sqliteOptionsAction = null) + { + if (context.ExistingConnection != null) + { + return context.DbContextOptions.UseSqlite(context.ExistingConnection, optionsBuilder => + { + optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); + sqliteOptionsAction?.Invoke(optionsBuilder); + }); + } + else + { + return context.DbContextOptions.UseSqlite(connection, optionsBuilder => + { + optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery); + sqliteOptionsAction?.Invoke(optionsBuilder); + }); + } + } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs index c891f3a406..986c19bbbf 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/IncomingEventRecord.cs @@ -48,13 +48,20 @@ public class IncomingEventRecord : public IncomingEventInfo ToIncomingEventInfo() { - return new IncomingEventInfo( + var info = new IncomingEventInfo( Id, MessageId, EventName, EventData, CreationTime ); + + foreach (var property in ExtraProperties) + { + info.SetProperty(property.Key, property.Value); + } + + return info; } public void MarkAsProcessed(DateTime processedTime) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs index 41c4d41ce4..fe639411a2 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/OutgoingEventRecord.cs @@ -41,11 +41,18 @@ public class OutgoingEventRecord : public OutgoingEventInfo ToOutgoingEventInfo() { - return new OutgoingEventInfo( + var info = new OutgoingEventInfo( Id, EventName, EventData, CreationTime ); + + foreach (var property in ExtraProperties) + { + info.SetProperty(property.Key, property.Value); + } + + return info; } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreDatabaseMigrationEventHandlerBase.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreDatabaseMigrationEventHandlerBase.cs new file mode 100644 index 0000000000..d9fc7db914 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreDatabaseMigrationEventHandlerBase.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.Migrations; + +public abstract class EfCoreDatabaseMigrationEventHandlerBase : + IDistributedEventHandler, + IDistributedEventHandler, + IDistributedEventHandler, + ITransientDependency + where TDbContext : DbContext, IEfCoreDbContext +{ + protected string DatabaseName { get; } + + protected const string TryCountPropertyName = "__TryCount"; + + protected int MaxEventTryCount { get; set; } = 3; + + /// + /// As milliseconds. + /// + protected int MinValueToWaitOnFailure { get; set; } = 5000; + + /// + /// As milliseconds. + /// + protected int MaxValueToWaitOnFailure { get; set; } = 15000; + + protected ICurrentTenant CurrentTenant { get; } + protected IUnitOfWorkManager UnitOfWorkManager { get; } + protected ITenantStore TenantStore { get; } + protected IDistributedEventBus DistributedEventBus { get; } + protected ILogger> Logger { get; } + + protected EfCoreDatabaseMigrationEventHandlerBase( + string databaseName, + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ITenantStore tenantStore, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory) + { + CurrentTenant = currentTenant; + UnitOfWorkManager = unitOfWorkManager; + TenantStore = tenantStore; + DatabaseName = databaseName; + DistributedEventBus = distributedEventBus; + + Logger = loggerFactory.CreateLogger>(); + } + + public virtual async Task HandleEventAsync(ApplyDatabaseMigrationsEto eventData) + { + if (eventData.DatabaseName != DatabaseName) + { + return; + } + + var schemaMigrated = false; + try + { + schemaMigrated = await MigrateDatabaseSchemaAsync(eventData.TenantId); + await SeedAsync(eventData.TenantId); + + if (schemaMigrated) + { + await DistributedEventBus.PublishAsync( + new AppliedDatabaseMigrationsEto + { + DatabaseName = DatabaseName, + TenantId = eventData.TenantId + } + ); + } + } + catch (Exception ex) + { + await HandleErrorOnApplyDatabaseMigrationAsync(eventData, ex); + } + + await AfterApplyDatabaseMigrations(eventData, schemaMigrated); + } + + protected virtual Task AfterApplyDatabaseMigrations(ApplyDatabaseMigrationsEto eventData, bool schemaMigrated) + { + return Task.CompletedTask; + } + + public virtual async Task HandleEventAsync(TenantCreatedEto eventData) + { + var schemaMigrated = false; + try + { + schemaMigrated = await MigrateDatabaseSchemaAsync(eventData.Id); + await SeedAsync(eventData.Id); + + if (schemaMigrated) + { + await DistributedEventBus.PublishAsync( + new AppliedDatabaseMigrationsEto + { + DatabaseName = DatabaseName, + TenantId = eventData.Id + } + ); + } + } + catch (Exception ex) + { + await HandleErrorTenantCreatedAsync(eventData, ex); + } + + await AfterTenantCreated(eventData, schemaMigrated); + } + + protected virtual Task AfterTenantCreated(TenantCreatedEto eventData, bool schemaMigrated) + { + return Task.CompletedTask; + } + + public virtual async Task HandleEventAsync(TenantConnectionStringUpdatedEto eventData) + { + if (eventData.ConnectionStringName != DatabaseName && + eventData.ConnectionStringName != Volo.Abp.Data.ConnectionStrings.DefaultConnectionStringName || + eventData.NewValue.IsNullOrWhiteSpace()) + { + return; + } + + var schemaMigrated = false; + try + { + schemaMigrated = await MigrateDatabaseSchemaAsync(eventData.Id); + await SeedAsync(eventData.Id); + + if (schemaMigrated) + { + await DistributedEventBus.PublishAsync( + new AppliedDatabaseMigrationsEto + { + DatabaseName = DatabaseName, + TenantId = eventData.Id + } + ); + } + } + catch (Exception ex) + { + await HandleErrorTenantConnectionStringUpdatedAsync(eventData, ex); + } + + await AfterTenantConnectionStringUpdated(eventData, schemaMigrated); + } + + protected virtual Task AfterTenantConnectionStringUpdated(TenantConnectionStringUpdatedEto eventData, + bool schemaMigrated) + { + return Task.CompletedTask; + } + + protected virtual Task SeedAsync(Guid? tenantId) + { + return Task.CompletedTask; + } + + /// + /// Apply pending EF Core schema migrations to the database. + /// Returns true if any migration has applied. + /// + protected virtual async Task MigrateDatabaseSchemaAsync(Guid? tenantId) + { + var result = false; + + using (CurrentTenant.Change(tenantId)) + { + using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) + { + async Task MigrateDatabaseSchemaWithDbContextAsync() + { + var dbContext = await uow.ServiceProvider + .GetRequiredService>() + .GetDbContextAsync(); + + if ((await dbContext.Database.GetPendingMigrationsAsync()).Any()) + { + await dbContext.Database.MigrateAsync(); + return true; + } + + return false; + } + + if (tenantId == null) + { + //Migrating the host database + Logger.LogInformation($"Migrating database of host. Database Name = {DatabaseName}"); + result = await MigrateDatabaseSchemaWithDbContextAsync(); + } + else + { + var tenantConfiguration = await TenantStore.FindAsync(tenantId.Value); + if (!tenantConfiguration.ConnectionStrings.Default.IsNullOrWhiteSpace() || + !tenantConfiguration.ConnectionStrings.GetOrDefault(DatabaseName).IsNullOrWhiteSpace()) + { + //Migrating the tenant database (only if tenant has a separate database) + Logger.LogInformation( + $"Migrating separate database of tenant. Database Name = {DatabaseName}, TenantId = {tenantId}"); + result = await MigrateDatabaseSchemaWithDbContextAsync(); + } + } + + await uow.CompleteAsync(); + } + } + + return result; + } + + protected virtual async Task HandleErrorOnApplyDatabaseMigrationAsync( + ApplyDatabaseMigrationsEto eventData, + Exception exception) + { + var tryCount = IncrementEventTryCount(eventData); + if (tryCount <= MaxEventTryCount) + { + Logger.LogWarning( + $"Could not apply database migrations. Re-queueing the operation. TenantId = {eventData.TenantId}, Database Name = {eventData.DatabaseName}."); + Logger.LogException(exception, LogLevel.Warning); + + await Task.Delay(RandomHelper.GetRandom(MinValueToWaitOnFailure, MaxValueToWaitOnFailure)); + await DistributedEventBus.PublishAsync(eventData); + } + else + { + Logger.LogError( + $"Could not apply database migrations. Canceling the operation. TenantId = {eventData.TenantId}, DatabaseName = {eventData.DatabaseName}."); + Logger.LogException(exception); + } + } + + protected virtual async Task HandleErrorTenantCreatedAsync( + TenantCreatedEto eventData, + Exception exception) + { + var tryCount = IncrementEventTryCount(eventData); + if (tryCount <= MaxEventTryCount) + { + Logger.LogWarning( + $"Could not perform tenant created event. Re-queueing the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception, LogLevel.Warning); + + await Task.Delay(RandomHelper.GetRandom(5000, 15000)); + await DistributedEventBus.PublishAsync(eventData); + } + else + { + Logger.LogError( + $"Could not perform tenant created event. Canceling the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception); + } + } + + protected virtual async Task HandleErrorTenantConnectionStringUpdatedAsync( + TenantConnectionStringUpdatedEto eventData, + Exception exception) + { + var tryCount = IncrementEventTryCount(eventData); + if (tryCount <= MaxEventTryCount) + { + Logger.LogWarning( + $"Could not perform tenant connection string updated event. Re-queueing the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception, LogLevel.Warning); + + await Task.Delay(RandomHelper.GetRandom(5000, 15000)); + await DistributedEventBus.PublishAsync(eventData); + } + else + { + Logger.LogError( + $"Could not perform tenant connection string updated event. Canceling the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception); + } + } + + private static int GetEventTryCount(EtoBase eventData) + { + var tryCountAsString = eventData.Properties.GetOrDefault(TryCountPropertyName); + if (tryCountAsString.IsNullOrEmpty()) + { + return 0; + } + + return int.Parse(tryCountAsString); + } + + private static void SetEventTryCount(EtoBase eventData, int count) + { + eventData.Properties[TryCountPropertyName] = count.ToString(); + } + + private static int IncrementEventTryCount(EtoBase eventData) + { + var count = GetEventTryCount(eventData) + 1; + SetEventTryCount(eventData, count); + return count; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreRuntimeDatabaseMigratorBase.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreRuntimeDatabaseMigratorBase.cs new file mode 100644 index 0000000000..9b9719ff1b --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreRuntimeDatabaseMigratorBase.cs @@ -0,0 +1,145 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace Volo.Abp.EntityFrameworkCore.Migrations; + +public abstract class EfCoreRuntimeDatabaseMigratorBase : ITransientDependency + where TDbContext : DbContext, IEfCoreDbContext +{ + protected int MinValueToWaitOnFailure { get; set; } = 5000; + protected int MaxValueToWaitOnFailure { get; set; } = 15000; + + protected string DatabaseName { get; } + + /// + /// Enabling this might be inefficient if you have many tenants! + /// If disabled (default), tenant databases will be seeded only + /// if there is a schema migration applied to the host database. + /// If enabled, tenant databases will be seeded always on every service startup. + /// + protected bool AlwaysSeedTenantDatabases { get; set; } = false; + + protected IUnitOfWorkManager UnitOfWorkManager { get; } + protected IServiceProvider ServiceProvider { get; } + protected ICurrentTenant CurrentTenant { get; } + protected IAbpDistributedLock DistributedLock { get; } + protected IDistributedEventBus DistributedEventBus { get; } + protected ILogger> Logger { get; } + + protected EfCoreRuntimeDatabaseMigratorBase( + string databaseName, + IUnitOfWorkManager unitOfWorkManager, + IServiceProvider serviceProvider, + ICurrentTenant currentTenant, + IAbpDistributedLock abpDistributedLock, + IDistributedEventBus distributedEventBus, + ILoggerFactory loggerFactory) + { + DatabaseName = databaseName; + UnitOfWorkManager = unitOfWorkManager; + ServiceProvider = serviceProvider; + CurrentTenant = currentTenant; + DistributedLock = abpDistributedLock; + DistributedEventBus = distributedEventBus; + Logger = loggerFactory.CreateLogger>(); + } + + public virtual async Task CheckAndApplyDatabaseMigrationsAsync() + { + await TryAsync(LockAndApplyDatabaseMigrationsAsync); + } + + protected virtual async Task LockAndApplyDatabaseMigrationsAsync() + { + Logger.LogInformation($"Trying to acquire the distributed lock for database migration: {DatabaseName}."); + + var schemaMigrated = false; + + await using (var handle = await DistributedLock.TryAcquireAsync("DatabaseMigration_" + DatabaseName)) + { + if (handle is null) + { + Logger.LogInformation($"Distributed lock could not be acquired for database migration: {DatabaseName}. Operation cancelled."); + return; + } + + Logger.LogInformation($"Distributed lock is acquired for database migration: {DatabaseName}..."); + + using (CurrentTenant.Change(null)) + { + // Create database tables if needed + using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) + { + var dbContext = await ServiceProvider + .GetRequiredService>() + .GetDbContextAsync(); + + var pendingMigrations = await dbContext + .Database + .GetPendingMigrationsAsync(); + + if (pendingMigrations.Any()) + { + await dbContext.Database.MigrateAsync(); + schemaMigrated = true; + } + + await uow.CompleteAsync(); + } + } + + await SeedAsync(); + + if (schemaMigrated || AlwaysSeedTenantDatabases) + { + await DistributedEventBus.PublishAsync( + new AppliedDatabaseMigrationsEto + { + DatabaseName = DatabaseName, + TenantId = null + } + ); + } + } + + Logger.LogInformation($"Distributed lock has been released for database migration: {DatabaseName}..."); + } + + protected virtual Task SeedAsync() + { + return Task.CompletedTask; + } + + protected virtual async Task TryAsync(Func task, int maxTryCount = 3) + { + try + { + await task(); + } + catch (Exception ex) + { + maxTryCount--; + + if (maxTryCount <= 0) + { + throw; + } + + Logger.LogWarning($"{ex.GetType().Name} has been thrown. The operation will be tried {maxTryCount} times more. Exception:\n{ex.Message}. Stack Trace:\n{ex.StackTrace}"); + + await Task.Delay(RandomHelper.GetRandom(MinValueToWaitOnFailure, MaxValueToWaitOnFailure)); + + await TryAsync(task, maxTryCount); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs index d28b28e4d6..372e4e3d77 100644 --- a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/IncomingEventInfo.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Volo.Abp.Data; namespace Volo.Abp.EventBus.Distributed; @@ -40,4 +41,14 @@ public class IncomingEventInfo : IHasExtraProperties ExtraProperties = new ExtraPropertyDictionary(); this.SetDefaultsForExtraProperties(); } + + public void SetCorrelationId(string correlationId) + { + ExtraProperties[EventBusConsts.CorrelationIdHeaderName] = correlationId; + } + + public string GetCorrelationId() + { + return ExtraProperties.GetOrDefault(EventBusConsts.CorrelationIdHeaderName)?.ToString(); + } } diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs index 359b33f3b3..299935741e 100644 --- a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutgoingEventInfo.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Volo.Abp.Data; namespace Volo.Abp.EventBus.Distributed; @@ -36,4 +37,14 @@ public class OutgoingEventInfo : IHasExtraProperties ExtraProperties = new ExtraPropertyDictionary(); this.SetDefaultsForExtraProperties(); } -} \ No newline at end of file + + public void SetCorrelationId(string correlationId) + { + ExtraProperties[EventBusConsts.CorrelationIdHeaderName] = correlationId; + } + + public string GetCorrelationId() + { + return ExtraProperties.GetOrDefault(EventBusConsts.CorrelationIdHeaderName)?.ToString(); + } +} diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/EventBusConsts.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/EventBusConsts.cs new file mode 100644 index 0000000000..f1fa920670 --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/EventBusConsts.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.EventBus; + +public static class EventBusConsts +{ + public const string CorrelationIdHeaderName = "X-Correlation-Id"; +} diff --git a/framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AzureDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AzureDistributedEventBus.cs index 8279a412a5..d7ca68bee6 100644 --- a/framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AzureDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Azure/Volo/Abp/EventBus/Azure/AzureDistributedEventBus.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Azure.Messaging.ServiceBus; +using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; @@ -14,6 +15,7 @@ using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.Threading; using Volo.Abp.Timing; +using Volo.Abp.Tracing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Azure; @@ -42,7 +44,8 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen IAzureServiceBusMessageConsumerFactory messageConsumerFactory, IPublisherPool publisherPool, IEventHandlerInvoker eventHandlerInvoker, - ILocalEventBus localEventBus) + ILocalEventBus localEventBus, + ICorrelationIdProvider correlationIdProvider) : base(serviceScopeFactory, currentTenant, unitOfWorkManager, @@ -50,7 +53,8 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen guidGenerator, clock, eventHandlerInvoker, - localEventBus) + localEventBus, + correlationIdProvider) { Options = abpAzureEventBusOptions.Value; Serializer = serializer; @@ -86,24 +90,30 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen var eventData = Serializer.Deserialize(message.Body.ToArray(), eventType); - if (await AddToInboxAsync(message.MessageId, eventName, eventType, eventData)) + if (await AddToInboxAsync(message.MessageId, eventName, eventType, eventData, message.CorrelationId)) { return; } - await TriggerHandlersDirectAsync(eventType, eventData); + using (CorrelationIdProvider.Change(message.CorrelationId)) + { + await TriggerHandlersDirectAsync(eventType, eventData); + } } public async override Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig) { - await TriggerDistributedEventSentAsync(new DistributedEventSent() + using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId())) { - Source = DistributedEventSource.Outbox, - EventName = outgoingEvent.EventName, - EventData = outgoingEvent.EventData - }); + await TriggerDistributedEventSentAsync(new DistributedEventSent() + { + Source = DistributedEventSource.Outbox, + EventName = outgoingEvent.EventName, + EventData = outgoingEvent.EventData + }); + } - await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, outgoingEvent.Id); + await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, outgoingEvent.GetCorrelationId(), outgoingEvent.Id); } public async override Task PublishManyFromOutboxAsync(IEnumerable outgoingEvents, OutboxConfig outboxConfig) @@ -125,18 +135,23 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen message.MessageId = outgoingEvent.Id.ToString(); } + message.CorrelationId = outgoingEvent.GetCorrelationId(); + if (!messageBatch.TryAddMessage(message)) { throw new AbpException( "The message is too large to fit in the batch. Set AbpEventBusBoxesOptions.OutboxWaitingEventMaxCount to reduce the number"); } - await TriggerDistributedEventSentAsync(new DistributedEventSent() + using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId())) { - Source = DistributedEventSource.Outbox, - EventName = outgoingEvent.EventName, - EventData = outgoingEvent.EventData - }); + await TriggerDistributedEventSentAsync(new DistributedEventSent() + { + Source = DistributedEventSource.Outbox, + EventName = outgoingEvent.EventName, + EventData = outgoingEvent.EventData + }); + } } await publisher.SendMessagesAsync(messageBatch); @@ -152,7 +167,10 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var exceptions = new List(); - await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); + using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId())) + { + await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); + } if (exceptions.Any()) { ThrowOriginalExceptions(eventType, exceptions); @@ -244,12 +262,13 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen { var body = Serializer.Serialize(eventData); - return PublishAsync(eventName, body, null); + return PublishAsync(eventName, body, CorrelationIdProvider.Get(), null); } protected virtual async Task PublishAsync( string eventName, byte[] body, + [CanBeNull] string correlationId, Guid? eventId) { var message = new ServiceBusMessage(body) @@ -262,6 +281,8 @@ public class AzureDistributedEventBus : DistributedEventBusBase, ISingletonDepen message.MessageId = (eventId ?? GuidGenerator.Create()).ToString("N"); } + message.CorrelationId = correlationId; + var publisher = await PublisherPool.GetAsync( Options.TopicName, Options.ConnectionName); diff --git a/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpDaprEventData.cs b/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpDaprEventData.cs new file mode 100644 index 0000000000..ee08586b8d --- /dev/null +++ b/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/AbpDaprEventData.cs @@ -0,0 +1,23 @@ +namespace Volo.Abp.EventBus.Dapr; + +public class AbpDaprEventData +{ + public string PubSubName { get; set; } + + public string Topic { get; set; } + + public string MessageId { get; set; } + + public string JsonData { get; set; } + + public string CorrelationId { get; set; } + + public AbpDaprEventData(string pubSubName, string topic, string messageId, string jsonData, string correlationId) + { + PubSubName = pubSubName; + Topic = topic; + MessageId = messageId; + JsonData = jsonData; + CorrelationId = correlationId; + } +} diff --git a/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs index 23cf8aa1e9..4912a58388 100644 --- a/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Dapr/Volo/Abp/EventBus/Dapr/DaprDistributedEventBus.cs @@ -13,6 +13,7 @@ using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.Threading; using Volo.Abp.Timing; +using Volo.Abp.Tracing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Dapr; @@ -39,8 +40,17 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend IDaprSerializer serializer, IOptions daprEventBusOptions, IAbpDaprClientFactory daprClientFactory, - ILocalEventBus localEventBus) - : base(serviceScopeFactory, currentTenant, unitOfWorkManager, abpDistributedEventBusOptions, guidGenerator, clock, eventHandlerInvoker, localEventBus) + ILocalEventBus localEventBus, + ICorrelationIdProvider correlationIdProvider) + : base(serviceScopeFactory, + currentTenant, + unitOfWorkManager, + abpDistributedEventBusOptions, + guidGenerator, + clock, + eventHandlerInvoker, + localEventBus, + correlationIdProvider) { Serializer = serializer; DaprEventBusOptions = daprEventBusOptions.Value; @@ -119,9 +129,9 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Clear()); } - protected override async Task PublishToEventBusAsync(Type eventType, object eventData) + protected async override Task PublishToEventBusAsync(Type eventType, object eventData) { - await PublishToDaprAsync(eventType, eventData); + await PublishToDaprAsync(eventType, eventData, null, CorrelationIdProvider.Get()); } protected override void AddToUnitOfWork(IUnitOfWork unitOfWork, UnitOfWorkEventRecord eventRecord) @@ -141,43 +151,52 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend return handlerFactoryList.ToArray(); } - public override async Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig) + public async override Task PublishFromOutboxAsync(OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig) { - await TriggerDistributedEventSentAsync(new DistributedEventSent() + using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId())) { - Source = DistributedEventSource.Outbox, - EventName = outgoingEvent.EventName, - EventData = outgoingEvent.EventData - }); + await TriggerDistributedEventSentAsync(new DistributedEventSent() + { + Source = DistributedEventSource.Outbox, + EventName = outgoingEvent.EventName, + EventData = outgoingEvent.EventData + }); + } - await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName))); + await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName)), outgoingEvent.Id, outgoingEvent.GetCorrelationId()); } - public override async Task PublishManyFromOutboxAsync(IEnumerable outgoingEvents, OutboxConfig outboxConfig) + public async override Task PublishManyFromOutboxAsync(IEnumerable outgoingEvents, OutboxConfig outboxConfig) { var outgoingEventArray = outgoingEvents.ToArray(); foreach (var outgoingEvent in outgoingEventArray) { - await TriggerDistributedEventSentAsync(new DistributedEventSent() + using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId())) { - Source = DistributedEventSource.Outbox, - EventName = outgoingEvent.EventName, - EventData = outgoingEvent.EventData - }); + await TriggerDistributedEventSentAsync(new DistributedEventSent() + { + Source = DistributedEventSource.Outbox, + EventName = outgoingEvent.EventName, + EventData = outgoingEvent.EventData + }); + } - await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName))); + await PublishToDaprAsync(outgoingEvent.EventName, Serializer.Deserialize(outgoingEvent.EventData, GetEventType(outgoingEvent.EventName)), outgoingEvent.Id, outgoingEvent.GetCorrelationId()); } } - public virtual async Task TriggerHandlersAsync(string messageId, Type eventType, object eventData) + public virtual async Task TriggerHandlersAsync(Type eventType, object eventData, string messageId = null, string correlationId = null) { - if (await AddToInboxAsync(messageId, EventNameAttribute.GetNameOrDefault(eventType), eventType, eventData)) + if (await AddToInboxAsync(messageId, EventNameAttribute.GetNameOrDefault(eventType), eventType, eventData, correlationId)) { return; } - await TriggerHandlersDirectAsync(eventType, eventData); + using (CorrelationIdProvider.Change(correlationId)) + { + await TriggerHandlersDirectAsync(eventType, eventData); + } } public async override Task ProcessFromInboxAsync(IncomingEventInfo incomingEvent, InboxConfig inboxConfig) @@ -190,7 +209,10 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var exceptions = new List(); - await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); + using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId())) + { + await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); + } if (exceptions.Any()) { ThrowOriginalExceptions(eventType, exceptions); @@ -226,15 +248,16 @@ public class DaprDistributedEventBus : DistributedEventBusBase, ISingletonDepend return EventTypes.GetOrDefault(eventName); } - protected virtual async Task PublishToDaprAsync(Type eventType, object eventData) + protected virtual async Task PublishToDaprAsync(Type eventType, object eventData, Guid? messageId = null, string correlationId = null) { - await PublishToDaprAsync(EventNameAttribute.GetNameOrDefault(eventType), eventData); + await PublishToDaprAsync(EventNameAttribute.GetNameOrDefault(eventType), eventData, messageId, correlationId); } - protected virtual async Task PublishToDaprAsync(string eventName, object eventData) + protected virtual async Task PublishToDaprAsync(string eventName, object eventData, Guid? messageId = null, string correlationId = null) { var client = DaprClientFactory.Create(); - await client.PublishEventAsync(pubsubName: DaprEventBusOptions.PubSubName, topicName: eventName, data: eventData); + var data = new AbpDaprEventData(DaprEventBusOptions.PubSubName, eventName, (messageId ?? GuidGenerator.Create()).ToString("N"), Serializer.SerializeToString(eventData), correlationId); + await client.PublishEventAsync(pubsubName: DaprEventBusOptions.PubSubName, topicName: eventName, data: data); } private static bool ShouldTriggerEventForHandler(Type targetEventType, Type handlerEventType) diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs index 62e161fad1..b49ffc07a9 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/KafkaDistributedEventBus.cs @@ -14,6 +14,7 @@ using Volo.Abp.Kafka; using Volo.Abp.MultiTenancy; using Volo.Abp.Threading; using Volo.Abp.Timing; +using Volo.Abp.Tracing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Kafka; @@ -42,7 +43,8 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen IGuidGenerator guidGenerator, IClock clock, IEventHandlerInvoker eventHandlerInvoker, - ILocalEventBus localEventBus) + ILocalEventBus localEventBus, + ICorrelationIdProvider correlationIdProvider) : base( serviceScopeFactory, currentTenant, @@ -51,7 +53,8 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen guidGenerator, clock, eventHandlerInvoker, - localEventBus) + localEventBus, + correlationIdProvider) { AbpKafkaEventBusOptions = abpKafkaEventBusOptions.Value; MessageConsumerFactory = messageConsumerFactory; @@ -84,13 +87,17 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen var messageId = message.GetMessageId(); var eventData = Serializer.Deserialize(message.Value, eventType); + var correlationId = message.GetCorrelationId(); - if (await AddToInboxAsync(messageId, eventName, eventType, eventData)) + if (await AddToInboxAsync(messageId, eventName, eventType, eventData, correlationId)) { return; } - await TriggerHandlersDirectAsync(eventType, eventData); + using (CorrelationIdProvider.Change(correlationId)) + { + await TriggerHandlersDirectAsync(eventType, eventData); + } } public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory) @@ -163,14 +170,21 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen protected async override Task PublishToEventBusAsync(Type eventType, object eventData) { + var headers = new Headers + { + { "messageId", System.Text.Encoding.UTF8.GetBytes(Guid.NewGuid().ToString("N")) } + }; + + if (CorrelationIdProvider.Get() != null) + { + headers.Add(EventBusConsts.CorrelationIdHeaderName, System.Text.Encoding.UTF8.GetBytes(CorrelationIdProvider.Get()!)); + } + await PublishAsync( AbpKafkaEventBusOptions.TopicName, eventType, eventData, - new Headers - { - { "messageId", System.Text.Encoding.UTF8.GetBytes(Guid.NewGuid().ToString("N")) } - } + headers ); } @@ -179,25 +193,34 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen unitOfWork.AddOrReplaceDistributedEvent(eventRecord); } - public override async Task PublishFromOutboxAsync( + public async override Task PublishFromOutboxAsync( OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig) { - await TriggerDistributedEventSentAsync(new DistributedEventSent() + using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId())) { - Source = DistributedEventSource.Outbox, - EventName = outgoingEvent.EventName, - EventData = outgoingEvent.EventData - }); + await TriggerDistributedEventSentAsync(new DistributedEventSent() + { + Source = DistributedEventSource.Outbox, + EventName = outgoingEvent.EventName, + EventData = outgoingEvent.EventData + }); + } + + var headers = new Headers + { + { "messageId", System.Text.Encoding.UTF8.GetBytes(outgoingEvent.Id.ToString("N")) } + }; + if (outgoingEvent.GetCorrelationId() != null) + { + headers.Add(EventBusConsts.CorrelationIdHeaderName, System.Text.Encoding.UTF8.GetBytes(outgoingEvent.GetCorrelationId()!)); + } await PublishAsync( AbpKafkaEventBusOptions.TopicName, outgoingEvent.EventName, outgoingEvent.EventData, - new Headers - { - { "messageId", System.Text.Encoding.UTF8.GetBytes(outgoingEvent.Id.ToString("N")) } - } + headers ); } @@ -214,12 +237,20 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen { "messageId", System.Text.Encoding.UTF8.GetBytes(messageId)} }; - await TriggerDistributedEventSentAsync(new DistributedEventSent() + if (outgoingEvent.GetCorrelationId() != null) { - Source = DistributedEventSource.Outbox, - EventName = outgoingEvent.EventName, - EventData = outgoingEvent.EventData - }); + headers.Add(EventBusConsts.CorrelationIdHeaderName, System.Text.Encoding.UTF8.GetBytes(outgoingEvent.GetCorrelationId()!)); + } + + using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId())) + { + await TriggerDistributedEventSentAsync(new DistributedEventSent() + { + Source = DistributedEventSource.Outbox, + EventName = outgoingEvent.EventName, + EventData = outgoingEvent.EventData + }); + } producer.Produce( AbpKafkaEventBusOptions.TopicName, @@ -244,7 +275,10 @@ public class KafkaDistributedEventBus : DistributedEventBusBase, ISingletonDepen var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var exceptions = new List(); - await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); + using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId())) + { + await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); + } if (exceptions.Any()) { ThrowOriginalExceptions(eventType, exceptions); diff --git a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/MessageExtensions.cs b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/MessageExtensions.cs index 17a80ec87c..569e56a1dc 100644 --- a/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/MessageExtensions.cs +++ b/framework/src/Volo.Abp.EventBus.Kafka/Volo/Abp/EventBus/Kafka/MessageExtensions.cs @@ -15,4 +15,16 @@ public static class MessageExtensions return messageId; } + + public static string GetCorrelationId(this Message message) + { + string correlationId = null; + + if (message.Headers.TryGetLastBytes(EventBusConsts.CorrelationIdHeaderName, out var correlationIdBytes)) + { + correlationId = System.Text.Encoding.UTF8.GetString(correlationIdBytes); + } + + return correlationId; + } } diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index 8d4756165a..a2459ea8d4 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using RabbitMQ.Client; @@ -15,6 +16,7 @@ using Volo.Abp.MultiTenancy; using Volo.Abp.RabbitMQ; using Volo.Abp.Threading; using Volo.Abp.Timing; +using Volo.Abp.Tracing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.RabbitMq; @@ -49,7 +51,8 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe IGuidGenerator guidGenerator, IClock clock, IEventHandlerInvoker eventHandlerInvoker, - ILocalEventBus localEventBus) + ILocalEventBus localEventBus, + ICorrelationIdProvider correlationIdProvider) : base( serviceScopeFactory, currentTenant, @@ -58,7 +61,8 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe guidGenerator, clock, eventHandlerInvoker, - localEventBus) + localEventBus, + correlationIdProvider) { ConnectionPool = connectionPool; Serializer = serializer; @@ -103,12 +107,16 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe var eventData = Serializer.Deserialize(ea.Body.ToArray(), eventType); - if (await AddToInboxAsync(ea.BasicProperties.MessageId, eventName, eventType, eventData)) + var correlationId = ea.BasicProperties.CorrelationId; + if (await AddToInboxAsync(ea.BasicProperties.MessageId, eventName, eventType, eventData, correlationId)) { return; } - await TriggerHandlersDirectAsync(eventType, eventData); + using (CorrelationIdProvider.Change(correlationId)) + { + await TriggerHandlersDirectAsync(eventType, eventData); + } } public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory) @@ -186,7 +194,7 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe protected async override Task PublishToEventBusAsync(Type eventType, object eventData) { - await PublishAsync(eventType, eventData, null); + await PublishAsync(eventType, eventData, correlationId: CorrelationIdProvider.Get()); } protected override void AddToUnitOfWork(IUnitOfWork unitOfWork, UnitOfWorkEventRecord eventRecord) @@ -194,18 +202,21 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe unitOfWork.AddOrReplaceDistributedEvent(eventRecord); } - public override async Task PublishFromOutboxAsync( + public async override Task PublishFromOutboxAsync( OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig) { - await TriggerDistributedEventSentAsync(new DistributedEventSent() + using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId())) { - Source = DistributedEventSource.Outbox, - EventName = outgoingEvent.EventName, - EventData = outgoingEvent.EventData - }); + await TriggerDistributedEventSentAsync(new DistributedEventSent() + { + Source = DistributedEventSource.Outbox, + EventName = outgoingEvent.EventName, + EventData = outgoingEvent.EventData + }); + } - await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, null, eventId: outgoingEvent.Id); + await PublishAsync(outgoingEvent.EventName, outgoingEvent.EventData, eventId: outgoingEvent.Id, correlationId: outgoingEvent.GetCorrelationId()); } public async override Task PublishManyFromOutboxAsync( @@ -219,19 +230,22 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe foreach (var outgoingEvent in outgoingEventArray) { - await TriggerDistributedEventSentAsync(new DistributedEventSent() + using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId())) { - Source = DistributedEventSource.Outbox, - EventName = outgoingEvent.EventName, - EventData = outgoingEvent.EventData - }); + await TriggerDistributedEventSentAsync(new DistributedEventSent() + { + Source = DistributedEventSource.Outbox, + EventName = outgoingEvent.EventName, + EventData = outgoingEvent.EventData + }); + } await PublishAsync( channel, outgoingEvent.EventName, outgoingEvent.EventData, - properties: null, - eventId: outgoingEvent.Id); + eventId: outgoingEvent.Id, + correlationId: outgoingEvent.GetCorrelationId()); } channel.WaitForConfirmsOrDie(); @@ -250,7 +264,10 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var exceptions = new List(); - await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); + using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId())) + { + await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); + } if (exceptions.Any()) { ThrowOriginalExceptions(eventType, exceptions); @@ -262,28 +279,29 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe return Serializer.Serialize(eventData); } - public Task PublishAsync( + public virtual Task PublishAsync( Type eventType, object eventData, - IBasicProperties properties, - Dictionary headersArguments = null) + Dictionary headersArguments = null, + Guid? eventId = null, + [CanBeNull] string correlationId = null) { var eventName = EventNameAttribute.GetNameOrDefault(eventType); var body = Serializer.Serialize(eventData); - return PublishAsync(eventName, body, properties, headersArguments); + return PublishAsync( eventName, body, headersArguments, eventId, correlationId); } protected virtual Task PublishAsync( string eventName, byte[] body, - IBasicProperties properties, Dictionary headersArguments = null, - Guid? eventId = null) + Guid? eventId = null, + [CanBeNull] string correlationId = null) { using (var channel = ConnectionPool.Get(AbpRabbitMqEventBusOptions.ConnectionName).CreateModel()) { - return PublishAsync(channel, eventName, body, properties, headersArguments, eventId); + return PublishAsync(channel, eventName, body, headersArguments, eventId, correlationId); } } @@ -291,23 +309,25 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, ISingletonDe IModel channel, string eventName, byte[] body, - IBasicProperties properties, Dictionary headersArguments = null, - Guid? eventId = null) + Guid? eventId = null, + [CanBeNull] string correlationId = null) { EnsureExchangeExists(channel); - if (properties == null) - { - properties = channel.CreateBasicProperties(); - properties.DeliveryMode = RabbitMqConsts.DeliveryModes.Persistent; - } + var properties = channel.CreateBasicProperties(); + properties.DeliveryMode = RabbitMqConsts.DeliveryModes.Persistent; if (properties.MessageId.IsNullOrEmpty()) { properties.MessageId = (eventId ?? GuidGenerator.Create()).ToString("N"); } + if (correlationId != null) + { + properties.CorrelationId = correlationId; + } + SetEventMessageHeaders(properties, headersArguments); channel.BasicPublish( diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs index 0983e98836..560b13ba14 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/RebusDistributedEventBus.cs @@ -16,6 +16,7 @@ using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.Threading; using Volo.Abp.Timing; +using Volo.Abp.Tracing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Rebus; @@ -43,7 +44,8 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen IGuidGenerator guidGenerator, IClock clock, IEventHandlerInvoker eventHandlerInvoker, - ILocalEventBus localEventBus) : + ILocalEventBus localEventBus, + ICorrelationIdProvider correlationIdProvider) : base( serviceScopeFactory, currentTenant, @@ -52,7 +54,8 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen guidGenerator, clock, eventHandlerInvoker, - localEventBus) + localEventBus, + correlationIdProvider) { Rebus = rebus; Serializer = serializer; @@ -144,18 +147,27 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen { var messageId = MessageContext.Current.TransportMessage.GetMessageId(); var eventName = EventNameAttribute.GetNameOrDefault(eventType); + var correlationId = MessageContext.Current.Headers.GetOrDefault(EventBusConsts.CorrelationIdHeaderName); - if (await AddToInboxAsync(messageId, eventName, eventType, eventData)) + if (await AddToInboxAsync(messageId, eventName, eventType, eventData, correlationId)) { return; } - await TriggerHandlersDirectAsync(eventType, eventData); + using (CorrelationIdProvider.Change(correlationId)) + { + await TriggerHandlersDirectAsync(eventType, eventData); + } } protected async override Task PublishToEventBusAsync(Type eventType, object eventData) { - await PublishAsync(eventType, eventData); + var headers = new Dictionary(); + if (CorrelationIdProvider.Get() != null) + { + headers.Add(EventBusConsts.CorrelationIdHeaderName, CorrelationIdProvider.Get()); + } + await PublishAsync(eventType, eventData, headersArguments: headers); } protected virtual async Task PublishAsync( @@ -234,21 +246,29 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen return false; } - public override async Task PublishFromOutboxAsync( + public async override Task PublishFromOutboxAsync( OutgoingEventInfo outgoingEvent, OutboxConfig outboxConfig) { var eventType = EventTypes.GetOrDefault(outgoingEvent.EventName); var eventData = Serializer.Deserialize(outgoingEvent.EventData, eventType); - await TriggerDistributedEventSentAsync(new DistributedEventSent() + using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId())) { - Source = DistributedEventSource.Outbox, - EventName = outgoingEvent.EventName, - EventData = outgoingEvent.EventData - }); + await TriggerDistributedEventSentAsync(new DistributedEventSent() { + Source = DistributedEventSource.Outbox, + EventName = outgoingEvent.EventName, + EventData = outgoingEvent.EventData + }); + } - await PublishAsync(eventType, eventData, eventId: outgoingEvent.Id); + var headers = new Dictionary(); + if (outgoingEvent.GetCorrelationId() != null) + { + headers.Add(EventBusConsts.CorrelationIdHeaderName, outgoingEvent.GetCorrelationId()); + } + + await PublishAsync(eventType, eventData, eventId: outgoingEvent.Id, headersArguments: headers); } public async override Task PublishManyFromOutboxAsync(IEnumerable outgoingEvents, OutboxConfig outboxConfig) @@ -259,12 +279,15 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen { foreach (var outgoingEvent in outgoingEventArray) { - await TriggerDistributedEventSentAsync(new DistributedEventSent() + using (CorrelationIdProvider.Change(outgoingEvent.GetCorrelationId())) { - Source = DistributedEventSource.Outbox, - EventName = outgoingEvent.EventName, - EventData = outgoingEvent.EventData - }); + await TriggerDistributedEventSentAsync(new DistributedEventSent() + { + Source = DistributedEventSource.Outbox, + EventName = outgoingEvent.EventName, + EventData = outgoingEvent.EventData + }); + } await PublishFromOutboxAsync(outgoingEvent, outboxConfig); } @@ -285,7 +308,10 @@ public class RebusDistributedEventBus : DistributedEventBusBase, ISingletonDepen var eventData = Serializer.Deserialize(incomingEvent.EventData, eventType); var exceptions = new List(); - await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); + using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId())) + { + await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); + } if (exceptions.Any()) { ThrowOriginalExceptions(eventType, exceptions); diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs index 89423ce111..2ca5c85bb0 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/DistributedEventBusBase.cs @@ -2,12 +2,14 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.EventBus.Local; using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.Timing; +using Volo.Abp.Tracing; using Volo.Abp.Uow; namespace Volo.Abp.EventBus.Distributed; @@ -18,6 +20,7 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB protected IClock Clock { get; } protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; } protected ILocalEventBus LocalEventBus { get; } + protected ICorrelationIdProvider CorrelationIdProvider { get; } protected DistributedEventBusBase( IServiceScopeFactory serviceScopeFactory, @@ -27,7 +30,8 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB IGuidGenerator guidGenerator, IClock clock, IEventHandlerInvoker eventHandlerInvoker, - ILocalEventBus localEventBus) : base( + ILocalEventBus localEventBus, + ICorrelationIdProvider correlationIdProvider) : base( serviceScopeFactory, currentTenant, unitOfWorkManager, @@ -37,6 +41,7 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB Clock = clock; AbpDistributedEventBusOptions = abpDistributedEventBusOptions.Value; LocalEventBus = localEventBus; + CorrelationIdProvider = correlationIdProvider; } public IDisposable Subscribe(IDistributedEventHandler handler) where TEvent : class @@ -129,14 +134,14 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB EventData = eventData }); - await eventOutbox.EnqueueAsync( - new OutgoingEventInfo( - GuidGenerator.Create(), - eventName, - Serialize(eventData), - Clock.Now - ) + var outgoingEventInfo = new OutgoingEventInfo( + GuidGenerator.Create(), + eventName, + Serialize(eventData), + Clock.Now ); + outgoingEventInfo.SetCorrelationId(CorrelationIdProvider.Get()); + await eventOutbox.EnqueueAsync(outgoingEventInfo); return true; } } @@ -153,7 +158,8 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB string messageId, string eventName, Type eventType, - object eventData) + object eventData, + [CanBeNull] string correlationId) { if (AbpDistributedEventBusOptions.Inboxes.Count <= 0) { @@ -177,22 +183,25 @@ public abstract class DistributedEventBusBase : EventBusBase, IDistributedEventB } } - await TriggerDistributedEventReceivedAsync(new DistributedEventReceived + using (CorrelationIdProvider.Change(correlationId)) { - Source = DistributedEventSource.Direct, - EventName = EventNameAttribute.GetNameOrDefault(eventType), - EventData = eventData - }); - - await eventInbox.EnqueueAsync( - new IncomingEventInfo( - GuidGenerator.Create(), - messageId, - eventName, - Serialize(eventData), - Clock.Now - ) + await TriggerDistributedEventReceivedAsync(new DistributedEventReceived + { + Source = DistributedEventSource.Direct, + EventName = EventNameAttribute.GetNameOrDefault(eventType), + EventData = eventData + }); + } + + var incomingEventInfo = new IncomingEventInfo( + GuidGenerator.Create(), + messageId, + eventName, + Serialize(eventData), + Clock.Now ); + incomingEventInfo.SetCorrelationId(correlationId); + await eventInbox.EnqueueAsync(incomingEventInfo); } } } diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo.Abp.ExceptionHandling.csproj b/framework/src/Volo.Abp.ExceptionHandling/Volo.Abp.ExceptionHandling.csproj index 7e3061e8c7..de9dc60c0d 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo.Abp.ExceptionHandling.csproj +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo.Abp.ExceptionHandling.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable true diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs index 1b8742af81..b068890b97 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs @@ -54,7 +54,7 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert return errorInfo; } - public RemoteServiceErrorInfo Convert(Exception exception, Action options = null) + public RemoteServiceErrorInfo Convert(Exception exception, Action? options = null) { var exceptionHandlingOptions = CreateDefaultOptions(); options?.Invoke(exceptionHandlingOptions); @@ -90,7 +90,7 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert if (exception is EntityNotFoundException) { - return CreateEntityNotFoundError(exception as EntityNotFoundException); + return CreateEntityNotFoundError((exception as EntityNotFoundException)!); } var errorInfo = new RemoteServiceErrorInfo(); @@ -110,10 +110,10 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert if (errorInfo.Details.IsNullOrEmpty()) { - errorInfo.Details = GetValidationErrorNarrative(exception as IHasValidationErrors); + errorInfo.Details = GetValidationErrorNarrative((exception as IHasValidationErrors)!); } - errorInfo.ValidationErrors = GetValidationErrorInfos(exception as IHasValidationErrors); + errorInfo.ValidationErrors = GetValidationErrorInfos((exception as IHasValidationErrors)!); } TryToLocalizeExceptionMessage(exception, errorInfo); @@ -146,7 +146,7 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert } if (exceptionWithErrorCode.Code.IsNullOrWhiteSpace() || - !exceptionWithErrorCode.Code.Contains(":")) + !exceptionWithErrorCode.Code!.Contains(":")) { return; } @@ -197,10 +197,8 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert protected virtual Exception TryToGetActualException(Exception exception) { - if (exception is AggregateException && exception.InnerException != null) + if (exception is AggregateException aggException && aggException.InnerException != null) { - var aggException = exception as AggregateException; - if (aggException.InnerException is AbpValidationException || aggException.InnerException is AbpAuthorizationException || aggException.InnerException is EntityNotFoundException || @@ -223,7 +221,7 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert if (exception is AbpValidationException) { - errorInfo.ValidationErrors = GetValidationErrorInfos(exception as AbpValidationException); + errorInfo.ValidationErrors = GetValidationErrorInfos((exception as AbpValidationException)!); } return errorInfo; @@ -246,9 +244,8 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert } //Additional info for AbpValidationException - if (exception is AbpValidationException) + if (exception is AbpValidationException validationException) { - var validationException = exception as AbpValidationException; if (validationException.ValidationErrors.Count > 0) { detailBuilder.AppendLine(GetValidationErrorNarrative(validationException)); @@ -268,9 +265,8 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert } //Inner exceptions for AggregateException - if (exception is AggregateException) + if (exception is AggregateException aggException) { - var aggException = exception as AggregateException; if (aggException.InnerExceptions.IsNullOrEmpty()) { return; @@ -289,7 +285,7 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert foreach (var validationResult in validationException.ValidationErrors) { - var validationError = new RemoteServiceValidationErrorInfo(validationResult.ErrorMessage); + var validationError = new RemoteServiceValidationErrorInfo(validationResult.ErrorMessage!); if (validationResult.MemberNames != null && validationResult.MemberNames.Any()) { diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/IExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/IExceptionToErrorInfoConverter.cs index ebf8993bd6..bd14010db0 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/IExceptionToErrorInfoConverter.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/IExceptionToErrorInfoConverter.cs @@ -24,5 +24,5 @@ public interface IExceptionToErrorInfoConverter /// The exception. /// Additional options. /// Error info or null - RemoteServiceErrorInfo Convert(Exception exception, Action options = null); + RemoteServiceErrorInfo Convert(Exception exception, Action? options = null); } diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Domain/Entities/EntityNotFoundException.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Domain/Entities/EntityNotFoundException.cs index 1feb8c4cbb..5f524f9578 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Domain/Entities/EntityNotFoundException.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Domain/Entities/EntityNotFoundException.cs @@ -10,12 +10,12 @@ public class EntityNotFoundException : AbpException /// /// Type of the entity. /// - public Type EntityType { get; set; } + public Type? EntityType { get; set; } /// /// Id of the Entity. /// - public object Id { get; set; } + public object? Id { get; set; } /// /// Creates a new object. @@ -37,7 +37,7 @@ public class EntityNotFoundException : AbpException /// /// Creates a new object. /// - public EntityNotFoundException(Type entityType, object id) + public EntityNotFoundException(Type entityType, object? id) : this(entityType, id, null) { @@ -46,7 +46,7 @@ public class EntityNotFoundException : AbpException /// /// Creates a new object. /// - public EntityNotFoundException(Type entityType, object id, Exception innerException) + public EntityNotFoundException(Type entityType, object? id, Exception? innerException) : base( id == null ? $"There is no such an entity given id. Entity type: {entityType.FullName}" diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs index 78c5bff6f9..887c8fb081 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/Client/AbpRemoteCallException.cs @@ -9,18 +9,18 @@ public class AbpRemoteCallException : AbpException, IHasErrorCode, IHasErrorDeta { public int HttpStatusCode { get; set; } - public string Code => Error?.Code; + public string? Code => Error?.Code; - public string Details => Error?.Details; + public string? Details => Error?.Details; - public RemoteServiceErrorInfo Error { get; set; } + public RemoteServiceErrorInfo? Error { get; set; } public AbpRemoteCallException() { } - public AbpRemoteCallException(string message, Exception innerException = null) + public AbpRemoteCallException(string message, Exception? innerException = null) : base(message, innerException) { @@ -32,7 +32,7 @@ public class AbpRemoteCallException : AbpException, IHasErrorCode, IHasErrorDeta } - public AbpRemoteCallException(RemoteServiceErrorInfo error, Exception innerException = null) + public AbpRemoteCallException(RemoteServiceErrorInfo error, Exception? innerException = null) : base(error.Message, innerException) { Error = error; diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/RemoteServiceErrorInfo.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/RemoteServiceErrorInfo.cs index 89ed87454a..e61d55e2d3 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/RemoteServiceErrorInfo.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/RemoteServiceErrorInfo.cs @@ -12,27 +12,27 @@ public class RemoteServiceErrorInfo /// /// Error code. /// - public string Code { get; set; } + public string? Code { get; set; } /// /// Error message. /// - public string Message { get; set; } + public string? Message { get; set; } /// /// Error details. /// - public string Details { get; set; } + public string? Details { get; set; } /// /// Error data. /// - public IDictionary Data { get; set; } + public IDictionary? Data { get; set; } /// /// Validation errors if exists. /// - public RemoteServiceValidationErrorInfo[] ValidationErrors { get; set; } + public RemoteServiceValidationErrorInfo[]? ValidationErrors { get; set; } /// /// Creates a new instance of . @@ -49,7 +49,7 @@ public class RemoteServiceErrorInfo /// Error details /// Error message /// Error data - public RemoteServiceErrorInfo(string message, string details = null, string code = null, IDictionary data = null) + public RemoteServiceErrorInfo(string message, string? details = null, string? code = null, IDictionary? data = null) { Message = message; Details = details; diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/RemoteServiceValidationErrorInfo.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/RemoteServiceValidationErrorInfo.cs index 4b86bbf4e3..64a31d7041 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/RemoteServiceValidationErrorInfo.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Http/RemoteServiceValidationErrorInfo.cs @@ -11,12 +11,12 @@ public class RemoteServiceValidationErrorInfo /// /// Validation error message. /// - public string Message { get; set; } + public string Message { get; set; } = default!; /// /// Relate invalid members (fields/properties). /// - public string[] Members { get; set; } + public string[] Members { get; set; } = default!; /// /// Creates a new instance of . diff --git a/framework/src/Volo.Abp.Guids/Volo.Abp.Guids.csproj b/framework/src/Volo.Abp.Guids/Volo.Abp.Guids.csproj index ed4e0af802..6aae43ce2a 100644 --- a/framework/src/Volo.Abp.Guids/Volo.Abp.Guids.csproj +++ b/framework/src/Volo.Abp.Guids/Volo.Abp.Guids.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Guids Volo.Abp.Guids $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Http.Client.Web/Volo/Abp/Http/Client/Web/AbpHttpClientWebModule.cs b/framework/src/Volo.Abp.Http.Client.Web/Volo/Abp/Http/Client/Web/AbpHttpClientWebModule.cs index 5fcab7a7f1..655f96f068 100644 --- a/framework/src/Volo.Abp.Http.Client.Web/Volo/Abp/Http/Client/Web/AbpHttpClientWebModule.cs +++ b/framework/src/Volo.Abp.Http.Client.Web/Volo/Abp/Http/Client/Web/AbpHttpClientWebModule.cs @@ -31,7 +31,7 @@ public class AbpHttpClientWebModule : AbpModule .ServiceProvider .GetRequiredService() .Modules - .Select(m => m.Type.Assembly) + .SelectMany(m => m.AllAssemblies) .Where(a => a.GetTypes().Any(AbpHttpClientProxyHelper.IsClientProxyService)) .Distinct()) { diff --git a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs index 32952a7050..6f5f8eda95 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs +++ b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs @@ -245,8 +245,9 @@ public class IdentityModelAuthenticationService : IIdentityModelAuthenticationSe throw new AbpException(response.ErrorDescription); } - Logger.LogInformation($"First copy your one-time code: {response.UserCode}"); - Logger.LogInformation($"Open {response.VerificationUri} in your browser..."); + Logger.LogInformation($"Open your browser, go to: \"{response.VerificationUri}\""); + Logger.LogInformation($"and enter the following one-time code:"); + Logger.LogInformation(response.UserCode); for (var i = 0; i < ((response.ExpiresIn ?? 300) / response.Interval + 1); i++) { diff --git a/framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageCompressor.cs b/framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageCompressor.cs index c68c7e3773..11789776c7 100644 --- a/framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageCompressor.cs +++ b/framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageCompressor.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; @@ -16,7 +17,7 @@ public class ImageCompressor : IImageCompressor, ITransientDependency public ImageCompressor(IEnumerable imageCompressorContributors, ICancellationTokenProvider cancellationTokenProvider) { - ImageCompressorContributors = imageCompressorContributors; + ImageCompressorContributors = imageCompressorContributors.Reverse(); CancellationTokenProvider = cancellationTokenProvider; } diff --git a/framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageResizer.cs b/framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageResizer.cs index 5576197797..139fc194dd 100644 --- a/framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageResizer.cs +++ b/framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageResizer.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; @@ -22,7 +23,7 @@ public class ImageResizer : IImageResizer, ITransientDependency IOptions imageResizeOptions, ICancellationTokenProvider cancellationTokenProvider) { - ImageResizerContributors = imageResizerContributors; + ImageResizerContributors = imageResizerContributors.Reverse(); CancellationTokenProvider = cancellationTokenProvider; ImageResizeOptions = imageResizeOptions.Value; } diff --git a/framework/src/Volo.Abp.Json.Abstractions/Volo.Abp.Json.Abstractions.csproj b/framework/src/Volo.Abp.Json.Abstractions/Volo.Abp.Json.Abstractions.csproj index d3f63e6e20..1be747846e 100644 --- a/framework/src/Volo.Abp.Json.Abstractions/Volo.Abp.Json.Abstractions.csproj +++ b/framework/src/Volo.Abp.Json.Abstractions/Volo.Abp.Json.Abstractions.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Json.Abstractions $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; false diff --git a/framework/src/Volo.Abp.Json.Abstractions/Volo/Abp/Json/AbpJsonOptions.cs b/framework/src/Volo.Abp.Json.Abstractions/Volo/Abp/Json/AbpJsonOptions.cs index 043c1081d7..bed36c8afa 100644 --- a/framework/src/Volo.Abp.Json.Abstractions/Volo/Abp/Json/AbpJsonOptions.cs +++ b/framework/src/Volo.Abp.Json.Abstractions/Volo/Abp/Json/AbpJsonOptions.cs @@ -12,7 +12,7 @@ public class AbpJsonOptions /// /// Format of output json date, Null or empty string means default format. /// - public string OutputDateTimeFormat { get; set; } + public string? OutputDateTimeFormat { get; set; } public AbpJsonOptions() { diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj b/framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj index 5349254ea3..094a6e3c0a 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Json.Newtonsoft Volo.Abp.Json.Newtonsoft $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs index 408f38e772..effda40057 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs @@ -31,7 +31,7 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency return objectType == typeof(DateTime) || objectType == typeof(DateTime?); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { var nullable = Nullable.GetUnderlyingType(objectType) != null; if (reader.TokenType == JsonToken.Null) @@ -46,7 +46,7 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency if (reader.TokenType == JsonToken.Date) { - return _clock.Normalize(reader.Value.To()); + return _clock.Normalize(reader.Value!.To()); } if (reader.TokenType != JsonToken.String) @@ -72,11 +72,11 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency } } - var date = DateTime.Parse(dateText, _culture, _dateTimeStyles); + var date = DateTime.Parse(dateText!, _culture, _dateTimeStyles); return _clock.Normalize(date); } - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value != null) { @@ -97,7 +97,7 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency } else { - throw new JsonSerializationException($"Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {value.GetType()}."); + throw new JsonSerializationException($"Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {value?.GetType()}."); } } diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs index ab65909cf9..2a21f5fbd7 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs @@ -26,12 +26,12 @@ public class AbpNewtonsoftJsonSerializer : IJsonSerializer, ITransientDependency public T Deserialize(string jsonString, bool camelCase = true) { - return JsonConvert.DeserializeObject(jsonString, CreateJsonSerializerOptions(camelCase)); + return JsonConvert.DeserializeObject(jsonString, CreateJsonSerializerOptions(camelCase))!; } public object Deserialize(Type type, string jsonString, bool camelCase = true) { - return JsonConvert.DeserializeObject(jsonString, type, CreateJsonSerializerOptions(camelCase)); + return JsonConvert.DeserializeObject(jsonString, type, CreateJsonSerializerOptions(camelCase))!; } private readonly static ConcurrentDictionary JsonSerializerOptionsCache = diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo.Abp.Json.SystemTextJson.csproj b/framework/src/Volo.Abp.Json.SystemTextJson/Volo.Abp.Json.SystemTextJson.csproj index e157d5b7db..1fc81dd3ac 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo.Abp.Json.SystemTextJson.csproj +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo.Abp.Json.SystemTextJson.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Json.SystemTextJson Volo.Abp.Json.SystemTextJson $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializer.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializer.cs index 8313f6ee99..6f433ce918 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializer.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializer.cs @@ -22,12 +22,12 @@ public class AbpSystemTextJsonSerializer : IJsonSerializer, ITransientDependency public T Deserialize(string jsonString, bool camelCase = true) { - return JsonSerializer.Deserialize(jsonString, CreateJsonSerializerOptions(camelCase)); + return JsonSerializer.Deserialize(jsonString, CreateJsonSerializerOptions(camelCase))!; } public object Deserialize(Type type, string jsonString, bool camelCase = true) { - return JsonSerializer.Deserialize(jsonString, type, CreateJsonSerializerOptions(camelCase)); + return JsonSerializer.Deserialize(jsonString, type, CreateJsonSerializerOptions(camelCase))!; } private static readonly ConcurrentDictionary JsonSerializerOptionsCache = diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableStringToGuidConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableStringToGuidConverter.cs index c80e5aa9a5..973faca170 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableStringToGuidConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableStringToGuidConverter.cs @@ -6,7 +6,7 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters; public class AbpNullableStringToGuidConverter : JsonConverter { - private JsonSerializerOptions _writeJsonSerializerOptions; + private JsonSerializerOptions? _writeJsonSerializerOptions; public override Guid? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToBooleanConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToBooleanConverter.cs index e704f2ceb0..443150e41a 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToBooleanConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToBooleanConverter.cs @@ -8,7 +8,7 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters; public class AbpStringToBooleanConverter : JsonConverter { - private JsonSerializerOptions _writeJsonSerializerOptions; + private JsonSerializerOptions? _writeJsonSerializerOptions; public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs index 6b7f32807e..d1e8fc555d 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs @@ -9,9 +9,9 @@ public class AbpStringToEnumConverter : JsonConverter { private readonly JsonStringEnumConverter _innerJsonStringEnumConverter; - private JsonSerializerOptions _readJsonSerializerOptions; + private JsonSerializerOptions? _readJsonSerializerOptions; - private JsonSerializerOptions _writeJsonSerializerOptions; + private JsonSerializerOptions? _writeJsonSerializerOptions; public AbpStringToEnumConverter() : this(namingPolicy: null, allowIntegerValues: true) @@ -19,7 +19,7 @@ public class AbpStringToEnumConverter : JsonConverter } - public AbpStringToEnumConverter(JsonNamingPolicy namingPolicy = null, bool allowIntegerValues = true) + public AbpStringToEnumConverter(JsonNamingPolicy? namingPolicy = null, bool allowIntegerValues = true) { _innerJsonStringEnumConverter = new JsonStringEnumConverter(namingPolicy, allowIntegerValues); } @@ -50,11 +50,11 @@ public class AbpStringToEnumConverter : JsonConverter public override T ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return (T)Enum.Parse(typeToConvert, reader.GetString()); + return (T)Enum.Parse(typeToConvert, reader.GetString()!); } public override void WriteAsPropertyName(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { - writer.WritePropertyName(Enum.GetName(typeof(T), value)); + writer.WritePropertyName(Enum.GetName(typeof(T), value)!); } } diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumFactory.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumFactory.cs index d94d85e546..bda510e5dc 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumFactory.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumFactory.cs @@ -7,7 +7,7 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters; public class AbpStringToEnumFactory : JsonConverterFactory { - private readonly JsonNamingPolicy _namingPolicy; + private readonly JsonNamingPolicy? _namingPolicy; private readonly bool _allowIntegerValues; public AbpStringToEnumFactory() @@ -16,7 +16,7 @@ public class AbpStringToEnumFactory : JsonConverterFactory } - public AbpStringToEnumFactory(JsonNamingPolicy namingPolicy, bool allowIntegerValues) + public AbpStringToEnumFactory(JsonNamingPolicy? namingPolicy, bool allowIntegerValues) { _namingPolicy = namingPolicy; _allowIntegerValues = allowIntegerValues; @@ -33,7 +33,7 @@ public class AbpStringToEnumFactory : JsonConverterFactory typeof(AbpStringToEnumConverter<>).MakeGenericType(typeToConvert), BindingFlags.Instance | BindingFlags.Public, binder: null, - new object[] { _namingPolicy, _allowIntegerValues }, + new object?[] { _namingPolicy, _allowIntegerValues }, culture: null)!; } } diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToGuidConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToGuidConverter.cs index 586e4462cf..5cb1062c0c 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToGuidConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToGuidConverter.cs @@ -6,7 +6,7 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters; public class AbpStringToGuidConverter : JsonConverter { - private JsonSerializerOptions _writeJsonSerializerOptions; + private JsonSerializerOptions? _writeJsonSerializerOptions; public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs index b1bffc95b8..bf017d041e 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs @@ -12,16 +12,16 @@ public class ObjectToInferredTypesConverter : JsonConverter public override object Read( ref Utf8JsonReader reader, Type typeToConvert, - JsonSerializerOptions options) => reader.TokenType switch - { - JsonTokenType.True => true, - JsonTokenType.False => false, - JsonTokenType.Number when reader.TryGetInt64(out long l) => l, - JsonTokenType.Number => reader.GetDouble(), - JsonTokenType.String when reader.TryGetDateTime(out DateTime datetime) => datetime, - JsonTokenType.String => reader.GetString(), - _ => JsonDocument.ParseValue(ref reader).RootElement.Clone() - }; + JsonSerializerOptions options) => (reader.TokenType switch + { + JsonTokenType.True => true, + JsonTokenType.False => false, + JsonTokenType.Number when reader.TryGetInt64(out long l) => l, + JsonTokenType.Number => reader.GetDouble(), + JsonTokenType.String when reader.TryGetDateTime(out DateTime datetime) => datetime, + JsonTokenType.String => reader.GetString(), + _ => JsonDocument.ParseValue(ref reader).RootElement.Clone() + })!; public override void Write( Utf8JsonWriter writer, diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpDateTimeConverterModifier.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpDateTimeConverterModifier.cs index a691423cf3..ba19ccfa29 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpDateTimeConverterModifier.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpDateTimeConverterModifier.cs @@ -10,7 +10,7 @@ namespace Volo.Abp.Json.SystemTextJson.Modifiers; public class AbpDateTimeConverterModifier { - private IServiceProvider _serviceProvider; + private IServiceProvider _serviceProvider = default!; public Action CreateModifyAction(IServiceProvider serviceProvider) { diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIgnorePropertiesModifiers.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIgnorePropertiesModifiers.cs index 27a50395bf..7c1db739d1 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIgnorePropertiesModifiers.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIgnorePropertiesModifiers.cs @@ -9,7 +9,7 @@ namespace Volo.Abp.Json.SystemTextJson.Modifiers; public class AbpIgnorePropertiesModifiers where TClass : class { - private Expression> _propertySelector; + private Expression> _propertySelector = default!; public Action CreateModifyAction(Expression> propertySelector) { diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIncludeExtraPropertiesModifiers.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIncludeExtraPropertiesModifiers.cs index f4a97e0e9d..c7fadc47db 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIncludeExtraPropertiesModifiers.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIncludeExtraPropertiesModifiers.cs @@ -17,7 +17,7 @@ public static class AbpIncludeExtraPropertiesModifiers .Where(x => x.AttributeProvider is MemberInfo) .FirstOrDefault(x => x.PropertyType == typeof(ExtraPropertyDictionary) && - x.AttributeProvider.As().Name == nameof(ExtensibleObject.ExtraProperties) && + x.AttributeProvider!.As().Name == nameof(ExtensibleObject.ExtraProperties) && x.Set == null); if (propertyJsonInfo != null) diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIncludeNonPublicPropertiesModifiers.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIncludeNonPublicPropertiesModifiers.cs index 4669ddc666..cc13db8d0c 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIncludeNonPublicPropertiesModifiers.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/Modifiers/AbpIncludeNonPublicPropertiesModifiers.cs @@ -9,7 +9,7 @@ namespace Volo.Abp.Json.SystemTextJson.Modifiers; public class AbpIncludeNonPublicPropertiesModifiers where TClass : class { - private Expression> _propertySelector; + private Expression> _propertySelector = default!; public Action CreateModifyAction(Expression> propertySelector) { diff --git a/framework/src/Volo.Abp.Ldap.Abstractions/Volo.Abp.Ldap.Abstractions.csproj b/framework/src/Volo.Abp.Ldap.Abstractions/Volo.Abp.Ldap.Abstractions.csproj index 9a61150096..6e25ebe8e6 100644 --- a/framework/src/Volo.Abp.Ldap.Abstractions/Volo.Abp.Ldap.Abstractions.csproj +++ b/framework/src/Volo.Abp.Ldap.Abstractions/Volo.Abp.Ldap.Abstractions.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Ldap.Abstractions Volo.Abp.Ldap.Abstractions $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Ldap.Abstractions/Volo/Abp/Ldap/ILdapSettingProvider.cs b/framework/src/Volo.Abp.Ldap.Abstractions/Volo/Abp/Ldap/ILdapSettingProvider.cs index efc109a762..c7320a36fa 100644 --- a/framework/src/Volo.Abp.Ldap.Abstractions/Volo/Abp/Ldap/ILdapSettingProvider.cs +++ b/framework/src/Volo.Abp.Ldap.Abstractions/Volo/Abp/Ldap/ILdapSettingProvider.cs @@ -4,15 +4,15 @@ namespace Volo.Abp.Ldap; public interface ILdapSettingProvider { - public Task GetServerHostAsync(); + public Task GetServerHostAsync(); public Task GetServerPortAsync(); - public Task GetBaseDcAsync(); + public Task GetBaseDcAsync(); - public Task GetDomainAsync(); + public Task GetDomainAsync(); - public Task GetUserNameAsync(); + public Task GetUserNameAsync(); - public Task GetPasswordAsync(); + public Task GetPasswordAsync(); } diff --git a/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj b/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj index 951cbf3be2..aee7d78518 100644 --- a/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj +++ b/framework/src/Volo.Abp.Ldap/Volo.Abp.Ldap.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Ldap Volo.Abp.Ldap $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapSettingProvider.cs b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapSettingProvider.cs index ab36c1bf5f..cf43f11d43 100644 --- a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapSettingProvider.cs +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/LdapSettingProvider.cs @@ -14,7 +14,7 @@ public class LdapSettingProvider : ILdapSettingProvider, ITransientDependency SettingProvider = settingProvider; } - public async Task GetServerHostAsync() + public async Task GetServerHostAsync() { return await SettingProvider.GetOrNullAsync(LdapSettingNames.ServerHost); } @@ -24,22 +24,22 @@ public class LdapSettingProvider : ILdapSettingProvider, ITransientDependency return (await SettingProvider.GetOrNullAsync(LdapSettingNames.ServerPort))?.To() ?? default; } - public async Task GetBaseDcAsync() + public async Task GetBaseDcAsync() { return await SettingProvider.GetOrNullAsync(LdapSettingNames.BaseDc); } - public async Task GetDomainAsync() + public async Task GetDomainAsync() { return await SettingProvider.GetOrNullAsync(LdapSettingNames.Domain); } - public async Task GetUserNameAsync() + public async Task GetUserNameAsync() { return await SettingProvider.GetOrNullAsync(LdapSettingNames.UserName); } - public async Task GetPasswordAsync() + public async Task GetPasswordAsync() { return await SettingProvider.GetOrNullAsync(LdapSettingNames.Password); } diff --git a/framework/src/Volo.Abp.Localization.Abstractions/Microsoft/Extensions/Localization/AbpStringLocalizerFactoryExtensions.cs b/framework/src/Volo.Abp.Localization.Abstractions/Microsoft/Extensions/Localization/AbpStringLocalizerFactoryExtensions.cs index 8aa2515a54..492372cc30 100644 --- a/framework/src/Volo.Abp.Localization.Abstractions/Microsoft/Extensions/Localization/AbpStringLocalizerFactoryExtensions.cs +++ b/framework/src/Volo.Abp.Localization.Abstractions/Microsoft/Extensions/Localization/AbpStringLocalizerFactoryExtensions.cs @@ -6,15 +6,13 @@ namespace Microsoft.Extensions.Localization; public static class AbpStringLocalizerFactoryExtensions { - [CanBeNull] - public static IStringLocalizer CreateDefaultOrNull(this IStringLocalizerFactory localizerFactory) + public static IStringLocalizer? CreateDefaultOrNull(this IStringLocalizerFactory localizerFactory) { return (localizerFactory as IAbpStringLocalizerFactory) ?.CreateDefaultOrNull(); } - [CanBeNull] - public static IStringLocalizer CreateByResourceNameOrNull( + public static IStringLocalizer? CreateByResourceNameOrNull( this IStringLocalizerFactory localizerFactory, string resourceName) { @@ -36,8 +34,7 @@ public static class AbpStringLocalizerFactoryExtensions return localizer; } - [ItemCanBeNull] - public static async Task CreateByResourceNameOrNullAsync( + public static async Task CreateByResourceNameOrNullAsync( this IStringLocalizerFactory localizerFactory, string resourceName) { diff --git a/framework/src/Volo.Abp.Localization.Abstractions/Microsoft/Extensions/Localization/IAbpStringLocalizerFactory.cs b/framework/src/Volo.Abp.Localization.Abstractions/Microsoft/Extensions/Localization/IAbpStringLocalizerFactory.cs index 8f6699a13d..030617583a 100644 --- a/framework/src/Volo.Abp.Localization.Abstractions/Microsoft/Extensions/Localization/IAbpStringLocalizerFactory.cs +++ b/framework/src/Volo.Abp.Localization.Abstractions/Microsoft/Extensions/Localization/IAbpStringLocalizerFactory.cs @@ -5,12 +5,9 @@ namespace Microsoft.Extensions.Localization; public interface IAbpStringLocalizerFactory { - [CanBeNull] - IStringLocalizer CreateDefaultOrNull(); + IStringLocalizer? CreateDefaultOrNull(); - [CanBeNull] - IStringLocalizer CreateByResourceNameOrNull([NotNull] string resourceName); + IStringLocalizer? CreateByResourceNameOrNull([NotNull] string resourceName); - [ItemCanBeNull] - Task CreateByResourceNameOrNullAsync([NotNull] string resourceName); + Task CreateByResourceNameOrNullAsync([NotNull] string resourceName); } diff --git a/framework/src/Volo.Abp.Localization.Abstractions/Volo.Abp.Localization.Abstractions.csproj b/framework/src/Volo.Abp.Localization.Abstractions/Volo.Abp.Localization.Abstractions.csproj index 952d59b739..1fb66c9b7c 100644 --- a/framework/src/Volo.Abp.Localization.Abstractions/Volo.Abp.Localization.Abstractions.csproj +++ b/framework/src/Volo.Abp.Localization.Abstractions/Volo.Abp.Localization.Abstractions.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Localization.Abstractions Volo.Abp.Localization.Abstractions $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/HasNameWithLocalizableDisplayNameExtensions.cs b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/HasNameWithLocalizableDisplayNameExtensions.cs index a73e4a6509..348d5b696b 100644 --- a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/HasNameWithLocalizableDisplayNameExtensions.cs +++ b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/HasNameWithLocalizableDisplayNameExtensions.cs @@ -10,7 +10,7 @@ public static class HasNameWithLocalizableDisplayNameExtensions public static string GetLocalizedDisplayName( [NotNull] this IHasNameWithLocalizableDisplayName source, [NotNull] IStringLocalizerFactory stringLocalizerFactory, - [CanBeNull] string localizationNamePrefix = "DisplayName:") + string? localizationNamePrefix = "DisplayName:") { if (source.DisplayName != null) { diff --git a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/IHasNameWithLocalizableDisplayName.cs b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/IHasNameWithLocalizableDisplayName.cs index f582a31379..de29047ddf 100644 --- a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/IHasNameWithLocalizableDisplayName.cs +++ b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/IHasNameWithLocalizableDisplayName.cs @@ -7,6 +7,5 @@ public interface IHasNameWithLocalizableDisplayName [NotNull] public string Name { get; } - [CanBeNull] - public ILocalizableString DisplayName { get; } + public ILocalizableString? DisplayName { get; } } diff --git a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizableString.cs b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizableString.cs index a98f207a55..038d170f2a 100644 --- a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizableString.cs +++ b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizableString.cs @@ -7,16 +7,14 @@ namespace Volo.Abp.Localization; public class LocalizableString : ILocalizableString, IAsyncLocalizableString { - [CanBeNull] - public string ResourceName { get; } + public string? ResourceName { get; } - [CanBeNull] - public Type ResourceType { get; } + public Type? ResourceType { get; } [NotNull] public string Name { get; } - public LocalizableString([CanBeNull] Type resourceType, [NotNull] string name) + public LocalizableString(Type? resourceType, [NotNull] string name) { Name = Check.NotNullOrEmpty(name, nameof(name)); ResourceType = resourceType; @@ -27,7 +25,7 @@ public class LocalizableString : ILocalizableString, IAsyncLocalizableString } } - public LocalizableString([NotNull] string name, [CanBeNull] string resourceName = null) + public LocalizableString([NotNull] string name, string? resourceName = null) { Name = Check.NotNullOrEmpty(name, nameof(name)); ResourceName = resourceName; @@ -79,7 +77,7 @@ public class LocalizableString : ILocalizableString, IAsyncLocalizableString return result; } - private IStringLocalizer CreateStringLocalizerOrNull(IStringLocalizerFactory stringLocalizerFactory) + private IStringLocalizer? CreateStringLocalizerOrNull(IStringLocalizerFactory stringLocalizerFactory) { if (ResourceType != null) { @@ -98,7 +96,7 @@ public class LocalizableString : ILocalizableString, IAsyncLocalizableString return stringLocalizerFactory.CreateDefaultOrNull(); } - private async Task CreateStringLocalizerOrNullAsync(IStringLocalizerFactory stringLocalizerFactory) + private async Task CreateStringLocalizerOrNullAsync(IStringLocalizerFactory stringLocalizerFactory) { if (ResourceType != null) { @@ -127,7 +125,7 @@ public class LocalizableString : ILocalizableString, IAsyncLocalizableString return new LocalizableString(resourceType, name); } - public static LocalizableString Create([NotNull] string name, [CanBeNull] string resourceName = null) + public static LocalizableString Create([NotNull] string name, string? resourceName = null) { return new LocalizableString(name, resourceName); } diff --git a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizationResourceNameAttribute.cs b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizationResourceNameAttribute.cs index 303214393b..6657ba5d2e 100644 --- a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizationResourceNameAttribute.cs +++ b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/LocalizationResourceNameAttribute.cs @@ -12,7 +12,7 @@ public class LocalizationResourceNameAttribute : Attribute Name = name; } - public static LocalizationResourceNameAttribute GetOrNull(Type resourceType) + public static LocalizationResourceNameAttribute? GetOrNull(Type resourceType) { return resourceType .GetCustomAttributes(true) @@ -22,6 +22,6 @@ public class LocalizationResourceNameAttribute : Attribute public static string GetName(Type resourceType) { - return GetOrNull(resourceType)?.Name ?? resourceType.FullName; + return (GetOrNull(resourceType)?.Name ?? resourceType.FullName)!; } } diff --git a/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj b/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj index 8b889e2057..f4c5c4ece2 100644 --- a/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj +++ b/framework/src/Volo.Abp.Localization/Volo.Abp.Localization.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Localization Volo.Abp.Localization $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpDictionaryBasedStringLocalizer.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpDictionaryBasedStringLocalizer.cs index cf5c1ebb82..86133cdf17 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpDictionaryBasedStringLocalizer.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpDictionaryBasedStringLocalizer.cs @@ -118,7 +118,7 @@ public class AbpDictionaryBasedStringLocalizer : IAbpStringLocalizer return value; } - protected virtual LocalizedString GetLocalizedStringOrNull( + protected virtual LocalizedString? GetLocalizedStringOrNull( string name, string cultureName, bool tryDefaults = true) @@ -153,7 +153,7 @@ public class AbpDictionaryBasedStringLocalizer : IAbpStringLocalizer //Try to get from default language if (!Resource.DefaultCultureName.IsNullOrEmpty()) { - var strDefault = Resource.Contributors.GetOrNull(Resource.DefaultCultureName, name); + var strDefault = Resource.Contributors.GetOrNull(Resource.DefaultCultureName!, name); if (strDefault != null) { return strDefault; @@ -208,7 +208,7 @@ public class AbpDictionaryBasedStringLocalizer : IAbpStringLocalizer //Fill all strings from default culture if (!Resource.DefaultCultureName.IsNullOrEmpty()) { - Resource.Contributors.Fill(Resource.DefaultCultureName, allStrings, includeDynamicContributors); + Resource.Contributors.Fill(Resource.DefaultCultureName!, allStrings, includeDynamicContributors); } //Overwrite all strings from the language based on country culture @@ -268,7 +268,7 @@ public class AbpDictionaryBasedStringLocalizer : IAbpStringLocalizer if (!Resource.DefaultCultureName.IsNullOrEmpty()) { await Resource.Contributors.FillAsync( - Resource.DefaultCultureName, + Resource.DefaultCultureName!, allStrings, includeDynamicContributors ); diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpEnumLocalizer.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpEnumLocalizer.cs index 3fc053da6a..b2acb3d072 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpEnumLocalizer.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpEnumLocalizer.cs @@ -19,14 +19,14 @@ public class AbpEnumLocalizer : IAbpEnumLocalizer, ITransientDependency return GetStringInternal(enumType, enumValue, StringLocalizerFactory.CreateDefaultOrNull()); } - public virtual string GetString(Type enumType, object enumValue, params IStringLocalizer[] specifyLocalizers) + public virtual string GetString(Type enumType, object enumValue, params IStringLocalizer?[] specifyLocalizers) { return GetStringInternal(enumType, enumValue, specifyLocalizers); } - protected virtual string GetStringInternal(Type enumType, object enumValue, params IStringLocalizer[] specifyLocalizers) + protected virtual string GetStringInternal(Type enumType, object enumValue, params IStringLocalizer?[] specifyLocalizers) { - var memberName = enumType.GetEnumName(enumValue); + var memberName = enumType.GetEnumName(enumValue)!; var localizedString = GetStringOrNull( specifyLocalizers, new[] @@ -42,7 +42,7 @@ public class AbpEnumLocalizer : IAbpEnumLocalizer, ITransientDependency return localizedString ?? memberName; } - protected virtual string GetStringOrNull(IStringLocalizer[] localizers, IEnumerable keys) + protected virtual string? GetStringOrNull(IStringLocalizer?[] localizers, IEnumerable keys) { foreach (var key in keys) { diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptions.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptions.cs index 5228f886e9..0fd9d47ac8 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptions.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationOptions.cs @@ -11,7 +11,7 @@ public class AbpLocalizationOptions /// /// Used as the default resource when resource was not specified on a localization operation. /// - public Type DefaultResourceType { get; set; } + public Type? DefaultResourceType { get; set; } public ITypeList GlobalContributors { get; } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerExtensions.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerExtensions.cs index 9b3bb2c201..91c7126a97 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerExtensions.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerExtensions.cs @@ -35,7 +35,7 @@ public static class AbpStringLocalizerExtensions throw new AbpException($"Could not find the _localizer field inside the {typeof(StringLocalizer<>).FullName} class. Probably its name has changed. Please report this issue to the ABP framework."); } - return localizerField.GetValue(stringLocalizer) as IStringLocalizer; + return (localizerField.GetValue(stringLocalizer) as IStringLocalizer)!; } public static IEnumerable GetAllStrings( diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerFactory.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerFactory.cs index b89a54abd9..f40385c128 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerFactory.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerFactory.cs @@ -52,12 +52,12 @@ public class AbpStringLocalizerFactory : IStringLocalizerFactory, IAbpStringLoca return CreateInternal(resource.ResourceName, resource, lockCache); } - public IStringLocalizer CreateByResourceNameOrNull(string resourceName) + public IStringLocalizer? CreateByResourceNameOrNull(string resourceName) { return CreateByResourceNameOrNullInternal(resourceName, lockCache: true); } - private IStringLocalizer CreateByResourceNameOrNullInternal( + private IStringLocalizer? CreateByResourceNameOrNullInternal( string resourceName, bool lockCache) { @@ -74,12 +74,12 @@ public class AbpStringLocalizerFactory : IStringLocalizerFactory, IAbpStringLoca return CreateInternal(resourceName, resource, lockCache); } - public Task CreateByResourceNameOrNullAsync(string resourceName) + public Task CreateByResourceNameOrNullAsync(string resourceName) { return CreateByResourceNameOrNullInternalAsync(resourceName, lockCache: true); } - private async Task CreateByResourceNameOrNullInternalAsync( + private async Task CreateByResourceNameOrNullInternalAsync( string resourceName, bool lockCache) { @@ -175,7 +175,7 @@ public class AbpStringLocalizerFactory : IStringLocalizerFactory, IAbpStringLoca { resource.Contributors.Add( Activator - .CreateInstance(globalContributorType) + .CreateInstance(globalContributorType)! .As() ); } @@ -194,7 +194,7 @@ public class AbpStringLocalizerFactory : IStringLocalizerFactory, IAbpStringLoca .BaseResourceNames .Select(x => CreateByResourceNameOrNullInternal(x, lockCache: false)) .Where(x => x != null) - .ToList(), + .ToList()!, AbpLocalizationOptions ) ); @@ -206,7 +206,7 @@ public class AbpStringLocalizerFactory : IStringLocalizerFactory, IAbpStringLoca { resource.Contributors.Add( Activator - .CreateInstance(globalContributorType) + .CreateInstance(globalContributorType)! .As() ); } @@ -259,7 +259,7 @@ public class AbpStringLocalizerFactory : IStringLocalizerFactory, IAbpStringLoca } } - public IStringLocalizer CreateDefaultOrNull() + public IStringLocalizer? CreateDefaultOrNull() { if (AbpLocalizationOptions.DefaultResourceType == null) { diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/External/IExternalLocalizationStore.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/External/IExternalLocalizationStore.cs index cd48bb1bd9..c2aa55cd2f 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/External/IExternalLocalizationStore.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/External/IExternalLocalizationStore.cs @@ -5,11 +5,9 @@ namespace Volo.Abp.Localization.External; public interface IExternalLocalizationStore { - [CanBeNull] - LocalizationResourceBase GetResourceOrNull([NotNull] string resourceName); + LocalizationResourceBase? GetResourceOrNull([NotNull] string resourceName); - [ItemCanBeNull] - Task GetResourceOrNullAsync([NotNull] string resourceName); + Task GetResourceOrNullAsync([NotNull] string resourceName); Task GetResourceNamesAsync(); diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/External/NullExternalLocalizationStore.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/External/NullExternalLocalizationStore.cs index 508f947981..891beba134 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/External/NullExternalLocalizationStore.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/External/NullExternalLocalizationStore.cs @@ -6,14 +6,14 @@ namespace Volo.Abp.Localization.External; public class NullExternalLocalizationStore : IExternalLocalizationStore, ISingletonDependency { - public LocalizationResourceBase GetResourceOrNull(string resourceName) + public LocalizationResourceBase? GetResourceOrNull(string resourceName) { return null; } - public Task GetResourceOrNullAsync(string resourceName) + public Task GetResourceOrNullAsync(string resourceName) { - return Task.FromResult(null); + return Task.FromResult(null); } public Task GetResourceNamesAsync() diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILanguageInfo.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILanguageInfo.cs index d4e06e9af5..e8ae6935de 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILanguageInfo.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILanguageInfo.cs @@ -8,5 +8,5 @@ public interface ILanguageInfo string DisplayName { get; } - string FlagIcon { get; } + string? FlagIcon { get; } } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizableStringSerializer.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizableStringSerializer.cs index 6f7a487b6c..7d068b9494 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizableStringSerializer.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizableStringSerializer.cs @@ -2,7 +2,7 @@ public interface ILocalizableStringSerializer { - string Serialize(ILocalizableString localizableString); + string? Serialize(ILocalizableString localizableString); ILocalizableString Deserialize(string value); } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationDictionary.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationDictionary.cs index d5fcab206b..e6879c0007 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationDictionary.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationDictionary.cs @@ -10,7 +10,7 @@ public interface ILocalizationDictionary { string CultureName { get; } - LocalizedString GetOrNull(string name); + LocalizedString? GetOrNull(string name); void Fill(Dictionary dictionary); } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationResourceContributor.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationResourceContributor.cs index 2a79d20821..2d3ade519f 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationResourceContributor.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationResourceContributor.cs @@ -10,7 +10,7 @@ public interface ILocalizationResourceContributor void Initialize(LocalizationResourceInitializationContext context); - LocalizedString GetOrNull(string cultureName, string name); + LocalizedString? GetOrNull(string cultureName, string name); void Fill(string cultureName, Dictionary dictionary); diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs index 04ec79aaf6..e4b66148a5 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Text.Json; -using JetBrains.Annotations; using Microsoft.Extensions.Localization; namespace Volo.Abp.Localization.Json; @@ -13,8 +12,7 @@ public static class JsonLocalizationDictionaryBuilder /// Builds an from given file. /// /// Path of the file - [CanBeNull] - public static ILocalizationDictionary BuildFromFile(string filePath) + public static ILocalizationDictionary? BuildFromFile(string filePath) { try { @@ -38,10 +36,9 @@ public static class JsonLocalizationDictionaryBuilder /// Builds an from given json string. /// /// Json string - [CanBeNull] - public static ILocalizationDictionary BuildFromJsonString(string jsonString) + public static ILocalizationDictionary? BuildFromJsonString(string jsonString) { - JsonLocalizationFile jsonFile; + JsonLocalizationFile? jsonFile; try { jsonFile = JsonSerializer.Deserialize(jsonString, DeserializeOptions); @@ -50,6 +47,11 @@ public static class JsonLocalizationDictionaryBuilder { throw new AbpException("Can not parse json string. " + ex.Message); } + + if (jsonFile == null) + { + return null; + } var cultureCode = jsonFile.Culture; if (string.IsNullOrEmpty(cultureCode)) diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs index 08daf70682..8470e2696f 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs @@ -7,7 +7,7 @@ public class JsonLocalizationFile /// /// Culture name; eg : en , en-us, zh-CN /// - public string Culture { get; set; } + public string Culture { get; set; } = default!; public Dictionary Texts { get; set; } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfo.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfo.cs index 9183b89c4e..a2274b5a69 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfo.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfo.cs @@ -8,19 +8,18 @@ namespace Volo.Abp.Localization; public class LanguageInfo : ILanguageInfo { [NotNull] - public virtual string CultureName { get; protected set; } + public virtual string CultureName { get; protected set; } = default!; [NotNull] - public virtual string UiCultureName { get; protected set; } + public virtual string UiCultureName { get; protected set; } = default!; [NotNull] - public virtual string DisplayName { get; protected set; } + public virtual string DisplayName { get; protected set; } = default!; [NotNull] - public virtual string TwoLetterISOLanguageName { get; protected set; } + public virtual string TwoLetterISOLanguageName { get; protected set; } = default!; - [CanBeNull] - public virtual string FlagIcon { get; set; } + public virtual string? FlagIcon { get; set; } protected LanguageInfo() @@ -30,30 +29,30 @@ public class LanguageInfo : ILanguageInfo public LanguageInfo( string cultureName, - string uiCultureName = null, - string displayName = null, - string flagIcon = null) + string? uiCultureName = null, + string? displayName = null, + string? flagIcon = null) { ChangeCultureInternal(cultureName, uiCultureName, displayName); FlagIcon = flagIcon; } - public virtual void ChangeCulture(string cultureName, string uiCultureName = null, string displayName = null) + public virtual void ChangeCulture(string cultureName, string? uiCultureName = null, string? displayName = null) { ChangeCultureInternal(cultureName, uiCultureName, displayName); } - private void ChangeCultureInternal(string cultureName, string uiCultureName, string displayName) + private void ChangeCultureInternal(string cultureName, string? uiCultureName, string? displayName) { CultureName = Check.NotNullOrWhiteSpace(cultureName, nameof(cultureName)); - UiCultureName = !uiCultureName.IsNullOrWhiteSpace() + UiCultureName = (!uiCultureName.IsNullOrWhiteSpace() ? uiCultureName - : cultureName; + : cultureName)!; - DisplayName = !displayName.IsNullOrWhiteSpace() + DisplayName = (!displayName.IsNullOrWhiteSpace() ? displayName - : cultureName; + : cultureName)!; TwoLetterISOLanguageName = new CultureInfo(cultureName) .TwoLetterISOLanguageName; diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfoExtensions.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfoExtensions.cs index 8909708b67..7b60cce40d 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfoExtensions.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfoExtensions.cs @@ -6,10 +6,10 @@ namespace Volo.Abp.Localization; public static class LanguageInfoExtensions { - public static T FindByCulture( + public static T? FindByCulture( [NotNull] this IEnumerable languages, [NotNull] string cultureName, - [CanBeNull] string uiCultureName = null) + string? uiCultureName = null) where T : class, ILanguageInfo { if (uiCultureName == null) diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizableStringSerializer.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizableStringSerializer.cs index 5006d62ea8..02b9cc8fac 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizableStringSerializer.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizableStringSerializer.cs @@ -13,7 +13,7 @@ public class LocalizableStringSerializer : ILocalizableStringSerializer, ITransi LocalizationOptions = localizationOptions.Value; } - public virtual string Serialize(ILocalizableString localizableString) + public virtual string? Serialize(ILocalizableString? localizableString) { if (localizableString == null) { diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResource.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResource.cs index 7a55f1f8a3..b6e0da82e4 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResource.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResource.cs @@ -12,8 +12,8 @@ public class LocalizationResource : LocalizationResourceBase public LocalizationResource( [NotNull] Type resourceType, - [CanBeNull] string defaultCultureName = null, - [CanBeNull] ILocalizationResourceContributor initialContributor = null) + string? defaultCultureName = null, + ILocalizationResourceContributor? initialContributor = null) : base( LocalizationResourceNameAttribute.GetName(resourceType), defaultCultureName, diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceBase.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceBase.cs index a7ec4fb93b..6cbbd98188 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceBase.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceBase.cs @@ -10,16 +10,15 @@ public abstract class LocalizationResourceBase public List BaseResourceNames { get; } - [CanBeNull] - public string DefaultCultureName { get; set; } + public string? DefaultCultureName { get; set; } [NotNull] public LocalizationResourceContributorList Contributors { get; } public LocalizationResourceBase( [NotNull] string resourceName, - [CanBeNull] string defaultCultureName = null, - [CanBeNull] ILocalizationResourceContributor initialContributor = null) + string? defaultCultureName = null, + ILocalizationResourceContributor? initialContributor = null) { ResourceName = Check.NotNullOrWhiteSpace(resourceName, nameof(resourceName)); DefaultCultureName = defaultCultureName; diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceContributorList.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceContributorList.cs index 6df15920da..9f11aa4051 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceContributorList.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceContributorList.cs @@ -7,7 +7,7 @@ namespace Volo.Abp.Localization; public class LocalizationResourceContributorList : List { - public LocalizedString GetOrNull( + public LocalizedString? GetOrNull( string cultureName, string name, bool includeDynamicContributors = true) diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceDictionary.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceDictionary.cs index 4a88eac199..f6487a85b7 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceDictionary.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResourceDictionary.cs @@ -8,12 +8,12 @@ public class LocalizationResourceDictionary : Dictionary _resourcesByTypes = new(); - public LocalizationResource Add([CanBeNull] string defaultCultureName = null) + public LocalizationResource Add(string? defaultCultureName = null) { return Add(typeof(TResouce), defaultCultureName); } - public LocalizationResource Add(Type resourceType, [CanBeNull] string defaultCultureName = null) + public LocalizationResource Add(Type resourceType, string? defaultCultureName = null) { var resourceName = LocalizationResourceNameAttribute.GetName(resourceType); if (ContainsKey(resourceName)) @@ -29,7 +29,7 @@ public class LocalizationResourceDictionary : Dictionary - public virtual LocalizedString GetOrNull(string name) + public virtual LocalizedString? GetOrNull(string name) { return Dictionary.GetOrDefault(name); } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/Json/JsonVirtualFileLocalizationResourceContributor.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/Json/JsonVirtualFileLocalizationResourceContributor.cs index fcafed49f3..71ca2744a0 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/Json/JsonVirtualFileLocalizationResourceContributor.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/Json/JsonVirtualFileLocalizationResourceContributor.cs @@ -19,7 +19,7 @@ public class JsonVirtualFileLocalizationResourceContributor : VirtualFileLocaliz return file.Name.EndsWith(".json", StringComparison.OrdinalIgnoreCase); } - protected override ILocalizationDictionary CreateDictionaryFromFileContent(string jsonString) + protected override ILocalizationDictionary? CreateDictionaryFromFileContent(string jsonString) { return JsonLocalizationDictionaryBuilder.BuildFromJsonString(jsonString); } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs index 40bb9de7c5..d87169ea31 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs @@ -16,11 +16,11 @@ public abstract class VirtualFileLocalizationResourceContributorBase : ILocaliza public bool IsDynamic => false; private readonly string _virtualPath; - private IVirtualFileProvider _virtualFileProvider; - private Dictionary _dictionaries; + private IVirtualFileProvider _virtualFileProvider = default!; + private Dictionary? _dictionaries; private bool _subscribedForChanges; private readonly object _syncObj = new object(); - private LocalizationResourceBase _resource; + private LocalizationResourceBase _resource = default!; protected VirtualFileLocalizationResourceContributorBase(string virtualPath) { @@ -33,7 +33,7 @@ public abstract class VirtualFileLocalizationResourceContributorBase : ILocaliza _virtualFileProvider = context.ServiceProvider.GetRequiredService(); } - public virtual LocalizedString GetOrNull(string cultureName, string name) + public virtual LocalizedString? GetOrNull(string cultureName, string name) { return GetDictionaries().GetOrDefault(cultureName)?.GetOrNull(name); } @@ -118,8 +118,7 @@ public abstract class VirtualFileLocalizationResourceContributorBase : ILocaliza protected abstract bool CanParseFile(IFileInfo file); - [CanBeNull] - protected virtual ILocalizationDictionary CreateDictionaryFromFile(IFileInfo file) + protected virtual ILocalizationDictionary? CreateDictionaryFromFile(IFileInfo file) { using (var stream = file.CreateReadStream()) { @@ -127,6 +126,5 @@ public abstract class VirtualFileLocalizationResourceContributorBase : ILocaliza } } - [CanBeNull] - protected abstract ILocalizationDictionary CreateDictionaryFromFileContent(string fileContent); + protected abstract ILocalizationDictionary? CreateDictionaryFromFileContent(string fileContent); } diff --git a/framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj b/framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj index f552541094..9ec0a51e40 100644 --- a/framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj +++ b/framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Minify Volo.Abp.Minify $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/IMinifier.cs b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/IMinifier.cs index 4f816a2f48..4c4f1881da 100644 --- a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/IMinifier.cs +++ b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/IMinifier.cs @@ -6,6 +6,6 @@ public interface IMinifier { string Minify( string source, - [CanBeNull] string fileName = null, - [CanBeNull] string originalFileName = null); + string? fileName = null, + string? originalFileName = null); } diff --git a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyCssMinifier.cs b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyCssMinifier.cs index 281f5c6aa3..d2f78d95d6 100644 --- a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyCssMinifier.cs +++ b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyCssMinifier.cs @@ -5,7 +5,7 @@ namespace Volo.Abp.Minify.NUglify; public class NUglifyCssMinifier : NUglifyMinifierBase, ICssMinifier { - protected override UglifyResult UglifySource(string source, string fileName) + protected override UglifyResult UglifySource(string source, string? fileName) { return Uglify.Css(source, fileName); } diff --git a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyException.cs b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyException.cs index 6b4d68b07e..bf623771d3 100644 --- a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyException.cs +++ b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyException.cs @@ -7,7 +7,7 @@ namespace Volo.Abp.Minify.NUglify; public class NUglifyException : AbpException { - public List Errors { get; set; } + public List? Errors { get; set; } public NUglifyException(string message, List errors) : base(message) diff --git a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyHtmlMinifier.cs b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyHtmlMinifier.cs index dc8bbe22ea..6698b3cdd0 100644 --- a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyHtmlMinifier.cs +++ b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyHtmlMinifier.cs @@ -5,7 +5,7 @@ namespace Volo.Abp.Minify.NUglify; public class NUglifyHtmlMinifier : NUglifyMinifierBase, IHtmlMinifier { - protected override UglifyResult UglifySource(string source, string fileName) + protected override UglifyResult UglifySource(string source, string? fileName) { return Uglify.Html(source, sourceFileName: fileName); } diff --git a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyJavascriptMinifier.cs b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyJavascriptMinifier.cs index 5b8fa54ce3..6c13d00129 100644 --- a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyJavascriptMinifier.cs +++ b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyJavascriptMinifier.cs @@ -5,7 +5,7 @@ namespace Volo.Abp.Minify.NUglify; public class NUglifyJavascriptMinifier : NUglifyMinifierBase, IJavascriptMinifier { - protected override UglifyResult UglifySource(string source, string fileName) + protected override UglifyResult UglifySource(string source, string? fileName) { return Uglify.Js(source, fileName); } diff --git a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyMinifierBase.cs b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyMinifierBase.cs index d5018a1b28..28e0267e17 100644 --- a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyMinifierBase.cs +++ b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyMinifierBase.cs @@ -8,7 +8,7 @@ namespace Volo.Abp.Minify.NUglify; public abstract class NUglifyMinifierBase : IMinifier, ITransientDependency { - private static void CheckErrors(UglifyResult result, string originalFileName) + private static void CheckErrors(UglifyResult result, string? originalFileName) { if (result.HasErrors) { @@ -28,8 +28,8 @@ public abstract class NUglifyMinifierBase : IMinifier, ITransientDependency public string Minify( string source, - string fileName = null, - string originalFileName = null) + string? fileName = null, + string? originalFileName = null) { try { @@ -50,5 +50,5 @@ public abstract class NUglifyMinifierBase : IMinifier, ITransientDependency } } - protected abstract UglifyResult UglifySource(string source, string fileName); + protected abstract UglifyResult UglifySource(string source, string? fileName); } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IncomingEventRecord.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IncomingEventRecord.cs index 22c1d860d1..e6ddc87bd6 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IncomingEventRecord.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/IncomingEventRecord.cs @@ -48,13 +48,20 @@ public class IncomingEventRecord : public IncomingEventInfo ToIncomingEventInfo() { - return new IncomingEventInfo( + var info = new IncomingEventInfo( Id, MessageId, EventName, EventData, CreationTime ); + + foreach (var property in ExtraProperties) + { + info.SetProperty(property.Key, property.Value); + } + + return info; } public void MarkAsProcessed(DateTime processedTime) diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/OutgoingEventRecord.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/OutgoingEventRecord.cs index 15dfac38f6..0f0798532b 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/OutgoingEventRecord.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/OutgoingEventRecord.cs @@ -41,11 +41,18 @@ public class OutgoingEventRecord : public OutgoingEventInfo ToOutgoingEventInfo() { - return new OutgoingEventInfo( + var info = new OutgoingEventInfo( Id, EventName, EventData, CreationTime ); + + foreach (var property in ExtraProperties) + { + info.SetProperty(property.Key, property.Value); + } + + return info; } } diff --git a/framework/src/Volo.Abp.MultiLingualObjects/Volo.Abp.MultiLingualObjects.csproj b/framework/src/Volo.Abp.MultiLingualObjects/Volo.Abp.MultiLingualObjects.csproj index 54c8469153..5b45ea638f 100644 --- a/framework/src/Volo.Abp.MultiLingualObjects/Volo.Abp.MultiLingualObjects.csproj +++ b/framework/src/Volo.Abp.MultiLingualObjects/Volo.Abp.MultiLingualObjects.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.MultiLingualObject $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; false diff --git a/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager.cs b/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager.cs index 908431e997..c41605ad0e 100644 --- a/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager.cs +++ b/framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager.cs @@ -1,97 +1,97 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Localization; -using Volo.Abp.Settings; - -namespace Volo.Abp.MultiLingualObjects; - -public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientDependency -{ - protected ISettingProvider SettingProvider { get; } - - protected const int MaxCultureFallbackDepth = 5; - - public MultiLingualObjectManager(ISettingProvider settingProvider) - { - SettingProvider = settingProvider; - } - public virtual async Task GetTranslationAsync( - IEnumerable translations, - string? culture, - bool fallbackToParentCultures) - where TTranslation : class, IObjectTranslation - - { - culture ??= CultureInfo.CurrentUICulture.Name; - - if (translations == null || !translations.Any()) - { - return null; - } - - var translation = translations.FirstOrDefault(pt => pt.Language == culture); - if (translation != null) - { - return translation; - } - - if (fallbackToParentCultures) - { - translation = GetTranslationBasedOnCulturalRecursive( - CultureInfo.CurrentUICulture.Parent, - translations, - 0 - ); - - if (translation != null) - { - return translation; - } - } - - var defaultLanguage = await SettingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage); - - translation = translations.FirstOrDefault(pt => pt.Language == defaultLanguage); - if (translation != null) - { - return translation; - } - - translation = translations.FirstOrDefault(); - return translation; - } - - public virtual Task GetTranslationAsync( - TMultiLingual multiLingual, - string? culture = null, - bool fallbackToParentCultures = true) - where TMultiLingual : IMultiLingualObject - where TTranslation : class, IObjectTranslation - { - return GetTranslationAsync(multiLingual.Translations, culture: culture, fallbackToParentCultures: fallbackToParentCultures); - } - - protected virtual TTranslation? GetTranslationBasedOnCulturalRecursive( - CultureInfo culture, IEnumerable translations, int currentDepth) - where TTranslation : class, IObjectTranslation - { - if (culture == null || - culture.Name.IsNullOrWhiteSpace() || - translations == null || !translations.Any() || - currentDepth > MaxCultureFallbackDepth) - { - return null; - } - - var translation = translations.FirstOrDefault(pt => pt.Language.Equals(culture.Name, StringComparison.OrdinalIgnoreCase)); - return translation ?? GetTranslationBasedOnCulturalRecursive(culture.Parent, translations, currentDepth + 1); +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Localization; +using Volo.Abp.Settings; + +namespace Volo.Abp.MultiLingualObjects; + +public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientDependency +{ + protected ISettingProvider SettingProvider { get; } + + protected const int MaxCultureFallbackDepth = 5; + + public MultiLingualObjectManager(ISettingProvider settingProvider) + { + SettingProvider = settingProvider; + } + public virtual async Task GetTranslationAsync( + IEnumerable? translations, + string? culture, + bool fallbackToParentCultures) + where TTranslation : class, IObjectTranslation + + { + culture ??= CultureInfo.CurrentUICulture.Name; + + if (translations == null || !translations.Any()) + { + return null; + } + + var translation = translations.FirstOrDefault(pt => pt.Language == culture); + if (translation != null) + { + return translation; + } + + if (fallbackToParentCultures) + { + translation = GetTranslationBasedOnCulturalRecursive( + CultureInfo.CurrentUICulture.Parent, + translations, + 0 + ); + + if (translation != null) + { + return translation; + } + } + + var defaultLanguage = await SettingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage); + + translation = translations.FirstOrDefault(pt => pt.Language == defaultLanguage); + if (translation != null) + { + return translation; + } + + translation = translations.FirstOrDefault(); + return translation; + } + + public virtual Task GetTranslationAsync( + TMultiLingual multiLingual, + string? culture = null, + bool fallbackToParentCultures = true) + where TMultiLingual : IMultiLingualObject + where TTranslation : class, IObjectTranslation + { + return GetTranslationAsync(multiLingual.Translations, culture: culture, fallbackToParentCultures: fallbackToParentCultures); + } + + protected virtual TTranslation? GetTranslationBasedOnCulturalRecursive( + CultureInfo? culture, IEnumerable? translations, int currentDepth) + where TTranslation : class, IObjectTranslation + { + if (culture == null || + culture.Name.IsNullOrWhiteSpace() || + translations == null || !translations.Any() || + currentDepth > MaxCultureFallbackDepth) + { + return null; + } + + var translation = translations.FirstOrDefault(pt => pt.Language.Equals(culture.Name, StringComparison.OrdinalIgnoreCase)); + return translation ?? GetTranslationBasedOnCulturalRecursive(culture.Parent, translations, currentDepth + 1); } - public virtual async Task> GetBulkTranslationsAsync(IEnumerable> translationsCombined, string? culture, bool fallbackToParentCultures) + public virtual async Task> GetBulkTranslationsAsync(IEnumerable>? translationsCombined, string? culture, bool fallbackToParentCultures) where TTranslation : class, IObjectTranslation { culture ??= CultureInfo.CurrentUICulture.Name; @@ -180,7 +180,7 @@ public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientD } public virtual async Task> GetBulkTranslationsAsync(IEnumerable multiLinguals, string? culture, bool fallbackToParentCultures) - where TMultiLingual : IMultiLingualObject + where TMultiLingual : IMultiLingualObject where TTranslation : class, IObjectTranslation { var resInitial = await GetBulkTranslationsAsync(multiLinguals.Select(x => x.Translations), culture, fallbackToParentCultures); @@ -193,4 +193,4 @@ public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientD } return res; } -} +} diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo.Abp.ObjectExtending.csproj b/framework/src/Volo.Abp.ObjectExtending/Volo.Abp.ObjectExtending.csproj index de9711ff6a..e427f154c7 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo.Abp.ObjectExtending.csproj +++ b/framework/src/Volo.Abp.ObjectExtending/Volo.Abp.ObjectExtending.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.ObjectExtending Volo.Abp.ObjectExtending $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/ExtraPropertyDictionaryExtensions.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/ExtraPropertyDictionaryExtensions.cs index d5de504afc..6c4cd02d1b 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/ExtraPropertyDictionaryExtensions.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/ExtraPropertyDictionaryExtensions.cs @@ -13,7 +13,7 @@ public static class ExtraPropertyDictionaryExtensions return (T)extraPropertyDictionary[key]; } - extraPropertyDictionary[key] = Enum.Parse(typeof(T), extraPropertyDictionary[key].ToString(), ignoreCase: true); + extraPropertyDictionary[key] = Enum.Parse(typeof(T), extraPropertyDictionary[key].ToString()!, ignoreCase: true); return (T)extraPropertyDictionary[key]; } @@ -24,7 +24,7 @@ public static class ExtraPropertyDictionaryExtensions return extraPropertyDictionary[key]; } - extraPropertyDictionary[key] = Enum.Parse(enumType, extraPropertyDictionary[key].ToString(), ignoreCase: true); + extraPropertyDictionary[key] = Enum.Parse(enumType, extraPropertyDictionary[key].ToString()!, ignoreCase: true); return extraPropertyDictionary[key]; } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/HasExtraPropertiesExtensions.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/HasExtraPropertiesExtensions.cs index 2e32a1b7dc..7423052772 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/HasExtraPropertiesExtensions.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/Data/HasExtraPropertiesExtensions.cs @@ -18,13 +18,13 @@ public static class HasExtraPropertiesExtensions return source.ExtraProperties.ContainsKey(name); } - public static object GetProperty(this IHasExtraProperties source, string name, object defaultValue = null) + public static object? GetProperty(this IHasExtraProperties source, string name, object? defaultValue = null) { return source.ExtraProperties?.GetOrDefault(name) ?? defaultValue; } - public static TProperty GetProperty(this IHasExtraProperties source, string name, TProperty defaultValue = default) + public static TProperty? GetProperty(this IHasExtraProperties source, string name, TProperty? defaultValue = default) { var value = source.GetProperty(name); if (value == null) @@ -42,7 +42,7 @@ public static class HasExtraPropertiesExtensions if (conversionType == typeof(Guid)) { - return (TProperty)TypeDescriptor.GetConverter(conversionType).ConvertFromInvariantString(value.ToString()); + return (TProperty)TypeDescriptor.GetConverter(conversionType).ConvertFromInvariantString(value.ToString()!)!; } if (conversionType.IsEnum) @@ -80,7 +80,7 @@ public static class HasExtraPropertiesExtensions return source; } - public static TSource SetDefaultsForExtraProperties(this TSource source, Type objectType = null) + public static TSource SetDefaultsForExtraProperties(this TSource source, Type? objectType = null) where TSource : IHasExtraProperties { if (objectType == null) @@ -98,7 +98,7 @@ public static class HasExtraPropertiesExtensions continue; } - source.ExtraProperties[property.Name] = property.GetDefaultValue(); + source.ExtraProperties[property.Name] = property.GetDefaultValue()!; } return source; diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs index 2de527866b..fbf277c55b 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectMapper.cs @@ -27,7 +27,7 @@ public static class ExtensibleObjectMapper [NotNull] TSource source, [NotNull] TDestination destination, MappingPropertyDefinitionChecks? definitionChecks = null, - string[] ignoredProperties = null) + string[]? ignoredProperties = null) where TSource : IHasExtraProperties where TDestination : IHasExtraProperties { @@ -78,7 +78,7 @@ public static class ExtensibleObjectMapper [NotNull] Dictionary sourceDictionary, [NotNull] Dictionary destinationDictionary, MappingPropertyDefinitionChecks? definitionChecks = null, - string[] ignoredProperties = null) + string[]? ignoredProperties = null) where TSource : IHasExtraProperties where TDestination : IHasExtraProperties { @@ -113,7 +113,7 @@ public static class ExtensibleObjectMapper [NotNull] Dictionary sourceDictionary, [NotNull] Dictionary destinationDictionary, MappingPropertyDefinitionChecks? definitionChecks = null, - string[] ignoredProperties = null) + string[]? ignoredProperties = null) { Check.AssignableTo(sourceType, nameof(sourceType)); Check.AssignableTo(destinationType, nameof(destinationType)); @@ -140,7 +140,7 @@ public static class ExtensibleObjectMapper public static bool CanMapProperty( [NotNull] string propertyName, MappingPropertyDefinitionChecks? definitionChecks = null, - string[] ignoredProperties = null) + string[]? ignoredProperties = null) { return CanMapProperty( typeof(TSource), @@ -156,7 +156,7 @@ public static class ExtensibleObjectMapper [NotNull] Type destinationType, [NotNull] string propertyName, MappingPropertyDefinitionChecks? definitionChecks = null, - string[] ignoredProperties = null) + string[]? ignoredProperties = null) { Check.AssignableTo(sourceType, nameof(sourceType)); Check.AssignableTo(destinationType, nameof(destinationType)); @@ -175,10 +175,10 @@ public static class ExtensibleObjectMapper private static bool CanMapProperty( [NotNull] string propertyName, - [CanBeNull] ObjectExtensionInfo sourceObjectExtension, - [CanBeNull] ObjectExtensionInfo destinationObjectExtension, + ObjectExtensionInfo? sourceObjectExtension, + ObjectExtensionInfo? destinationObjectExtension, MappingPropertyDefinitionChecks? definitionChecks = null, - string[] ignoredProperties = null) + string[]? ignoredProperties = null) { Check.NotNull(propertyName, nameof(propertyName)); diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectValidator.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectValidator.cs index 8252051fad..09228fe927 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectValidator.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObjectValidator.cs @@ -13,7 +13,7 @@ public static class ExtensibleObjectValidator public static void CheckValue( [NotNull] IHasExtraProperties extensibleObject, [NotNull] string propertyName, - [CanBeNull] object value) + object? value) { var validationErrors = GetValidationErrors( extensibleObject, @@ -29,7 +29,7 @@ public static class ExtensibleObjectValidator public static bool IsValid( [NotNull] IHasExtraProperties extensibleObject, - [CanBeNull] ValidationContext objectValidationContext = null) + ValidationContext? objectValidationContext = null) { return GetValidationErrors( extensibleObject, @@ -40,8 +40,8 @@ public static class ExtensibleObjectValidator public static bool IsValid( [NotNull] IHasExtraProperties extensibleObject, [NotNull] string propertyName, - [CanBeNull] object value, - [CanBeNull] ValidationContext objectValidationContext = null) + object? value, + ValidationContext? objectValidationContext = null) { return GetValidationErrors( extensibleObject, @@ -54,7 +54,7 @@ public static class ExtensibleObjectValidator [NotNull] public static List GetValidationErrors( [NotNull] IHasExtraProperties extensibleObject, - [CanBeNull] ValidationContext objectValidationContext = null) + ValidationContext? objectValidationContext = null) { var validationErrors = new List(); @@ -71,8 +71,8 @@ public static class ExtensibleObjectValidator public static List GetValidationErrors( [NotNull] IHasExtraProperties extensibleObject, [NotNull] string propertyName, - [CanBeNull] object value, - [CanBeNull] ValidationContext objectValidationContext = null) + object? value, + ValidationContext? objectValidationContext = null) { var validationErrors = new List(); @@ -90,7 +90,7 @@ public static class ExtensibleObjectValidator public static void AddValidationErrors( [NotNull] IHasExtraProperties extensibleObject, [NotNull] List validationErrors, - [CanBeNull] ValidationContext objectValidationContext = null) + ValidationContext? objectValidationContext = null) { Check.NotNull(extensibleObject, nameof(extensibleObject)); Check.NotNull(validationErrors, nameof(validationErrors)); @@ -100,7 +100,7 @@ public static class ExtensibleObjectValidator objectValidationContext = new ValidationContext( extensibleObject, null, - new Dictionary() + new Dictionary() ); } @@ -133,8 +133,8 @@ public static class ExtensibleObjectValidator [NotNull] IHasExtraProperties extensibleObject, [NotNull] List validationErrors, [NotNull] string propertyName, - [CanBeNull] object value, - [CanBeNull] ValidationContext objectValidationContext = null) + object? value, + ValidationContext? objectValidationContext = null) { Check.NotNull(extensibleObject, nameof(extensibleObject)); Check.NotNull(validationErrors, nameof(validationErrors)); @@ -145,7 +145,7 @@ public static class ExtensibleObjectValidator objectValidationContext = new ValidationContext( extensibleObject, null, - new Dictionary() + new Dictionary() ); } @@ -203,7 +203,7 @@ public static class ExtensibleObjectValidator List validationErrors, ValidationContext objectValidationContext, ObjectExtensionPropertyInfo property, - object value) + object? value) { AddPropertyValidationAttributeErrors( extensibleObject, @@ -227,7 +227,7 @@ public static class ExtensibleObjectValidator List validationErrors, ValidationContext objectValidationContext, ObjectExtensionPropertyInfo property, - object value) + object? value) { var validationAttributes = property.GetValidationAttributes(); @@ -261,7 +261,7 @@ public static class ExtensibleObjectValidator List validationErrors, ValidationContext objectValidationContext, ObjectExtensionPropertyInfo property, - object value) + object? value) { if (!property.Validators.Any()) { diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensionPropertyHelper.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensionPropertyHelper.cs index d2b6976bf1..89a5e8c87c 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensionPropertyHelper.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensionPropertyHelper.cs @@ -20,10 +20,10 @@ internal static class ExtensionPropertyHelper } } - public static object GetDefaultValue( + public static object? GetDefaultValue( Type propertyType, - Func defaultValueFactory, - object defaultValue) + Func? defaultValueFactory, + object? defaultValue) { if (defaultValueFactory != null) { diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs index 12c6bfb984..d44a900314 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs @@ -24,7 +24,7 @@ public static class HasExtraPropertiesObjectExtendingExtensions [NotNull] this TSource source, [NotNull] TDestination destination, MappingPropertyDefinitionChecks? definitionChecks = null, - string[] ignoredProperties = null) + string[]? ignoredProperties = null) where TSource : IHasExtraProperties where TDestination : IHasExtraProperties { diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/IBasicObjectExtensionPropertyInfo.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/IBasicObjectExtensionPropertyInfo.cs index 8fd6270eda..86f34354a8 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/IBasicObjectExtensionPropertyInfo.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/IBasicObjectExtensionPropertyInfo.cs @@ -20,19 +20,16 @@ public interface IBasicObjectExtensionPropertyInfo [NotNull] public List> Validators { get; } - [CanBeNull] - public ILocalizableString DisplayName { get; } + public ILocalizableString? DisplayName { get; } /// /// Uses as the default value if was not set. /// - [CanBeNull] - public object DefaultValue { get; set; } + public object? DefaultValue { get; set; } /// /// Used with the first priority to create the default value for the property. /// Uses to the if this was not set. /// - [CanBeNull] - public Func DefaultValueFactory { get; set; } + public Func? DefaultValueFactory { get; set; } } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs index 82c6658c23..83429e36ce 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; using JetBrains.Annotations; using Volo.Abp.Localization; @@ -26,7 +27,7 @@ public class EntityExtensionConfiguration [NotNull] public virtual EntityExtensionConfiguration AddOrUpdateProperty( [NotNull] string propertyName, - [CanBeNull] Action configureAction = null) + Action? configureAction = null) { return AddOrUpdateProperty( typeof(TProperty), @@ -39,7 +40,7 @@ public class EntityExtensionConfiguration public virtual EntityExtensionConfiguration AddOrUpdateProperty( [NotNull] Type propertyType, [NotNull] string propertyName, - [CanBeNull] Action configureAction = null) + Action? configureAction = null) { Check.NotNull(propertyType, nameof(propertyType)); Check.NotNull(propertyName, nameof(propertyName)); @@ -74,7 +75,7 @@ public class EntityExtensionConfiguration [NotNull] public virtual ImmutableList GetProperties() { - return Properties.Values.ToImmutableList(); + return Properties.Values.OrderBy(t => t.UI.Order).ToImmutableList(); } private static void NormalizeProperty(ExtensionPropertyConfiguration propertyInfo) diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs index eaad223cfa..8099f1fc14 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs @@ -23,8 +23,7 @@ public class ExtensionPropertyConfiguration : IHasNameWithLocalizableDisplayName [NotNull] public List> Validators { get; } - [CanBeNull] - public ILocalizableString DisplayName { get; set; } + public ILocalizableString? DisplayName { get; set; } [NotNull] public Dictionary Configuration { get; } @@ -49,15 +48,13 @@ public class ExtensionPropertyConfiguration : IHasNameWithLocalizableDisplayName /// /// Uses as the default value if was not set. /// - [CanBeNull] - public object DefaultValue { get; set; } + public object? DefaultValue { get; set; } /// /// Used with the first priority to create the default value for the property. /// Uses to the if this was not set. /// - [CanBeNull] - public Func DefaultValueFactory { get; set; } + public Func? DefaultValueFactory { get; set; } public ExtensionPropertyConfiguration( [NotNull] EntityExtensionConfiguration entityExtensionConfiguration, @@ -80,7 +77,7 @@ public class ExtensionPropertyConfiguration : IHasNameWithLocalizableDisplayName DefaultValue = TypeHelper.GetDefaultValue(Type); } - public object GetDefaultValue() + public object? GetDefaultValue() { return ExtensionPropertyHelper.GetDefaultValue(Type, DefaultValueFactory, DefaultValue); } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfigurationExtensions.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfigurationExtensions.cs index 085e486756..0b826a0ec5 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfigurationExtensions.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfigurationExtensions.cs @@ -5,7 +5,7 @@ namespace Volo.Abp.ObjectExtending.Modularity; public static class ExtensionPropertyConfigurationExtensions { - public static string GetLocalizationResourceNameOrNull( + public static string? GetLocalizationResourceNameOrNull( this ExtensionPropertyConfiguration property) { if (property.DisplayName is LocalizableString localizableString) @@ -16,7 +16,7 @@ public static class ExtensionPropertyConfigurationExtensions return null; } - public static Type GetLocalizationResourceTypeOrNull( + public static Type? GetLocalizationResourceTypeOrNull( this ExtensionPropertyConfiguration property) { if (property.DisplayName is LocalizableString localizableString) diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyLookupConfiguration.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyLookupConfiguration.cs index 599ed7bed5..bd1cb61b20 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyLookupConfiguration.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyLookupConfiguration.cs @@ -4,7 +4,7 @@ namespace Volo.Abp.ObjectExtending.Modularity; public class ExtensionPropertyLookupConfiguration { - public string Url { get; set; } + public string Url { get; set; } = default!; /// /// Default value: "items". diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyUiConfiguration.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyUiConfiguration.cs index 38b47b71ad..3c4a0e921f 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyUiConfiguration.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyUiConfiguration.cs @@ -4,6 +4,8 @@ namespace Volo.Abp.ObjectExtending.Modularity; public class ExtensionPropertyUiConfiguration { + public const int DefaultOrder = 1000; + [NotNull] public ExtensionPropertyUiTableConfiguration OnTable { get; } @@ -15,6 +17,8 @@ public class ExtensionPropertyUiConfiguration [NotNull] public ExtensionPropertyLookupConfiguration Lookup { get; set; } + + public int Order { get; set; } public ExtensionPropertyUiConfiguration() { @@ -22,5 +26,6 @@ public class ExtensionPropertyUiConfiguration OnCreateForm = new ExtensionPropertyUiFormConfiguration(); OnEditForm = new ExtensionPropertyUiFormConfiguration(); Lookup = new ExtensionPropertyLookupConfiguration(); + Order = DefaultOrder; } } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs index 642cd07a84..c1426e3833 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs @@ -29,9 +29,9 @@ public static class ModuleExtensionConfigurationHelper public static void ApplyEntityConfigurationToApi( string moduleName, string objectName, - Type[] getApiTypes = null, - Type[] createApiTypes = null, - Type[] updateApiTypes = null) + Type[]? getApiTypes = null, + Type[]? createApiTypes = null, + Type[]? updateApiTypes = null) { lock (SyncLock) { @@ -66,8 +66,8 @@ public static class ModuleExtensionConfigurationHelper public static void ApplyEntityConfigurationToUi( string moduleName, string entityName, - Type[] createFormTypes = null, - Type[] editFormTypes = null) + Type[]? createFormTypes = null, + Type[]? editFormTypes = null) { lock (SyncLock) { @@ -96,12 +96,12 @@ public static class ModuleExtensionConfigurationHelper public static void ApplyEntityConfigurations( string moduleName, string entityName, - Type entityType = null, - Type[] createFormTypes = null, - Type[] editFormTypes = null, - Type[] getApiTypes = null, - Type[] createApiTypes = null, - Type[] updateApiTypes = null) + Type? entityType = null, + Type[]? createFormTypes = null, + Type[]? editFormTypes = null, + Type[]? getApiTypes = null, + Type[]? createApiTypes = null, + Type[]? updateApiTypes = null) { lock (SyncLock) { @@ -174,6 +174,7 @@ public static class ModuleExtensionConfigurationHelper property.DefaultValue = propertyConfig.DefaultValue; property.DefaultValueFactory = propertyConfig.DefaultValueFactory; property.Lookup = propertyConfig.UI.Lookup; + property.UI.Order = propertyConfig.UI.Order; foreach (var configuration in propertyConfig.Configuration) { property.Configuration[configuration.Key] = configuration.Value; diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ModuleObjectExtensionManagerExtensions.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ModuleObjectExtensionManagerExtensions.cs index f74b36f6ca..92a8f9ecd5 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ModuleObjectExtensionManagerExtensions.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ModuleObjectExtensionManagerExtensions.cs @@ -12,9 +12,9 @@ public static class ModuleObjectExtensionManagerExtensions { Check.NotNull(objectExtensionManager, nameof(objectExtensionManager)); - return objectExtensionManager.Configuration.GetOrAdd( + return (objectExtensionManager.Configuration.GetOrAdd( ObjectExtensionManagerConfigurationKey, _ => new ModuleExtensionConfigurationDictionary() - ) as ModuleExtensionConfigurationDictionary; + ) as ModuleExtensionConfigurationDictionary)!; } } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs index 69b7123c50..c7ebe2f961 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs @@ -38,7 +38,7 @@ public class ObjectExtensionInfo [NotNull] public virtual ObjectExtensionInfo AddOrUpdateProperty( [NotNull] string propertyName, - [CanBeNull] Action configureAction = null) + Action? configureAction = null) { return AddOrUpdateProperty( typeof(TProperty), @@ -51,7 +51,7 @@ public class ObjectExtensionInfo public virtual ObjectExtensionInfo AddOrUpdateProperty( [NotNull] Type propertyType, [NotNull] string propertyName, - [CanBeNull] Action configureAction = null) + Action? configureAction = null) { Check.NotNull(propertyType, nameof(propertyType)); Check.NotNull(propertyName, nameof(propertyName)); @@ -69,13 +69,11 @@ public class ObjectExtensionInfo [NotNull] public virtual ImmutableList GetProperties() { - return Properties.OrderBy(t => t.Key) - .Select(t => t.Value) + return Properties.OrderBy(t => t.Value.UI.Order).Select(t => t.Value) .ToImmutableList(); } - [CanBeNull] - public virtual ObjectExtensionPropertyInfo GetPropertyOrNull( + public virtual ObjectExtensionPropertyInfo? GetPropertyOrNull( [NotNull] string propertyName) { Check.NotNullOrEmpty(propertyName, nameof(propertyName)); diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManager.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManager.cs index ff62d1bd91..1d7ad836b4 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManager.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManager.cs @@ -24,7 +24,7 @@ public class ObjectExtensionManager [NotNull] public virtual ObjectExtensionManager AddOrUpdate( - [CanBeNull] Action configureAction = null) + Action? configureAction = null) { return AddOrUpdate(typeof(TObject), configureAction); } @@ -32,7 +32,7 @@ public class ObjectExtensionManager [NotNull] public virtual ObjectExtensionManager AddOrUpdate( [NotNull] Type[] types, - [CanBeNull] Action configureAction = null) + Action? configureAction = null) { Check.NotNull(types, nameof(types)); @@ -47,7 +47,7 @@ public class ObjectExtensionManager [NotNull] public virtual ObjectExtensionManager AddOrUpdate( [NotNull] Type type, - [CanBeNull] Action configureAction = null) + Action? configureAction = null) { var extensionInfo = ObjectsExtensions.GetOrAdd( type, @@ -59,14 +59,12 @@ public class ObjectExtensionManager return this; } - [CanBeNull] - public virtual ObjectExtensionInfo GetOrNull() + public virtual ObjectExtensionInfo? GetOrNull() { return GetOrNull(typeof(TObject)); } - [CanBeNull] - public virtual ObjectExtensionInfo GetOrNull([NotNull] Type type) + public virtual ObjectExtensionInfo? GetOrNull([NotNull] Type type) { return ObjectsExtensions.GetOrDefault(type); } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManagerExtensions.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManagerExtensions.cs index a9c5c8a76f..71c7d78353 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManagerExtensions.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManagerExtensions.cs @@ -13,7 +13,7 @@ public static class ObjectExtensionManagerExtensions [NotNull] this ObjectExtensionManager objectExtensionManager, [NotNull] Type[] objectTypes, [NotNull] string propertyName, - [CanBeNull] Action configureAction = null) + Action? configureAction = null) { return objectExtensionManager.AddOrUpdateProperty( objectTypes, @@ -26,7 +26,7 @@ public static class ObjectExtensionManagerExtensions public static ObjectExtensionManager AddOrUpdateProperty( [NotNull] this ObjectExtensionManager objectExtensionManager, [NotNull] string propertyName, - [CanBeNull] Action configureAction = null) + Action? configureAction = null) where TObject : IHasExtraProperties { return objectExtensionManager.AddOrUpdateProperty( @@ -43,7 +43,7 @@ public static class ObjectExtensionManagerExtensions [NotNull] Type[] objectTypes, [NotNull] Type propertyType, [NotNull] string propertyName, - [CanBeNull] Action configureAction = null) + Action? configureAction = null) { Check.NotNull(objectTypes, nameof(objectTypes)); @@ -66,7 +66,7 @@ public static class ObjectExtensionManagerExtensions [NotNull] Type objectType, [NotNull] Type propertyType, [NotNull] string propertyName, - [CanBeNull] Action configureAction = null) + Action? configureAction = null) { Check.NotNull(objectExtensionManager, nameof(objectExtensionManager)); @@ -82,7 +82,7 @@ public static class ObjectExtensionManagerExtensions }); } - public static ObjectExtensionPropertyInfo GetPropertyOrNull( + public static ObjectExtensionPropertyInfo? GetPropertyOrNull( [NotNull] this ObjectExtensionManager objectExtensionManager, [NotNull] string propertyName) { @@ -92,7 +92,7 @@ public static class ObjectExtensionManagerExtensions ); } - public static ObjectExtensionPropertyInfo GetPropertyOrNull( + public static ObjectExtensionPropertyInfo? GetPropertyOrNull( [NotNull] this ObjectExtensionManager objectExtensionManager, [NotNull] Type objectType, [NotNull] string propertyName) diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs index f89035d733..ab941a2f15 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs @@ -24,8 +24,7 @@ public class ObjectExtensionPropertyInfo : IHasNameWithLocalizableDisplayName, I [NotNull] public List> Validators { get; } - [CanBeNull] - public ILocalizableString DisplayName { get; set; } + public ILocalizableString? DisplayName { get; set; } /// /// Indicates whether to check the other side of the object mapping @@ -47,19 +46,19 @@ public class ObjectExtensionPropertyInfo : IHasNameWithLocalizableDisplayName, I /// /// Uses as the default value if was not set. /// - [CanBeNull] - public object DefaultValue { get; set; } + public object? DefaultValue { get; set; } /// /// Used with the first priority to create the default value for the property. /// Uses to the if this was not set. /// - [CanBeNull] - public Func DefaultValueFactory { get; set; } + public Func? DefaultValueFactory { get; set; } [NotNull] public ExtensionPropertyLookupConfiguration Lookup { get; set; } + public ExtensionPropertyUI UI { get; set; } + public ObjectExtensionPropertyInfo( [NotNull] ObjectExtensionInfo objectExtension, [NotNull] Type type, @@ -76,10 +75,28 @@ public class ObjectExtensionPropertyInfo : IHasNameWithLocalizableDisplayName, I Attributes.AddRange(ExtensionPropertyHelper.GetDefaultAttributes(Type)); DefaultValue = TypeHelper.GetDefaultValue(Type); Lookup = new ExtensionPropertyLookupConfiguration(); + UI = new ExtensionPropertyUI(); } - public object GetDefaultValue() + public object? GetDefaultValue() { return ExtensionPropertyHelper.GetDefaultValue(Type, DefaultValueFactory, DefaultValue); } + + public class ExtensionPropertyUI + { + public int Order { get; set; } + + public ExtensionPropertyUIEditModal EditModal { get; set; } + + public ExtensionPropertyUI() + { + EditModal = new ExtensionPropertyUIEditModal(); + } + } + + public class ExtensionPropertyUIEditModal + { + public bool IsReadOnly { get; set; } + } } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyValidationContext.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyValidationContext.cs index 7546954dfa..077941d91c 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyValidationContext.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyValidationContext.cs @@ -35,22 +35,20 @@ public class ObjectExtensionPropertyValidationContext /// /// The value of the validating property of the . /// - [CanBeNull] - public object Value { get; } + public object? Value { get; } /// /// Can be used to resolve services from the dependency injection container. /// This can be null when SetProperty method is used on the object. /// - [CanBeNull] - public IServiceProvider ServiceProvider => ValidationContext; + public IServiceProvider? ServiceProvider => ValidationContext; public ObjectExtensionPropertyValidationContext( [NotNull] ObjectExtensionPropertyInfo objectExtensionPropertyInfo, [NotNull] IHasExtraProperties validatingObject, [NotNull] List validationErrors, [NotNull] ValidationContext validationContext, - [CanBeNull] object value) + object? value) { ExtensionPropertyInfo = Check.NotNull(objectExtensionPropertyInfo, nameof(objectExtensionPropertyInfo)); ValidatingObject = Check.NotNull(validatingObject, nameof(validatingObject)); diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionValidationContext.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionValidationContext.cs index 14b5b042f2..df7b8de8a2 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionValidationContext.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionValidationContext.cs @@ -35,8 +35,7 @@ public class ObjectExtensionValidationContext /// /// Can be used to resolve services from the dependency injection container. /// - [CanBeNull] - public IServiceProvider ServiceProvider => ValidationContext; + public IServiceProvider? ServiceProvider => ValidationContext; public ObjectExtensionValidationContext( [NotNull] ObjectExtensionInfo objectExtensionInfo, diff --git a/framework/src/Volo.Abp.RemoteServices/Volo.Abp.RemoteServices.csproj b/framework/src/Volo.Abp.RemoteServices/Volo.Abp.RemoteServices.csproj index 52d536b51a..bdd0f16c25 100644 --- a/framework/src/Volo.Abp.RemoteServices/Volo.Abp.RemoteServices.csproj +++ b/framework/src/Volo.Abp.RemoteServices/Volo.Abp.RemoteServices.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.RemoteServices Volo.Abp.RemoteServices $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/IRemoteServiceConfigurationProvider.cs b/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/IRemoteServiceConfigurationProvider.cs index 12b779141e..e869b19637 100644 --- a/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/IRemoteServiceConfigurationProvider.cs +++ b/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/IRemoteServiceConfigurationProvider.cs @@ -8,6 +8,5 @@ public interface IRemoteServiceConfigurationProvider [ItemNotNull] Task GetConfigurationOrDefaultAsync(string name); - [ItemCanBeNull] - Task GetConfigurationOrDefaultOrNullAsync(string name); + Task GetConfigurationOrDefaultOrNullAsync(string name); } diff --git a/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfiguration.cs b/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfiguration.cs index 34510be354..89d0b79f48 100644 --- a/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfiguration.cs +++ b/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfiguration.cs @@ -2,12 +2,12 @@ namespace Volo.Abp.Http.Client; -public class RemoteServiceConfiguration : Dictionary +public class RemoteServiceConfiguration : Dictionary { /// /// Base Url. /// - public string BaseUrl { + public string? BaseUrl { get => this.GetOrDefault(nameof(BaseUrl)); set => this[nameof(BaseUrl)] = value; } @@ -15,7 +15,7 @@ public class RemoteServiceConfiguration : Dictionary /// /// Version. /// - public string Version { + public string? Version { get => this.GetOrDefault(nameof(Version)); set => this[nameof(Version)] = value; } @@ -25,7 +25,7 @@ public class RemoteServiceConfiguration : Dictionary } - public RemoteServiceConfiguration(string baseUrl, string version = null) + public RemoteServiceConfiguration(string baseUrl, string? version = null) { this[nameof(BaseUrl)] = baseUrl; this[nameof(Version)] = version; diff --git a/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfigurationDictionary.cs b/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfigurationDictionary.cs index b79cf96414..ef4c5f5b77 100644 --- a/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfigurationDictionary.cs +++ b/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfigurationDictionary.cs @@ -3,11 +3,11 @@ using JetBrains.Annotations; namespace Volo.Abp.Http.Client; -public class RemoteServiceConfigurationDictionary : Dictionary +public class RemoteServiceConfigurationDictionary : Dictionary { public const string DefaultName = "Default"; - public RemoteServiceConfiguration Default { + public RemoteServiceConfiguration? Default { get => this.GetOrDefault(DefaultName); set => this[DefaultName] = value; } @@ -20,8 +20,7 @@ public class RemoteServiceConfigurationDictionary : Dictionary GetConfigurationOrDefaultOrNullAsync(string name) + public Task GetConfigurationOrDefaultOrNullAsync(string name) { return Task.FromResult(Options.RemoteServices.GetConfigurationOrDefaultOrNull(name)); } diff --git a/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfigurationProviderExtensions.cs b/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfigurationProviderExtensions.cs index 1c6aaac21d..6ec0a874da 100644 --- a/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfigurationProviderExtensions.cs +++ b/framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfigurationProviderExtensions.cs @@ -10,8 +10,7 @@ public static class RemoteServiceConfigurationProviderExtensions this IRemoteServiceConfigurationProvider provider) => provider.GetConfigurationOrDefaultAsync(RemoteServiceConfigurationDictionary.DefaultName); - [ItemNotNull] - public static Task GetConfigurationOrDefaultOrNullAsync( + public static Task GetConfigurationOrDefaultOrNullAsync( this IRemoteServiceConfigurationProvider provider) => provider.GetConfigurationOrDefaultOrNullAsync(RemoteServiceConfigurationDictionary.DefaultName); } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs b/framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs index b48c372728..6c12decd19 100644 --- a/framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs +++ b/framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs @@ -84,7 +84,7 @@ public static class AbpClaimsIdentityExtensions return null; } - public static string FindClientId([NotNull] this ClaimsPrincipal principal) + public static string? FindClientId([NotNull] this ClaimsPrincipal principal) { Check.NotNull(principal, nameof(principal)); @@ -97,7 +97,7 @@ public static class AbpClaimsIdentityExtensions return clientIdOrNull.Value; } - public static string FindClientId([NotNull] this IIdentity identity) + public static string? FindClientId([NotNull] this IIdentity identity) { Check.NotNull(identity, nameof(identity)); diff --git a/framework/src/Volo.Abp.Security/Volo.Abp.Security.csproj b/framework/src/Volo.Abp.Security/Volo.Abp.Security.csproj index ab99014a5d..b12428be84 100644 --- a/framework/src/Volo.Abp.Security/Volo.Abp.Security.csproj +++ b/framework/src/Volo.Abp.Security/Volo.Abp.Security.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Security Volo.Abp.Security $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs index 68cdf5431d..5cae98964c 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs @@ -21,7 +21,7 @@ public class AbpAuthorizationException : AbpException, IHasLogLevel, IHasErrorCo /// /// Error code. /// - public string Code { get; } + public string? Code { get; } /// /// Creates a new object. @@ -67,7 +67,7 @@ public class AbpAuthorizationException : AbpException, IHasLogLevel, IHasErrorCo /// Exception message /// Exception code /// Inner exception - public AbpAuthorizationException(string message = null, string code = null, Exception innerException = null) + public AbpAuthorizationException(string? message = null, string? code = null, Exception? innerException = null) : base(message, innerException) { Code = code; diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Clients/CurrentClient.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Clients/CurrentClient.cs index b82098d737..4ce2382c25 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Clients/CurrentClient.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Clients/CurrentClient.cs @@ -6,7 +6,7 @@ namespace Volo.Abp.Clients; public class CurrentClient : ICurrentClient, ITransientDependency { - public virtual string Id => _principalAccessor.Principal?.FindClientId(); + public virtual string? Id => _principalAccessor.Principal?.FindClientId(); public virtual bool IsAuthenticated => Id != null; diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Clients/ICurrentClient.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Clients/ICurrentClient.cs index 6ecd3f216d..9db5834f4f 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Clients/ICurrentClient.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Clients/ICurrentClient.cs @@ -2,7 +2,7 @@ public interface ICurrentClient { - string Id { get; } + string? Id { get; } bool IsAuthenticated { get; } } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/AbpSecurityModule.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/AbpSecurityModule.cs index 921aca8d7e..69107c6d1d 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/AbpSecurityModule.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/AbpSecurityModule.cs @@ -23,7 +23,7 @@ public class AbpSecurityModule : AbpModule { Configure(options => { - options.ApplicationName = applicationName; + options.ApplicationName = applicationName!; }); } @@ -42,19 +42,19 @@ public class AbpSecurityModule : AbpModule var defaultPassPhrase = configuration["StringEncryption:DefaultPassPhrase"]; if (!defaultPassPhrase.IsNullOrWhiteSpace()) { - options.DefaultPassPhrase = defaultPassPhrase; + options.DefaultPassPhrase = defaultPassPhrase!; } var initVectorBytes = configuration["StringEncryption:InitVectorBytes"]; if (!initVectorBytes.IsNullOrWhiteSpace()) { - options.InitVectorBytes = Encoding.ASCII.GetBytes(initVectorBytes); ; + options.InitVectorBytes = Encoding.ASCII.GetBytes(initVectorBytes!); } var defaultSalt = configuration["StringEncryption:DefaultSalt"]; if (!defaultSalt.IsNullOrWhiteSpace()) { - options.DefaultSalt = Encoding.ASCII.GetBytes(defaultSalt); ; + options.DefaultSalt = Encoding.ASCII.GetBytes(defaultSalt!); } }); } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory.cs index 1e9221cd88..ae9d947fb0 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory.cs @@ -21,7 +21,7 @@ public class AbpClaimsPrincipalFactory : IAbpClaimsPrincipalFactory, ITransientD Options = abpClaimOptions.Value; } - public virtual async Task CreateAsync(ClaimsPrincipal existsClaimsPrincipal = null) + public virtual async Task CreateAsync(ClaimsPrincipal? existsClaimsPrincipal = null) { using (var scope = ServiceScopeFactory.CreateScope()) { diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/IAbpClaimsPrincipalFactory.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/IAbpClaimsPrincipalFactory.cs index fcfcf4d348..b4f3046c9d 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/IAbpClaimsPrincipalFactory.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/IAbpClaimsPrincipalFactory.cs @@ -5,5 +5,5 @@ namespace Volo.Abp.Security.Claims; public interface IAbpClaimsPrincipalFactory { - Task CreateAsync(ClaimsPrincipal existsClaimsPrincipal = null); + Task CreateAsync(ClaimsPrincipal? existsClaimsPrincipal = null); } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ThreadCurrentPrincipalAccessor.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ThreadCurrentPrincipalAccessor.cs index 76030076a3..ab42441f98 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ThreadCurrentPrincipalAccessor.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ThreadCurrentPrincipalAccessor.cs @@ -8,6 +8,6 @@ public class ThreadCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ISin { protected override ClaimsPrincipal GetClaimsPrincipal() { - return Thread.CurrentPrincipal as ClaimsPrincipal; + return (Thread.CurrentPrincipal as ClaimsPrincipal)!; } } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/IStringEncryptionService.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/IStringEncryptionService.cs index 8a28dc7703..fdf077d483 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/IStringEncryptionService.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/IStringEncryptionService.cs @@ -15,8 +15,7 @@ public interface IStringEncryptionService /// A phrase to use as the encryption key (optional, uses default if not provided) /// Salt value (optional, uses default if not provided) /// Enrypted text - [CanBeNull] - string Encrypt([CanBeNull] string plainText, string passPhrase = null, byte[] salt = null); + string? Encrypt(string? plainText, string? passPhrase = null, byte[]? salt = null); /// /// Decrypts a text that is encrypted by the method. @@ -25,6 +24,5 @@ public interface IStringEncryptionService /// A phrase to use as the encryption key (optional, uses default if not provided) /// Salt value (optional, uses default if not provided) /// Decrypted text - [CanBeNull] - string Decrypt([CanBeNull] string cipherText, string passPhrase = null, byte[] salt = null); + string? Decrypt(string? cipherText, string? passPhrase = null, byte[]? salt = null); } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionService.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionService.cs index c02c6bca9a..e1e7e94b7a 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionService.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionService.cs @@ -19,7 +19,7 @@ public class StringEncryptionService : IStringEncryptionService, ITransientDepen Options = options.Value; } - public virtual string Encrypt(string plainText, string passPhrase = null, byte[] salt = null) + public virtual string? Encrypt(string? plainText, string? passPhrase = null, byte[]? salt = null) { if (plainText == null) { @@ -60,7 +60,7 @@ public class StringEncryptionService : IStringEncryptionService, ITransientDepen } } - public virtual string Decrypt(string cipherText, string passPhrase = null, byte[] salt = null) + public virtual string? Decrypt(string? cipherText, string? passPhrase = null, byte[]? salt = null) { if (string.IsNullOrEmpty(cipherText)) { diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/AbpSecurityLogOptions.cs b/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/AbpSecurityLogOptions.cs index 24a885cba4..23db29baff 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/AbpSecurityLogOptions.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/AbpSecurityLogOptions.cs @@ -11,7 +11,7 @@ public class AbpSecurityLogOptions /// The name of the application or service writing security log. /// Default: null. /// - public string ApplicationName { get; set; } + public string? ApplicationName { get; set; } public AbpSecurityLogOptions() { diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/DefaultSecurityLogManager.cs b/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/DefaultSecurityLogManager.cs index 392c8fa869..b870b553c3 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/DefaultSecurityLogManager.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/DefaultSecurityLogManager.cs @@ -19,7 +19,7 @@ public class DefaultSecurityLogManager : ISecurityLogManager, ITransientDependen SecurityLogOptions = securityLogOptions.Value; } - public async Task SaveAsync(Action saveAction = null) + public async Task SaveAsync(Action? saveAction = null) { if (!SecurityLogOptions.IsEnabled) { diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/ISecurityLogManager.cs b/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/ISecurityLogManager.cs index 69c71b96af..0e406d2daf 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/ISecurityLogManager.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/ISecurityLogManager.cs @@ -5,5 +5,5 @@ namespace Volo.Abp.SecurityLog; public interface ISecurityLogManager { - Task SaveAsync(Action saveAction = null); + Task SaveAsync(Action? saveAction = null); } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/SecurityLogInfo.cs b/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/SecurityLogInfo.cs index b5bef5e3fc..f2bb55b5ea 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/SecurityLogInfo.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/SecurityLog/SecurityLogInfo.cs @@ -6,29 +6,29 @@ namespace Volo.Abp.SecurityLog; [Serializable] public class SecurityLogInfo { - public string ApplicationName { get; set; } + public string? ApplicationName { get; set; } - public string Identity { get; set; } + public string? Identity { get; set; } - public string Action { get; set; } + public string? Action { get; set; } public Dictionary ExtraProperties { get; } public Guid? UserId { get; set; } - public string UserName { get; set; } + public string? UserName { get; set; } public Guid? TenantId { get; set; } - public string TenantName { get; set; } + public string? TenantName { get; set; } - public string ClientId { get; set; } + public string? ClientId { get; set; } - public string CorrelationId { get; set; } + public string? CorrelationId { get; set; } - public string ClientIpAddress { get; set; } + public string? ClientIpAddress { get; set; } - public string BrowserInfo { get; set; } + public string? BrowserInfo { get; set; } public DateTime CreationTime { get; set; } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUser.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUser.cs index 771fa7927b..cf52f1afa7 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUser.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUser.cs @@ -15,17 +15,17 @@ public class CurrentUser : ICurrentUser, ITransientDependency public virtual Guid? Id => _principalAccessor.Principal?.FindUserId(); - public virtual string UserName => this.FindClaimValue(AbpClaimTypes.UserName); + public virtual string? UserName => this.FindClaimValue(AbpClaimTypes.UserName); - public virtual string Name => this.FindClaimValue(AbpClaimTypes.Name); + public virtual string? Name => this.FindClaimValue(AbpClaimTypes.Name); - public virtual string SurName => this.FindClaimValue(AbpClaimTypes.SurName); + public virtual string? SurName => this.FindClaimValue(AbpClaimTypes.SurName); - public virtual string PhoneNumber => this.FindClaimValue(AbpClaimTypes.PhoneNumber); + public virtual string? PhoneNumber => this.FindClaimValue(AbpClaimTypes.PhoneNumber); public virtual bool PhoneNumberVerified => string.Equals(this.FindClaimValue(AbpClaimTypes.PhoneNumberVerified), "true", StringComparison.InvariantCultureIgnoreCase); - public virtual string Email => this.FindClaimValue(AbpClaimTypes.Email); + public virtual string? Email => this.FindClaimValue(AbpClaimTypes.Email); public virtual bool EmailVerified => string.Equals(this.FindClaimValue(AbpClaimTypes.EmailVerified), "true", StringComparison.InvariantCultureIgnoreCase); @@ -40,7 +40,7 @@ public class CurrentUser : ICurrentUser, ITransientDependency _principalAccessor = principalAccessor; } - public virtual Claim FindClaim(string claimType) + public virtual Claim? FindClaim(string claimType) { return _principalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == claimType); } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs index 7e10df87c6..b702bcffde 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs @@ -7,8 +7,7 @@ namespace Volo.Abp.Users; public static class CurrentUserExtensions { - [CanBeNull] - public static string FindClaimValue(this ICurrentUser currentUser, string claimType) + public static string? FindClaimValue(this ICurrentUser currentUser, string claimType) { return currentUser.FindClaim(claimType)?.Value; } @@ -29,7 +28,7 @@ public static class CurrentUserExtensions { Debug.Assert(currentUser.Id != null, "currentUser.Id != null"); - return currentUser.Id.Value; + return currentUser!.Id!.Value; } public static Guid? FindImpersonatorTenantId([NotNull] this ICurrentUser currentUser) @@ -62,12 +61,12 @@ public static class CurrentUserExtensions return null; } - public static string FindImpersonatorTenantName([NotNull] this ICurrentUser currentUser) + public static string? FindImpersonatorTenantName([NotNull] this ICurrentUser currentUser) { return currentUser.FindClaimValue(AbpClaimTypes.ImpersonatorTenantName); } - public static string FindImpersonatorUserName([NotNull] this ICurrentUser currentUser) + public static string? FindImpersonatorUserName([NotNull] this ICurrentUser currentUser) { return currentUser.FindClaimValue(AbpClaimTypes.ImpersonatorUserName); } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Users/ICurrentUser.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Users/ICurrentUser.cs index 95aecca83a..aacf001279 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Users/ICurrentUser.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Users/ICurrentUser.cs @@ -11,22 +11,17 @@ public interface ICurrentUser [CanBeNull] Guid? Id { get; } - [CanBeNull] - string UserName { get; } + string? UserName { get; } - [CanBeNull] - string Name { get; } + string? Name { get; } - [CanBeNull] - string SurName { get; } + string? SurName { get; } - [CanBeNull] - string PhoneNumber { get; } + string? PhoneNumber { get; } bool PhoneNumberVerified { get; } - [CanBeNull] - string Email { get; } + string? Email { get; } bool EmailVerified { get; } @@ -35,8 +30,7 @@ public interface ICurrentUser [NotNull] string[] Roles { get; } - [CanBeNull] - Claim FindClaim(string claimType); + Claim? FindClaim(string claimType); [NotNull] Claim[] FindClaims(string claimType); diff --git a/framework/src/Volo.Abp.Serialization/Volo.Abp.Serialization.csproj b/framework/src/Volo.Abp.Serialization/Volo.Abp.Serialization.csproj index f410670e83..c4c751210b 100644 --- a/framework/src/Volo.Abp.Serialization/Volo.Abp.Serialization.csproj +++ b/framework/src/Volo.Abp.Serialization/Volo.Abp.Serialization.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Serialization Volo.Abp.Serialization $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/DefaultObjectSerializer.cs b/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/DefaultObjectSerializer.cs index 0f95d782b0..99ec929ca8 100644 --- a/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/DefaultObjectSerializer.cs +++ b/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/DefaultObjectSerializer.cs @@ -15,7 +15,7 @@ public class DefaultObjectSerializer : IObjectSerializer, ITransientDependency _serviceProvider = serviceProvider; } - public virtual byte[] Serialize(T obj) + public virtual byte[]? Serialize(T? obj) { if (obj == null) { @@ -35,8 +35,7 @@ public class DefaultObjectSerializer : IObjectSerializer, ITransientDependency return AutoSerialize(obj); } - [CanBeNull] - public virtual T Deserialize(byte[] bytes) + public virtual T? Deserialize(byte[]? bytes) { if (bytes == null) { @@ -61,7 +60,7 @@ public class DefaultObjectSerializer : IObjectSerializer, ITransientDependency return JsonSerializer.SerializeToUtf8Bytes(obj); } - protected virtual T AutoDeserialize(byte[] bytes) + protected virtual T? AutoDeserialize(byte[] bytes) { return JsonSerializer.Deserialize(bytes); } diff --git a/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/IObjectSerializer.cs b/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/IObjectSerializer.cs index bb82d410b0..6631cb966d 100644 --- a/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/IObjectSerializer.cs +++ b/framework/src/Volo.Abp.Serialization/Volo/Abp/Serialization/IObjectSerializer.cs @@ -2,14 +2,14 @@ public interface IObjectSerializer { - byte[] Serialize(T obj); + byte[]? Serialize(T? obj); - T Deserialize(byte[] bytes); + T? Deserialize(byte[] bytes); } public interface IObjectSerializer { - byte[] Serialize(T obj); + byte[]? Serialize(T? obj); - T Deserialize(byte[] bytes); + T? Deserialize(byte[]? bytes); } diff --git a/framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj b/framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj index 524f932e9c..efec1d42c5 100644 --- a/framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj +++ b/framework/src/Volo.Abp.Settings/Volo.Abp.Settings.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Settings Volo.Abp.Settings $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ConfigurationSettingValueProvider.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ConfigurationSettingValueProvider.cs index 853b510d04..51e0a882b0 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ConfigurationSettingValueProvider.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ConfigurationSettingValueProvider.cs @@ -21,7 +21,7 @@ public class ConfigurationSettingValueProvider : ISettingValueProvider, ITransie Configuration = configuration; } - public virtual Task GetOrNullAsync(SettingDefinition setting) + public virtual Task GetOrNullAsync(SettingDefinition setting) { return Task.FromResult(Configuration[ConfigurationNamePrefix + setting.Name]); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/DefaultValueSettingValueProvider.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/DefaultValueSettingValueProvider.cs index e5e7275281..299f9e63bc 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/DefaultValueSettingValueProvider.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/DefaultValueSettingValueProvider.cs @@ -16,7 +16,7 @@ public class DefaultValueSettingValueProvider : SettingValueProvider } - public override Task GetOrNullAsync(SettingDefinition setting) + public override Task GetOrNullAsync(SettingDefinition setting) { return Task.FromResult(setting.DefaultValue); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/GlobalSettingValueProvider.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/GlobalSettingValueProvider.cs index 34439c6aef..6c0e8883d7 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/GlobalSettingValueProvider.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/GlobalSettingValueProvider.cs @@ -15,7 +15,7 @@ public class GlobalSettingValueProvider : SettingValueProvider { } - public override Task GetOrNullAsync(SettingDefinition setting) + public override Task GetOrNullAsync(SettingDefinition setting) { return SettingStore.GetOrNullAsync(setting.Name, Name, null); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingDefinitionContext.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingDefinitionContext.cs index 8257c73adb..deecea1107 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingDefinitionContext.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingDefinitionContext.cs @@ -4,7 +4,7 @@ namespace Volo.Abp.Settings; public interface ISettingDefinitionContext { - SettingDefinition GetOrNull(string name); + SettingDefinition? GetOrNull(string name); IReadOnlyList GetAll(); diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingDefinitionManager.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingDefinitionManager.cs index 865fe5557a..7939d113c4 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingDefinitionManager.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingDefinitionManager.cs @@ -10,5 +10,5 @@ public interface ISettingDefinitionManager IReadOnlyList GetAll(); - SettingDefinition GetOrNull(string name); + SettingDefinition? GetOrNull(string name); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingEncryptionService.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingEncryptionService.cs index f91e8f808a..5c1328e8c3 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingEncryptionService.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingEncryptionService.cs @@ -4,9 +4,7 @@ namespace Volo.Abp.Settings; public interface ISettingEncryptionService { - [CanBeNull] - string Encrypt([NotNull] SettingDefinition settingDefinition, [CanBeNull] string plainValue); + string? Encrypt([NotNull] SettingDefinition settingDefinition, string? plainValue); - [CanBeNull] - string Decrypt([NotNull] SettingDefinition settingDefinition, [CanBeNull] string encryptedValue); + string? Decrypt([NotNull] SettingDefinition settingDefinition, string? encryptedValue); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingProvider.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingProvider.cs index d58a21b874..a24060b5ff 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingProvider.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingProvider.cs @@ -6,7 +6,7 @@ namespace Volo.Abp.Settings; public interface ISettingProvider { - Task GetOrNullAsync([NotNull] string name); + Task GetOrNullAsync([NotNull] string name); Task> GetAllAsync([NotNull] string[] names); diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingStore.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingStore.cs index a8be20c7d8..89f933f877 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingStore.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingStore.cs @@ -6,15 +6,15 @@ namespace Volo.Abp.Settings; public interface ISettingStore { - Task GetOrNullAsync( + Task GetOrNullAsync( [NotNull] string name, - [CanBeNull] string providerName, - [CanBeNull] string providerKey + string? providerName, + string? providerKey ); Task> GetAllAsync( [NotNull] string[] names, - [CanBeNull] string providerName, - [CanBeNull] string providerKey + string? providerName, + string? providerKey ); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingValueProvider.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingValueProvider.cs index 6878fda17b..1619052cbd 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingValueProvider.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/ISettingValueProvider.cs @@ -8,7 +8,7 @@ public interface ISettingValueProvider { string Name { get; } - Task GetOrNullAsync([NotNull] SettingDefinition setting); + Task GetOrNullAsync([NotNull] SettingDefinition setting); Task> GetAllAsync([NotNull] SettingDefinition[] settings); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/NullSettingStore.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/NullSettingStore.cs index 8db9286a14..f6d04e0b4a 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/NullSettingStore.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/NullSettingStore.cs @@ -17,12 +17,12 @@ public class NullSettingStore : ISettingStore, ISingletonDependency Logger = NullLogger.Instance; } - public Task GetOrNullAsync(string name, string providerName, string providerKey) + public Task GetOrNullAsync(string name, string? providerName, string? providerKey) { - return Task.FromResult((string)null); + return Task.FromResult((string?)null); } - public Task> GetAllAsync(string[] names, string providerName, string providerKey) + public Task> GetAllAsync(string[] names, string? providerName, string? providerKey) { return Task.FromResult(names.Select(x => new SettingValue(x, null)).ToList()); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs index 536a407271..72ccfcd3f3 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs @@ -17,16 +17,14 @@ public class SettingDefinition get => _displayName; set => _displayName = Check.NotNull(value, nameof(value)); } - private ILocalizableString _displayName; + private ILocalizableString _displayName = default!; - [CanBeNull] - public ILocalizableString Description { get; set; } + public ILocalizableString? Description { get; set; } /// /// Default value of the setting. /// - [CanBeNull] - public string DefaultValue { get; set; } + public string? DefaultValue { get; set; } /// /// Can clients see this setting and it's value. @@ -61,9 +59,9 @@ public class SettingDefinition public SettingDefinition( string name, - string defaultValue = null, - ILocalizableString displayName = null, - ILocalizableString description = null, + string? defaultValue = null, + ILocalizableString? displayName = null, + ILocalizableString? description = null, bool isVisibleToClients = false, bool isInherited = true, bool isEncrypted = false) diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionContext.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionContext.cs index e06395f614..a1192c96c9 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionContext.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionContext.cs @@ -12,7 +12,7 @@ public class SettingDefinitionContext : ISettingDefinitionContext Settings = settings; } - public virtual SettingDefinition GetOrNull(string name) + public virtual SettingDefinition? GetOrNull(string name) { return Settings.GetOrDefault(name); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionManager.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionManager.cs index ed285422b3..87f173d04e 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionManager.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionManager.cs @@ -45,7 +45,7 @@ public class SettingDefinitionManager : ISettingDefinitionManager, ISingletonDep return SettingDefinitions.Value.Values.ToImmutableList(); } - public virtual SettingDefinition GetOrNull(string name) + public virtual SettingDefinition? GetOrNull(string name) { return SettingDefinitions.Value.GetOrDefault(name); } @@ -63,7 +63,7 @@ public class SettingDefinitionManager : ISettingDefinitionManager, ISingletonDep foreach (var provider in providers) { - provider.Define(new SettingDefinitionContext(settings)); + provider!.Define(new SettingDefinitionContext(settings)); } } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingEncryptionService.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingEncryptionService.cs index 9f59f57910..45a3362d30 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingEncryptionService.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingEncryptionService.cs @@ -17,7 +17,7 @@ public class SettingEncryptionService : ISettingEncryptionService, ITransientDep Logger = NullLogger.Instance; } - public virtual string Encrypt(SettingDefinition settingDefinition, string plainValue) + public virtual string? Encrypt(SettingDefinition settingDefinition, string? plainValue) { if (plainValue.IsNullOrEmpty()) { @@ -27,7 +27,7 @@ public class SettingEncryptionService : ISettingEncryptionService, ITransientDep return StringEncryptionService.Encrypt(plainValue); } - public virtual string Decrypt(SettingDefinition settingDefinition, string encryptedValue) + public virtual string? Decrypt(SettingDefinition settingDefinition, string? encryptedValue) { if (encryptedValue.IsNullOrEmpty()) { diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingProvider.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingProvider.cs index 01791bef00..31dfecc4c0 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingProvider.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingProvider.cs @@ -21,7 +21,7 @@ public class SettingProvider : ISettingProvider, ITransientDependency SettingValueProviderManager = settingValueProviderManager; } - public virtual async Task GetOrNullAsync(string name) + public virtual async Task GetOrNullAsync(string name) { var setting = SettingDefinitionManager.Get(name); var providers = Enumerable @@ -95,7 +95,7 @@ public class SettingProvider : ISettingProvider, ITransientDependency return settingValues; } - protected virtual async Task GetOrNullValueFromProvidersAsync( + protected virtual async Task GetOrNullValueFromProvidersAsync( IEnumerable providers, SettingDefinition setting) { diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValue.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValue.cs index 63f6ab063f..56e972611b 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValue.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValue.cs @@ -3,14 +3,14 @@ namespace Volo.Abp.Settings; [Serializable] -public class SettingValue : NameValue +public class SettingValue : NameValue { public SettingValue() { } - public SettingValue(string name, string value) + public SettingValue(string name, string? value) { Name = name; Value = value; diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProvider.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProvider.cs index c8b994986d..57d4b18a51 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProvider.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProvider.cs @@ -15,7 +15,7 @@ public abstract class SettingValueProvider : ISettingValueProvider, ITransientDe SettingStore = settingStore; } - public abstract Task GetOrNullAsync(SettingDefinition setting); + public abstract Task GetOrNullAsync(SettingDefinition setting); public abstract Task> GetAllAsync(SettingDefinition[] settings); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs index f54b3cfda3..d0300357dc 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingValueProviderManager.cs @@ -24,7 +24,7 @@ public class SettingValueProviderManager : ISettingValueProviderManager, ISingle () => Options .ValueProviders .Select(type => serviceProvider.GetRequiredService(type) as ISettingValueProvider) - .ToList(), + .ToList()!, true ); } diff --git a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/UserSettingValueProvider.cs b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/UserSettingValueProvider.cs index 791bef3709..7c1d65740a 100644 --- a/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/UserSettingValueProvider.cs +++ b/framework/src/Volo.Abp.Settings/Volo/Abp/Settings/UserSettingValueProvider.cs @@ -19,7 +19,7 @@ public class UserSettingValueProvider : SettingValueProvider CurrentUser = currentUser; } - public override async Task GetOrNullAsync(SettingDefinition setting) + public override async Task GetOrNullAsync(SettingDefinition setting) { if (CurrentUser.Id == null) { diff --git a/framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj b/framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj index 8b007b7a4a..e59ce4be49 100644 --- a/framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj +++ b/framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj @@ -4,6 +4,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Sms.Aliyun Volo.Abp.Sms.Aliyun $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpAliyunSmsOptions.cs b/framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpAliyunSmsOptions.cs index 1b3eac289c..895e03c710 100644 --- a/framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpAliyunSmsOptions.cs +++ b/framework/src/Volo.Abp.Sms.Aliyun/Volo/Abp/Sms/Aliyun/AbpAliyunSmsOptions.cs @@ -2,9 +2,9 @@ namespace Volo.Abp.Sms.Aliyun; public class AbpAliyunSmsOptions { - public string AccessKeySecret { get; set; } + public string AccessKeySecret { get; set; } = default!; - public string AccessKeyId { get; set; } + public string AccessKeyId { get; set; } = default!; - public string EndPoint { get; set; } + public string EndPoint { get; set; } = default!; } diff --git a/framework/src/Volo.Abp.Sms/Volo.Abp.Sms.csproj b/framework/src/Volo.Abp.Sms/Volo.Abp.Sms.csproj index becbe00e65..7bba35f34a 100644 --- a/framework/src/Volo.Abp.Sms/Volo.Abp.Sms.csproj +++ b/framework/src/Volo.Abp.Sms/Volo.Abp.Sms.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Sms Volo.Abp.Sms $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Specifications/Volo.Abp.Specifications.csproj b/framework/src/Volo.Abp.Specifications/Volo.Abp.Specifications.csproj index f6a5b54948..98d2f529e3 100644 --- a/framework/src/Volo.Abp.Specifications/Volo.Abp.Specifications.csproj +++ b/framework/src/Volo.Abp.Specifications/Volo.Abp.Specifications.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Specifications Volo.Abp.Specifications $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs b/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs index 3c27c640cd..0f5698ab08 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using JetBrains.Annotations; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; +using Swashbuckle.AspNetCore.SwaggerUI; using Volo.Abp.Content; namespace Microsoft.Extensions.DependencyInjection; @@ -61,20 +62,70 @@ public static class AbpSwaggerGenServiceCollectionExtensions options.AddSecurityRequirement(new OpenApiSecurityRequirement { + { + new OpenApiSecurityScheme { - new OpenApiSecurityScheme + Reference = new OpenApiReference { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "oauth2" - } - }, - Array.Empty() - } + Type = ReferenceType.SecurityScheme, + Id = "oauth2" + } + }, + Array.Empty() + } }); setupAction?.Invoke(options); }); } + + public static IServiceCollection AddAbpSwaggerGenWithOidc( + this IServiceCollection services, + [NotNull] string authority, + string[] scopes = null, + string[] flows = null, + string discoveryEndpoint = null, + Action setupAction = null) + { + var discoveryUrl = discoveryEndpoint != null ? + new Uri(discoveryEndpoint) : + new Uri($"{authority.TrimEnd('/')}/.well-known/openid-configuration"); + + flows ??= new [] { "authorization_code" }; + + services.Configure(swaggerUiOptions => + { + swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedFlows"] = flows; + swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedScopes"] = scopes; + swaggerUiOptions.ConfigObject.AdditionalItems["oidcDiscoveryEndpoint"] = discoveryEndpoint; + }); + + return services + .AddAbpSwaggerGen() + .AddSwaggerGen( + options => + { + options.AddSecurityDefinition("oidc", new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OpenIdConnect, + OpenIdConnectUrl = discoveryUrl + }); + + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "oidc" + } + }, + Array.Empty() + } + }); + setupAction?.Invoke(options); + }); + } } diff --git a/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js b/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js index c143b7e75e..6edbe815be 100644 --- a/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js +++ b/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js @@ -1,16 +1,20 @@ var abp = abp || {}; -(function() { +(function () { - abp.SwaggerUIBundle = function(configObject) { + abp.SwaggerUIBundle = function (configObject) { var excludeUrl = ["swagger.json", "connect/token"] var firstRequest = true; + var oidcSupportedFlows = configObject.oidcSupportedFlows || []; + var oidcSupportedScopes = configObject.oidcSupportedScopes || []; + var oidcDiscoveryEndpoint = configObject.oidcDiscoveryEndpoint || []; abp.appPath = configObject.baseUrl || abp.appPath; var requestInterceptor = configObject.requestInterceptor; + var responseInterceptor = configObject.responseInterceptor; - configObject.requestInterceptor = async function(request) { + configObject.requestInterceptor = async function (request) { if (request.url.includes(excludeUrl[1])) { firstRequest = true; @@ -22,6 +26,10 @@ var abp = abp || {}; }); firstRequest = false; } + // Intercept .well-known request when the discoveryEndpoint is provided + if (!firstRequest && oidcDiscoveryEndpoint.length !== 0 && request.url.includes(".well-known/openid-configuration")) { + request.url = oidcDiscoveryEndpoint; + } var antiForgeryToken = abp.security.antiForgery.getToken(); if (antiForgeryToken) { @@ -38,6 +46,31 @@ var abp = abp || {}; return request; }; + configObject.responseInterceptor = async function (response) { + if (response.url.endsWith(".well-known/openid-configuration") && response.status === 200) { + var openIdConnectData = JSON.parse(response.text); + + if (oidcDiscoveryEndpoint.length > 0) { + openIdConnectData.grant_types_supported = oidcSupportedFlows; + } + + if (oidcSupportedFlows.length > 0) { + openIdConnectData.grant_types_supported = oidcSupportedFlows; + } + + if (oidcSupportedScopes.length > 0) { + openIdConnectData.scopes_supported = oidcSupportedScopes; + } + + response.text = JSON.stringify(openIdConnectData); + } + + if (responseInterceptor) { + responseInterceptor(response); + } + return response; + }; + return SwaggerUIBundle(configObject); } })(); diff --git a/framework/src/Volo.Abp.TestBase/Volo.Abp.TestBase.csproj b/framework/src/Volo.Abp.TestBase/Volo.Abp.TestBase.csproj index 4b90693b3e..9cf201a287 100644 --- a/framework/src/Volo.Abp.TestBase/Volo.Abp.TestBase.csproj +++ b/framework/src/Volo.Abp.TestBase/Volo.Abp.TestBase.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.TestBase Volo.Abp.TestBase $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.TestBase/Volo/Abp/AbpTestBaseWithServiceProvider.cs b/framework/src/Volo.Abp.TestBase/Volo/Abp/AbpTestBaseWithServiceProvider.cs index 407660e854..04879b4fce 100644 --- a/framework/src/Volo.Abp.TestBase/Volo/Abp/AbpTestBaseWithServiceProvider.cs +++ b/framework/src/Volo.Abp.TestBase/Volo/Abp/AbpTestBaseWithServiceProvider.cs @@ -5,14 +5,14 @@ namespace Volo.Abp; public abstract class AbpTestBaseWithServiceProvider { - protected IServiceProvider ServiceProvider { get; set; } + protected IServiceProvider ServiceProvider { get; set; } = default!; - protected virtual T GetService() + protected virtual T? GetService() { return ServiceProvider.GetService(); } - - protected virtual T GetRequiredService() + + protected virtual T GetRequiredService() where T : notnull { return ServiceProvider.GetRequiredService(); } diff --git a/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpAsyncIntegratedTest.cs b/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpAsyncIntegratedTest.cs index 4238a8712b..4004c110a4 100644 --- a/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpAsyncIntegratedTest.cs +++ b/framework/src/Volo.Abp.TestBase/Volo/Abp/Testing/AbpAsyncIntegratedTest.cs @@ -8,11 +8,11 @@ namespace Volo.Abp.Testing; public class AbpAsyncIntegratedTest : AbpTestBaseWithServiceProvider where TStartupModule : IAbpModule { - protected IAbpApplication Application { get; set; } + protected IAbpApplication Application { get; set; } = default!; - protected IServiceProvider RootServiceProvider { get; set; } + protected IServiceProvider RootServiceProvider { get; set; } = default!; - protected IServiceScope TestServiceScope { get; set; } + protected IServiceScope TestServiceScope { get; set; } = default!; public virtual async Task InitializeAsync() { diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs index ba87dfb4ae..43cc829010 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs @@ -29,7 +29,7 @@ public class AbpTemplateRenderer : ITemplateRenderer, ITransientDependency string cultureName = null, Dictionary globalContext = null) { - var templateDefinition = TemplateDefinitionManager.Get(templateName); + var templateDefinition = await TemplateDefinitionManager.GetAsync(templateName); var renderEngine = templateDefinition.RenderEngine; diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs index 3c98daa22b..28b2e28ad0 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs @@ -12,10 +12,13 @@ public class AbpTextTemplatingOptions public string DefaultRenderingEngine { get; set; } + public HashSet DeletedTemplates { get; } + public AbpTextTemplatingOptions() { DefinitionProviders = new TypeList(); ContentContributors = new TypeList(); RenderingEngines = new Dictionary(); + DeletedTemplates = new HashSet(); } } diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IDynamicTemplateDefinitionStore.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IDynamicTemplateDefinitionStore.cs new file mode 100644 index 0000000000..e275eb39be --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IDynamicTemplateDefinitionStore.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace Volo.Abp.TextTemplating; + +public interface IDynamicTemplateDefinitionStore +{ + Task GetAsync([NotNull] string name); + + Task> GetAllAsync(); + + Task GetOrNullAsync(string name); +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IStaticTemplateDefinitionStore.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IStaticTemplateDefinitionStore.cs new file mode 100644 index 0000000000..d298a42541 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/IStaticTemplateDefinitionStore.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace Volo.Abp.TextTemplating; + +public interface IStaticTemplateDefinitionStore +{ + Task GetAsync([NotNull] string name); + + Task> GetAllAsync(); + + Task GetOrNullAsync(string name); +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs index 31af5d1da5..fa20673cea 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs @@ -1,16 +1,17 @@ using System.Collections.Generic; +using System.Threading.Tasks; using JetBrains.Annotations; namespace Volo.Abp.TextTemplating; public interface ITemplateDefinitionManager { - [NotNull] - TemplateDefinition Get([NotNull] string name); + [ItemNotNull] + Task GetAsync([NotNull] string name); - [NotNull] - IReadOnlyList GetAll(); + [ItemNotNull] + Task> GetAllAsync(); - [CanBeNull] - TemplateDefinition GetOrNull(string name); + [ItemCanBeNull] + Task GetOrNullAsync(string name); } diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/NullIDynamicTemplateDefinitionStore.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/NullIDynamicTemplateDefinitionStore.cs new file mode 100644 index 0000000000..326b525c0e --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/NullIDynamicTemplateDefinitionStore.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.TextTemplating; + +public class NullIDynamicTemplateDefinitionStore : IDynamicTemplateDefinitionStore, ISingletonDependency +{ + private readonly static Task CachedTemplateResult = Task.FromResult((TemplateDefinition)null); + + private readonly static Task> CachedFeaturesResult = Task.FromResult((IReadOnlyList)Array.Empty().ToImmutableList()); + + public Task GetAsync(string name) + { + return CachedTemplateResult; + } + + public Task> GetAllAsync() + { + return CachedFeaturesResult; + } + + public Task GetOrNullAsync(string name) + { + return CachedTemplateResult; + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/StaticTemplateDefinitionStore.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/StaticTemplateDefinitionStore.cs new file mode 100644 index 0000000000..d12db86da8 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/StaticTemplateDefinitionStore.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.TextTemplating; + +public class StaticTemplateDefinitionStore : IStaticTemplateDefinitionStore, ISingletonDependency +{ + protected Lazy> TemplateDefinitions { get; } + + protected AbpTextTemplatingOptions Options { get; } + + protected IServiceProvider ServiceProvider { get; } + + public StaticTemplateDefinitionStore(IOptions options, IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + Options = options.Value; + + TemplateDefinitions = new Lazy>(CreateTextTemplateDefinitions, true); + } + + public virtual Task GetAsync(string name) + { + Check.NotNull(name, nameof(name)); + + var template = GetOrNullAsync(name); + + if (template == null) + { + throw new AbpException("Undefined template: " + name); + } + + return template; + } + + public virtual Task> GetAllAsync() + { + return Task.FromResult>(TemplateDefinitions.Value.Values.ToImmutableList()); + } + + public virtual Task GetOrNullAsync(string name) + { + return Task.FromResult(TemplateDefinitions.Value.GetOrDefault(name)); + } + + protected virtual IDictionary CreateTextTemplateDefinitions() + { + var templates = new Dictionary(); + + using (var scope = ServiceProvider.CreateScope()) + { + var providers = Options + .DefinitionProviders + .Select(p => scope.ServiceProvider.GetRequiredService(p) as ITemplateDefinitionProvider) + .ToList(); + + var context = new TemplateDefinitionContext(templates); + + foreach (var provider in providers) + { + provider.PreDefine(context); + } + + foreach (var provider in providers) + { + provider.Define(context); + } + + foreach (var provider in providers) + { + provider.PostDefine(context); + } + } + + return templates; + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentProvider.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentProvider.cs index 58ffcc491f..64ecd1f4c7 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentProvider.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentProvider.cs @@ -26,14 +26,14 @@ public class TemplateContentProvider : ITemplateContentProvider, ITransientDepen _templateDefinitionManager = templateDefinitionManager; } - public virtual Task GetContentOrNullAsync( + public virtual async Task GetContentOrNullAsync( [NotNull] string templateName, [CanBeNull] string cultureName = null, bool tryDefaults = true, bool useCurrentCultureIfCultureNameIsNull = true) { - var template = _templateDefinitionManager.Get(templateName); - return GetContentOrNullAsync(template, cultureName); + var template = await _templateDefinitionManager.GetAsync(templateName); + return await GetContentOrNullAsync(template, cultureName); } public virtual async Task GetContentOrNullAsync( diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs index d028f46702..64aeba815e 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs @@ -28,7 +28,7 @@ public class TemplateDefinition : IHasNameWithLocalizableDisplayName public string Layout { get; set; } [CanBeNull] - public Type LocalizationResource { get; set; } + public string LocalizationResourceName { get; set; } public bool IsInlineLocalized { get; set; } @@ -60,14 +60,26 @@ public class TemplateDefinition : IHasNameWithLocalizableDisplayName public TemplateDefinition( [NotNull] string name, - [CanBeNull] Type localizationResource = null, + [NotNull] Type localizationResource, + [CanBeNull] ILocalizableString displayName = null, + bool isLayout = false, + string layout = null, + string defaultCultureName = null) + : this(name, LocalizationResourceNameAttribute.GetName(localizationResource), displayName, isLayout, layout, defaultCultureName) + { + + } + + public TemplateDefinition( + [NotNull] string name, + [CanBeNull] string localizationResourceName = null, [CanBeNull] ILocalizableString displayName = null, bool isLayout = false, string layout = null, string defaultCultureName = null) { Name = Check.NotNullOrWhiteSpace(name, nameof(name), MaxNameLength); - LocalizationResource = localizationResource; + LocalizationResourceName = localizationResourceName; DisplayName = displayName ?? new FixedLocalizableString(Name); IsLayout = isLayout; Layout = layout; diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs index a282b5e5e2..7e2920e446 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs @@ -1,85 +1,50 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; +using System.Threading.Tasks; using Volo.Abp.DependencyInjection; namespace Volo.Abp.TextTemplating; public class TemplateDefinitionManager : ITemplateDefinitionManager, ISingletonDependency { - protected Lazy> TemplateDefinitions { get; } + protected readonly IStaticTemplateDefinitionStore StaticStore; + protected readonly IDynamicTemplateDefinitionStore DynamicStore; - protected AbpTextTemplatingOptions Options { get; } - - protected IServiceProvider ServiceProvider { get; } - - public TemplateDefinitionManager( - IOptions options, - IServiceProvider serviceProvider) + public TemplateDefinitionManager(IStaticTemplateDefinitionStore staticStore, IDynamicTemplateDefinitionStore dynamicStore) { - ServiceProvider = serviceProvider; - Options = options.Value; - - TemplateDefinitions = - new Lazy>(CreateTextTemplateDefinitions, true); + StaticStore = staticStore; + DynamicStore = dynamicStore; } - public virtual TemplateDefinition Get(string name) + public virtual async Task GetAsync(string name) { - Check.NotNull(name, nameof(name)); - - var template = GetOrNull(name); - - if (template == null) + var permission = await GetOrNullAsync(name); + if (permission == null) { - throw new AbpException("Undefined template: " + name); + throw new AbpException("Undefined Template: " + name); } - return template; + return permission; } - public virtual IReadOnlyList GetAll() + public virtual async Task GetOrNullAsync(string name) { - return TemplateDefinitions.Value.Values.ToImmutableList(); - } + Check.NotNull(name, nameof(name)); - public virtual TemplateDefinition GetOrNull(string name) - { - return TemplateDefinitions.Value.GetOrDefault(name); + return await StaticStore.GetOrNullAsync(name) ?? await DynamicStore.GetOrNullAsync(name); } - protected virtual IDictionary CreateTextTemplateDefinitions() + public virtual async Task> GetAllAsync() { - var templates = new Dictionary(); - - using (var scope = ServiceProvider.CreateScope()) - { - var providers = Options - .DefinitionProviders - .Select(p => scope.ServiceProvider.GetRequiredService(p) as ITemplateDefinitionProvider) - .ToList(); - - var context = new TemplateDefinitionContext(templates); + var staticTemplates = await StaticStore.GetAllAsync(); + var staticTemplateNames = staticTemplates + .Select(p => p.Name) + .ToImmutableHashSet(); - foreach (var provider in providers) - { - provider.PreDefine(context); - } - - foreach (var provider in providers) - { - provider.Define(context); - } - - foreach (var provider in providers) - { - provider.PostDefine(context); - } - } + var dynamicTemplates = await DynamicStore.GetAllAsync(); - return templates; + /* We prefer static Templates over dynamics */ + return staticTemplates.Concat(dynamicTemplates.Where(d => !staticTemplateNames.Contains(d.Name))).ToImmutableList(); } } diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs index f496a8fea8..a2c354801d 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs @@ -31,9 +31,9 @@ public abstract class TemplateRenderingEngineBase : ITemplateRenderingEngine protected virtual IStringLocalizer GetLocalizerOrNull(TemplateDefinition templateDefinition) { - if (templateDefinition.LocalizationResource != null) + if (templateDefinition.LocalizationResourceName != null) { - return StringLocalizerFactory.Create(templateDefinition.LocalizationResource); + return StringLocalizerFactory.CreateByResourceName(templateDefinition.LocalizationResourceName); } return StringLocalizerFactory.CreateDefaultOrNull(); diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs index 0ae297a136..27e400c082 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs @@ -5,10 +5,12 @@ namespace Volo.Abp.TextTemplating.VirtualFiles; public class FileInfoLocalizedTemplateContentReader : ILocalizedTemplateContentReader { + private IFileInfo _fileInfo; private string _content; public async Task ReadContentsAsync(IFileInfo fileInfo) { + _fileInfo = fileInfo; _content = await fileInfo.ReadAsStringAsync(); } @@ -21,4 +23,13 @@ public class FileInfoLocalizedTemplateContentReader : ILocalizedTemplateContentR return null; } + + public TemplateContentFileInfo GetFile() + { + return new TemplateContentFileInfo() + { + FileName = _fileInfo.Name, + FileContent = _content + }; + } } diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileInfo.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileInfo.cs new file mode 100644 index 0000000000..5469700432 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileInfo.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.TextTemplating.VirtualFiles; + +public class TemplateContentFileInfo +{ + public string FileName { get; set; } + + public string FileContent { get; set; } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileProvider.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileProvider.cs new file mode 100644 index 0000000000..0b049b07ab --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/TemplateContentFileProvider.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.VirtualFileSystem; + +namespace Volo.Abp.TextTemplating.VirtualFiles; + +public class TemplateContentFileProvider : ITransientDependency +{ + protected IVirtualFileProvider VirtualFileProvider { get; } + + public TemplateContentFileProvider(IVirtualFileProvider virtualFileProvider) + { + VirtualFileProvider = virtualFileProvider; + } + + public async Task> GetFilesAsync(TemplateDefinition templateDefinition) + { + var files = new List(); + + var virtualPath = templateDefinition.GetVirtualFilePathOrNull(); + if (virtualPath == null) + { + return files; + } + + var fileInfo = VirtualFileProvider.GetFileInfo(virtualPath); + if (!fileInfo.Exists) + { + var directoryContents = VirtualFileProvider.GetDirectoryContents(virtualPath); + if (!directoryContents.Exists) + { + throw new AbpException("Could not find a file/folder at the location: " + virtualPath); + } + + fileInfo = new VirtualDirectoryFileInfo(virtualPath, virtualPath, DateTimeOffset.UtcNow); + } + + if (fileInfo.IsDirectory) + { + //TODO: Configure file extensions. + var folderReader = new VirtualFolderLocalizedTemplateContentReader(new[] { ".tpl", ".cshtml" }); + await folderReader.ReadContentsAsync(VirtualFileProvider, virtualPath); + files.AddRange(folderReader.GetFiles()); + } + else + { + var singleFileReader = new FileInfoLocalizedTemplateContentReader(); + await singleFileReader.ReadContentsAsync(fileInfo); + files.Add(singleFileReader.GetFile()); + } + + return files; + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs index 6ff24e4801..828978b1d2 100644 --- a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.FileProviders; using Volo.Abp.VirtualFileSystem; @@ -8,7 +9,7 @@ namespace Volo.Abp.TextTemplating.VirtualFiles; public class VirtualFolderLocalizedTemplateContentReader : ILocalizedTemplateContentReader { - private Dictionary _dictionary; + private Dictionary _dictionary; private readonly string[] _fileExtension; public VirtualFolderLocalizedTemplateContentReader(string[] fileExtension) @@ -20,7 +21,7 @@ public class VirtualFolderLocalizedTemplateContentReader : ILocalizedTemplateCon IVirtualFileProvider virtualFileProvider, string virtualPath) { - _dictionary = new Dictionary(); + _dictionary = new Dictionary(); var directoryContents = virtualFileProvider.GetDirectoryContents(virtualPath); if (!directoryContents.Exists) @@ -35,7 +36,11 @@ public class VirtualFolderLocalizedTemplateContentReader : ILocalizedTemplateCon continue; } - _dictionary.Add(file.Name.RemovePostFix(_fileExtension), await file.ReadAsStringAsync()); + _dictionary.Add(file.Name.RemovePostFix(_fileExtension), new TemplateContentFileInfo() + { + FileName = file.Name, + FileContent = await file.ReadAsStringAsync() + }); } } @@ -46,6 +51,11 @@ public class VirtualFolderLocalizedTemplateContentReader : ILocalizedTemplateCon return null; } - return _dictionary.GetOrDefault(cultureName); + return _dictionary.GetOrDefault(cultureName)?.FileContent; + } + + public List GetFiles() + { + return _dictionary.Values.ToList(); } } diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs index 10312e1513..109547ada5 100644 --- a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs @@ -45,6 +45,11 @@ public class DefaultAbpCompiledViewProvider : IAbpCompiledViewProvider, ITransie } var templateContent = await _templateContentProvider.GetContentOrNullAsync(templateDefinition); + if (templateContent == null) + { + throw new AbpException($"Razor template content of {templateDefinition.Name} is null!"); + } + return CachedAssembles.GetOrAdd((templateDefinition.Name + templateContent).ToMd5(), await CreateAssembly(templateContent)); } diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs index 582ebaf907..86298f2daf 100644 --- a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs @@ -74,7 +74,7 @@ public class RazorTemplateRenderingEngine : TemplateRenderingEngineBase, ITransi Dictionary globalContext, object model = null) { - var templateDefinition = TemplateDefinitionManager.Get(templateName); + var templateDefinition = await TemplateDefinitionManager.GetAsync(templateName); var renderedContent = await RenderSingleTemplateAsync( templateDefinition, diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs index 4612ec04df..a4da669893 100644 --- a/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs +++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs @@ -61,7 +61,7 @@ public class ScribanTemplateRenderingEngine : TemplateRenderingEngineBase, ITran Dictionary globalContext, object model = null) { - var templateDefinition = TemplateDefinitionManager.Get(templateName); + var templateDefinition = await TemplateDefinitionManager.GetAsync(templateName); var renderedContent = await RenderSingleTemplateAsync( templateDefinition, diff --git a/framework/src/Volo.Abp.Threading/Volo.Abp.Threading.csproj b/framework/src/Volo.Abp.Threading/Volo.Abp.Threading.csproj index 70f9ecb0f8..2197766f6b 100644 --- a/framework/src/Volo.Abp.Threading/Volo.Abp.Threading.csproj +++ b/framework/src/Volo.Abp.Threading/Volo.Abp.Threading.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Threading Volo.Abp.Threading $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs index b6f4600caf..108d3bb595 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/AsyncQueryableExecuter.cs @@ -17,7 +17,7 @@ public class AsyncQueryableExecuter : IAsyncQueryableExecuter, ISingletonDepende Providers = providers; } - protected virtual IAsyncQueryableProvider FindProvider(IQueryable queryable) + protected virtual IAsyncQueryableProvider? FindProvider(IQueryable queryable) { return Providers.FirstOrDefault(p => p.CanExecute(queryable)); } @@ -102,21 +102,29 @@ public class AsyncQueryableExecuter : IAsyncQueryableExecuter, ISingletonDepende : Task.FromResult(queryable.First(predicate)); } - public Task FirstOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) + public Task FirstOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) { var provider = FindProvider(queryable); - return provider != null - ? provider.FirstOrDefaultAsync(queryable, cancellationToken) - : Task.FromResult(queryable.FirstOrDefault()); + + if (provider != null) + { + return provider.FirstOrDefaultAsync(queryable, cancellationToken); + } + + return Task.FromResult(queryable.FirstOrDefault())!; } - public Task FirstOrDefaultAsync(IQueryable queryable, Expression> predicate, + public Task FirstOrDefaultAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { var provider = FindProvider(queryable); - return provider != null - ? provider.FirstOrDefaultAsync(queryable, predicate, cancellationToken) - : Task.FromResult(queryable.FirstOrDefault(predicate)); + + if (provider != null) + { + return provider.FirstOrDefaultAsync(queryable, predicate, cancellationToken); + } + + return Task.FromResult(queryable.FirstOrDefault(predicate))!; } public Task LastAsync(IQueryable queryable, CancellationToken cancellationToken = default) @@ -135,21 +143,29 @@ public class AsyncQueryableExecuter : IAsyncQueryableExecuter, ISingletonDepende : Task.FromResult(queryable.Last(predicate)); } - public Task LastOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) + public Task LastOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) { var provider = FindProvider(queryable); - return provider != null - ? provider.LastOrDefaultAsync(queryable, cancellationToken) - : Task.FromResult(queryable.LastOrDefault()); + + if (provider != null) + { + return provider.LastOrDefaultAsync(queryable, cancellationToken); + } + + return Task.FromResult(queryable.LastOrDefault())!; } - public Task LastOrDefaultAsync(IQueryable queryable, Expression> predicate, + public Task LastOrDefaultAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { var provider = FindProvider(queryable); - return provider != null - ? provider.LastOrDefaultAsync(queryable, predicate, cancellationToken) - : Task.FromResult(queryable.LastOrDefault(predicate)); + + if (provider != null) + { + return provider.LastOrDefaultAsync(queryable, predicate, cancellationToken); + } + + return Task.FromResult(queryable.LastOrDefault(predicate))!; } public Task SingleAsync(IQueryable queryable, CancellationToken cancellationToken = default) @@ -168,53 +184,77 @@ public class AsyncQueryableExecuter : IAsyncQueryableExecuter, ISingletonDepende : Task.FromResult(queryable.Single(predicate)); } - public Task SingleOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) + public Task SingleOrDefaultAsync(IQueryable queryable, CancellationToken cancellationToken = default) { var provider = FindProvider(queryable); - return provider != null - ? provider.SingleOrDefaultAsync(queryable, cancellationToken) - : Task.FromResult(queryable.SingleOrDefault()); + + if (provider != null) + { + return provider.SingleOrDefaultAsync(queryable, cancellationToken); + } + + return Task.FromResult(queryable.SingleOrDefault())!; } - public Task SingleOrDefaultAsync(IQueryable queryable, Expression> predicate, + public Task SingleOrDefaultAsync(IQueryable queryable, Expression> predicate, CancellationToken cancellationToken = default) { var provider = FindProvider(queryable); - return provider != null - ? provider.SingleOrDefaultAsync(queryable, predicate, cancellationToken) - : Task.FromResult(queryable.SingleOrDefault(predicate)); + + if (provider != null) + { + return provider.SingleOrDefaultAsync(queryable, predicate, cancellationToken); + } + + return Task.FromResult(queryable.SingleOrDefault(predicate))!; } - public Task MinAsync(IQueryable queryable, CancellationToken cancellationToken = default) + public Task MinAsync(IQueryable queryable, CancellationToken cancellationToken = default) { var provider = FindProvider(queryable); - return provider != null - ? provider.MinAsync(queryable, cancellationToken) - : Task.FromResult(queryable.Min()); + + if(provider != null) + { + return provider.MinAsync(queryable, cancellationToken); + } + + return Task.FromResult(queryable.Min())!; } - public Task MinAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) + public Task MinAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { var provider = FindProvider(queryable); - return provider != null - ? provider.MinAsync(queryable, selector, cancellationToken) - : Task.FromResult(queryable.Min(selector)); + + if(provider != null) + { + return provider.MinAsync(queryable, selector, cancellationToken); + } + + return Task.FromResult(queryable.Min(selector))!; } - public Task MaxAsync(IQueryable queryable, CancellationToken cancellationToken = default) + public Task MaxAsync(IQueryable queryable, CancellationToken cancellationToken = default) { var provider = FindProvider(queryable); - return provider != null - ? provider.MaxAsync(queryable, cancellationToken) - : Task.FromResult(queryable.Max()); + + if(provider != null) + { + return provider.MaxAsync(queryable, cancellationToken); + } + + return Task.FromResult(queryable.Max())!; } - public Task MaxAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) + public Task MaxAsync(IQueryable queryable, Expression> selector, CancellationToken cancellationToken = default) { var provider = FindProvider(queryable); - return provider != null - ? provider.MaxAsync(queryable, selector, cancellationToken) - : Task.FromResult(queryable.Max(selector)); + + if(provider != null) + { + return provider.MaxAsync(queryable, selector, cancellationToken); + } + + return Task.FromResult(queryable.Max(selector))!; } public Task SumAsync(IQueryable queryable, CancellationToken cancellationToken = default) diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableExecuter.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableExecuter.cs index 5d1e3cf7d1..2bea6c4604 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableExecuter.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableExecuter.cs @@ -75,12 +75,12 @@ public interface IAsyncQueryableExecuter CancellationToken cancellationToken = default); - Task FirstOrDefaultAsync( + Task FirstOrDefaultAsync( [NotNull] IQueryable queryable, CancellationToken cancellationToken = default); - Task FirstOrDefaultAsync( + Task FirstOrDefaultAsync( [NotNull] IQueryable queryable, [NotNull] Expression> predicate, CancellationToken cancellationToken = default); @@ -100,12 +100,12 @@ public interface IAsyncQueryableExecuter CancellationToken cancellationToken = default); - Task LastOrDefaultAsync( + Task LastOrDefaultAsync( [NotNull] IQueryable queryable, CancellationToken cancellationToken = default); - Task LastOrDefaultAsync( + Task LastOrDefaultAsync( [NotNull] IQueryable queryable, [NotNull] Expression> predicate, CancellationToken cancellationToken = default); @@ -124,11 +124,11 @@ public interface IAsyncQueryableExecuter [NotNull] Expression> predicate, CancellationToken cancellationToken = default); - Task SingleOrDefaultAsync( + Task SingleOrDefaultAsync( [NotNull] IQueryable queryable, CancellationToken cancellationToken = default); - Task SingleOrDefaultAsync( + Task SingleOrDefaultAsync( [NotNull] IQueryable queryable, [NotNull] Expression> predicate, CancellationToken cancellationToken = default); @@ -137,12 +137,12 @@ public interface IAsyncQueryableExecuter #region Min - Task MinAsync( + Task MinAsync( [NotNull] IQueryable queryable, CancellationToken cancellationToken = default); - Task MinAsync( + Task MinAsync( [NotNull] IQueryable queryable, [NotNull] Expression> selector, CancellationToken cancellationToken = default); @@ -151,12 +151,12 @@ public interface IAsyncQueryableExecuter #region Max - Task MaxAsync( + Task MaxAsync( [NotNull] IQueryable queryable, CancellationToken cancellationToken = default); - Task MaxAsync( + Task MaxAsync( [NotNull] IQueryable queryable, [NotNull] Expression> selector, CancellationToken cancellationToken = default); diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableProvider.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableProvider.cs index f32153d901..3f38553ac5 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableProvider.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Linq/IAsyncQueryableProvider.cs @@ -77,12 +77,12 @@ public interface IAsyncQueryableProvider CancellationToken cancellationToken = default); - Task FirstOrDefaultAsync( + Task FirstOrDefaultAsync( [NotNull] IQueryable queryable, CancellationToken cancellationToken = default); - Task FirstOrDefaultAsync( + Task FirstOrDefaultAsync( [NotNull] IQueryable queryable, [NotNull] Expression> predicate, CancellationToken cancellationToken = default); @@ -102,12 +102,12 @@ public interface IAsyncQueryableProvider CancellationToken cancellationToken = default); - Task LastOrDefaultAsync( + Task LastOrDefaultAsync( [NotNull] IQueryable queryable, CancellationToken cancellationToken = default); - Task LastOrDefaultAsync( + Task LastOrDefaultAsync( [NotNull] IQueryable queryable, [NotNull] Expression> predicate, CancellationToken cancellationToken = default); @@ -126,11 +126,11 @@ public interface IAsyncQueryableProvider [NotNull] Expression> predicate, CancellationToken cancellationToken = default); - Task SingleOrDefaultAsync( + Task SingleOrDefaultAsync( [NotNull] IQueryable queryable, CancellationToken cancellationToken = default); - Task SingleOrDefaultAsync( + Task SingleOrDefaultAsync( [NotNull] IQueryable queryable, [NotNull] Expression> predicate, CancellationToken cancellationToken = default); @@ -139,12 +139,12 @@ public interface IAsyncQueryableProvider #region Min - Task MinAsync( + Task MinAsync( [NotNull] IQueryable queryable, CancellationToken cancellationToken = default); - Task MinAsync( + Task MinAsync( [NotNull] IQueryable queryable, [NotNull] Expression> selector, CancellationToken cancellationToken = default); @@ -153,12 +153,12 @@ public interface IAsyncQueryableProvider #region Max - Task MaxAsync( + Task MaxAsync( [NotNull] IQueryable queryable, CancellationToken cancellationToken = default); - Task MaxAsync( + Task MaxAsync( [NotNull] IQueryable queryable, [NotNull] Expression> selector, CancellationToken cancellationToken = default); diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpAsyncTimer.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpAsyncTimer.cs index 908b3fa09d..c17861ac21 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpAsyncTimer.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpAsyncTimer.cs @@ -43,7 +43,7 @@ public class AbpAsyncTimer : ITransientDependency Logger = NullLogger.Instance; _taskTimer = new Timer( - TimerCallBack, + TimerCallBack!, null, Timeout.Infinite, Timeout.Infinite diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs index a5d7a4bdb8..05e4b14daa 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs @@ -15,7 +15,7 @@ public class AbpTimer : ITransientDependency /// /// This event is raised periodically according to Period of Timer. /// - public event EventHandler Elapsed; + public event EventHandler Elapsed = default!; /// /// Task period of timer (as milliseconds). @@ -42,7 +42,7 @@ public class AbpTimer : ITransientDependency Logger = NullLogger.Instance; _taskTimer = new Timer( - TimerCallBack, + TimerCallBack!, null, Timeout.Infinite, Timeout.Infinite diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AmbientDataContextAmbientScopeProvider.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AmbientDataContextAmbientScopeProvider.cs index 06b71d16f3..3eabab1390 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AmbientDataContextAmbientScopeProvider.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AmbientDataContextAmbientScopeProvider.cs @@ -24,7 +24,7 @@ public class AmbientDataContextAmbientScopeProvider : IAmbientScopeProvider>.Instance; } - public T GetValue(string contextKey) + public T? GetValue(string contextKey) { var item = GetCurrentItem(contextKey); if (item == null) @@ -52,6 +52,11 @@ public class AmbientDataContextAmbientScopeProvider : IAmbientScopeProvider : IAmbientScopeProvider : IAmbientScopeProvider> AsyncLocalDictionary = new ConcurrentDictionary>(); + private static readonly ConcurrentDictionary> AsyncLocalDictionary = new ConcurrentDictionary>(); - public void SetData(string key, object value) + public void SetData(string key, object? value) { - var asyncLocal = AsyncLocalDictionary.GetOrAdd(key, (k) => new AsyncLocal()); + var asyncLocal = AsyncLocalDictionary.GetOrAdd(key, (k) => new AsyncLocal()); asyncLocal.Value = value; } - public object GetData(string key) + public object? GetData(string key) { - var asyncLocal = AsyncLocalDictionary.GetOrAdd(key, (k) => new AsyncLocal()); + var asyncLocal = AsyncLocalDictionary.GetOrAdd(key, (k) => new AsyncLocal()); return asyncLocal.Value; } } diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AsyncLocalSimpleScopeExtensions.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AsyncLocalSimpleScopeExtensions.cs index 3d353921d9..5ad251f30c 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AsyncLocalSimpleScopeExtensions.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AsyncLocalSimpleScopeExtensions.cs @@ -5,11 +5,11 @@ namespace Volo.Abp.Threading; public static class AsyncLocalSimpleScopeExtensions { - public static IDisposable SetScoped(this AsyncLocal asyncLocal, T value) + public static IDisposable SetScoped(this AsyncLocal asyncLocal, T value) { var previousValue = asyncLocal.Value; asyncLocal.Value = value; - return new DisposeAction, T>>(static (state) => + return new DisposeAction, T?>>(static (state) => { var (asyncLocal, previousValue) = state; asyncLocal.Value = previousValue; diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs index 7de1270ff0..a713d3a7fd 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs @@ -11,7 +11,7 @@ public abstract class CancellationTokenProviderBase : ICancellationTokenProvider protected IAmbientScopeProvider CancellationTokenOverrideScopeProvider { get; } - protected CancellationTokenOverride OverrideValue => CancellationTokenOverrideScopeProvider.GetValue(CancellationTokenOverrideContextKey); + protected CancellationTokenOverride? OverrideValue => CancellationTokenOverrideScopeProvider.GetValue(CancellationTokenOverrideContextKey); protected CancellationTokenProviderBase(IAmbientScopeProvider cancellationTokenOverrideScopeProvider) { diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/IAmbientDataContext.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/IAmbientDataContext.cs index 78482aba53..ae5a2aeb92 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/IAmbientDataContext.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/IAmbientDataContext.cs @@ -2,7 +2,7 @@ public interface IAmbientDataContext { - void SetData(string key, object value); + void SetData(string key, object? value); - object GetData(string key); + object? GetData(string key); } diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/IAmbientScopeProvider.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/IAmbientScopeProvider.cs index 4f2cd7650c..b65edec931 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/IAmbientScopeProvider.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/IAmbientScopeProvider.cs @@ -4,7 +4,7 @@ namespace Volo.Abp.Threading; public interface IAmbientScopeProvider { - T GetValue(string contextKey); + T? GetValue(string contextKey); IDisposable BeginScope(string contextKey, T value); } diff --git a/framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj b/framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj index 4ba0547035..67875083a6 100644 --- a/framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj +++ b/framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Timing Volo.Abp.Timing $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimeZoneHelper.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimeZoneHelper.cs new file mode 100644 index 0000000000..6101585878 --- /dev/null +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimeZoneHelper.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TimeZoneConverter; + +namespace Volo.Abp.Timing; + +public static class TimeZoneHelper +{ + public static List GetTimezones(List timezones) + { + return timezones + .OrderBy(x => x.Name) + .Select(x => new NameValue( $"{x.Name} ({GetTimezoneOffset(TZConvert.GetTimeZoneInfo(x.Name))})", x.Name)) + .ToList(); + } + + public static string GetTimezoneOffset(TimeZoneInfo timeZoneInfo) + { + if (timeZoneInfo.BaseUtcOffset < TimeSpan.Zero) + { + return "-" + timeZoneInfo.BaseUtcOffset.ToString(@"hh\:mm"); + } + + return "+" + timeZoneInfo.BaseUtcOffset.ToString(@"hh\:mm"); + } +} diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo.Abp.UI.Navigation.csproj b/framework/src/Volo.Abp.UI.Navigation/Volo.Abp.UI.Navigation.csproj index 65b07f1579..e23d96950e 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo.Abp.UI.Navigation.csproj +++ b/framework/src/Volo.Abp.UI.Navigation/Volo.Abp.UI.Navigation.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.UI.Navigation Volo.Abp.UI.Navigation $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenu.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenu.cs index 9f48aebf97..d38279b1cd 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenu.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenu.cs @@ -26,7 +26,7 @@ public class ApplicationMenu : IHasMenuItems, IHasMenuGroups _displayName = value; } } - private string _displayName; + private string _displayName = default!; /// [NotNull] @@ -44,7 +44,7 @@ public class ApplicationMenu : IHasMenuItems, IHasMenuGroups public ApplicationMenu( [NotNull] string name, - string displayName = null) + string? displayName = null) { Check.NotNullOrWhiteSpace(name, nameof(name)); diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs index 624abde425..59814ff3be 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs @@ -29,8 +29,7 @@ public static class ApplicationMenuExtensions return menuItem; } - [CanBeNull] - public static ApplicationMenuItem GetMenuItemOrNull( + public static ApplicationMenuItem? GetMenuItemOrNull( [NotNull] this IHasMenuItems menuWithItems, string menuItemName) { @@ -79,8 +78,7 @@ public static class ApplicationMenuExtensions return menuGroup; } - [CanBeNull] - public static ApplicationMenuGroup GetMenuGroupOrNull( + public static ApplicationMenuGroup? GetMenuGroupOrNull( [NotNull] this IHasMenuGroups menuWithGroups, string menuGroupName) { diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs index 8d29e99552..ab76c1c337 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuGroup.cs @@ -4,8 +4,8 @@ namespace Volo.Abp.UI.Navigation; public class ApplicationMenuGroup { - private string _displayName; - private string _elementId; + private string _displayName = default!; + private string? _elementId; /// /// Default value of a group item. @@ -33,7 +33,7 @@ public class ApplicationMenuGroup /// /// Can be used to render the element with a specific Id for DOM selections. /// - public string ElementId { + public string? ElementId { get { return _elementId; } set { _elementId = NormalizeElementId(value); @@ -49,7 +49,7 @@ public class ApplicationMenuGroup public ApplicationMenuGroup( [NotNull] string name, [NotNull] string displayName, - string elementId = null, + string? elementId = null, int order = DefaultOrder) { Check.NotNullOrWhiteSpace(name, nameof(name)); @@ -57,7 +57,7 @@ public class ApplicationMenuGroup Name = name; DisplayName = displayName; - ElementId = elementId; + ElementId = elementId ?? GetDefaultElementId(); Order = order; } @@ -66,7 +66,7 @@ public class ApplicationMenuGroup return "MenuGroup_" + Name; } - private string NormalizeElementId(string elementId) + private string? NormalizeElementId(string? elementId) { return elementId?.Replace(".", "_"); } diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs index 54bd591469..0c42a15c5e 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs @@ -7,8 +7,8 @@ namespace Volo.Abp.UI.Navigation; public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers { - private string _displayName; - private string _elementId; + private string _displayName = default!; + private string? _elementId; /// /// Default value of a menu item. @@ -42,14 +42,12 @@ public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers /// The URL to navigate when this menu item is selected. /// - [CanBeNull] - public string Url { get; set; } + public string? Url { get; set; } /// /// Icon of the menu item if exists. /// - [CanBeNull] - public string Icon { get; set; } + public string? Icon { get; set; } /// /// Returns true if this menu item has no child . @@ -59,8 +57,7 @@ public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers /// Target of the menu item. Can be null, "_blank", "_self", "_parent", "_top" or a frame name for web applications. /// - [CanBeNull] - public string Target { get; set; } + public string? Target { get; set; } /// /// Can be used to disable this menu item. @@ -71,9 +68,8 @@ public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers> StateCheckers { get; } @@ -86,7 +82,7 @@ public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers /// Can be used to render the element with a specific Id for DOM selections. /// - public string ElementId { + public string? ElementId { get { return _elementId; } set { _elementId = NormalizeElementId(value); @@ -96,24 +92,24 @@ public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers /// Can be used to render the element with extra CSS classes. /// - public string CssClass { get; set; } + public string? CssClass { get; set; } /// /// Can be used to group menu items. /// - public string GroupName { get; set; } + public string? GroupName { get; set; } public ApplicationMenuItem( [NotNull] string name, [NotNull] string displayName, - string url = null, - string icon = null, + string? url = null, + string? icon = null, int order = DefaultOrder, - string target = null, - string elementId = null, - string cssClass = null, - string groupName = null, - string requiredPermissionName = null) + string? target = null, + string? elementId = null, + string? cssClass = null, + string? groupName = null, + string? requiredPermissionName = null) { Check.NotNullOrWhiteSpace(name, nameof(name)); Check.NotNullOrWhiteSpace(displayName, nameof(displayName)); @@ -158,7 +154,7 @@ public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers !x.GroupName.IsNullOrWhiteSpace()).GroupBy(x => x.GroupName)) { - var group = applicationMenu.GetMenuGroupOrNull(menuGroup.First().GroupName); + var group = applicationMenu.GetMenuGroupOrNull(menuGroup.First().GroupName!); if (group != null) { continue; diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs index ff1db3a772..17a4e684e9 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs @@ -33,7 +33,7 @@ public class AppUrlProvider : IAppUrlProvider, ITransientDependency Logger = NullLogger.Instance; } - public virtual async Task GetUrlAsync(string appName, string urlName = null) + public virtual async Task GetUrlAsync(string appName, string? urlName = null) { return await ReplacePlaceHoldersAsync( await GetConfiguredUrl( @@ -53,12 +53,12 @@ public class AppUrlProvider : IAppUrlProvider, ITransientDependency return allow; } - protected virtual async Task GetConfiguredUrl(string appName, string urlName) + protected virtual async Task GetConfiguredUrl(string appName, string? urlName) { var url = await GetUrlOrNullAsync(appName, urlName); if (!url.IsNullOrEmpty()) { - return url; + return url!; } if (!urlName.IsNullOrEmpty()) @@ -115,10 +115,10 @@ public class AppUrlProvider : IAppUrlProvider, ITransientDependency return tenantConfiguration.Name; } - return CurrentTenant.Name; + return CurrentTenant.Name!; } - public Task GetUrlOrNullAsync([NotNull] string appName, [CanBeNull] string urlName = null) + public Task GetUrlOrNullAsync([NotNull] string appName, string? urlName = null) { var app = Options.Applications[appName]; @@ -127,13 +127,13 @@ public class AppUrlProvider : IAppUrlProvider, ITransientDependency return Task.FromResult(app.RootUrl); } - var url = app.Urls.GetOrDefault(urlName); + var url = app.Urls.GetOrDefault(urlName!); if (app.RootUrl == null) { return Task.FromResult(url); } - return Task.FromResult(app.RootUrl.EnsureEndsWith('/') + url); + return Task.FromResult(app.RootUrl.EnsureEndsWith('/') + url); } } diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/ApplicationUrlInfo.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/ApplicationUrlInfo.cs index 3e57fadcae..0e00c8039c 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/ApplicationUrlInfo.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/ApplicationUrlInfo.cs @@ -4,7 +4,7 @@ namespace Volo.Abp.UI.Navigation.Urls; public class ApplicationUrlInfo { - public string RootUrl { get; set; } + public string? RootUrl { get; set; } public IDictionary Urls { get; } diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/IAppUrlProvider.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/IAppUrlProvider.cs index 51f6a56afa..9241c5f428 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/IAppUrlProvider.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/IAppUrlProvider.cs @@ -5,9 +5,9 @@ namespace Volo.Abp.UI.Navigation.Urls; public interface IAppUrlProvider { - Task GetUrlAsync([NotNull] string appName, [CanBeNull] string urlName = null); + Task GetUrlAsync([NotNull] string appName, string? urlName = null); - Task GetUrlOrNullAsync([NotNull] string appName, [CanBeNull] string urlName = null); + Task GetUrlOrNullAsync([NotNull] string appName, string? urlName = null); bool IsRedirectAllowedUrl(string url); } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json index 8d45d26654..45b80c1aeb 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json @@ -52,6 +52,7 @@ "OthersGroup": "Other", "Today": "Today", "Apply": "Apply", + "InternetConnectionInfo": "The operation could not be performed. Your internet connection is not available at the moment.", "CopiedToTheClipboard": "Copied to the clipboard" } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json index 366156564a..f3ede9eb41 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json @@ -52,6 +52,7 @@ "OthersGroup": "Diğer", "Today": "Bugün", "Apply": "Uygula", + "InternetConnectionInfo": "İşlem gerçekleştirilemedi. İnternet bağlantısı mevcut değil.", "CopiedToTheClipboard": "Panoya kopyalandı" } } diff --git a/framework/src/Volo.Abp.UI/Volo.Abp.UI.csproj b/framework/src/Volo.Abp.UI/Volo.Abp.UI.csproj index 0cf11fba78..b0bd555c96 100644 --- a/framework/src/Volo.Abp.UI/Volo.Abp.UI.csproj +++ b/framework/src/Volo.Abp.UI/Volo.Abp.UI.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.UI Volo.Abp.UI $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/DefaultBrandingProvider.cs b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/DefaultBrandingProvider.cs index 785c03a0e1..fcb1a7545e 100644 --- a/framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/DefaultBrandingProvider.cs +++ b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/DefaultBrandingProvider.cs @@ -6,7 +6,7 @@ public class DefaultBrandingProvider : IBrandingProvider, ITransientDependency { public virtual string AppName => "MyApplication"; - public virtual string LogoUrl => null; + public virtual string? LogoUrl => null; - public virtual string LogoReverseUrl => null; + public virtual string? LogoReverseUrl => null; } diff --git a/framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/IBrandingProvider.cs b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/IBrandingProvider.cs index 95085f56a6..f37ee09df1 100644 --- a/framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/IBrandingProvider.cs +++ b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/Branding/IBrandingProvider.cs @@ -7,10 +7,10 @@ public interface IBrandingProvider /// /// Logo on white background /// - string LogoUrl { get; } + string? LogoUrl { get; } /// /// Logo on dark background /// - string LogoReverseUrl { get; } + string? LogoReverseUrl { get; } } diff --git a/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/AbpLayoutHookOptions.cs b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/AbpLayoutHookOptions.cs index d5ba4aa239..b76e713a8e 100644 --- a/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/AbpLayoutHookOptions.cs +++ b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/AbpLayoutHookOptions.cs @@ -12,7 +12,7 @@ public class AbpLayoutHookOptions Hooks = new Dictionary>(); } - public AbpLayoutHookOptions Add(string name, Type componentType, string layout = null) + public AbpLayoutHookOptions Add(string name, Type componentType, string? layout = null) { Hooks .GetOrAdd(name, () => new List()) diff --git a/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHookInfo.cs b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHookInfo.cs index db4ca39466..bb5c8e4801 100644 --- a/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHookInfo.cs +++ b/framework/src/Volo.Abp.UI/Volo/Abp/Ui/LayoutHooks/LayoutHookInfo.cs @@ -13,9 +13,9 @@ public class LayoutHookInfo /// Specifies the layout name to apply this hook. /// null indicates that this hook will be applied to all layouts. /// - public string Layout { get; } + public string? Layout { get; } - public LayoutHookInfo(Type componentType, string layout = null) + public LayoutHookInfo(Type componentType, string? layout = null) { ComponentType = componentType; Layout = layout; diff --git a/framework/src/Volo.Abp.Uow/Volo.Abp.Uow.csproj b/framework/src/Volo.Abp.Uow/Volo.Abp.Uow.csproj index f33af433e7..f1c8b13cad 100644 --- a/framework/src/Volo.Abp.Uow/Volo.Abp.Uow.csproj +++ b/framework/src/Volo.Abp.Uow/Volo.Abp.Uow.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Uow Volo.Abp.Uow $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AlwaysDisableTransactionsUnitOfWorkManager.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AlwaysDisableTransactionsUnitOfWorkManager.cs index a02f63c3e1..462c001e6d 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AlwaysDisableTransactionsUnitOfWorkManager.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AlwaysDisableTransactionsUnitOfWorkManager.cs @@ -12,7 +12,7 @@ public class AlwaysDisableTransactionsUnitOfWorkManager : IUnitOfWorkManager _unitOfWorkManager = unitOfWorkManager; } - public IUnitOfWork Current => _unitOfWorkManager.Current; + public IUnitOfWork? Current => _unitOfWorkManager.Current; public IUnitOfWork Begin(AbpUnitOfWorkOptions options, bool requiresNew = false) { diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AmbientUnitOfWork.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AmbientUnitOfWork.cs index 183126cb50..dc70dfad46 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AmbientUnitOfWork.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AmbientUnitOfWork.cs @@ -6,21 +6,21 @@ namespace Volo.Abp.Uow; [ExposeServices(typeof(IAmbientUnitOfWork), typeof(IUnitOfWorkAccessor))] public class AmbientUnitOfWork : IAmbientUnitOfWork, ISingletonDependency { - public IUnitOfWork UnitOfWork => _currentUow.Value; + public IUnitOfWork? UnitOfWork => _currentUow.Value; - private readonly AsyncLocal _currentUow; + private readonly AsyncLocal _currentUow; public AmbientUnitOfWork() { - _currentUow = new AsyncLocal(); + _currentUow = new AsyncLocal(); } - public void SetUnitOfWork(IUnitOfWork unitOfWork) + public void SetUnitOfWork(IUnitOfWork? unitOfWork) { _currentUow.Value = unitOfWork; } - public IUnitOfWork GetCurrentByChecking() + public IUnitOfWork? GetCurrentByChecking() { var uow = UnitOfWork; diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ChildUnitOfWork.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ChildUnitOfWork.cs index bf8a44f724..eb51d8c189 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ChildUnitOfWork.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ChildUnitOfWork.cs @@ -10,9 +10,9 @@ internal class ChildUnitOfWork : IUnitOfWork { public Guid Id => _parent.Id; - public IAbpUnitOfWorkOptions Options => _parent.Options; + public IAbpUnitOfWorkOptions? Options => _parent.Options; - public IUnitOfWork Outer => _parent.Outer; + public IUnitOfWork? Outer => _parent.Outer; public bool IsReserved => _parent.IsReserved; @@ -20,10 +20,10 @@ internal class ChildUnitOfWork : IUnitOfWork public bool IsCompleted => _parent.IsCompleted; - public string ReservationName => _parent.ReservationName; + public string? ReservationName => _parent.ReservationName; - public event EventHandler Failed; - public event EventHandler Disposed; + public event EventHandler Failed = default!; + public event EventHandler Disposed = default!; public IServiceProvider ServiceProvider => _parent.ServiceProvider; @@ -37,11 +37,11 @@ internal class ChildUnitOfWork : IUnitOfWork _parent = parent; - _parent.Failed += (sender, args) => { Failed.InvokeSafely(sender, args); }; - _parent.Disposed += (sender, args) => { Disposed.InvokeSafely(sender, args); }; + _parent.Failed += (sender, args) => { Failed.InvokeSafely(sender!, args); }; + _parent.Disposed += (sender, args) => { Disposed.InvokeSafely(sender!, args); }; } - public void SetOuter(IUnitOfWork outer) + public void SetOuter(IUnitOfWork? outer) { _parent.SetOuter(outer); } @@ -78,19 +78,19 @@ internal class ChildUnitOfWork : IUnitOfWork public void AddOrReplaceLocalEvent( UnitOfWorkEventRecord eventRecord, - Predicate replacementSelector = null) + Predicate? replacementSelector = null) { _parent.AddOrReplaceLocalEvent(eventRecord, replacementSelector); } public void AddOrReplaceDistributedEvent( UnitOfWorkEventRecord eventRecord, - Predicate replacementSelector = null) + Predicate? replacementSelector = null) { _parent.AddOrReplaceDistributedEvent(eventRecord, replacementSelector); } - public IDatabaseApi FindDatabaseApi(string key) + public IDatabaseApi? FindDatabaseApi(string key) { return _parent.FindDatabaseApi(key); } @@ -105,7 +105,7 @@ internal class ChildUnitOfWork : IUnitOfWork return _parent.GetOrAddDatabaseApi(key, factory); } - public ITransactionApi FindTransactionApi(string key) + public ITransactionApi? FindTransactionApi(string key) { return _parent.FindTransactionApi(key); } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IAmbientUnitOfWork.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IAmbientUnitOfWork.cs index e29ed5aa6a..5781da4140 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IAmbientUnitOfWork.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IAmbientUnitOfWork.cs @@ -2,5 +2,5 @@ public interface IAmbientUnitOfWork : IUnitOfWorkAccessor { - IUnitOfWork GetCurrentByChecking(); + IUnitOfWork? GetCurrentByChecking(); } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IDatabaseApiContainer.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IDatabaseApiContainer.cs index 429bd48998..23d3b0f20b 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IDatabaseApiContainer.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IDatabaseApiContainer.cs @@ -6,8 +6,7 @@ namespace Volo.Abp.Uow; public interface IDatabaseApiContainer : IServiceProviderAccessor { - [CanBeNull] - IDatabaseApi FindDatabaseApi([NotNull] string key); + IDatabaseApi? FindDatabaseApi([NotNull] string key); void AddDatabaseApi([NotNull] string key, [NotNull] IDatabaseApi api); diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ITransactionApiContainer.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ITransactionApiContainer.cs index f5bdf13ccb..9acce6ce69 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ITransactionApiContainer.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/ITransactionApiContainer.cs @@ -5,8 +5,7 @@ namespace Volo.Abp.Uow; public interface ITransactionApiContainer { - [CanBeNull] - ITransactionApi FindTransactionApi([NotNull] string key); + ITransactionApi? FindTransactionApi([NotNull] string key); void AddTransactionApi([NotNull] string key, [NotNull] ITransactionApi api); diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWork.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWork.cs index 200ce937d9..15dc2bdec0 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWork.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWork.cs @@ -17,9 +17,9 @@ public interface IUnitOfWork : IDatabaseApiContainer, ITransactionApiContainer, event EventHandler Disposed; - IAbpUnitOfWorkOptions Options { get; } + IAbpUnitOfWorkOptions? Options { get; } - IUnitOfWork Outer { get; } + IUnitOfWork? Outer { get; } bool IsReserved { get; } @@ -27,9 +27,9 @@ public interface IUnitOfWork : IDatabaseApiContainer, ITransactionApiContainer, bool IsCompleted { get; } - string ReservationName { get; } + string? ReservationName { get; } - void SetOuter([CanBeNull] IUnitOfWork outer); + void SetOuter(IUnitOfWork? outer); void Initialize([NotNull] AbpUnitOfWorkOptions options); @@ -45,11 +45,11 @@ public interface IUnitOfWork : IDatabaseApiContainer, ITransactionApiContainer, void AddOrReplaceLocalEvent( UnitOfWorkEventRecord eventRecord, - Predicate replacementSelector = null + Predicate? replacementSelector = null ); void AddOrReplaceDistributedEvent( UnitOfWorkEventRecord eventRecord, - Predicate replacementSelector = null + Predicate? replacementSelector = null ); } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkAccessor.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkAccessor.cs index 59fd00ce96..e2333b5bbc 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkAccessor.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkAccessor.cs @@ -4,8 +4,7 @@ namespace Volo.Abp.Uow; public interface IUnitOfWorkAccessor { - [CanBeNull] - IUnitOfWork UnitOfWork { get; } + IUnitOfWork? UnitOfWork { get; } - void SetUnitOfWork([CanBeNull] IUnitOfWork unitOfWork); + void SetUnitOfWork(IUnitOfWork? unitOfWork); } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkManager.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkManager.cs index 34796fe15b..4263dc5778 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkManager.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IUnitOfWorkManager.cs @@ -4,8 +4,7 @@ namespace Volo.Abp.Uow; public interface IUnitOfWorkManager { - [CanBeNull] - IUnitOfWork Current { get; } + IUnitOfWork? Current { get; } [NotNull] IUnitOfWork Begin([NotNull] AbpUnitOfWorkOptions options, bool requiresNew = false); diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs index 626c74478b..c04393d104 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs @@ -21,9 +21,9 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency public Guid Id { get; } = Guid.NewGuid(); - public IAbpUnitOfWorkOptions Options { get; private set; } + public IAbpUnitOfWorkOptions? Options { get; private set; } - public IUnitOfWork Outer { get; private set; } + public IUnitOfWork? Outer { get; private set; } public bool IsReserved { get; set; } @@ -31,14 +31,14 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency public bool IsCompleted { get; private set; } - public string ReservationName { get; set; } + public string? ReservationName { get; set; } protected List> CompletedHandlers { get; } = new List>(); protected List DistributedEvents { get; } = new List(); protected List LocalEvents { get; } = new List(); - public event EventHandler Failed; - public event EventHandler Disposed; + public event EventHandler Failed = default!; + public event EventHandler Disposed = default!; public IServiceProvider ServiceProvider { get; } protected IUnitOfWorkEventPublisher UnitOfWorkEventPublisher { get; } @@ -50,7 +50,7 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency private readonly Dictionary _transactionApis; private readonly AbpUnitOfWorkDefaultOptions _defaultOptions; - private Exception _exception; + private Exception? _exception; private bool _isCompleting; private bool _isRolledback; @@ -75,7 +75,7 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency if (Options != null) { - throw new AbpException("This unit of work is already initialized before!"); + throw new AbpException("This unit of work has already been initialized."); } Options = _defaultOptions.Normalize(options.Clone()); @@ -84,13 +84,13 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency public virtual void Reserve(string reservationName) { - Check.NotNull(reservationName, nameof(reservationName)); + Check.NotNullOrWhiteSpace(reservationName, nameof(reservationName)); ReservationName = reservationName; IsReserved = true; } - public virtual void SetOuter(IUnitOfWork outer) + public virtual void SetOuter(IUnitOfWork? outer) { Outer = outer; } @@ -104,9 +104,9 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency foreach (var databaseApi in GetAllActiveDatabaseApis()) { - if (databaseApi is ISupportsSavingChanges) + if (databaseApi is ISupportsSavingChanges supportsSavingChangesDatabaseApi) { - await (databaseApi as ISupportsSavingChanges).SaveChangesAsync(cancellationToken); + await supportsSavingChangesDatabaseApi.SaveChangesAsync(cancellationToken); } } } @@ -181,19 +181,19 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency await RollbackAllAsync(cancellationToken); } - public virtual IDatabaseApi FindDatabaseApi(string key) + public virtual IDatabaseApi? FindDatabaseApi(string key) { return _databaseApis.GetOrDefault(key); } public virtual void AddDatabaseApi(string key, IDatabaseApi api) { - Check.NotNull(key, nameof(key)); + Check.NotNullOrWhiteSpace(key, nameof(key)); Check.NotNull(api, nameof(api)); if (_databaseApis.ContainsKey(key)) { - throw new AbpException("There is already a database API in this unit of work with given key."); + throw new AbpException("This unit of work already contains a database API for the given key."); } _databaseApis.Add(key, api); @@ -201,27 +201,27 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency public virtual IDatabaseApi GetOrAddDatabaseApi(string key, Func factory) { - Check.NotNull(key, nameof(key)); + Check.NotNullOrWhiteSpace(key, nameof(key)); Check.NotNull(factory, nameof(factory)); return _databaseApis.GetOrAdd(key, factory); } - public virtual ITransactionApi FindTransactionApi(string key) + public virtual ITransactionApi? FindTransactionApi(string key) { - Check.NotNull(key, nameof(key)); + Check.NotNullOrWhiteSpace(key, nameof(key)); return _transactionApis.GetOrDefault(key); } public virtual void AddTransactionApi(string key, ITransactionApi api) { - Check.NotNull(key, nameof(key)); + Check.NotNullOrWhiteSpace(key, nameof(key)); Check.NotNull(api, nameof(api)); if (_transactionApis.ContainsKey(key)) { - throw new AbpException("There is already a transaction API in this unit of work with given key."); + throw new AbpException("This unit of work already contains a transaction API for the given key."); } _transactionApis.Add(key, api); @@ -229,7 +229,7 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency public virtual ITransactionApi GetOrAddTransactionApi(string key, Func factory) { - Check.NotNull(key, nameof(key)); + Check.NotNullOrWhiteSpace(key, nameof(key)); Check.NotNull(factory, nameof(factory)); return _transactionApis.GetOrAdd(key, factory); @@ -242,14 +242,14 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency public virtual void AddOrReplaceLocalEvent( UnitOfWorkEventRecord eventRecord, - Predicate replacementSelector = null) + Predicate? replacementSelector = null) { AddOrReplaceEvent(LocalEvents, eventRecord, replacementSelector); } public virtual void AddOrReplaceDistributedEvent( UnitOfWorkEventRecord eventRecord, - Predicate replacementSelector = null) + Predicate? replacementSelector = null) { AddOrReplaceEvent(DistributedEvents, eventRecord, replacementSelector); } @@ -257,7 +257,7 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency public virtual void AddOrReplaceEvent( List eventRecords, UnitOfWorkEventRecord eventRecord, - Predicate replacementSelector = null) + Predicate? replacementSelector = null) { if (replacementSelector == null) { @@ -332,7 +332,7 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency { if (IsCompleted || _isCompleting) { - throw new AbpException("Complete is called before!"); + throw new AbpException("Completion has already been requested for this unit of work."); } } @@ -340,11 +340,11 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency { foreach (var databaseApi in GetAllActiveDatabaseApis()) { - if (databaseApi is ISupportsRollback) + if (databaseApi is ISupportsRollback supportsRollbackDatabaseApi) { try { - await (databaseApi as ISupportsRollback).RollbackAsync(cancellationToken); + await supportsRollbackDatabaseApi.RollbackAsync(cancellationToken); } catch { } } @@ -352,11 +352,11 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency foreach (var transactionApi in GetAllActiveTransactionApis()) { - if (transactionApi is ISupportsRollback) + if (transactionApi is ISupportsRollback supportsRollbackTransactionApi) { try { - await (transactionApi as ISupportsRollback).RollbackAsync(cancellationToken); + await supportsRollbackTransactionApi.RollbackAsync(cancellationToken); } catch { } } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs index e8c1d293d7..5867beab13 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkFailedEventArgs.cs @@ -13,8 +13,7 @@ public class UnitOfWorkFailedEventArgs : UnitOfWorkEventArgs /// Can be null if there is no exception, but is not called. /// Can be null if another exception occurred during the UOW. /// - [CanBeNull] - public Exception Exception { get; } + public Exception? Exception { get; } /// /// True, if the unit of work is manually rolled back. @@ -24,7 +23,7 @@ public class UnitOfWorkFailedEventArgs : UnitOfWorkEventArgs /// /// Creates a new object. /// - public UnitOfWorkFailedEventArgs([NotNull] IUnitOfWork unitOfWork, [CanBeNull] Exception exception, bool isRolledback) + public UnitOfWorkFailedEventArgs([NotNull] IUnitOfWork unitOfWork, Exception? exception, bool isRolledback) : base(unitOfWork) { Exception = exception; diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkHelper.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkHelper.cs index 94929a6d1c..3e836a9ed0 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkHelper.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkHelper.cs @@ -23,7 +23,7 @@ public static class UnitOfWorkHelper return false; } - public static bool IsUnitOfWorkMethod([NotNull] MethodInfo methodInfo, [CanBeNull] out UnitOfWorkAttribute unitOfWorkAttribute) + public static bool IsUnitOfWorkMethod([NotNull] MethodInfo methodInfo, out UnitOfWorkAttribute? unitOfWorkAttribute) { Check.NotNull(methodInfo, nameof(methodInfo)); @@ -57,7 +57,7 @@ public static class UnitOfWorkHelper return false; } - public static UnitOfWorkAttribute GetUnitOfWorkAttributeOrNull(MethodInfo methodInfo) + public static UnitOfWorkAttribute? GetUnitOfWorkAttributeOrNull(MethodInfo methodInfo) { var attrs = methodInfo.GetCustomAttributes(true).OfType().ToArray(); if (attrs.Length > 0) @@ -65,12 +65,15 @@ public static class UnitOfWorkHelper return attrs[0]; } - attrs = methodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes(true).OfType().ToArray(); - if (attrs.Length > 0) + if (methodInfo.DeclaringType != null) { - return attrs[0]; + attrs = methodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes(true).OfType().ToArray(); + if (attrs.Length > 0) + { + return attrs[0]; + } } - + return null; } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs index 130f1d3e7b..d49d131299 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkInterceptor.cs @@ -52,7 +52,7 @@ public class UnitOfWorkInterceptor : AbpInterceptor, ITransientDependency } } - private AbpUnitOfWorkOptions CreateOptions(IServiceProvider serviceProvider, IAbpMethodInvocation invocation, [CanBeNull] UnitOfWorkAttribute unitOfWorkAttribute) + private AbpUnitOfWorkOptions CreateOptions(IServiceProvider serviceProvider, IAbpMethodInvocation invocation, UnitOfWorkAttribute? unitOfWorkAttribute) { var options = new AbpUnitOfWorkOptions(); diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkManager.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkManager.cs index 4752f5bdba..970f7030ca 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkManager.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkManager.cs @@ -10,7 +10,7 @@ public class UnitOfWorkManager : IUnitOfWorkManager, ISingletonDependency [Obsolete("This will be removed in next versions.")] public static AsyncLocal DisableObsoleteDbContextCreationWarning { get; } = new AsyncLocal(); - public IUnitOfWork Current => _ambientUnitOfWork.GetCurrentByChecking(); + public IUnitOfWork? Current => _ambientUnitOfWork.GetCurrentByChecking(); private readonly IServiceScopeFactory _serviceScopeFactory; private readonly IAmbientUnitOfWork _ambientUnitOfWork; diff --git a/framework/src/Volo.Abp.Validation.Abstractions/Volo.Abp.Validation.Abstractions.csproj b/framework/src/Volo.Abp.Validation.Abstractions/Volo.Abp.Validation.Abstractions.csproj index ff9731ff00..ea7347dd66 100644 --- a/framework/src/Volo.Abp.Validation.Abstractions/Volo.Abp.Validation.Abstractions.csproj +++ b/framework/src/Volo.Abp.Validation.Abstractions/Volo.Abp.Validation.Abstractions.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Validation.Abstractions Volo.Abp.Validation.Abstractions $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Validation/Volo.Abp.Validation.csproj b/framework/src/Volo.Abp.Validation/Volo.Abp.Validation.csproj index b8f10667a2..d56374024d 100644 --- a/framework/src/Volo.Abp.Validation/Volo.Abp.Validation.csproj +++ b/framework/src/Volo.Abp.Validation/Volo.Abp.Validation.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.Validation Volo.Abp.Validation $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs index 8119e71271..90afe4d60e 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs @@ -33,7 +33,7 @@ public class DataAnnotationObjectValidationContributor : IObjectValidationContri return Task.CompletedTask; } - protected virtual void ValidateObjectRecursively(List errors, object validatingObject, int currentDepth) + protected virtual void ValidateObjectRecursively(List errors, object? validatingObject, int currentDepth) { if (currentDepth > MaxRecursiveParameterValidationDepth) { diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DefaultAttributeValidationResultProvider.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DefaultAttributeValidationResultProvider.cs index feb8db8184..ced3615d04 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DefaultAttributeValidationResultProvider.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DefaultAttributeValidationResultProvider.cs @@ -5,7 +5,7 @@ namespace Volo.Abp.Validation; public class DefaultAttributeValidationResultProvider : IAttributeValidationResultProvider, ITransientDependency { - public virtual ValidationResult GetOrDefault(ValidationAttribute validationAttribute, object validatingObject, ValidationContext validationContext) + public virtual ValidationResult? GetOrDefault(ValidationAttribute validationAttribute, object? validatingObject, ValidationContext validationContext) { return validationAttribute.GetValidationResult(validatingObject, validationContext); } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IAttributeValidationResultProvider.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IAttributeValidationResultProvider.cs index 737dbac508..5cc919b967 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IAttributeValidationResultProvider.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IAttributeValidationResultProvider.cs @@ -4,5 +4,5 @@ namespace Volo.Abp.Validation; public interface IAttributeValidationResultProvider { - ValidationResult GetOrDefault(ValidationAttribute validationAttribute, object validatingObject, ValidationContext validationContext); + ValidationResult? GetOrDefault(ValidationAttribute validationAttribute, object? validatingObject, ValidationContext validationContext); } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs index 57d60b0f8e..51cff66c10 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs @@ -8,13 +8,13 @@ public interface IObjectValidator { Task ValidateAsync( object validatingObject, - string name = null, + string? name = null, bool allowNull = false ); Task> GetErrorsAsync( object validatingObject, - string name = null, + string? name = null, bool allowNull = false ); } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs index 83dd17521f..dd3ff2f395 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs @@ -19,7 +19,7 @@ public class ObjectValidator : IObjectValidator, ITransientDependency Options = options.Value; } - public virtual async Task ValidateAsync(object validatingObject, string name = null, bool allowNull = false) + public virtual async Task ValidateAsync(object validatingObject, string? name = null, bool allowNull = false) { var errors = await GetErrorsAsync(validatingObject, name, allowNull); @@ -32,7 +32,7 @@ public class ObjectValidator : IObjectValidator, ITransientDependency } } - public virtual async Task> GetErrorsAsync(object validatingObject, string name = null, bool allowNull = false) + public virtual async Task> GetErrorsAsync(object validatingObject, string? name = null, bool allowNull = false) { if (validatingObject == null) { diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/AlwaysValidValueValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/AlwaysValidValueValidator.cs index e986124fd9..1aad057983 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/AlwaysValidValueValidator.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/AlwaysValidValueValidator.cs @@ -6,7 +6,7 @@ namespace Volo.Abp.Validation.StringValues; [ValueValidator("NULL")] public class AlwaysValidValueValidator : ValueValidatorBase { - public override bool IsValid(object value) + public override bool IsValid(object? value) { return true; } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/BooleanValueValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/BooleanValueValidator.cs index 3330b2bd49..5328cc8590 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/BooleanValueValidator.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/BooleanValueValidator.cs @@ -6,7 +6,7 @@ namespace Volo.Abp.Validation.StringValues; [ValueValidator("BOOLEAN")] public class BooleanValueValidator : ValueValidatorBase { - public override bool IsValid(object value) + public override bool IsValid(object? value) { if (value == null) { diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/IStringValueType.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/IStringValueType.cs index 6cddb0701c..94493fd2b4 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/IStringValueType.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/IStringValueType.cs @@ -7,11 +7,10 @@ public interface IStringValueType { string Name { get; } - [CanBeNull] - object this[string key] { get; set; } + object? this[string key] { get; set; } [NotNull] - Dictionary Properties { get; } + Dictionary Properties { get; } IValueValidator Validator { get; set; } } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/IValueValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/IValueValidator.cs index c449ed891e..6095f6ecc4 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/IValueValidator.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/IValueValidator.cs @@ -7,11 +7,10 @@ public interface IValueValidator { string Name { get; } - [CanBeNull] - object this[string key] { get; set; } + object? this[string key] { get; set; } [NotNull] - IDictionary Properties { get; } + IDictionary Properties { get; } - bool IsValid(object value); + bool IsValid(object? value); } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/LocalizableSelectionStringValueItem.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/LocalizableSelectionStringValueItem.cs index e01b7ee69b..753b4a8df0 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/LocalizableSelectionStringValueItem.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/LocalizableSelectionStringValueItem.cs @@ -2,7 +2,7 @@ public class LocalizableSelectionStringValueItem : ISelectionStringValueItem { - public string Value { get; set; } + public string Value { get; set; } = default!; - public LocalizableStringInfo DisplayText { get; set; } + public LocalizableStringInfo DisplayText { get; set; } = default!; } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/NumericValueValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/NumericValueValidator.cs index 213327f884..e665301247 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/NumericValueValidator.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/NumericValueValidator.cs @@ -28,7 +28,7 @@ public class NumericValueValidator : ValueValidatorBase MaxValue = maxValue; } - public override bool IsValid(object value) + public override bool IsValid(object? value) { if (value == null) { diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/SelectionStringValueType.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/SelectionStringValueType.cs index 50fd401f00..92145ac764 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/SelectionStringValueType.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/SelectionStringValueType.cs @@ -6,7 +6,7 @@ namespace Volo.Abp.Validation.StringValues; [StringValueType("SELECTION")] public class SelectionStringValueType : StringValueTypeBase { - public ISelectionStringValueItemSource ItemSource { get; set; } + public ISelectionStringValueItemSource ItemSource { get; set; } = default!; public SelectionStringValueType() { diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/StringValueTypeBase.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/StringValueTypeBase.cs index 2700b691f1..4e4f44b1d7 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/StringValueTypeBase.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/StringValueTypeBase.cs @@ -8,12 +8,12 @@ public abstract class StringValueTypeBase : IStringValueType { public virtual string Name => ValueValidatorAttribute.GetName(GetType()); - public object this[string key] { + public object? this[string key] { get => Properties.GetOrDefault(key); set => Properties[key] = value; } - public Dictionary Properties { get; } + public Dictionary Properties { get; } public IValueValidator Validator { get; set; } @@ -26,6 +26,6 @@ public abstract class StringValueTypeBase : IStringValueType protected StringValueTypeBase(IValueValidator validator) { Validator = validator; - Properties = new Dictionary(); + Properties = new Dictionary(); } } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/StringValueValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/StringValueValidator.cs index 4b2cea9b67..3b3318719a 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/StringValueValidator.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/StringValueValidator.cs @@ -22,7 +22,7 @@ public class StringValueValidator : ValueValidatorBase set => this["MaxLength"] = value; } - public string RegularExpression { + public string? RegularExpression { get => this["RegularExpression"] as string; set => this["RegularExpression"] = value; } @@ -32,7 +32,7 @@ public class StringValueValidator : ValueValidatorBase } - public StringValueValidator(int minLength = 0, int maxLength = 0, string regularExpression = null, bool allowNull = false) + public StringValueValidator(int minLength = 0, int maxLength = 0, string? regularExpression = null, bool allowNull = false) { MinLength = minLength; MaxLength = maxLength; @@ -40,20 +40,18 @@ public class StringValueValidator : ValueValidatorBase AllowNull = allowNull; } - public override bool IsValid(object value) + public override bool IsValid(object? value) { if (value == null) { return AllowNull; } - if (!(value is string)) + if (!(value is string strValue)) { return false; } - var strValue = value as string; - if (MinLength > 0 && strValue.Length < MinLength) { return false; @@ -66,7 +64,7 @@ public class StringValueValidator : ValueValidatorBase if (!RegularExpression.IsNullOrEmpty()) { - return Regex.IsMatch(strValue, RegularExpression); + return Regex.IsMatch(strValue, RegularExpression!); } return true; diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/ValueValidatorBase.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/ValueValidatorBase.cs index 4537562301..5befa8ce7c 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/ValueValidatorBase.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/StringValues/ValueValidatorBase.cs @@ -8,17 +8,17 @@ public abstract class ValueValidatorBase : IValueValidator { public virtual string Name => ValueValidatorAttribute.GetName(GetType()); - public object this[string key] { + public object? this[string key] { get => Properties.GetOrDefault(key); set => Properties[key] = value; } - public IDictionary Properties { get; } + public IDictionary Properties { get; } protected ValueValidatorBase() { - Properties = new Dictionary(); + Properties = new Dictionary(); } - public abstract bool IsValid(object value); + public abstract bool IsValid(object? value); } diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Microsoft/Extensions/FileProviders/AbpFileInfoExtensions.cs b/framework/src/Volo.Abp.VirtualFileSystem/Microsoft/Extensions/FileProviders/AbpFileInfoExtensions.cs index 14db7846f3..8ca3c11c42 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Microsoft/Extensions/FileProviders/AbpFileInfoExtensions.cs +++ b/framework/src/Volo.Abp.VirtualFileSystem/Microsoft/Extensions/FileProviders/AbpFileInfoExtensions.cs @@ -84,7 +84,7 @@ public static class AbpFileInfoExtensions } } - public static string GetVirtualOrPhysicalPathOrNull([NotNull] this IFileInfo fileInfo) + public static string? GetVirtualOrPhysicalPathOrNull([NotNull] this IFileInfo fileInfo) { Check.NotNull(fileInfo, nameof(fileInfo)); diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj b/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj index 7e4ade4eca..97698351c7 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj +++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj @@ -5,6 +5,8 @@ netstandard2.0;netstandard2.1;net7.0 + enable + Nullable Volo.Abp.VirtualFileSystem Volo.Abp.VirtualFileSystem $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs index fddf2fec76..cb0786393b 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs +++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs @@ -9,11 +9,11 @@ public abstract class DictionaryBasedFileProvider : IFileProvider { protected abstract IDictionary Files { get; } - public virtual IFileInfo GetFileInfo(string subpath) + public virtual IFileInfo GetFileInfo(string? subpath) { if (subpath == null) { - return new NotFoundFileInfo(subpath); + return new NotFoundFileInfo(subpath!); } var file = Files.GetOrDefault(NormalizePath(subpath)); @@ -40,7 +40,7 @@ public abstract class DictionaryBasedFileProvider : IFileProvider foreach (var fileInfo in Files.Values) { var fullPath = fileInfo.GetVirtualOrPhysicalPathOrNull(); - if (!fullPath.StartsWith(directoryPath)) + if (fullPath == null || !fullPath.StartsWith(directoryPath)) { continue; } diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs index c10ca90afe..12e5184a97 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs +++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs @@ -32,8 +32,8 @@ public class DynamicFileProvider : DictionaryBasedFileProvider, IDynamicFileProv public void AddOrUpdate(IFileInfo fileInfo) { var filePath = fileInfo.GetVirtualOrPhysicalPathOrNull(); - DynamicFiles.AddOrUpdate(filePath, fileInfo, (key, value) => fileInfo); - ReportChange(filePath); + DynamicFiles.AddOrUpdate(filePath!, fileInfo, (key, value) => fileInfo); + ReportChange(filePath!); } public bool Delete(string filePath) diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/AbpEmbeddedFileProvider.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/AbpEmbeddedFileProvider.cs index e147cfc347..9ea816e0eb 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/AbpEmbeddedFileProvider.cs +++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/AbpEmbeddedFileProvider.cs @@ -13,15 +13,14 @@ public class AbpEmbeddedFileProvider : DictionaryBasedFileProvider [NotNull] public Assembly Assembly { get; } - [CanBeNull] - public string BaseNamespace { get; } + public string? BaseNamespace { get; } protected override IDictionary Files => _files.Value; private readonly Lazy> _files; public AbpEmbeddedFileProvider( [NotNull] Assembly assembly, - [CanBeNull] string baseNamespace = null) + string? baseNamespace = null) { Check.NotNull(assembly, nameof(assembly)); @@ -40,7 +39,7 @@ public class AbpEmbeddedFileProvider : DictionaryBasedFileProvider foreach (var resourcePath in Assembly.GetManifestResourceNames()) { - if (!BaseNamespace.IsNullOrEmpty() && !resourcePath.StartsWith(BaseNamespace)) + if (!BaseNamespace.IsNullOrEmpty() && !resourcePath.StartsWith(BaseNamespace!)) { continue; } @@ -106,7 +105,7 @@ public class AbpEmbeddedFileProvider : DictionaryBasedFileProvider { if (!BaseNamespace.IsNullOrEmpty()) { - resourceName = resourceName.Substring(BaseNamespace.Length + 1); + resourceName = resourceName.Substring(BaseNamespace!.Length + 1); } var pathParts = resourceName.Split('.'); diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedResourceFileInfo.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedResourceFileInfo.cs index 8dfc13f66b..33ddb0bec7 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedResourceFileInfo.cs +++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedResourceFileInfo.cs @@ -18,7 +18,7 @@ public class EmbeddedResourceFileInfo : IFileInfo { using (var stream = _assembly.GetManifestResourceStream(_resourcePath)) { - _length = stream.Length; + _length = stream!.Length; } } @@ -27,7 +27,7 @@ public class EmbeddedResourceFileInfo : IFileInfo } private long? _length; - public string PhysicalPath => null; + public string? PhysicalPath => null; public string VirtualPath { get; } @@ -68,7 +68,7 @@ public class EmbeddedResourceFileInfo : IFileInfo _length = stream.Length; } - return stream; + return stream!; } public override string ToString() diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedVirtualFileSetInfo.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedVirtualFileSetInfo.cs index 37642fc6fe..3515722b77 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedVirtualFileSetInfo.cs +++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedVirtualFileSetInfo.cs @@ -7,12 +7,12 @@ public class EmbeddedVirtualFileSetInfo : VirtualFileSetInfo { public Assembly Assembly { get; } - public string BaseFolder { get; } + public string? BaseFolder { get; } public EmbeddedVirtualFileSetInfo( IFileProvider fileProvider, Assembly assembly, - string baseFolder = null) + string? baseFolder = null) : base(fileProvider) { Assembly = assembly; diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs index db3932b1ee..f192766aaf 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs +++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs @@ -10,7 +10,7 @@ public class InMemoryFileInfo : IFileInfo public long Length => _fileContent.Length; - public string PhysicalPath => null; + public string? PhysicalPath => null; public string Name { get; } diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileSetListExtensions.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileSetListExtensions.cs index 3767645861..e25721f00f 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileSetListExtensions.cs +++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileSetListExtensions.cs @@ -13,8 +13,8 @@ public static class VirtualFileSetListExtensions { public static void AddEmbedded( [NotNull] this VirtualFileSetList list, - [CanBeNull] string baseNamespace = null, - [CanBeNull] string baseFolder = null) + string? baseNamespace = null, + string? baseFolder = null) { Check.NotNull(list, nameof(list)); @@ -42,8 +42,8 @@ public static class VirtualFileSetListExtensions private static IFileProvider CreateFileProvider( [NotNull] Assembly assembly, - [CanBeNull] string baseNamespace = null, - [CanBeNull] string baseFolder = null) + string? baseNamespace = null, + string? baseFolder = null) { Check.NotNull(assembly, nameof(assembly)); @@ -80,7 +80,7 @@ public static class VirtualFileSetListExtensions if (!embeddedVirtualFileSet.BaseFolder.IsNullOrEmpty()) { - thisPath = Path.Combine(thisPath, embeddedVirtualFileSet.BaseFolder); + thisPath = Path.Combine(thisPath, embeddedVirtualFileSet.BaseFolder!); } fileSets[i] = new PhysicalVirtualFileSetInfo(new PhysicalFileProvider(thisPath), thisPath); diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/CorrelationIdProvider/CorrelationIdProviderController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/CorrelationIdProvider/CorrelationIdProviderController.cs new file mode 100644 index 0000000000..185d206dc6 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/CorrelationIdProvider/CorrelationIdProviderController.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Tracing; + +namespace Volo.Abp.AspNetCore.CorrelationIdProvider; + +[Route("api/correlation")] +public class CorrelationIdProviderController : AbpController +{ + [HttpGet] + [Route("get")] + public string Get() + { + return this.HttpContext.RequestServices.GetRequiredService().Get(); + } +} diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/CorrelationIdProvider/CorrelationIdProvider_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/CorrelationIdProvider/CorrelationIdProvider_Tests.cs new file mode 100644 index 0000000000..0db761f57d --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/CorrelationIdProvider/CorrelationIdProvider_Tests.cs @@ -0,0 +1,48 @@ +using System; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.AspNetCore.Mvc; +using Xunit; + +namespace Volo.Abp.AspNetCore.CorrelationIdProvider; + +public class CorrelationIdProvider_Tests : AspNetCoreMvcTestBase +{ + [Fact] + public async Task Test() + { + // Test AbpCorrelationIdMiddleware without X-Correlation-Id header + using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, "/api/correlation/404")) + { + var response = await Client.SendAsync(requestMessage); + response.StatusCode.ShouldBe(HttpStatusCode.NotFound); + + response.Headers.ShouldContain(x => x.Key == "X-Correlation-Id" && x.Value.First() != null); + } + + var correlationId = Guid.NewGuid().ToString("N"); + + // Test AbpCorrelationIdMiddleware + using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, "/api/correlation/404")) + { + requestMessage.Headers.Add("X-Correlation-Id", correlationId); + var response = await Client.SendAsync(requestMessage); + response.StatusCode.ShouldBe(HttpStatusCode.NotFound); + + response.Headers.ShouldContain(x => x.Key == "X-Correlation-Id" && x.Value.First() == correlationId); + } + + // Test AspNetCoreCorrelationIdProvider + using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, "/api/correlation/get")) + { + requestMessage.Headers.Add("X-Correlation-Id", correlationId); + var response = await Client.SendAsync(requestMessage); + response.StatusCode.ShouldBe(HttpStatusCode.OK); + + (await response.Content.ReadAsStringAsync()).ShouldBe(correlationId); + } + } +} diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs index d8a49abf23..6051ae6520 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs @@ -88,6 +88,8 @@ public class AbpAspNetCoreMvcTestModule : AbpModule ? "phones" : urlActionNameNormalizerContext.ActionNameInUrl; }); + + options.ExposeIntegrationServices = true; }); Configure(options => diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/CorrelationIdProvider/CorrelationIdProvider_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/CorrelationIdProvider/CorrelationIdProvider_Tests.cs new file mode 100644 index 0000000000..997038afa1 --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/CorrelationIdProvider/CorrelationIdProvider_Tests.cs @@ -0,0 +1,33 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Modularity; +using Volo.Abp.Tracing; +using Xunit; + +namespace Volo.Abp.CorrelationIdProvider; + +public class CorrelationIdProvider_Tests +{ + [Fact] + public async Task Test() + { + using (var application = await AbpApplicationFactory.CreateAsync()) + { + await application.InitializeAsync(); + + var correlationIdProvider = application.ServiceProvider.GetRequiredService(); + + correlationIdProvider.Get().ShouldBeNull(); + + var correlationId = Guid.NewGuid().ToString("N"); + using (correlationIdProvider.Change(correlationId)) + { + correlationIdProvider.Get().ShouldBe(correlationId); + } + + correlationIdProvider.Get().ShouldBeNull(); + } + } +} diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs index eb15943670..941465b814 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Modularity/ModuleLoader_Tests.cs @@ -21,9 +21,14 @@ public class ModuleLoader_Tests modules.Length.ShouldBe(2); modules[0].Type.ShouldBe(typeof(IndependentEmptyModule)); modules[1].Type.ShouldBe(typeof(MyStartupModule)); + modules[1].Assembly.ShouldBe(typeof(MyStartupModule).Assembly); + modules[1].AllAssemblies.Length.ShouldBe(2); + modules[1].AllAssemblies[0].ShouldBe(typeof(IAbpApplication).Assembly); + modules[1].AllAssemblies[1].ShouldBe(typeof(MyStartupModule).Assembly); } [DependsOn(typeof(IndependentEmptyModule))] + [AdditionalAssembly(typeof(IAbpApplication))] public class MyStartupModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs index 2ba02eee6b..edf44d5338 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/Reflection/AssemblyFinder_Tests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using NSubstitute; using Shouldly; using Volo.Abp.Modularity; @@ -50,6 +51,7 @@ public class AssemblyFinder_Tests { var moduleDescriptor = Substitute.For(); moduleDescriptor.Type.Returns(moduleType); + moduleDescriptor.AllAssemblies.Returns(new [] { moduleType.Assembly }); return moduleDescriptor; } } diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs index 6a0edcb3f5..fada3effe7 100644 --- a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs @@ -38,7 +38,7 @@ public class AbpCompiledViewProviderOptions_Tests : TemplateDefinitionTests +{ + [Fact] + public async Task GetRazorFilesAsync() + { + var definition = await TemplateDefinitionManager.GetAsync(TestTemplates.WelcomeEmail); + var files = await TemplateContentFileProvider.GetFilesAsync(definition); + files.Count.ShouldBe(2); + files.ShouldContain(x => x.FileName == "en.cshtml" && x.FileContent.Contains("Welcome @Model.Name to the abp.io!")); + files.ShouldContain(x => x.FileName == "tr.cshtml" && x.FileContent.Contains("Merhaba @Model.Name, abp.io'ya hoşgeldiniz!")); + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ScribanTemplateContentFileProvider_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ScribanTemplateContentFileProvider_Tests.cs new file mode 100644 index 0000000000..674173313c --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ScribanTemplateContentFileProvider_Tests.cs @@ -0,0 +1,19 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.TextTemplating.VirtualFiles; +using Xunit; + +namespace Volo.Abp.TextTemplating.Scriban.SampleTemplates; + +public class ScribanTemplateContentFileProvider_Tests : TemplateContentFileProvider_Tests +{ + [Fact] + public async Task GetScribanFilesAsync() + { + var definition = await TemplateDefinitionManager.GetAsync(TestTemplates.WelcomeEmail); + var files = await TemplateContentFileProvider.GetFilesAsync(definition); + files.Count.ShouldBe(2); + files.ShouldContain(x => x.FileName == "en.tpl" && x.FileContent.Contains("Welcome {{model.name}} to the abp.io!")); + files.ShouldContain(x => x.FileName == "tr.tpl" && x.FileContent.Contains("Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!")); + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs index 036080cc26..02ce27d2b7 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs @@ -1,4 +1,5 @@ -using Shouldly; +using System.Threading.Tasks; +using Shouldly; using Volo.Abp.Modularity; using Xunit; @@ -15,28 +16,28 @@ public abstract class TemplateDefinitionTests : AbpTextTemplatin } [Fact] - public void Should_Retrieve_Template_Definition_By_Name() + public async Task Should_Retrieve_Template_Definition_By_Name() { - var welcomeEmailTemplate = TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail); + var welcomeEmailTemplate = await TemplateDefinitionManager.GetAsync(TestTemplates.WelcomeEmail); welcomeEmailTemplate.Name.ShouldBe(TestTemplates.WelcomeEmail); welcomeEmailTemplate.IsInlineLocalized.ShouldBeFalse(); - var forgotPasswordEmailTemplate = TemplateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail); + var forgotPasswordEmailTemplate = await TemplateDefinitionManager.GetAsync(TestTemplates.ForgotPasswordEmail); forgotPasswordEmailTemplate.Name.ShouldBe(TestTemplates.ForgotPasswordEmail); forgotPasswordEmailTemplate.IsInlineLocalized.ShouldBeTrue(); } [Fact] - public void Should_Get_Null_If_Template_Not_Found() + public async Task Should_Get_Null_If_Template_Not_Found() { - var definition = TemplateDefinitionManager.GetOrNull("undefined-template"); + var definition = await TemplateDefinitionManager.GetOrNullAsync("undefined-template"); definition.ShouldBeNull(); } [Fact] - public void Should_Retrieve_All_Template_Definitions() + public async Task Should_Retrieve_All_Template_Definitions() { - var definitions = TemplateDefinitionManager.GetAll(); + var definitions = await TemplateDefinitionManager.GetAllAsync(); definitions.Count.ShouldBeGreaterThan(1); } } diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs index 7ba1850d9c..aee41db4be 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs @@ -24,7 +24,7 @@ public abstract class LocalizedTemplateContentReaderFactory_Tests : AbpTextTemplatingTestBase + where TStartupModule : IAbpModule +{ + protected readonly TemplateContentFileProvider TemplateContentFileProvider; + protected readonly ITemplateDefinitionManager TemplateDefinitionManager; + + protected TemplateContentFileProvider_Tests() + { + TemplateContentFileProvider = GetRequiredService(); + TemplateDefinitionManager = GetRequiredService(); + } + + [Fact] + public async Task GetFilesAsync() + { + var definition = await TemplateDefinitionManager.GetAsync(TestTemplates.HybridTemplateScriban); + + var files = await TemplateContentFileProvider.GetFilesAsync(definition); + files.Count.ShouldBe(1); + files.ShouldContain(x => x.FileName == "TestScribanTemplate.tpl" && x.FileContent == "Hello {{model.name}}, {{L \"HowAreYou\" }}"); + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs index 89dc93051c..f2f0cdafef 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs @@ -24,13 +24,13 @@ public abstract class VirtualFileTemplateContributor_Tests : Abp public async Task Should_Get_Localized_Content_By_Culture() { (await VirtualFileTemplateContentContributor.GetOrNullAsync( - new TemplateContentContributorContext(TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail), + new TemplateContentContributorContext(await TemplateDefinitionManager.GetAsync(TestTemplates.WelcomeEmail), ServiceProvider, "en"))) .ShouldBe(WelcomeEmailEnglishContent); (await VirtualFileTemplateContentContributor.GetOrNullAsync( - new TemplateContentContributorContext(TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail), + new TemplateContentContributorContext(await TemplateDefinitionManager.GetAsync(TestTemplates.WelcomeEmail), ServiceProvider, "tr"))) .ShouldBe(WelcomeEmailTurkishContent); @@ -41,7 +41,7 @@ public abstract class VirtualFileTemplateContributor_Tests : Abp { (await VirtualFileTemplateContentContributor.GetOrNullAsync( new TemplateContentContributorContext( - TemplateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail), + await TemplateDefinitionManager.GetAsync(TestTemplates.ForgotPasswordEmail), ServiceProvider, null))) .ShouldBe(ForgotPasswordEmailEnglishContent); diff --git a/latest-versions.json b/latest-versions.json index ee5249ef27..1e25f674d5 100644 --- a/latest-versions.json +++ b/latest-versions.json @@ -1,8 +1,8 @@ [ - { - "version": "7.2.2", - "releaseDate": "", - "type": "stable", - "message": "" - } -] + { + "version": "7.2.3", + "releaseDate": "", + "type": "stable", + "message": "" + } +] \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs index 316323a5cd..f9489f7797 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs @@ -144,7 +144,7 @@ public class RegisterModel : AccountPageModel ))).CheckErrors(); } - await SignInManager.SignInAsync(user, isPersistent: true); + await SignInManager.SignInAsync(user, isPersistent: true, ExternalLoginAuthSchema); } protected virtual async Task CheckSelfRegistrationAsync() diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/AbpAspNetCoreMvcUiBootstrapDemoModule.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/AbpAspNetCoreMvcUiBootstrapDemoModule.cs index c0c03a8dfe..654ada13fc 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/AbpAspNetCoreMvcUiBootstrapDemoModule.cs +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/AbpAspNetCoreMvcUiBootstrapDemoModule.cs @@ -1,11 +1,15 @@ using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Hosting; +using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Favicon; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.HighlightJs; +using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.Menus; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; using Volo.Abp.Autofac; using Volo.Abp.Modularity; +using Volo.Abp.Ui.LayoutHooks; using Volo.Abp.UI.Navigation; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo; @@ -37,7 +41,15 @@ public class AbpAspNetCoreMvcUiBootstrapDemoModule : AbpModule { options.StyleBundles .Get(StandardBundles.Styles.Global) - .AddFiles("/css/demo.css"); + .AddFiles("/css/demo.css") + .AddContributors(typeof(PrismjsStyleBundleContributor)) + .AddContributors(typeof(HighlightJsStyleContributor)); + + options.ScriptBundles + .Get(StandardBundles.Scripts.Global) + .AddFiles("/js/demo.js") + .AddContributors(typeof(PrismjsScriptBundleContributor)) + .AddContributors(typeof(HighlightJsScriptContributor)); } ); Configure(options => @@ -56,5 +68,9 @@ public class AbpAspNetCoreMvcUiBootstrapDemoModule : AbpModule ); }); + Configure(options => + { + options.Add(LayoutHooks.Head.First, typeof(FaviconViewComponent)); + }); } } diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/BootstrapUrlHelper.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/BootstrapUrlHelper.cs new file mode 100644 index 0000000000..0eccbf4b96 --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/BootstrapUrlHelper.cs @@ -0,0 +1,12 @@ +using System; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo; + +public static class BootstrapUrlHelper +{ + public const string BootstrapVersion = "5.3"; + public static string GetDocUrl(string path) + { + return $"https://getbootstrap.com/docs/{BootstrapVersion}{path.EnsureStartsWith('/')}"; + } +} \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Favicon/Default.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Favicon/Default.cshtml new file mode 100644 index 0000000000..4f73c90dbd --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Favicon/Default.cshtml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Favicon/FaviconViewComponent.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Favicon/FaviconViewComponent.cs new file mode 100644 index 0000000000..d6fd6e41e7 --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Favicon/FaviconViewComponent.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Favicon; + +public class FaviconViewComponent : AbpViewComponent +{ + public IViewComponentResult Invoke() + { + return View("~/Favicon/Default.cshtml"); + } +} \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Alerts.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Alerts.cshtml index daff8229bc..fd4591073e 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Alerts.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Alerts.cshtml @@ -1,30 +1,13 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.AlertsModel @{ ViewData["Title"] = "Alerts"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Alerts

-

Based on Bootstrap Alert.

+

Based on Bootstrap Alert.

Examples

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Badges.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Badges.cshtml index 28f7469997..602c752dfd 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Badges.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Badges.cshtml @@ -1,30 +1,18 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Badge +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.BadgesModel @{ ViewData["Title"] = "Badges"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Badges

-

Based on Bootstrap Badge.

+

Based on Bootstrap Badge.

Example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Blockquotes.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Blockquotes.cshtml index 4f8b1c3a5f..34ab545163 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Blockquotes.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Blockquotes.cshtml @@ -1,18 +1,15 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.BlockquotesModel @{ ViewData["Title"] = "Badges"; } -@section styles { - - - -} -

Blockquotes

-

Based on Bootstrap Blockquotes.

+

Based on Bootstrap Blockquotes.

# Blockquote Examples

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml index ad1abeabaf..7473c84bb8 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml @@ -1,22 +1,10 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.BordersModel @{ ViewData["Title"] = "Borders"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Borders

-

Based on Bootstrap Border.

+

Based on Bootstrap Border.

Border

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Breadcrumbs.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Breadcrumbs.cshtml index 3279fbaaa2..4c4164a823 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Breadcrumbs.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Breadcrumbs.cshtml @@ -1,30 +1,13 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.BreadcrumbsModel @{ ViewData["Title"] = "Breadcrumbs"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Breadcrumbs

-

Based on Bootstrap Breadcrumb.

+

Based on Bootstrap Breadcrumb.

Example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ButtonGroups.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ButtonGroups.cshtml index ee081b5494..94e0d7ee70 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ButtonGroups.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ButtonGroups.cshtml @@ -1,30 +1,13 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.ButtonGroupsModel @{ ViewData["Title"] = "ButtonGroups"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Button groups

-

Based on Bootstrap Button group.

+

Based on Bootstrap Button group.

Basic example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml index b55633b820..08d1e0093a 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml @@ -1,31 +1,13 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.ButtonsModel @{ ViewData["Title"] = "Buttons"; } -@section styles { - - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Buttons

-

Based on Bootstrap button.

+

Based on Bootstrap button.

Examples

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml index 0d51658b5f..2880f8b179 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml @@ -1,31 +1,14 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.CardsModel @{ ViewData["Title"] = "Cards"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Cards

-

Based on Bootstrap card.

+

Based on Bootstrap card.

Example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml index b16e223d18..d1b6cbe0b1 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml @@ -1,4 +1,5 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.CarouselsModel @{ ViewData["Title"] = "Carousels"; @@ -9,28 +10,10 @@ } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Carousels

-

Based on Bootstrap Carousel.

+

Based on Bootstrap Carousel.

Slides only

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Collapse.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Collapse.cshtml index d2f736000d..728afc0a1e 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Collapse.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Collapse.cshtml @@ -1,32 +1,14 @@ @page -@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.CollapseModel @{ ViewData["Title"] = "Collapse"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Collapse

-

Based on Bootstrap Collapse.

+

Based on Bootstrap Collapse.

Example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DatePicker.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DatePicker.cshtml index b1c6bd3626..b65eaf15be 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DatePicker.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DatePicker.cshtml @@ -1,17 +1,6 @@ @page @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.DatePickerModel -@section styles { - - - -} - - - - -

Date Picker & Date Range Picker

@@ -167,7 +156,7 @@ public class DatePickerModel : PageModel
- +
@@ -182,14 +171,14 @@ public class DatePickerModel : PageModel

-<abp-date-picker auto-update-input="true" today-button-classes="btn-primary" asp-for="NullableDateTime"/>
+<abp-date-picker today-button-classes="btn-primary" asp-for="NullableDateTime"/>
 

 <div class="mb-3">
     <label class="form-label" for="NullableDateTime">NullableDateTime</label>
-    <abp-date-picker data-today-button-classes="btn-primary" data-auto-update-input="true">
+    <abp-date-picker data-today-button-classes="btn-primary">
         <div class="input-group">
             <input type="text" autocomplete="off" class="form-control">
             <button type="button" tabindex="-1" data-type="open" class="btn btn-outline-secondary d-none" data-busy-text="Processing...">
@@ -227,7 +216,7 @@ public class DatePickerModel : PageModel
             
             
                 

-<abp-date-picker auto-update-input="true" today-button-classes="btn-primary" asp-for="NullableDateTime"/>
+<abp-date-picker today-button-classes="btn-primary" asp-for="NullableDateTime"/>
 
@@ -251,7 +240,7 @@ public class DatePickerModel : PageModel
- +
@@ -271,14 +260,14 @@ public class DatePickerModel : PageModel

-<abp-date-picker auto-update-input="true" today-button-classes="btn-primary" asp-for="DateTimeDateTimeOffset"/>
+<abp-date-picker today-button-classes="btn-primary" asp-for="DateTimeDateTimeOffset"/>
 

 <div class="mb-3">
     <label class="form-label" for="DateTimeDateTimeOffset">DateTimeDateTimeOffset</label>
-    <abp-date-picker data-today-button-classes="btn-primary" data-auto-update-input="true" data-date="2023-04-12T18:10:05.6171150+03:00">
+    <abp-date-picker data-today-button-classes="btn-primary" data-date="2023-04-12T18:10:05.6171150+03:00">
         <div class="input-group">
             <input type="text" autocomplete="off" class="form-control">
             <button type="button" tabindex="-1" data-type="open" class="btn btn-outline-secondary d-none" data-busy-text="Processing...">
@@ -346,7 +335,7 @@ public class DatePickerModel : PageModel
 
 
- +
@@ -361,14 +350,14 @@ public class DatePickerModel : PageModel

-<abp-date-picker auto-update-input="true" today-button-classes="btn-primary" asp-for="NullableDateTimeDateTimeOffset"/>
+<abp-date-picker today-button-classes="btn-primary" asp-for="NullableDateTimeDateTimeOffset"/>
 

 <div class="mb-3">
     <label class="form-label" for="NullableDateTimeDateTimeOffset">NullableDateTimeDateTimeOffset</label>
-    <abp-date-picker data-today-button-classes="btn-primary" data-auto-update-input="true">
+    <abp-date-picker data-today-button-classes="btn-primary">
         <div class="input-group">
             <input type="text" autocomplete="off" class="form-control">
             <button type="button" tabindex="-1" data-type="open" class="btn btn-outline-secondary d-none" data-busy-text="Processing...">
@@ -430,7 +419,7 @@ public class DatePickerModel : PageModel
 
 
- +
@@ -445,14 +434,14 @@ public class DatePickerModel : PageModel

-<abp-date-picker auto-update-input="true" today-button-classes="btn-primary" asp-for="StringDate"/>
+<abp-date-picker today-button-classes="btn-primary" asp-for="StringDate"/>
 

 <div class="mb-3">
     <label class="form-label" for="StringDate">StringDate</label>
-    <abp-date-picker data-today-button-classes="btn-primary" data-auto-update-input="true">
+    <abp-date-picker data-today-button-classes="btn-primary">
         <div class="input-group">
             <input type="text" autocomplete="off" class="form-control">
             <button type="button" tabindex="-1" data-type="open" class="btn btn-outline-secondary d-none" data-busy-text="Processing...">
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Dropdowns.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Dropdowns.cshtml
index 79effa0a03..3f5717033d 100644
--- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Dropdowns.cshtml
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Dropdowns.cshtml
@@ -1,30 +1,14 @@
 @page
+@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo
 @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.DropdownsModel
 @{
     ViewData["Title"] = "Dropdowns";
 }
 
-@section styles {
-    
-        
-    
-}
-
-@section scripts {
-    
-        @*
-            *@
-    
-}
-
-
-
-
 
 

Dropdowns

-

Based on Bootstrap button.

+

Based on Bootstrap button.

Single button

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DynamicForms.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DynamicForms.cshtml index 8c3df73387..cbec1ee01c 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DynamicForms.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DynamicForms.cshtml @@ -6,23 +6,6 @@ ViewData["Title"] = "Forms"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - -

Dynamic Forms

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml index cbbbccb8c5..e637aebfad 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml @@ -6,23 +6,6 @@ ViewData["Title"] = "Form Elements"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Grids.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Grids.cshtml index 6271aed80b..0e33d39c59 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Grids.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Grids.cshtml @@ -1,30 +1,13 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.GridsModel @{ ViewData["Title"] = "Grids"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Grids

-

Based on Bootstrap grid.

+

Based on Bootstrap grid.

Equal-width

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ListGroup.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ListGroup.cshtml index 2d3e317f4b..ce66b8d5aa 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ListGroup.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ListGroup.cshtml @@ -1,30 +1,14 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.ListGroupsModel @{ ViewData["Title"] = "List Groups"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - -

List Groups

-

Based on Bootstrap List Group.

+

Based on Bootstrap List Group.

Basic example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml index 0df420a887..9e51ef25a3 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml @@ -1,32 +1,16 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.ModalsModel @{ ViewData["Title"] = "Modals"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - -

Modals

-

Based on Bootstrap Modal.

+

Based on Bootstrap Modal.

Example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Navs.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Navs.cshtml index 31e3d9bf61..ca9828d348 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Navs.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Navs.cshtml @@ -1,31 +1,15 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.NavsModel @{ ViewData["Title"] = "Navs"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - -

Navs

-

Based on Bootstrap Navs.

+

Based on Bootstrap Navs.

Base nav

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Paginator.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Paginator.cshtml index f8484e03d1..00666c091a 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Paginator.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Paginator.cshtml @@ -4,23 +4,6 @@ ViewData["Title"] = "Paginator"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - -

Paginator

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml index 3e1d6cb1be..ddc87ba66d 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml @@ -1,31 +1,14 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.PopoversModel @{ ViewData["Title"] = "Popovers"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Popovers

-

Based on Bootstrap Popovers.

+

Based on Bootstrap Popovers.

Example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml index 25f7f5b96e..0390090e9a 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml @@ -1,18 +1,14 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.ProgressBarsModel @{ ViewData["Title"] = "Progress Bars"; } -@section styles { - - - -}

Progress Bars

-

Based on Bootstrap Progress Bars.

+

Based on Bootstrap Progress Bars.

Example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml index 840ad1ff2e..b5f80680f6 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml @@ -1,31 +1,14 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.TablesModel @{ ViewData["Title"] = "Tables"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - -

Tables

-

Based on Bootstrap Tables.

+

Based on Bootstrap Tables.

Examples

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml index 466065bfaf..e9631ed179 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml @@ -1,31 +1,15 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.TabsModel @{ ViewData["Title"] = "Tabs"; } -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - -

Tabs

-

Based on Bootstrap tab.

+

Based on Bootstrap tab.

Example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml index b76d29b958..f19161d515 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml @@ -1,18 +1,14 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.TooltipsModel @{ ViewData["Title"] = "Tooltips"; } -@section styles { - - - -}

Tooltips

-

Based on Bootstrap Tooltips.

+

Based on Bootstrap Tooltips.

Example

diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_Layout.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_Layout.cshtml index 9df9f9278f..98e3d74767 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_Layout.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_Layout.cshtml @@ -23,7 +23,7 @@ @await RenderSectionAsync("styles", false) - +
@RenderBody()
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json index bb7260b280..a9aed1ec97 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json @@ -3,8 +3,9 @@ "name": "asp.net", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.shared": "~7.3.0-rc.3", - "highlight.js": "^9.13.1" + "@abp/aspnetcore.mvc.ui.theme.shared": "~7.2.3", + "@abp/prismjs": "^7.2.3", + "@abp/highlight.js": "^7.2.3" }, "devDependencies": {} } diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/android-chrome-192x192.png b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/android-chrome-192x192.png new file mode 100644 index 0000000000..497227df07 Binary files /dev/null and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/android-chrome-192x192.png differ diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/android-chrome-512x512.png b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/android-chrome-512x512.png new file mode 100644 index 0000000000..cee7b172df Binary files /dev/null and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/android-chrome-512x512.png differ diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/apple-touch-icon.png b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/apple-touch-icon.png new file mode 100644 index 0000000000..7987b1fd16 Binary files /dev/null and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/apple-touch-icon.png differ diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/favicon-16x16.png b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/favicon-16x16.png new file mode 100644 index 0000000000..1b6cec7bf1 Binary files /dev/null and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/favicon-16x16.png differ diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/favicon-32x32.png b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/favicon-32x32.png new file mode 100644 index 0000000000..2b3f15dee5 Binary files /dev/null and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/favicon-32x32.png differ diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/favicon.ico b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/favicon.ico new file mode 100644 index 0000000000..5a711f0057 Binary files /dev/null and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/favicon.ico differ diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/site.webmanifest b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/site.webmanifest new file mode 100644 index 0000000000..45dc8a2065 --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/favicon.ico/site.webmanifest @@ -0,0 +1 @@ +{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/js/demo.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/js/demo.js new file mode 100644 index 0000000000..9c48543c6e --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/js/demo.js @@ -0,0 +1,3 @@ +$(function (){ + hljs.initHighlightingOnLoad(); +}) \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/clipboard/clipboard.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/clipboard/clipboard.js new file mode 100644 index 0000000000..aeb826f0fb --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/clipboard/clipboard.js @@ -0,0 +1,890 @@ +/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["ClipboardJS"] = factory(); + else + root["ClipboardJS"] = factory(); +})(this, function() { +return /******/ (function() { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ 686: +/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXPORTS +__webpack_require__.d(__webpack_exports__, { + "default": function() { return /* binding */ clipboard; } +}); + +// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js +var tiny_emitter = __webpack_require__(279); +var tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter); +// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js +var listen = __webpack_require__(370); +var listen_default = /*#__PURE__*/__webpack_require__.n(listen); +// EXTERNAL MODULE: ./node_modules/select/src/select.js +var src_select = __webpack_require__(817); +var select_default = /*#__PURE__*/__webpack_require__.n(src_select); +;// CONCATENATED MODULE: ./src/common/command.js +/** + * Executes a given operation type. + * @param {String} type + * @return {Boolean} + */ +function command(type) { + try { + return document.execCommand(type); + } catch (err) { + return false; + } +} +;// CONCATENATED MODULE: ./src/actions/cut.js + + +/** + * Cut action wrapper. + * @param {String|HTMLElement} target + * @return {String} + */ + +var ClipboardActionCut = function ClipboardActionCut(target) { + var selectedText = select_default()(target); + command('cut'); + return selectedText; +}; + +/* harmony default export */ var actions_cut = (ClipboardActionCut); +;// CONCATENATED MODULE: ./src/common/create-fake-element.js +/** + * Creates a fake textarea element with a value. + * @param {String} value + * @return {HTMLElement} + */ +function createFakeElement(value) { + var isRTL = document.documentElement.getAttribute('dir') === 'rtl'; + var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS + + fakeElement.style.fontSize = '12pt'; // Reset box model + + fakeElement.style.border = '0'; + fakeElement.style.padding = '0'; + fakeElement.style.margin = '0'; // Move element out of screen horizontally + + fakeElement.style.position = 'absolute'; + fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically + + var yPosition = window.pageYOffset || document.documentElement.scrollTop; + fakeElement.style.top = "".concat(yPosition, "px"); + fakeElement.setAttribute('readonly', ''); + fakeElement.value = value; + return fakeElement; +} +;// CONCATENATED MODULE: ./src/actions/copy.js + + + +/** + * Create fake copy action wrapper using a fake element. + * @param {String} target + * @param {Object} options + * @return {String} + */ + +var fakeCopyAction = function fakeCopyAction(value, options) { + var fakeElement = createFakeElement(value); + options.container.appendChild(fakeElement); + var selectedText = select_default()(fakeElement); + command('copy'); + fakeElement.remove(); + return selectedText; +}; +/** + * Copy action wrapper. + * @param {String|HTMLElement} target + * @param {Object} options + * @return {String} + */ + + +var ClipboardActionCopy = function ClipboardActionCopy(target) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + container: document.body + }; + var selectedText = ''; + + if (typeof target === 'string') { + selectedText = fakeCopyAction(target, options); + } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) { + // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange + selectedText = fakeCopyAction(target.value, options); + } else { + selectedText = select_default()(target); + command('copy'); + } + + return selectedText; +}; + +/* harmony default export */ var actions_copy = (ClipboardActionCopy); +;// CONCATENATED MODULE: ./src/actions/default.js +function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + + + +/** + * Inner function which performs selection from either `text` or `target` + * properties and then executes copy or cut operations. + * @param {Object} options + */ + +var ClipboardActionDefault = function ClipboardActionDefault() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + // Defines base properties passed from constructor. + var _options$action = options.action, + action = _options$action === void 0 ? 'copy' : _options$action, + container = options.container, + target = options.target, + text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'. + + if (action !== 'copy' && action !== 'cut') { + throw new Error('Invalid "action" value, use either "copy" or "cut"'); + } // Sets the `target` property using an element that will be have its content copied. + + + if (target !== undefined) { + if (target && _typeof(target) === 'object' && target.nodeType === 1) { + if (action === 'copy' && target.hasAttribute('disabled')) { + throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute'); + } + + if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) { + throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes'); + } + } else { + throw new Error('Invalid "target" value, use a valid Element'); + } + } // Define selection strategy based on `text` property. + + + if (text) { + return actions_copy(text, { + container: container + }); + } // Defines which selection strategy based on `target` property. + + + if (target) { + return action === 'cut' ? actions_cut(target) : actions_copy(target, { + container: container + }); + } +}; + +/* harmony default export */ var actions_default = (ClipboardActionDefault); +;// CONCATENATED MODULE: ./src/clipboard.js +function clipboard_typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return clipboard_typeof(obj); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } + +function _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + + + + + + +/** + * Helper function to retrieve attribute value. + * @param {String} suffix + * @param {Element} element + */ + +function getAttributeValue(suffix, element) { + var attribute = "data-clipboard-".concat(suffix); + + if (!element.hasAttribute(attribute)) { + return; + } + + return element.getAttribute(attribute); +} +/** + * Base class which takes one or more elements, adds event listeners to them, + * and instantiates a new `ClipboardAction` on each click. + */ + + +var Clipboard = /*#__PURE__*/function (_Emitter) { + _inherits(Clipboard, _Emitter); + + var _super = _createSuper(Clipboard); + + /** + * @param {String|HTMLElement|HTMLCollection|NodeList} trigger + * @param {Object} options + */ + function Clipboard(trigger, options) { + var _this; + + _classCallCheck(this, Clipboard); + + _this = _super.call(this); + + _this.resolveOptions(options); + + _this.listenClick(trigger); + + return _this; + } + /** + * Defines if attributes would be resolved using internal setter functions + * or custom functions that were passed in the constructor. + * @param {Object} options + */ + + + _createClass(Clipboard, [{ + key: "resolveOptions", + value: function resolveOptions() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + this.action = typeof options.action === 'function' ? options.action : this.defaultAction; + this.target = typeof options.target === 'function' ? options.target : this.defaultTarget; + this.text = typeof options.text === 'function' ? options.text : this.defaultText; + this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body; + } + /** + * Adds a click event listener to the passed trigger. + * @param {String|HTMLElement|HTMLCollection|NodeList} trigger + */ + + }, { + key: "listenClick", + value: function listenClick(trigger) { + var _this2 = this; + + this.listener = listen_default()(trigger, 'click', function (e) { + return _this2.onClick(e); + }); + } + /** + * Defines a new `ClipboardAction` on each click event. + * @param {Event} e + */ + + }, { + key: "onClick", + value: function onClick(e) { + var trigger = e.delegateTarget || e.currentTarget; + var action = this.action(trigger) || 'copy'; + var text = actions_default({ + action: action, + container: this.container, + target: this.target(trigger), + text: this.text(trigger) + }); // Fires an event based on the copy operation result. + + this.emit(text ? 'success' : 'error', { + action: action, + text: text, + trigger: trigger, + clearSelection: function clearSelection() { + if (trigger) { + trigger.focus(); + } + + window.getSelection().removeAllRanges(); + } + }); + } + /** + * Default `action` lookup function. + * @param {Element} trigger + */ + + }, { + key: "defaultAction", + value: function defaultAction(trigger) { + return getAttributeValue('action', trigger); + } + /** + * Default `target` lookup function. + * @param {Element} trigger + */ + + }, { + key: "defaultTarget", + value: function defaultTarget(trigger) { + var selector = getAttributeValue('target', trigger); + + if (selector) { + return document.querySelector(selector); + } + } + /** + * Allow fire programmatically a copy action + * @param {String|HTMLElement} target + * @param {Object} options + * @returns Text copied. + */ + + }, { + key: "defaultText", + + /** + * Default `text` lookup function. + * @param {Element} trigger + */ + value: function defaultText(trigger) { + return getAttributeValue('text', trigger); + } + /** + * Destroy lifecycle. + */ + + }, { + key: "destroy", + value: function destroy() { + this.listener.destroy(); + } + }], [{ + key: "copy", + value: function copy(target) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + container: document.body + }; + return actions_copy(target, options); + } + /** + * Allow fire programmatically a cut action + * @param {String|HTMLElement} target + * @returns Text cutted. + */ + + }, { + key: "cut", + value: function cut(target) { + return actions_cut(target); + } + /** + * Returns the support of the given action, or all actions if no action is + * given. + * @param {String} [action] + */ + + }, { + key: "isSupported", + value: function isSupported() { + var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut']; + var actions = typeof action === 'string' ? [action] : action; + var support = !!document.queryCommandSupported; + actions.forEach(function (action) { + support = support && !!document.queryCommandSupported(action); + }); + return support; + } + }]); + + return Clipboard; +}((tiny_emitter_default())); + +/* harmony default export */ var clipboard = (Clipboard); + +/***/ }), + +/***/ 828: +/***/ (function(module) { + +var DOCUMENT_NODE_TYPE = 9; + +/** + * A polyfill for Element.matches() + */ +if (typeof Element !== 'undefined' && !Element.prototype.matches) { + var proto = Element.prototype; + + proto.matches = proto.matchesSelector || + proto.mozMatchesSelector || + proto.msMatchesSelector || + proto.oMatchesSelector || + proto.webkitMatchesSelector; +} + +/** + * Finds the closest parent that matches a selector. + * + * @param {Element} element + * @param {String} selector + * @return {Function} + */ +function closest (element, selector) { + while (element && element.nodeType !== DOCUMENT_NODE_TYPE) { + if (typeof element.matches === 'function' && + element.matches(selector)) { + return element; + } + element = element.parentNode; + } +} + +module.exports = closest; + + +/***/ }), + +/***/ 438: +/***/ (function(module, __unused_webpack_exports, __webpack_require__) { + +var closest = __webpack_require__(828); + +/** + * Delegates event to a selector. + * + * @param {Element} element + * @param {String} selector + * @param {String} type + * @param {Function} callback + * @param {Boolean} useCapture + * @return {Object} + */ +function _delegate(element, selector, type, callback, useCapture) { + var listenerFn = listener.apply(this, arguments); + + element.addEventListener(type, listenerFn, useCapture); + + return { + destroy: function() { + element.removeEventListener(type, listenerFn, useCapture); + } + } +} + +/** + * Delegates event to a selector. + * + * @param {Element|String|Array} [elements] + * @param {String} selector + * @param {String} type + * @param {Function} callback + * @param {Boolean} useCapture + * @return {Object} + */ +function delegate(elements, selector, type, callback, useCapture) { + // Handle the regular Element usage + if (typeof elements.addEventListener === 'function') { + return _delegate.apply(null, arguments); + } + + // Handle Element-less usage, it defaults to global delegation + if (typeof type === 'function') { + // Use `document` as the first parameter, then apply arguments + // This is a short way to .unshift `arguments` without running into deoptimizations + return _delegate.bind(null, document).apply(null, arguments); + } + + // Handle Selector-based usage + if (typeof elements === 'string') { + elements = document.querySelectorAll(elements); + } + + // Handle Array-like based usage + return Array.prototype.map.call(elements, function (element) { + return _delegate(element, selector, type, callback, useCapture); + }); +} + +/** + * Finds closest match and invokes callback. + * + * @param {Element} element + * @param {String} selector + * @param {String} type + * @param {Function} callback + * @return {Function} + */ +function listener(element, selector, type, callback) { + return function(e) { + e.delegateTarget = closest(e.target, selector); + + if (e.delegateTarget) { + callback.call(element, e); + } + } +} + +module.exports = delegate; + + +/***/ }), + +/***/ 879: +/***/ (function(__unused_webpack_module, exports) { + +/** + * Check if argument is a HTML element. + * + * @param {Object} value + * @return {Boolean} + */ +exports.node = function(value) { + return value !== undefined + && value instanceof HTMLElement + && value.nodeType === 1; +}; + +/** + * Check if argument is a list of HTML elements. + * + * @param {Object} value + * @return {Boolean} + */ +exports.nodeList = function(value) { + var type = Object.prototype.toString.call(value); + + return value !== undefined + && (type === '[object NodeList]' || type === '[object HTMLCollection]') + && ('length' in value) + && (value.length === 0 || exports.node(value[0])); +}; + +/** + * Check if argument is a string. + * + * @param {Object} value + * @return {Boolean} + */ +exports.string = function(value) { + return typeof value === 'string' + || value instanceof String; +}; + +/** + * Check if argument is a function. + * + * @param {Object} value + * @return {Boolean} + */ +exports.fn = function(value) { + var type = Object.prototype.toString.call(value); + + return type === '[object Function]'; +}; + + +/***/ }), + +/***/ 370: +/***/ (function(module, __unused_webpack_exports, __webpack_require__) { + +var is = __webpack_require__(879); +var delegate = __webpack_require__(438); + +/** + * Validates all params and calls the right + * listener function based on its target type. + * + * @param {String|HTMLElement|HTMLCollection|NodeList} target + * @param {String} type + * @param {Function} callback + * @return {Object} + */ +function listen(target, type, callback) { + if (!target && !type && !callback) { + throw new Error('Missing required arguments'); + } + + if (!is.string(type)) { + throw new TypeError('Second argument must be a String'); + } + + if (!is.fn(callback)) { + throw new TypeError('Third argument must be a Function'); + } + + if (is.node(target)) { + return listenNode(target, type, callback); + } + else if (is.nodeList(target)) { + return listenNodeList(target, type, callback); + } + else if (is.string(target)) { + return listenSelector(target, type, callback); + } + else { + throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList'); + } +} + +/** + * Adds an event listener to a HTML element + * and returns a remove listener function. + * + * @param {HTMLElement} node + * @param {String} type + * @param {Function} callback + * @return {Object} + */ +function listenNode(node, type, callback) { + node.addEventListener(type, callback); + + return { + destroy: function() { + node.removeEventListener(type, callback); + } + } +} + +/** + * Add an event listener to a list of HTML elements + * and returns a remove listener function. + * + * @param {NodeList|HTMLCollection} nodeList + * @param {String} type + * @param {Function} callback + * @return {Object} + */ +function listenNodeList(nodeList, type, callback) { + Array.prototype.forEach.call(nodeList, function(node) { + node.addEventListener(type, callback); + }); + + return { + destroy: function() { + Array.prototype.forEach.call(nodeList, function(node) { + node.removeEventListener(type, callback); + }); + } + } +} + +/** + * Add an event listener to a selector + * and returns a remove listener function. + * + * @param {String} selector + * @param {String} type + * @param {Function} callback + * @return {Object} + */ +function listenSelector(selector, type, callback) { + return delegate(document.body, selector, type, callback); +} + +module.exports = listen; + + +/***/ }), + +/***/ 817: +/***/ (function(module) { + +function select(element) { + var selectedText; + + if (element.nodeName === 'SELECT') { + element.focus(); + + selectedText = element.value; + } + else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') { + var isReadOnly = element.hasAttribute('readonly'); + + if (!isReadOnly) { + element.setAttribute('readonly', ''); + } + + element.select(); + element.setSelectionRange(0, element.value.length); + + if (!isReadOnly) { + element.removeAttribute('readonly'); + } + + selectedText = element.value; + } + else { + if (element.hasAttribute('contenteditable')) { + element.focus(); + } + + var selection = window.getSelection(); + var range = document.createRange(); + + range.selectNodeContents(element); + selection.removeAllRanges(); + selection.addRange(range); + + selectedText = selection.toString(); + } + + return selectedText; +} + +module.exports = select; + + +/***/ }), + +/***/ 279: +/***/ (function(module) { + +function E () { + // Keep this empty so it's easier to inherit from + // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3) +} + +E.prototype = { + on: function (name, callback, ctx) { + var e = this.e || (this.e = {}); + + (e[name] || (e[name] = [])).push({ + fn: callback, + ctx: ctx + }); + + return this; + }, + + once: function (name, callback, ctx) { + var self = this; + function listener () { + self.off(name, listener); + callback.apply(ctx, arguments); + }; + + listener._ = callback + return this.on(name, listener, ctx); + }, + + emit: function (name) { + var data = [].slice.call(arguments, 1); + var evtArr = ((this.e || (this.e = {}))[name] || []).slice(); + var i = 0; + var len = evtArr.length; + + for (i; i < len; i++) { + evtArr[i].fn.apply(evtArr[i].ctx, data); + } + + return this; + }, + + off: function (name, callback) { + var e = this.e || (this.e = {}); + var evts = e[name]; + var liveEvents = []; + + if (evts && callback) { + for (var i = 0, len = evts.length; i < len; i++) { + if (evts[i].fn !== callback && evts[i].fn._ !== callback) + liveEvents.push(evts[i]); + } + } + + // Remove event from queue to prevent memory leak + // Suggested by https://github.com/lazd + // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910 + + (liveEvents.length) + ? e[name] = liveEvents + : delete e[name]; + + return this; + } +}; + +module.exports = E; +module.exports.TinyEmitter = E; + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ if(__webpack_module_cache__[moduleId]) { +/******/ return __webpack_module_cache__[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ !function() { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function() { return module['default']; } : +/******/ function() { return module; }; +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ }(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ !function() { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = function(exports, definition) { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ }(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ !function() { +/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } +/******/ }(); +/******/ +/************************************************************************/ +/******/ // module exports must be returned from runtime so entry inlining is disabled +/******/ // startup +/******/ // Load entry module and return exports +/******/ return __webpack_require__(686); +/******/ })() +.default; +}); \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/clipboard/clipboard.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/clipboard/clipboard.min.js new file mode 100644 index 0000000000..1103f811ed --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/clipboard/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return b}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),r=n.n(e);function c(t){try{return document.execCommand(t)}catch(t){return}}var a=function(t){t=r()(t);return c("cut"),t};function o(t,e){var n,o,t=(n=t,o="rtl"===document.documentElement.getAttribute("dir"),(t=document.createElement("textarea")).style.fontSize="12pt",t.style.border="0",t.style.padding="0",t.style.margin="0",t.style.position="absolute",t.style[o?"right":"left"]="-9999px",o=window.pageYOffset||document.documentElement.scrollTop,t.style.top="".concat(o,"px"),t.setAttribute("readonly",""),t.value=n,t);return e.container.appendChild(t),e=r()(t),c("copy"),t.remove(),e}var f=function(t){var e=1 - - -``` - -This will find and highlight code inside of `
` tags; it tries
-to detect the language automatically. If automatic detection doesn’t
-work for you, you can specify the language in the `class` attribute:
-
-```html
-
...
-``` - -Classes may also be prefixed with either `language-` or `lang-`. - -```html -
...
-``` - -### Plaintext and Disabling Highlighting - -To style arbitrary text like code, but without any highlighting, use the -`plaintext` class: - -```html -
...
-``` - -To disable highlighting of a tag completely, use the `nohighlight` class: - -```html -
...
-``` - -### Supported Languages - -The table below shows the full list of supported languages (and corresponding classes) that are bundled with the library. Note: Which languages are available may depend on how you've built or included the library in your app. See [Getting the Library](#getting-the-library) below. - -
-Reveal the full list of languages... - -| Language | Classes | Package | -| :-----------------------| :--------------------- | :------ | -| 1C | 1c | | -| ABNF | abnf | | -| Access logs | accesslog | | -| Ada | ada | | -| ARM assembler | armasm, arm | | -| AVR assembler | avrasm | | -| ActionScript | actionscript, as | | -| Alan | alan, i | [highlightjs-alan](https://github.com/highlightjs/highlightjs-alan) | -| AngelScript | angelscript, asc | | -| Apache | apache, apacheconf | | -| AppleScript | applescript, osascript | | -| Arcade | arcade | | -| AsciiDoc | asciidoc, adoc | | -| AspectJ | aspectj | | -| AutoHotkey | autohotkey | | -| AutoIt | autoit | | -| Awk | awk, mawk, nawk, gawk | | -| Axapta | axapta | | -| Bash | bash, sh, zsh | | -| Basic | basic | | -| BNF | bnf | | -| Brainfuck | brainfuck, bf | | -| C# | cs, csharp | | -| C++ | cpp, c, cc, h, c++, h++, hpp | | -| C/AL | cal | | -| Cache Object Script | cos, cls | | -| CMake | cmake, cmake.in | | -| Coq | coq | | -| CSP | csp | | -| CSS | css | | -| Cap’n Proto | capnproto, capnp | | -| Clojure | clojure, clj | | -| CoffeeScript | coffeescript, coffee, cson, iced | | -| Crmsh | crmsh, crm, pcmk | | -| Crystal | crystal, cr | | -| Cypher (Neo4j) | cypher | [highlightjs-cypher](https://github.com/highlightjs/highlightjs-cypher) | -| D | d | | -| DNS Zone file | dns, zone, bind | | -| DOS | dos, bat, cmd | | -| Dart | dart | | -| Delphi | delphi, dpr, dfm, pas, pascal, freepascal, lazarus, lpr, lfm | | -| Diff | diff, patch | | -| Django | django, jinja | | -| Dockerfile | dockerfile, docker | | -| dsconfig | dsconfig | | -| DTS (Device Tree) | dts | | -| Dust | dust, dst | | -| Dylan | dylan | [highlight-dylan](https://github.com/highlightjs/highlight-dylan) | -| EBNF | ebnf | | -| Elixir | elixir | | -| Elm | elm | | -| Erlang | erlang, erl | | -| Excel | excel, xls, xlsx | | -| Extempore | extempore, xtlang, xtm | [highlightjs-xtlang](https://github.com/highlightjs/highlightjs-xtlang) | -| F# | fsharp, fs | | -| FIX | fix | | -| Fortran | fortran, f90, f95 | | -| G-Code | gcode, nc | | -| Gams | gams, gms | | -| GAUSS | gauss, gss | | -| GDScript | godot, gdscript | [highlightjs-gdscript](https://github.com/highlightjs/highlightjs-gdscript) | -| Gherkin | gherkin | | -| GN for Ninja | gn, gni | [highlightjs-GN](https://github.com/highlightjs/highlightjs-GN/blob/master/gn.js) | -| Go | go, golang | | -| Grammatical Framework | gf | [highlightjs-gf](https://github.com/johnjcamilleri/highlightjs-gf) | -| Golo | golo, gololang | | -| Gradle | gradle | | -| Groovy | groovy | | -| HTML, XML | xml, html, xhtml, rss, atom, xjb, xsd, xsl, plist, svg | | -| HTTP | http, https | | -| Haml | haml | | -| Handlebars | handlebars, hbs, html.hbs, html.handlebars | | -| Haskell | haskell, hs | | -| Haxe | haxe, hx | | -| Hy | hy, hylang | | -| Ini, TOML | ini, toml | | -| Inform7 | inform7, i7 | | -| IRPF90 | irpf90 | | -| JSON | json | | -| Java | java, jsp | | -| JavaScript | javascript, js, jsx | | -| Kotlin | kotlin, kt | | -| Leaf | leaf | | -| Lasso | lasso, ls, lassoscript | | -| Less | less | | -| LDIF | ldif | | -| Lisp | lisp | | -| LiveCode Server | livecodeserver | | -| LiveScript | livescript, ls | | -| Lua | lua | | -| Makefile | makefile, mk, mak | | -| Markdown | markdown, md, mkdown, mkd | | -| Mathematica | mathematica, mma, wl | | -| Matlab | matlab | | -| Maxima | maxima | | -| Maya Embedded Language | mel | | -| Mercury | mercury | | -| mIRC Scripting Language | mirc, mrc | [highlightjs-mirc](https://github.com/highlightjs/highlightjs-mirc) | -| Mizar | mizar | | -| Mojolicious | mojolicious | | -| Monkey | monkey | | -| Moonscript | moonscript, moon | | -| N1QL | n1ql | | -| NSIS | nsis | | -| Nginx | nginx, nginxconf | | -| Nimrod | nimrod, nim | | -| Nix | nix | | -| OCaml | ocaml, ml | | -| Objective C | objectivec, mm, objc, obj-c | | -| OpenGL Shading Language | glsl | | -| OpenSCAD | openscad, scad | | -| Oracle Rules Language | ruleslanguage | | -| Oxygene | oxygene | | -| PF | pf, pf.conf | | -| PHP | php, php3, php4, php5, php6, php7 | | -| Parser3 | parser3 | | -| Perl | perl, pl, pm | | -| Plaintext: no highlight | plaintext | | -| Pony | pony | | -| PostgreSQL & PL/pgSQL | pgsql, postgres, postgresql | | -| PowerShell | powershell, ps, ps1 | | -| Processing | processing | | -| Prolog | prolog | | -| Properties | properties | | -| Protocol Buffers | protobuf | | -| Puppet | puppet, pp | | -| Python | python, py, gyp | | -| Python profiler results | profile | | -| Q | k, kdb | | -| QML | qml | | -| R | r | | -| Razor CSHTML | cshtml, razor, razor-cshtml | [highlightjs-cshtml-razor](https://github.com/highlightjs/highlightjs-cshtml-razor) | -| ReasonML | reasonml, re | | -| RenderMan RIB | rib | | -| RenderMan RSL | rsl | | -| Roboconf | graph, instances | | -| Robot Framework | robot, rf | [highlightjs-robot](https://github.com/highlightjs/highlightjs-robot) | -| RPM spec files | rpm-specfile, rpm, spec, rpm-spec, specfile | [highlightjs-rpm-specfile](https://github.com/highlightjs/highlightjs-rpm-specfile) | -| Ruby | ruby, rb, gemspec, podspec, thor, irb | | -| Rust | rust, rs | | -| SAS | SAS, sas | | -| SCSS | scss | | -| SQL | sql | | -| STEP Part 21 | p21, step, stp | | -| Scala | scala | | -| Scheme | scheme | | -| Scilab | scilab, sci | | -| Shape Expressions | shexc | [highlightjs-shexc](https://github.com/highlightjs/highlightjs-shexc) | -| Shell | shell, console | | -| Smali | smali | | -| Smalltalk | smalltalk, st | | -| Solidity | solidity, sol | [highlightjs-solidity](https://github.com/highlightjs/highlightjs-solidity) | -| Stan | stan, stanfuncs | | -| Stata | stata | | -| Structured Text | iecst, scl, stl, structured-text | [highlightjs-structured-text](https://github.com/highlightjs/highlightjs-structured-text) | -| Stylus | stylus, styl | | -| SubUnit | subunit | | -| Supercollider | supercollider, sc | [highlightjs-supercollider](https://github.com/highlightjs/highlightjs-supercollider) | -| Swift | swift | | -| Tcl | tcl, tk | | -| Terraform (HCL) | terraform, tf, hcl | [highlightjs-terraform](https://github.com/highlightjs/highlightjs-terraform) | -| Test Anything Protocol | tap | | -| TeX | tex | | -| Thrift | thrift | | -| TP | tp | | -| Twig | twig, craftcms | | -| TypeScript | typescript, ts | | -| VB.Net | vbnet, vb | | -| VBScript | vbscript, vbs | | -| VHDL | vhdl | | -| Vala | vala | | -| Verilog | verilog, v | | -| Vim Script | vim | | -| x86 Assembly | x86asm | | -| XL | xl, tao | | -| XQuery | xquery, xpath, xq | | -| YAML | yml, yaml | | -| Zephir | zephir, zep | | - -Languages with the specified package name are defined in separate repositories -and not included in `highlight.pack.js`. -
- - -## Custom Initialization - -When you need a bit more control over the initialization of -highlight.js, you can use the [`highlightBlock`][3] and [`configure`][4] -functions. This allows you to control *what* to highlight and *when*. - -Here’s an equivalent way to calling [`initHighlightingOnLoad`][1] using -vanilla JS: - -```js -document.addEventListener('DOMContentLoaded', (event) => { - document.querySelectorAll('pre code').forEach((block) => { - hljs.highlightBlock(block); - }); -}); -``` - -You can use any tags instead of `
` to mark up your code. If
-you don't use a container that preserves line breaks you will need to
-configure highlight.js to use the `
` tag: - -```js -hljs.configure({useBR: true}); - -document.querySelectorAll('div.code').forEach((block) => { - hljs.highlightBlock(block); -}); -``` - -For other options refer to the documentation for [`configure`][4]. - - -## Web Workers - -You can run highlighting inside a web worker to avoid freezing the browser -window while dealing with very big chunks of code. - -In your main script: - -```js -addEventListener('load', () => { - const code = document.querySelector('#code'); - const worker = new Worker('worker.js'); - worker.onmessage = (event) => { code.innerHTML = event.data; } - worker.postMessage(code.textContent); -}); -``` - -In worker.js: - -```js -onmessage = (event) => { - importScripts('/highlight.pack.js'); - const result = self.hljs.highlightAuto(event.data); - postMessage(result.value); -}; -``` - -## Node.js - -You can use highlight.js with node to highlight content before sending it to the browser. -Make sure to use the `.value` property to get the formatted html. -For more info about the returned object refer to the api docs https://highlightjs.readthedocs.io/en/latest/api.html - - -```js -// require the highlight.js library including all languages -const hljs = require('./highlight.js'); -const highlightedCode = hljs.highlightAuto('Hello World!').value -``` - -```js -// require the highlight.js library without languages -const hljs = require("highlight.js/lib/highlight.js"); -// separately require languages -hljs.registerLanguage('html', require('highlight.js/lib/languages/html')); -hljs.registerLanguage('sql', require('highlight.js/lib/languages/sql')); -// highlight with providing the language -const highlightedCode = hljs.highlight('html', 'Hello World!').value -``` - -## Getting the Library - -You can get highlight.js as a hosted, or custom-build, browser script or -as a server module. Right out of the box the browser script supports -both AMD and CommonJS, so if you wish you can use RequireJS or -Browserify without having to build from source. The server module also -works perfectly fine with Browserify, but there is the option to use a -build specific to browsers rather than something meant for a server. -Head over to the [download page][5] for all the options. - -**Don't link to GitHub directly.** The library is not supposed to work straight -from the source, it requires building. If none of the pre-packaged options -work for you refer to the [building documentation][6]. - -**The CDN-hosted package doesn't have all the languages.** Otherwise it'd be -too big. If you don't see the language you need in the ["Common" section][5], -it can be added manually: - -```html - -``` - -**On Almond.** You need to use the optimizer to give the module a name. For -example: - -```bash -r.js -o name=hljs paths.hljs=/path/to/highlight out=highlight.js -``` - - -### CommonJS - -You can import Highlight.js as a CommonJS-module: - -```bash -npm install highlight.js --save -``` - -In your application: - -```js -import hljs from 'highlight.js'; -``` - -The default import imports all languages! Therefore it is likely to be more efficient to import only the library and the languages you need: - -```js -import hljs from 'highlight.js/lib/highlight'; -import javascript from 'highlight.js/lib/languages/javascript'; -hljs.registerLanguage('javascript', javascript); -``` - -To set the syntax highlighting style, if your build tool processes CSS from your JavaScript entry point, you can import the stylesheet directly into your CommonJS-module: - -```js -import hljs from 'highlight.js/lib/highlight'; -import 'highlight.js/styles/github.css'; -``` - -## License - -Highlight.js is released under the BSD License. See [LICENSE][7] file -for details. - -## Links - -The official site for the library is at . - -Further in-depth documentation for the API and other topics is at -. - -Authors and contributors are listed in the [AUTHORS.txt][8] file. - -[1]: http://highlightjs.readthedocs.io/en/latest/api.html#inithighlightingonload -[2]: http://highlightjs.readthedocs.io/en/latest/css-classes-reference.html -[3]: http://highlightjs.readthedocs.io/en/latest/api.html#highlightblock-block -[4]: http://highlightjs.readthedocs.io/en/latest/api.html#configure-options -[5]: https://highlightjs.org/download/ -[6]: http://highlightjs.readthedocs.io/en/latest/building-testing.html -[7]: https://github.com/highlightjs/highlight.js/blob/master/LICENSE -[8]: https://github.com/highlightjs/highlight.js/blob/master/AUTHORS.txt diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/deprecated.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/deprecated.js deleted file mode 100644 index 7746087b1c..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/deprecated.js +++ /dev/null @@ -1,26 +0,0 @@ -Reset = "\x1b[0m" -FgRed = "\x1b[31m" -FgWhite = "\x1b[37m" -FgWhite = "\x1b[37m" -Bright = "\x1b[1m" -FgBlue = "\x1b[34m" -BgRed = "\x1b[41m" - -DEPRECATION = `${BgRed + FgWhite}-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*${Reset} -${Bright}${FgWhite} - Verion 9 of Highlight.js has reached EOL. It will no longer - be supported or receive security updates in the future. - Please upgrade to version 10 or encourage your indirect - dependencies to do so. - - For more info: - ${FgBlue} - https://github.com/highlightjs/highlight.js/issues/2877 - https://github.com/highlightjs/highlight.js/blob/master/VERSION_10_UPGRADE.md - ${BgRed + FgWhite} --*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*${Reset} -`.trim() - -if (!process.env["HLJS_HIDE_UPGRADE_WARNING"]) { - console.log(DEPRECATION) -} diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/api.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/api.rst deleted file mode 100644 index aaa0588b9e..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/api.rst +++ /dev/null @@ -1,151 +0,0 @@ -Library API -=========== - -Highlight.js exports a few functions as methods of the ``hljs`` object. - - -``highlight(languageName, code, ignore_illegals, continuation)`` ---------------------------------------------------------- - -Core highlighting function. -Accepts a language name, or an alias, and a string with the code to highlight. -The ``ignore_illegals`` parameter, when present and evaluates to a true value, -forces highlighting to finish even in case of detecting illegal syntax for the -language instead of throwing an exception. -The ``continuation`` is an optional mode stack representing unfinished parsing. -When present, the function will restart parsing from this state instead of -initializing a new one. This is used internally for `sublanguage` support. - -Note: `continuation` is NOT intended to support line-by-line highlighting -because there is no requirement that a grammar handle linebreaks in any special -way. It's quite possible for a grammar to have a single mode/regex that matches -MANY lines at once. This is not discouraged and entirely up to the grammar. - -Returns an object with the following properties: - -* ``language``: language name, same as the name passed in ``languageName``, returned for consistency with ``highlightAuto`` -* ``relevance``: integer value representing the relevance score -* ``value``: HTML string with highlighting markup -* ``top``: top of the current mode stack -* ``illegal``: boolean representing whether any illegal matches were found - - -``highlightAuto(code, languageSubset)`` ----------------------------------------- - -Highlighting with language detection. -Accepts a string with the code to highlight and an optional array of language names and aliases restricting detection to only those languages. The subset can also be set with ``configure``, but the local parameter overrides the option if set. - -Returns an object with the following properties: - -* ``language``: detected language -* ``relevance``: integer value representing the relevance score -* ``value``: HTML string with highlighting markup -* ``second_best``: object with the same structure for second-best heuristically detected language (may be absent) - - -``fixMarkup(value)`` --------------------- - -Post-processing of the highlighted markup. Currently consists of replacing indentation TAB characters and using ``
`` tags instead of new-line characters. Options are set globally with ``configure``. - -Accepts a string with the highlighted markup. - - -``highlightBlock(block)`` -------------------------- - -Applies highlighting to a DOM node containing code. - -This function is the one to use to apply highlighting dynamically after page load -or within initialization code of third-party Javascript frameworks. - -The function uses language detection by default but you can specify the language -in the ``class`` attribute of the DOM node. See the :doc:`class reference -` for all available language names and aliases. - - -``configure(options)`` ----------------------- - -Configures global options: - -* ``tabReplace``: a string used to replace TAB characters in indentation. -* ``useBR``: a flag to generate ``
`` tags instead of new-line characters in the output, useful when code is marked up using a non-``
`` container.
-* ``classPrefix``: a string prefix added before class names in the generated markup, used for backwards compatibility with stylesheets.
-* ``languages``: an array of language names and aliases restricting auto detection to only these languages.
-
-Accepts an object representing options with the values to updated. Other options don't change
-::
-
-  hljs.configure({
-    tabReplace: '    ', // 4 spaces
-    classPrefix: ''     // don't append class prefix
-                        // … other options aren't changed
-  })
-  hljs.initHighlighting();
-
-
-``initHighlighting()``
-----------------------
-
-Applies highlighting to all ``
..
`` blocks on a page. - - - -``initHighlightingOnLoad()`` ----------------------------- - -Attaches highlighting to the page load event. - - -``registerLanguage(name, language)`` ------------------------------------- - -Adds new language to the library under the specified name. Used mostly internally. - -* ``name``: a string with the name of the language being registered -* ``language``: a function that returns an object which represents the - language definition. The function is passed the ``hljs`` object to be able - to use common regular expressions defined within it. - - -``listLanguages()`` ----------------------------- - -Returns the languages names list. - - - -.. _getLanguage: - - -``getLanguage(name)`` ---------------------- - -Looks up a language by name or alias. - -Returns the language object if found, ``undefined`` otherwise. - - -``requireLanguage(name)`` ---------------------- - -Looks up a language by name or alias. - -This should be used when one language definition depends on another. -Using this function (vs ``getLanguage``) will provide better error messaging -when a required language is missing. - -Returns the language object if found, raises a hard error otherwise. - - -``debugMode()`` ---------------- - -Enables *debug/development* mode. **This mode purposely makes Highlight.js more fragile! It should only be used for testing and local development (of languages or the library itself).** By default "Safe Mode" is used, providing the most reliable experience for production usage. - -For example, if a new version suddenly had a serious bug (or breaking change) that affected only a single language: - -* **In Safe Mode**: All other languages would continue to highlight just fine. The broken language would appear as a code block, but without any highlighting (as if it were plaintext). -* **In Debug Mode**: All highlighting would stop when an error was encountered and a JavaScript error would be thrown. diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/building-testing.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/building-testing.rst deleted file mode 100644 index 16292cb84a..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/building-testing.rst +++ /dev/null @@ -1,88 +0,0 @@ -Building and testing -==================== - -To actually run highlight.js it is necessary to build it for the environment -where you're going to run it: a browser, the node.js server, etc. - - -Building --------- - -The build tool is written in JavaScript using node.js. Before running the -script, make sure to have node installed and run ``npm install`` to get the -dependencies. - -The tool is located in ``tools/build.js``. A few useful examples: - -* Build for a browser using only common languages:: - - node tools/build.js :common - -* Build for node.js including all available languages:: - - node tools/build.js -t node - -* Build two specific languages for debugging, skipping compression in this case:: - - node tools/build.js -n python ruby - -On some systems the node binary is named ``nodejs``; simply replace ``node`` -with ``nodejs`` in the examples above if that is the case. - -The full option reference is available with the usual ``--help`` option. - -The build result will be in the ``build/`` directory. - -.. _basic-testing: - -Basic testing -------------- - -The usual approach to debugging and testing a language is first doing it -visually. You need to build highlight.js with only the language you're working -on (without compression, to have readable code in browser error messages) and -then use the Developer tool in ``tools/developer.html`` to see how it highlights -a test snippet in that language. - -A test snippet should be short and give the idea of the overall look of the -language. It shouldn't include every possible syntactic element and shouldn't -even make practical sense. - -After you satisfied with the result you need to make sure that language -detection still works with your language definition included in the whole suite. - -Testing is done using `Mocha `_ and the -files are found in the ``test/`` directory. You can use the node build to -run the tests in the command line with ``npm test`` after installing the -dependencies with ``npm install``. - -**Note**: for Debian-based machine, like Ubuntu, you might need to create an -alias or symbolic link for nodejs to node. The reason for this is the -dependencies that are requires to test highlight.js has a reference to -"node". - -Place the snippet you used inside the browser in -``test/detect//default.txt``, build the package with all the languages -for node and run the test suite. If your language breaks auto-detection, it -should be fixed by :ref:`improving relevance `, which is a black art -in and of itself. When in doubt, please refer to the discussion group! - - -Testing markup --------------- - -You can also provide additional markup tests for the language to test isolated -cases of various syntactic construct. If your language has 19 different string -literals or complicated heuristics for telling division (``/``) apart from -regexes (``/ .. /``) -- this is the place. - -A test case consists of two files: - -* ``test/markup//.txt``: test code -* ``test/markup//.expect.txt``: reference rendering - -To generate reference rendering use the Developer tool located at -``tools/developer.html``. Make sure to explicitly select your language in the -drop-down menu, as automatic detection is unlikely to work in this case. - - diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/css-classes-reference.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/css-classes-reference.rst deleted file mode 100644 index a75e411a50..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/css-classes-reference.rst +++ /dev/null @@ -1,140 +0,0 @@ -CSS classes reference -===================== - - -Stylable classes ----------------- - -+------------------------------------------------------------------------------+ -| **General-purpose** | -+--------------------------+---------------------------------------------------+ -| keyword | keyword in a regular Algol-style language | -+--------------------------+---------------------------------------------------+ -| built_in | built-in or library object (constant, class, | -| | function) | -+--------------------------+---------------------------------------------------+ -| type | user-defined type in a language with first-class | -| | syntactically significant types, like Haskell | -+--------------------------+---------------------------------------------------+ -| literal | special identifier for a built-in value ("true", | -| | "false", "null") | -+--------------------------+---------------------------------------------------+ -| number | number, including units and modifiers, if any. | -+--------------------------+---------------------------------------------------+ -| regexp | literal regular expression | -+--------------------------+---------------------------------------------------+ -| string | literal string, character | -+--------------------------+---------------------------------------------------+ -| subst | parsed section inside a literal string | -+--------------------------+---------------------------------------------------+ -| symbol | symbolic constant, interned string, goto label | -+--------------------------+---------------------------------------------------+ -| class | class or class-level declaration (interfaces, | -| | traits, modules, etc) | -+--------------------------+---------------------------------------------------+ -| function | function or method declaration | -+--------------------------+---------------------------------------------------+ -| title | name of a class or a function at the place of | -| | declaration | -+--------------------------+---------------------------------------------------+ -| params | block of function arguments (parameters) at the | -| | place of declaration | -+--------------------------+---------------------------------------------------+ -| **Meta** | -+--------------------------+---------------------------------------------------+ -| comment | comment | -+--------------------------+---------------------------------------------------+ -| doctag | documentation markup within comments | -+--------------------------+---------------------------------------------------+ -| meta | flags, modifiers, annotations, processing | -| | instructions, preprocessor directive, etc | -+--------------------------+---------------------------------------------------+ -| meta-keyword | keyword or built-in within meta construct | -+--------------------------+---------------------------------------------------+ -| meta-string | string within meta construct | -+--------------------------+---------------------------------------------------+ -| **Tags, attributes, configs** | -+--------------------------+---------------------------------------------------+ -| section | heading of a section in a config file, heading in | -| | text markup | -+--------------------------+---------------------------------------------------+ -| tag | XML/HTML tag | -+--------------------------+---------------------------------------------------+ -| name | name of an XML tag, the first word in an | -| | s-expression | -+--------------------------+---------------------------------------------------+ -| builtin-name | s-expression name from the language standard | -| | library | -+--------------------------+---------------------------------------------------+ -| attr | name of an attribute with no language defined | -| | semantics (keys in JSON, setting names in .ini), | -| | also sub-attribute within another highlighted | -| | object, like XML tag | -+--------------------------+---------------------------------------------------+ -| attribute | name of an attribute followed by a structured | -| | value part, like CSS properties | -+--------------------------+---------------------------------------------------+ -| variable | variable in a config or a template file, | -| | environment var expansion in a script | -+--------------------------+---------------------------------------------------+ -| **Markup** | -+--------------------------+---------------------------------------------------+ -| bullet | list item bullet in text markup | -+--------------------------+---------------------------------------------------+ -| code | code block in text markup | -+--------------------------+---------------------------------------------------+ -| emphasis | emphasis in text markup | -+--------------------------+---------------------------------------------------+ -| strong | strong emphasis in text markup | -+--------------------------+---------------------------------------------------+ -| formula | mathematical formula in text markup | -+--------------------------+---------------------------------------------------+ -| link | hyperlink in text markup | -+--------------------------+---------------------------------------------------+ -| quote | quotation in text markup | -+--------------------------+---------------------------------------------------+ -| **CSS** | -+--------------------------+---------------------------------------------------+ -| selector-tag | tag selector in CSS | -+--------------------------+---------------------------------------------------+ -| selector-id | #id selector in CSS | -+--------------------------+---------------------------------------------------+ -| selector-class | .class selector in CSS | -+--------------------------+---------------------------------------------------+ -| selector-attr | [attr] selector in CSS | -+--------------------------+---------------------------------------------------+ -| selector-pseudo | :pseudo selector in CSS | -+--------------------------+---------------------------------------------------+ -| **Templates** | -+--------------------------+---------------------------------------------------+ -| template-tag | tag of a template language | -+--------------------------+---------------------------------------------------+ -| template-variable | variable in a template language | -+--------------------------+---------------------------------------------------+ -| **diff** | -+--------------------------+---------------------------------------------------+ -| addition | added or changed line in a diff | -+--------------------------+---------------------------------------------------+ -| deletion | deleted line in a diff | -+--------------------------+---------------------------------------------------+ -| **ReasonML** | -+--------------------------+---------------------------------------------------+ -| operator | reasonml operator such as pipe | -+--------------------------+---------------------------------------------------+ -| pattern-match | reasonml pattern matching matchers | -+--------------------------+---------------------------------------------------+ -| typing | type signatures on function parameters | -+--------------------------+---------------------------------------------------+ -| constructor | type constructors | -+--------------------------+---------------------------------------------------+ -| module-access | scope access into a ReasonML module | -+--------------------------+---------------------------------------------------+ -| module | ReasonML module reference within scope access | -+--------------------------+---------------------------------------------------+ - - -Language names and aliases --------------------------- - -The language names and aliases table has moved to `the project -README `_. diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/index.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/index.rst deleted file mode 100644 index 3288758bb5..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/index.rst +++ /dev/null @@ -1,44 +0,0 @@ -.. highlight.js documentation master file, created by - sphinx-quickstart on Wed Sep 12 23:48:27 2012. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -``highlight.js`` developer documentation -========================================== - -Contents: - -.. toctree:: - :maxdepth: 1 - - api - language-guide - reference - css-classes-reference - style-guide - language-contribution - building-testing - maintainers-guide - -Miscellaneous: - -.. toctree:: - :maxdepth: 1 - - line-numbers - language-requests - -Links: - -- Code: https://github.com/highlightjs/highlight.js -- Discussion: http://groups.google.com/group/highlightjs -- Bug tracking: https://github.com/highlightjs/highlight.js/issues - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-contribution.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-contribution.rst deleted file mode 100644 index 614e816339..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-contribution.rst +++ /dev/null @@ -1,77 +0,0 @@ -Language contributor checklist -============================== - -1. Put language definition into a .js file ------------------------------------------- - -The file defines a function accepting a reference to the library and returning a language object. -The library parameter is useful to access common modes and regexps. You should not immediately call this function, -this is done during the build process and details differ for different build targets. - -:: - - function(hljs) { - return { - keywords: 'foo bar', - contains: [ ..., hljs.NUMBER_MODE, ... ] - } - } - -The name of the file is used as a short language identifier and should be usable as a class name in HTML and CSS. - - -2. Provide meta data --------------------- - -At the top of the file there is a specially formatted comment with meta data processed by a build system. -Meta data format is simply key-value pairs each occupying its own line: - -:: - - /* - Language: Superlanguage - Requires: java.js, sql.js - Author: John Smith - Contributors: Mike Johnson <...@...>, Matt Wilson <...@...> - Description: Some cool language definition - */ - -``Language`` — the only required header giving a human-readable language name. - -``Requires`` — a list of other language files required for this language to work. -This make it possible to describe languages that extend definitions of other ones. -Required files aren't processed in any special way. -The build system just makes sure that they will be in the final package in -``LANGUAGES`` object. - -The meaning of the other headers is pretty obvious. - - -3. Create a code example ------------------------- - -The code example is used both to test language detection and for the demo page -on https://highlightjs.org/. Put it in ``test/detect//default.txt``. - -Take inspiration from other languages in ``test/detect/`` and read -:ref:`testing instructions ` for more details. - - -4. Write class reference ------------------------- - -Class reference lives in the :doc:`CSS classes reference `.. -Describe shortly names of all meaningful modes used in your language definition. - - -5. Add yourself to AUTHORS.*.txt and CHANGES.md ------------------------------------------------ - -If you're a new contributor add yourself to the authors list. -Also it will be good to update CHANGES.md. - - -6. Create a pull request ------------------------- - -Send your contribution as a pull request on GitHub. diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-guide.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-guide.rst deleted file mode 100644 index 0971524e52..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-guide.rst +++ /dev/null @@ -1,284 +0,0 @@ -Language definition guide -========================= - -Highlighting overview ---------------------- - -Programming language code consists of parts with different rules of parsing: keywords like ``for`` or ``if`` -don't make sense inside strings, strings may contain backslash-escaped symbols like ``\"`` -and comments usually don't contain anything interesting except the end of the comment. - -In highlight.js such parts are called "modes". - -Each mode consists of: - -* starting condition -* ending condition -* list of contained sub-modes -* lexing rules and keywords -* …exotic stuff like another language inside a language - -The parser's work is to look for modes and their keywords. -Upon finding, it wraps them into the markup ``...`` -and puts the name of the mode ("string", "comment", "number") -or a keyword group name ("keyword", "literal", "built-in") as the span's class name. - - -General syntax --------------- - -A language definition is a JavaScript object describing the default parsing mode for the language. -This default mode contains sub-modes which in turn contain other sub-modes, effectively making the language definition a tree of modes. - -Here's an example: - -:: - - { - case_insensitive: true, // language is case-insensitive - keywords: 'for if while', - contains: [ - { - className: 'string', - begin: '"', end: '"' - }, - hljs.COMMENT( - '/\\*', // begin - '\\*/', // end - { - contains: [ - { - className: 'doc', begin: '@\\w+' - } - ] - } - ) - ] - } - -Usually the default mode accounts for the majority of the code and describes all language keywords. -A notable exception here is XML in which a default mode is just a user text that doesn't contain any keywords, -and most interesting parsing happens inside tags. - - -Keywords --------- - -In the simple case language keywords are defined in a string, separated by space: - -:: - - { - keywords: 'else for if while' - } - -Some languages have different kinds of "keywords" that might not be called as such by the language spec -but are very close to them from the point of view of a syntax highlighter. These are all sorts of "literals", "built-ins", "symbols" and such. -To define such keyword groups the attribute ``keywords`` becomes an object each property of which defines its own group of keywords: - -:: - - { - keywords: { - keyword: 'else for if while', - literal: 'false true null' - } - } - -The group name becomes then a class name in a generated markup enabling different styling for different kinds of keywords. - -To detect keywords highlight.js breaks the processed chunk of code into separate words — a process called lexing. -The "word" here is defined by the regexp ``[a-zA-Z][a-zA-Z0-9_]*`` that works for keywords in most languages. -Different lexing rules can be defined by the ``lexemes`` attribute: - -:: - - { - lexemes: '-[a-z]+', - keywords: '-import -export' - } - - -Sub-modes ---------- - -Sub-modes are listed in the ``contains`` attribute: - -:: - - { - keywords: '...', - contains: [ - hljs.QUOTE_STRING_MODE, - hljs.C_LINE_COMMENT, - { ... custom mode definition ... } - ] - } - -A mode can reference itself in the ``contains`` array by using a special keyword ``'self``'. -This is commonly used to define nested modes: - -:: - - { - className: 'object', - begin: '{', end: '}', - contains: [hljs.QUOTE_STRING_MODE, 'self'] - } - -Note: ``self`` may not be used in the root level ``contains`` of a language. The root level mode is special and may not be self-referential. - - -Comments --------- - -To define custom comments it is recommended to use a built-in helper function ``hljs.COMMENT`` instead of describing the mode directly, as it also defines a few default sub-modes that improve language detection and do other nice things. - -Parameters for the function are: - -:: - - hljs.COMMENT( - begin, // begin regex - end, // end regex - extra // optional object with extra attributes to override defaults - // (for example {relevance: 0}) - ) - - -Markup generation ------------------ - -Modes usually generate actual highlighting markup — ```` elements with specific class names that are defined by the ``className`` attribute: - -:: - - { - contains: [ - { - className: 'string', - // ... other attributes - }, - { - className: 'number', - // ... - } - ] - } - -Names are not required to be unique, it's quite common to have several definitions with the same name. -For example, many languages have various syntaxes for strings, comments, etc… - -Sometimes modes are defined only to support specific parsing rules and aren't needed in the final markup. -A classic example is an escaping sequence inside strings allowing them to contain an ending quote. - -:: - - { - className: 'string', - begin: '"', end: '"', - contains: [{begin: '\\\\.'}], - } - -For such modes ``className`` attribute should be omitted so they won't generate excessive markup. - - -Mode attributes ---------------- - -Other useful attributes are defined in the :doc:`mode reference `. - - -.. _relevance: - -Relevance ---------- - -Highlight.js tries to automatically detect the language of a code fragment. -The heuristics is essentially simple: it tries to highlight a fragment with all the language definitions -and the one that yields most specific modes and keywords wins. The job of a language definition -is to help this heuristics by hinting relative relevance (or irrelevance) of modes. - -This is best illustrated by example. Python has special kinds of strings defined by prefix letters before the quotes: -``r"..."``, ``u"..."``. If a code fragment contains such strings there is a good chance that it's in Python. -So these string modes are given high relevance: - -:: - - { - className: 'string', - begin: 'r"', end: '"', - relevance: 10 - } - -On the other hand, conventional strings in plain single or double quotes aren't specific to any language -and it makes sense to bring their relevance to zero to lessen statistical noise: - -:: - - { - className: 'string', - begin: '"', end: '"', - relevance: 0 - } - -The default value for relevance is 1. When setting an explicit value it's recommended to use either 10 or 0. - -Keywords also influence relevance. Each of them usually has a relevance of 1, but there are some unique names -that aren't likely to be found outside of their languages, even in the form of variable names. -For example just having ``reinterpret_cast`` somewhere in the code is a good indicator that we're looking at C++. -It's worth to set relevance of such keywords a bit higher. This is done with a pipe: - -:: - - { - keywords: 'for if reinterpret_cast|10' - } - - -Illegal symbols ---------------- - -Another way to improve language detection is to define illegal symbols for a mode. -For example in Python first line of class definition (``class MyClass(object):``) cannot contain symbol "{" or a newline. -Presence of these symbols clearly shows that the language is not Python and the parser can drop this attempt early. - -Illegal symbols are defined as a a single regular expression: - -:: - - { - className: 'class', - illegal: '[${]' - } - - -Pre-defined modes and regular expressions ------------------------------------------ - -Many languages share common modes and regular expressions. Such expressions are defined in core highlight.js code -at the end under "Common regexps" and "Common modes" titles. Use them when possible. - - -Regular Expression Features ---------------------------- - -The goal of Highlight.js is to support whatever regex features Javascript itself supports. You're using real regular expressions, use them responsibly. That said, due to the design of the parser, there are some caveats. These are addressed below. - -Things we support now that we did not always: - -* look-ahead regex matching for `begin` (#2135) -* look-ahead regex matching for `end` (#2237) -* look-ahead regex matching for `illegal` (#2135) -* back-references within your regex matches (#1897) -* look-behind matching (when JS supports it) for `begin` (#2135) - -Things we currently know are still issues: - -* look-behind matching (when JS supports it) for `end` matchers - - -Contributing ------------- - -Follow the :doc:`contributor checklist `. diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-requests.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-requests.rst deleted file mode 100644 index 4e4c2f0b61..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-requests.rst +++ /dev/null @@ -1,17 +0,0 @@ -On requesting new languages -=========================== - -This is a general answer to requests for adding new languages that appear from -time to time in the highlight.js issue tracker and discussion group. - - Highlight.js doesn't have a fundamental plan for implementing languages, - instead the project works by accepting language definitions from - interested contributors. There are also no rules at the moment forbidding - any languages from being added to the library, no matter how obscure or - weird. - - This means that there's no point in requesting a new language without - providing an implementation for it. If you want to see a particular language - included in highlight.js but cannot implement it, the best way to make it - happen is to get another developer interested in doing so. Here's our - :doc:`language-guide`. diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/line-numbers.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/line-numbers.rst deleted file mode 100644 index 674542d4ed..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/line-numbers.rst +++ /dev/null @@ -1,39 +0,0 @@ -Line numbers -============ - -Highlight.js' notable lack of line numbers support is not an oversight but a -feature. Following is the explanation of this policy from the current project -maintainer (hey guys!): - - One of the defining design principles for highlight.js from the start was - simplicity. Not the simplicity of code (in fact, it's quite complex) but - the simplicity of usage and of the actual look of highlighted snippets on - HTML pages. Many highlighters, in my opinion, are overdoing it with such - things as separate colors for every single type of lexemes, striped - backgrounds, fancy buttons around code blocks and — yes — line numbers. - The more fancy stuff resides around the code the more it distracts a - reader from understanding it. - - This is why it's not a straightforward decision: this new feature will not - just make highlight.js better, it might actually make it worse simply by - making it look more bloated in blog posts around the Internet. This is why - I'm asking people to show that it's worth it. - - The only real use-case that ever was brought up in support of line numbers - is referencing code from the descriptive text around it. On my own blog I - was always solving this either with comments within the code itself or by - breaking the larger snippets into smaller ones and describing each small - part separately. I'm not saying that my solution is better. But I don't - see how line numbers are better either. And the only way to show that they - are better is to set up some usability research on the subject. I doubt - anyone would bother to do it. - - Then there's maintenance. So far the core code of highlight.js is - maintained by only one person — yours truly. Inclusion of any new code in - highlight.js means that from that moment I will have to fix bugs in it, - improve it further, make it work together with the rest of the code, - defend its design. And I don't want to do all this for the feature that I - consider "evil" and probably will never use myself. - -This position is `subject to discuss `_. -Also it doesn't stop anyone from forking the code and maintaining line-numbers implementation separately. diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/maintainers-guide.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/maintainers-guide.rst deleted file mode 100644 index 0ac3719e84..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/maintainers-guide.rst +++ /dev/null @@ -1,43 +0,0 @@ -Maintainer's guide -================== - - -Commit policy -------------- - -* Pull requests from outside contributors require a review from a maintainer. - -* Maintainers should avoid working on a master branch directly and create branches for everything. A code review from another maintainer is recommended but not required, use your best judgment. - - - -Release process ---------------- - -Releases (minor) typically happen on a 6-week schedule. - -For major/minor releases you'll be releasing from ``master``. For patch releases you'll be releasing from a stable branch, such as ``9-16-stable``. This allows ongoing development of new features to continue in isolation (in master) without those changes leaking into patch releases (which should focus only on fixing breaking changes). - -The goal being that minor version series always get more stable over time and that patch releases do not add features. - -* For patch releases: First switch to the associated stable branch (i.e., ``9-16-stable``) - -* Update CHANGES.md with everything interesting since the last update. - -* Update version numbers using the three-part x.y.z notation everywhere: - - * The header in CHANGES.md (this is where the site looks for the latest version number) - * ``"version"`` attribute in package.json - * ``"version"`` attribute in package-lock.json (run `npm install`) - * Two places in docs/conf.py (``version`` and ``release``) - -* Commit the version changes and tag the commit with the version number (``9.16.2``, no "v" prefix or anything like that) - -* For major/minor releases: Create a new ``[major]-[minor]-stable`` branch such as ``9-16-stable`` - -* Push the commit and the tags (``git push && git push --tags``) - - -Pushing the tag triggers the update process which can be monitored at http://highlightjs.org/api/release/ - -When something didn't work *and* it's fixable in code (version numbers mismatch, last minute patches, etc), simply make another release incrementing the third (revision) part of the version number. diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/reference.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/reference.rst deleted file mode 100644 index dafee4abd2..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/reference.rst +++ /dev/null @@ -1,361 +0,0 @@ -Mode reference -============== - -Types ------ - -Types of attributes values in this reference: - -+------------+-------------------------------------------------------------------------------------+ -| identifier | String suitable to be used as a Javascript variable and CSS class name | -| | (i.e. mostly ``/[A-Za-z0-9_]+/``) | -+------------+-------------------------------------------------------------------------------------+ -| regexp | String representing a Javascript regexp. | -| | Note that since it's not a literal regexp all back-slashes should be repeated twice | -+------------+-------------------------------------------------------------------------------------+ -| boolean | Javascript boolean: ``true`` or ``false`` | -+------------+-------------------------------------------------------------------------------------+ -| number | Javascript number | -+------------+-------------------------------------------------------------------------------------+ -| object | Javascript object: ``{ ... }`` | -+------------+-------------------------------------------------------------------------------------+ -| array | Javascript array: ``[ ... ]`` | -+------------+-------------------------------------------------------------------------------------+ - - -Attributes ----------- - -case_insensitive -^^^^^^^^^^^^^^^^ - -**type**: boolean - -Case insensitivity of language keywords and regexps. Used only on the top-level mode. - - -aliases -^^^^^^^ - -**type**: array - -A list of additional names (besides the canonical one given by the filename) that can be used to identify a language in HTML classes and in a call to :ref:`getLanguage `. - - -className -^^^^^^^^^ - -**type**: identifier - -The name of the mode. It is used as a class name in HTML markup. - -Multiple modes can have the same name. This is useful when a language has multiple variants of syntax -for one thing like string in single or double quotes. - - -begin -^^^^^ - -**type**: regexp - -Regular expression starting a mode. For example a single quote for strings or two forward slashes for C-style comments. -If absent, ``begin`` defaults to a regexp that matches anything, so the mode starts immediately. - - -end -^^^ - -**type**: regexp - -Regular expression ending a mode. For example a single quote for strings or "$" (end of line) for one-line comments. - -It's often the case that a beginning regular expression defines the entire mode and doesn't need any special ending. -For example a number can be defined with ``begin: "\\b\\d+"`` which spans all the digits. - -If absent, ``end`` defaults to a regexp that matches anything, so the mode ends immediately (after possibly -matching any ``contains`` sub-modes). - -Sometimes a mode can end not by itself but implicitly with its containing (parent) mode. -This is achieved with :ref:`endsWithParent ` attribute. - - -beginKeywords -^^^^^^^^^^^^^^^^ - -**type**: string - -Used instead of ``begin`` for modes starting with keywords to avoid needless repetition: - -:: - - { - begin: '\\b(extends|implements) ', - keywords: 'extends implements' - } - -… becomes: - -:: - - { - beginKeywords: 'extends implements' - } - -Unlike the :ref:`keywords ` attribute, this one allows only a simple list of space separated keywords. -If you do need additional features of ``keywords`` or you just need more keywords for this mode you may include ``keywords`` along with ``beginKeywords``. - - -.. _endsWithParent: - -endsWithParent -^^^^^^^^^^^^^^ - -**type**: boolean - -A flag showing that a mode ends when its parent ends. - -This is best demonstrated by example. In CSS syntax a selector has a set of rules contained within symbols "{" and "}". -Individual rules separated by ";" but the last one in a set can omit the terminating semicolon: - -:: - - p { - width: 100%; color: red - } - -This is when ``endsWithParent`` comes into play: - -:: - - { - className: 'rules', begin: '{', end: '}', - contains: [ - {className: 'rule', /* ... */ end: ';', endsWithParent: true} - ] - } - -.. _endsParent: - -endsParent -^^^^^^^^^^^^^^ - -**type**: boolean - -Forces closing of the parent mode right after the current mode is closed. - -This is used for modes that don't have an easily expressible ending lexeme but -instead could be closed after the last interesting sub-mode is found. - -Here's an example with two ways of defining functions in Elixir, one using a -keyword ``do`` and another using a comma: - -:: - - def foo :clear, list do - :ok - end - - def foo, do: IO.puts "hello world" - -Note that in the first case the parameter list after the function title may also -include a comma. And if we're only interested in highlighting a title we can -tell it to end the function definition after itself: - -:: - - { - className: 'function', - beginKeywords: 'def', end: /\B\b/, - contains: [ - { - className: 'title', - begin: hljs.IDENT_RE, endsParent: true - } - ] - } - -(The ``end: /\B\b/`` regex tells function to never end by itself.) - -.. _endSameAsBegin: - -endSameAsBegin -^^^^^^^^^^^^^^ - -**type**: boolean - -Acts as ``end`` matching exactly the same string that was found by the -corresponding ``begin`` regexp. - -For example, in PostgreSQL string constants can uee "dollar quotes", -consisting of a dollar sign, an optional tag of zero or more characters, -and another dollar sign. String constant must be ended with the same -construct using the same tag. It is possible to nest dollar-quoted string -constants by choosing different tags at each nesting level: - -:: - - $foo$ - ... - $bar$ nested $bar$ - ... - $foo$ - -In this case you can't simply specify the same regexp for ``begin`` and -``end`` (say, ``"\\$[a-z]\\$"``), but you can use ``begin: "\\$[a-z]\\$"`` -and ``endSameAsBegin: true``. - -.. _lexemes: - -lexemes -^^^^^^^ - -**type**: regexp - -A regular expression that extracts individual lexemes from language text to find :ref:`keywords ` among them. -Default value is ``hljs.IDENT_RE`` which works for most languages. - - -.. _keywords: - -keywords -^^^^^^^^ - -**type**: object - -Keyword definition comes in two forms: - -* ``'for while if else weird_voodoo|10 ... '`` -- a string of space-separated keywords with an optional relevance over a pipe -* ``{'keyword': ' ... ', 'literal': ' ... '}`` -- an object whose keys are names of different kinds of keywords and values are keyword definition strings in the first form - -For detailed explanation see :doc:`Language definition guide `. - - -illegal -^^^^^^^ - -**type**: regexp - -A regular expression that defines symbols illegal for the mode. -When the parser finds a match for illegal expression it immediately drops parsing the whole language altogether. - - -excludeBegin, excludeEnd -^^^^^^^^^^^^^^^^^^^^^^^^ - -**type**: boolean - -Exclude beginning or ending lexemes out of mode's generated markup. For example in CSS syntax a rule ends with a semicolon. -However visually it's better not to color it as the rule contents. Having ``excludeEnd: true`` forces a ```` element for the rule to close before the semicolon. - - -returnBegin -^^^^^^^^^^^ - -**type**: boolean - -Returns just found beginning lexeme back into parser. This is used when beginning of a sub-mode is a complex expression -that should not only be found within a parent mode but also parsed according to the rules of a sub-mode. - -Since the parser is effectively goes back it's quite possible to create a infinite loop here so use with caution! - - -returnEnd -^^^^^^^^^ - -**type**: boolean - -Returns just found ending lexeme back into parser. This is used for example to parse Javascript embedded into HTML. -A Javascript block ends with the HTML closing tag ```` that cannot be parsed with Javascript rules. -So it is returned back into its parent HTML mode that knows what to do with it. - -Since the parser is effectively goes back it's quite possible to create a infinite loop here so use with caution! - - -contains -^^^^^^^^ - -**type**: array - -The list of sub-modes that can be found inside the mode. For detailed explanation see :doc:`Language definition guide `. - - -starts -^^^^^^ - -**type**: identifier - -The name of the mode that will start right after the current mode ends. The new mode won't be contained within the current one. - -Currently this attribute is used to highlight Javascript and CSS contained within HTML. -Tags ``