diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..9805011759f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,137 @@ +# EditorConfig is awesome: https://EditorConfig.org +# Please feel free to update it (by considering the code style of ABP Team). +# top-most EditorConfig file +root = true + +[*.cs] + +#Namespace settings +csharp_style_namespace_declarations = file_scoped +dotnet_diagnostic.IDE0161.severity = warning + +#Core editorconfig formatting - indentation + +#use tabs for indentation +indent_style = tabs + +#Formatting - indentation options + +#indent switch case contents. +csharp_indent_case_contents = true +#indent switch labels +csharp_indent_switch_labels = true + +#Formatting - new line options + +#place catch statements on a new line +csharp_new_line_before_catch = true +#place else statements on a new line +csharp_new_line_before_else = true +#require members of object intializers to be on separate lines +csharp_new_line_before_members_in_object_initializers = true +#require braces to be on a new line for object_collection_array_initializers, methods, control_blocks, types, and lambdas (also known as "Allman" style) +csharp_new_line_before_open_brace = object_collection_array_initializers, methods, control_blocks, types, lambdas + +#Formatting - organize using options + +#sort System.* using directives alphabetically, and place them before other usings +dotnet_sort_system_directives_first = true + +#Formatting - spacing options + +#require NO space between a cast and the value +csharp_space_after_cast = false +#require a space before the colon for bases or interfaces in a type declaration +csharp_space_after_colon_in_inheritance_clause = true +#require a space after a keyword in a control flow statement such as a for loop +csharp_space_after_keywords_in_control_flow_statements = true +#require a space before the colon for bases or interfaces in a type declaration +csharp_space_before_colon_in_inheritance_clause = true +#remove space within empty argument list parentheses +csharp_space_between_method_call_empty_parameter_list_parentheses = false +#remove space between method call name and opening parenthesis +csharp_space_between_method_call_name_and_opening_parenthesis = false +#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call +csharp_space_between_method_call_parameter_list_parentheses = false +#remove space within empty parameter list parentheses for a method declaration +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list. +csharp_space_between_method_declaration_parameter_list_parentheses = false + +#Formatting - wrapping options + +#leave code block on single line +csharp_preserve_single_line_blocks = true + +#Style - Code block preferences + +#prefer curly braces even for one line of code +csharp_prefer_braces = true:suggestion + +#Style - expression bodied member options + +#prefer block bodies for constructors +csharp_style_expression_bodied_constructors = false:suggestion +#prefer block bodies for methods +csharp_style_expression_bodied_methods = false:suggestion +#prefer expression-bodied members for properties +csharp_style_expression_bodied_properties = true:suggestion + +#Style - expression level options + +#prefer out variables to be declared inline in the argument list of a method call when possible +csharp_style_inlined_variable_declaration = true:suggestion +#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_member_access = true:suggestion + +#Style - Expression-level preferences + +#prefer default over default(T) +csharp_prefer_simple_default_expression = true:suggestion +#prefer objects to be initialized using object initializers when possible +dotnet_style_object_initializer = true:suggestion +#prefer inferred tuple element names +dotnet_style_prefer_inferred_tuple_names = true:suggestion + +#Style - implicit and explicit types + +#prefer var over explicit type in all cases, unless overridden by another code style rule +csharp_style_var_elsewhere = true:suggestion +#prefer var is used to declare variables with built-in system types such as int +csharp_style_var_for_built_in_types = true:suggestion +#prefer var when the type is already mentioned on the right-hand side of a declaration expression +csharp_style_var_when_type_is_apparent = true:suggestion + +#Style - language keyword and framework type options + +#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion + +#Style - Miscellaneous preferences + +#prefer local functions over anonymous functions +csharp_style_pattern_local_over_anonymous_function = true:suggestion + +#Style - modifier options + +#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods. +dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion + +#Style - Modifier preferences + +#when this rule is set to a list of modifiers, prefer the specified ordering. +csharp_preferred_modifier_order = public,protected,private,virtual,async,readonly,static,override,abstract:suggestion + +#Style - Pattern matching + +#prefer pattern matching instead of is expression with type casts +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion + +#Style - qualification options + +#prefer fields not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_field = false:suggestion +#prefer methods not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_method = false:suggestion +#prefer properties not to be prefaced with this. or Me. in Visual Basic +dotnet_style_qualification_for_property = false:suggestion diff --git a/.gitignore b/.gitignore index 79d0ea6388b..1faf2fac917 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ *.user *.userosscache *.sln.docstates -*.editorconfig + # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json index 4ea99af7e15..f64b3859085 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json @@ -210,6 +210,10 @@ "Completed": "Completed", "Failed": "Failed", "PaymentRequestDeletionWarningMessage": "This payment request will be deleted. Do you confirm that?", - "Payment": "Payment" + "Payment": "Payment", + "Permission:SendWelcomeEmail": "Send Welcome Email", + "SendWelcomeEmail": "Send Welcome Email", + "SendWelcomeEmailWarningMessage": "Are you sure you want to send welcome email to the organization members?", + "SendWelcomeEmailSuccessMessage": "Welcome email sent successfully!" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 923535cfdda..f9262592978 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -352,6 +352,11 @@ "Volo.AbpIo.Commercial:030008": "Purchase date can be set only when status is Purchased!", "Volo.AbpIo.Commercial:030009": "User not found!", "Volo.AbpIo.Commercial:030010": "To purchase the trial license, first you need to activate your trial license!", - "Volo.AbpIo.Commercial:030011": "You cannot delete a trial license when it is purchased!" + "Volo.AbpIo.Commercial:030011": "You cannot delete a trial license when it is purchased!", + "Permission:SendWelcomeEmail": "Send Welcome Email", + "SendWelcomeEmail": "Send Welcome Email", + "SendWelcomeEmailWarningMessage": "Are you sure you want to send welcome email to the organization members?", + "SendWelcomeEmailSuccessMessage": "Welcome email sent successfully!", + "PaymentRequestId": "Payment Request Id" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json index 1bba0bb964d..5942fca747d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json @@ -348,6 +348,10 @@ "Volo.AbpIo.Commercial:030008": "Satın alma tarihi yalnızca durum Satın Alındı olduğunda ayarlanabilir!", "Volo.AbpIo.Commercial:030009": "Kullanıcı bulunamadı!", "Volo.AbpIo.Commercial:030010": "Deneme lisansını satın almak için önce deneme lisansınızı etkinleştirmeniz gerekir!", - "Volo.AbpIo.Commercial:030011": "Satın alındığında bir deneme lisansını silemezsiniz!" + "Volo.AbpIo.Commercial:030011": "Satın alındığında bir deneme lisansını silemezsiniz!", + "Permission:SendWelcomeEmail": "Hoşgeldin Emaili Gönder", + "SendWelcomeEmail": "Hoşgeldin Emaili Gönder", + "SendWelcomeEmailWarningMessage": "Organizasyon üyelerine hoşgeldin emaili göndermek istediğinden emin misin?", + "SendWelcomeEmailSuccessMessage": "Hoşgeldin emaili başarıyla gönderilmiştir!" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json index 87b934f8c52..caa14e8d94b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json @@ -102,6 +102,10 @@ "InvalidFormInputs": "Please, type the valid information specified on the form.", "DDDBookEmailBody": "Thank you.
To download your book, click here.", "FreeDDDEBook": "Free DDD E-Book", - "CommercialNewsletterConfirmationMessage": "I agree to the Terms & Conditions and Privacy Policy." + "CommercialNewsletterConfirmationMessage": "I agree to the Terms & Conditions and Privacy Policy.", + "RemoveCurrentUserFromOrganizationWarningMessage": "You are removing yourself from your own organization. You will no longer be able to manage this organization, do you confirm?", + "RenewExistingOrganizationOrCreateNewOneMessage": "You can renew the license of your organization(s) by clicking the below \"Extend Now\" button(s) and thus you can extend the license expiry date by 1 year. If you continue to checkout, you will have a new organization. Do you want to continue with a new organization?", + "ExtendNow": "Extend Now", + "ContinueWithNewOrganization": "Continue with a new organization" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index f4a8153ec14..9720354d995 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -178,7 +178,7 @@ "ChangingLicenseType": "Can I upgrade my license type later?", "ChangingLicenseTypeExplanation": "You can upgrade to a higher license by paying the difference within your active license period. When you upgrade to a higher license plan, you get the benefits of the new plan, but the license upgrade does not change the license expiry date. Besides, you can also add new developer seats to your existing license, see \"How many developers can work on the ABP Commercial?\"", "LicenseExtendUpgradeDiff": "What is the difference between license extend and upgrade?", - "LicenseExtendUpgradeDiffExplanation": "Extending: By extending/renewing your license, you will continue to get premium support and get major updates for the modules and themes. Besides, you will be able to continue creating new projects. And you will still be able to use ABP Suite which speeds up your development.
Upgrading: By upgrading your license, you will promote to a higher license plan which will allow you to get additional benefits. See the license comparison table to check the differences between the license plans.On the other hand, when you upgrade, your license expiry date will not change!To extend your license end date, you need to extend your license.", + "LicenseExtendUpgradeDiffExplanation": "Extending: By extending/renewing your license, you will continue to get premium support and get major updates for the modules and themes. Besides, you will be able to continue creating new projects. And you will still be able to use ABP Suite which speeds up your development. When you extend your license, 1 year is added to your license expiry date.
Upgrading: By upgrading your license, you will promote to a higher license plan which will allow you to get additional benefits. See the license comparison table to check the differences between the license plans.On the other hand, when you upgrade, your license expiry date will not change!To extend your license end date, you need to extend your license.", "LicenseRenewalCost": "What is the license renewal cost after 1 year?", "LicenseRenewalCostExplanation": "The renewal (extend) rate of all ABP Commercial perpetual licenses is {0} of the license list price. The renewal price of the standard Team License is ${1}, standard Business License is ${2} and standard Enterprise License is ${3}. If you are already a customer, log into your account to review the available renewal pricing.", "HowDoIRenewMyLicense": "How do I renew my license?", @@ -193,7 +193,7 @@ "WhatHappensWhenLicenseEnds": "What happens when my license period ends?", "WhatHappensWhenLicenseEndsExplanation1": "ABP Commercial license type is perpetual license. After your license expires, you can continue developing your project. And you are not obliged to renew your license. Your license comes with a one-year Updates and Support plan out of the box. To continue to receive new features, performance enhancements, bug fixes, support and continue to use ABP Suite, make sure to renew your plan each year. When your license expires, you will not be able to get more of the following benefits;", "WhatHappensWhenLicenseEndsExplanation2": "You can not create new solutions using the ABP Commercial, but you can continue to develop your existing applications forever.", - "WhatHappensWhenLicenseEndsExplanation3": "You will be able to get updates for the modules and themes within your MAJOR version. For example; if you are using v3.2.0 of a module, you can still get updates for v3.x.x (v3.3.0, v3.5.2... etc.) of that module. But you cannot get updates for the next major version (like v4.x, v5.x)", + "WhatHappensWhenLicenseEndsExplanation3": "You will be able to get updates for the modules and themes within your MAJOR version (except RC or Preview versions). For example; if you are using v3.2.0 of a module, you can still get updates for v3.x.x (v3.3.0, v3.5.2... etc.) of that module. But you cannot get updates for the next major version (like v4.x, v5.x). Let's say, when your license expired, the latest release was v4.4.3 and the latest preview version was v5.0.0-rc.2, you can only access the v4.X.X but you cannot access the v5.X.X.", "WhatHappensWhenLicenseEndsExplanation4": "You can not install new modules and themes added to the ABP Commercial platform after your license ends.", "WhatHappensWhenLicenseEndsExplanation5": "You can not use the ABP Suite.", "WhatHappensWhenLicenseEndsExplanation6": "You can not get the premium support anymore.", @@ -390,6 +390,16 @@ "TrialLicenseExpireMessage": "You are using the trial license and your trial license will expire on {0}.", "TryForFree": "Try For Free", "TrialLicenseExpiredInfo": "Your trial license period has expired!", - "CommercialNewsletterConfirmationMessage": "I agree to the Terms & Conditions and Privacy Policy." + "CommercialNewsletterConfirmationMessage": "I agree to the Terms & Conditions and Privacy Policy.", + "DowngradeLicensePlan": "Can I downgrade to a lower license plan in the future?", + "DowngradeLicensePlanExplanation": "You cannot downgrade your existing license plan. But you can purchase a new lower license plan and continue to your development on the new license. After you purchase a lower license, you just need to login to your new license plan via ABP CLI command: ` abp login -o `.", + "LicenseTransfer": "Can a license be transferred from one developer to another?", + "LicenseTransferExplanation": "Yes! When you purchase a license, you become the license holder, hence you will have access to the organization management page. An organization has owner and developer roles. Owners can manage the developer seats and assign developers. Each assigned developer will login via ABP CLI command into the system and will have development and support permissions.", + "UserOwnerDescription": "The 'Owner' of the organization is the admin of this account. He/she manages the organization by purchasing licenses, allocating developers. An 'Owner' cannot write code in the ABP Commercial projects, cannot download the ABP sample projects, or cannot ask questions on the support website. If you want to do all these, you have to add yourself as a developer too.", + "UserDeveloperDescription": "The 'Developers' can write code in the ABP Commercial projects, download the ABP sample projects, or ask questions on the support website. On the other hand, the 'Developers' cannot manage this organization.", + "RemoveCurrentUserFromOrganizationWarningMessage": "You are removing yourself from your own organization. You will no longer be able to manage this organization, do you confirm?", + "RenewExistingOrganizationOrCreateNewOneMessage": "You can renew the license of your organization(s) by clicking the below \"Extend Now\" button(s) and thus you can extend the license expiry date by 1 year. If you continue to checkout, you will have a new organization. Do you want to continue with a new organization?", + "ExtendNow": "Extend Now", + "ContinueWithNewOrganization": "Continue with a new organization" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json index ae472a27f06..5e93833b0d3 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json @@ -390,6 +390,10 @@ "TrialLicenseExpireMessage": "Deneme lisansını kullanıyorsunuz ve deneme lisansınızın süresi {0} tarihinde sona erecek.", "TryForFree": "Ücretsiz deneyin", "TrialLicenseExpiredInfo": "Deneme lisansınızın süresi doldu!", - "CommercialNewsletterConfirmationMessage": "Şartlar, Koşullar ve Gizlilik politikasını kabul ediyorum." + "CommercialNewsletterConfirmationMessage": "Şartlar, Koşullar ve Gizlilik politikasını kabul ediyorum.", + "RemoveCurrentUserFromOrganizationWarningMessage": "Organizasyondan kendinizi kaldırıyorsunuz. Artık bu organizasyonu yönetemeyeceksiniz, onaylıyor musunuz? ", + "RenewExistingOrganizationOrCreateNewOneMessage": "Aşağıdaki \"Şimdi Uzat\" buton(lar)una tıklayarak organizasyon(lar)ınızın lisansını yenileyebilir ve böylece lisans geçerlilik süresini 1 yıl uzatabilirsiniz. Ödemeye devam ederseniz, yeni bir organizasyonunuz olacak. Yeni bir organizasyonla devam etmek istiyor musunuz? ", + "ExtendNow": "Şimdi Uzat", + "ContinueWithNewOrganization": "Yeni bir organizasyon ile devam et" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json index 44d5d79aaca..751b33613e1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "يجب عليك إدخال 3 أحرف على الأقل!", "Volo.AbpIo.Domain:060001": "عنوان URL المصدر (\"{ArticleUrl}\") ليس عنوان URL لـ Github", "Volo.AbpIo.Domain:060002": "محتوى المقالة غير متوفر من مورد Github (\"{ArticleUrl}\").", - "Volo.AbpIo.Domain:060003": "لم يتم العثور على محتوى مقال!" + "Volo.AbpIo.Domain:060003": "لم يتم العثور على محتوى مقال!", + "SeeMore": "شاهد المزيد" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de-DE.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de-DE.json index 9dc7da3144f..f3da536e7ed 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de-DE.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de-DE.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "Sie müssen mindestens 3 Zeichen eingeben!", "Volo.AbpIo.Domain:060001": "Quell-URL(\"{ArticleUrl}\") ist keine Github-URL", "Volo.AbpIo.Domain:060002": "Artikelinhalt ist über die Github(\"{ArticleUrl}\")-Ressource nicht verfügbar.", - "Volo.AbpIo.Domain:060003": "Kein Artikelinhalt gefunden!" + "Volo.AbpIo.Domain:060003": "Kein Artikelinhalt gefunden!", + "SeeMore": "Mehr Sehen" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json index 652090d8644..5925ffb1721 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en-GB.json @@ -101,6 +101,7 @@ "ArticleRequestMessageTitle": "Open an issue on the GitHub to request an article/tutorial you want to see on this web site.", "ArticleRequestMessageBody": "Here is the list of the requested articles by the Community. Do you want to write a requested article? Please click on the request and join the discussion.", "Language": "Language", - "CreateArticleLanguageInfo": "The language in which the article is written" + "CreateArticleLanguageInfo": "Language of the article", + "SeeMore": "See More" } -} \ No newline at end of file +} diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index 2da4a624813..16a86cac37d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "You must enter at least 3 characters!", "Volo.AbpIo.Domain:060001": "Source URL(\"{ArticleUrl}\") is not Github URL", "Volo.AbpIo.Domain:060002": "Article Content is not available from Github(\"{ArticleUrl}\") resource.", - "Volo.AbpIo.Domain:060003": "No article content found!" + "Volo.AbpIo.Domain:060003": "No article content found!", + "SeeMore": "See More" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json index 7b34e043a75..3066263e8b1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "¡Debes ingresar al menos 3 caracteres!", "Volo.AbpIo.Domain:060001": "La URL de origen (\"{ArticleUrl}\") no es la URL de Github", "Volo.AbpIo.Domain:060002": "El contenido del artículo no está disponible en el recurso de Github (\"{ArticleUrl}\").", - "Volo.AbpIo.Domain:060003": "¡No se encontró contenido del artículo!" + "Volo.AbpIo.Domain:060003": "¡No se encontró contenido del artículo!", + "SeeMore": "Ver Más" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json index 2c099847744..435ac1ef928 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "Sinun on annettava vähintään 3 merkkiä!", "Volo.AbpIo.Domain:060001": "Lähteen URL-osoite (\"{ArticleUrl}\") ei ole Githubin URL-osoite", "Volo.AbpIo.Domain:060002": "Artikkelin sisältö ei ole saatavilla Githubin (\"{ArticleUrl}\") -resurssista.", - "Volo.AbpIo.Domain:060003": "Artikkelin sisältöä ei löytynyt!" + "Volo.AbpIo.Domain:060003": "Artikkelin sisältöä ei löytynyt!", + "SeeMore": "Katso Lisää" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json index 42f239f9879..cbeb8ae0844 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "Vous devez saisir au moins 3 caractères!", "Volo.AbpIo.Domain:060001": "L'URL source (\"{ArticleUrl}\") n'est pas une URL Github", "Volo.AbpIo.Domain:060002": "Le contenu de l'article n'est pas disponible à partir de la ressource Github(\"{ArticleUrl}\").", - "Volo.AbpIo.Domain:060003": "Aucun contenu d'article trouvé !" + "Volo.AbpIo.Domain:060003": "Aucun contenu d'article trouvé !", + "SeeMore": "Voir Plus" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json index aa351262ca4..1e8d5a9e9f4 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "आपको कम से कम 3 वर्ण दर्ज करने होंगे!", "Volo.AbpIo.Domain:060001": "स्रोत URL (\"{ArticleUrl}\") जीथब URL नहीं है", "Volo.AbpIo.Domain:060002": "लेख सामग्री Github (\"{ArticleUrl}\") संसाधन से उपलब्ध नहीं है।", - "Volo.AbpIo.Domain:060003": "कोई लेख सामग्री नहीं मिली!" + "Volo.AbpIo.Domain:060003": "कोई लेख सामग्री नहीं मिली!", + "SeeMore": "और देखें" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json index fd128eb596e..7c8f3f2fba0 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "Þú verður að slá inn að minnsta kosti 3 stafi!", "Volo.AbpIo.Domain:060001": "Upprunaslóð (\"{ArticleUrl} \") er ekki Github slóð", "Volo.AbpIo.Domain:060002": "Innihald greinar er ekki fáanlegt frá Github (\"{ArticleUrl} \") resoursum.", - "Volo.AbpIo.Domain:060003": "Innihald greinar fannst ekki!" + "Volo.AbpIo.Domain:060003": "Innihald greinar fannst ekki!", + "SeeMore": "Sjá Meira" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json index f104045682b..1b305d9b4a4 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "Devi inserire almeno 3 caratteri!", "Volo.AbpIo.Domain:060001": "Source URL(\"{ArticleUrl}\") non è un URL di GitHub", "Volo.AbpIo.Domain:060002": "Il contenuto dell'articolo non è disponibile dalla risorsa Github(\"{ArticleUrl}\").", - "Volo.AbpIo.Domain:060003": "Nessun contenuto dell'articolo trovato!" + "Volo.AbpIo.Domain:060003": "Nessun contenuto dell'articolo trovato!", + "SeeMore": "Vedi Altro" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json index 4c78f15d99a..a15a1bc102b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "Trebuie să introduceţi cel putin 3 caractere!", "Volo.AbpIo.Domain:060001": "Sursa URL(\"{ArticleUrl}\") nu este URL GitHub", "Volo.AbpIo.Domain:060002": "Conţinutul articolului nu este disponibil din resursa de pe GitHub(\"{ArticleUrl}\").", - "Volo.AbpIo.Domain:060003": "Nu a fost găsit conţinutul articolului!" + "Volo.AbpIo.Domain:060003": "Nu a fost găsit conţinutul articolului!", + "SeeMore": "Vezi mai mult" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json index e01e2019698..3a2b2e5f1d1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "Musíte zadať aspoň 3 znaky!", "Volo.AbpIo.Domain:060001": "Zdrojová URL(\"{ArticleUrl}\") nie je URL Githubu", "Volo.AbpIo.Domain:060002": "Obsah článku nie je dostupný v Github zdroji(\"{ArticleUrl}\").", - "Volo.AbpIo.Domain:060003": "Nenašiel sa žiadny obsah článku!" + "Volo.AbpIo.Domain:060003": "Nenašiel sa žiadny obsah článku!", + "SeeMore": "Vidět Víc" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json index f504842e706..15dd748d6e9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json @@ -142,6 +142,7 @@ "MinimumSearchContent": "您必须输入至少 3 个字符!", "Volo.AbpIo.Domain:060001": "源 URL(\"{ArticleUrl}\") 不是 Github URL", "Volo.AbpIo.Domain:060002": "文章内容无法从 Github(\"{ArticleUrl}\") 资源中获得。", - "Volo.AbpIo.Domain:060003": "没有找到文章内容!" + "Volo.AbpIo.Domain:060003": "没有找到文章内容!", + "SeeMore": "查看更多" } } \ No newline at end of file diff --git a/common.props b/common.props index a343f7cd044..4eb29c0b8ea 100644 --- a/common.props +++ b/common.props @@ -1,7 +1,7 @@ latest - 5.0.1 + 5.1.0 $(NoWarn);CS1591;CS0436 https://abp.io/assets/abp_nupkg.png https://abp.io/ diff --git a/docs/en/Blog-Posts/2021-11-18 v5_0_Preview/POST.md b/docs/en/Blog-Posts/2021-11-18 v5_0_Preview/POST.md index e1bc93e23a2..32ab4684f26 100644 --- a/docs/en/Blog-Posts/2021-11-18 v5_0_Preview/POST.md +++ b/docs/en/Blog-Posts/2021-11-18 v5_0_Preview/POST.md @@ -127,13 +127,7 @@ First of all, you need to have EF Core or MongoDB installed into your solution. #### Install the packages -Install the new [Volo.Abp.EventBus.Boxes](https://www.nuget.org/packages/Volo.Abp.EventBus.Boxes) NuGet package to your database layer (to `EntityFrameworkCore` or `MongoDB` project) or to the host application. Open a command-line terminal at the root directory of your database (or host) project and execute the following command: - -````csharp -abp add-package Volo.Abp.EventBus.Boxes -```` - -This will install the package and setup the ABP module dependency. This package depends on [DistributedLock.Core](https://www.nuget.org/packages/DistributedLock.Core) library which provides a distributed locking system for concurrency control in a distributed environment. There are [many distributed lock providers](https://github.com/madelson/DistributedLock#implementations), including Redis, SqlServer and ZooKeeper. You can use the one you like. Here, I will show the Redis provider. +For the outbox & inbox functionality, ABP depends on [DistributedLock.Core](https://www.nuget.org/packages/DistributedLock.Core) library which provides a distributed locking system for concurrency control in a distributed environment. There are [many distributed lock providers](https://github.com/madelson/DistributedLock#implementations), including Redis, SqlServer and ZooKeeper. You can use the one you like. Here, I will show the Redis provider. Add [DistributedLock.Redis](https://www.nuget.org/packages/DistributedLock.Redis) NuGet package to your project, then add the following code into the ConfigureService method of your ABP module class: @@ -285,6 +279,16 @@ This can be a breaking change in rare cases (for example, if you create host sid ## Community News +### ABP Community Talks 2021.12 + +![community-talks](community-talks.png) + +As the core ABP development team, we've decided to organize monthly live meetings with the ABP community. The first live meeting will be at **December 16, 2021, 17:00 (UTC)** on YouTube. ABP core team members will present some of the new features coming with ABP 5.0. + +**Join this event on the Kommunity platform: https://kommunity.com/volosoft/events/abp-community-talks-4afca9c9** + +You can also [subscribe to the Volosoft channel](https://www.youtube.com/channel/UCO3XKlpvq8CA5MQNVS6b3dQ) for reminders for further ABP events and videos. + ### ABP was on ASP.NET Community Startup! It was great for us to be invited to Microsoft's [ASP.NET Community Weekly Standup](https://dotnet.microsoft.com/live/community-standup) show, at September 28. There was a very high attention and that made us very happy. Thanks to the ABP Community and all the watchers :) If you've missed the talk, [you can watch it here](https://www.youtube.com/watch?v=vMWM-_ihjwM). diff --git a/docs/en/Blog-Posts/2021-11-18 v5_0_Preview/community-talks.png b/docs/en/Blog-Posts/2021-11-18 v5_0_Preview/community-talks.png new file mode 100644 index 00000000000..4056d1afb8b Binary files /dev/null and b/docs/en/Blog-Posts/2021-11-18 v5_0_Preview/community-talks.png differ diff --git a/docs/en/Blog-Posts/2021-11-18 v5_0_Preview/cover-50.png b/docs/en/Blog-Posts/2021-11-18 v5_0_Preview/cover-50.png new file mode 100644 index 00000000000..bd343e70b02 Binary files /dev/null and b/docs/en/Blog-Posts/2021-11-18 v5_0_Preview/cover-50.png differ diff --git a/docs/en/Blog-Posts/2021-12-15 v5_0_Release_Stable/POST.md b/docs/en/Blog-Posts/2021-12-15 v5_0_Release_Stable/POST.md new file mode 100644 index 00000000000..329db94af35 --- /dev/null +++ b/docs/en/Blog-Posts/2021-12-15 v5_0_Release_Stable/POST.md @@ -0,0 +1,47 @@ +# ABP.IO Platform 5.0 Final Has Been Released! + +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 5.0 versions have been released today. + +## What's new with 5.0? + +Since all the new features are already explained in details with the [5.0 RC.1 Announcement Post](https://blog.abp.io/abp/ABP-IO-Platform-5.0-RC-1-Has-Been-Released), I will not repeat all the details again. See the [RC Blog Post](https://blog.abp.io/abp/ABP-IO-Platform-5.0-RC-1-Has-Been-Released) for all the features and enhancements. + +## Getting started with 5.0 + +### Creating new solutions + +You can create a new solution with the ABP Framework version 5.0 by either using the `abp new` command or using the **direct download** tab on the [get started page](https://abp.io/get-started). + +Type the following command in a command-line terminal to install the ABP CLI version 5.0: + +````bash +dotnet tool install -g Volo.Abp.Cli --version 5.0.0 +```` + +To upgrade your existing ABP CLI installation: + +````bash +dotnet tool update -g Volo.Abp.Cli --version 5.0.0 +```` + +Then you can create a new solution using the `abp new` command: + +````bash +abp new Acme.BookStore +```` + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for details. + +### Upgrading existing solutions + +Check [the migration guide](https://docs.abp.io/en/abp/latest/Migration-Guides/Abp-5_0) for the applications with the version 4.x upgrading to the version 5.0. Also see [the upgrading guide](https://docs.abp.io/en/abp/latest/Upgrading) to understand how to update existing solutions. + +## ABP Community Talks 2021.12 + +![community-talks](community-talks.png) + +As the core ABP development team, we've decided to organize monthly live meetings with the ABP community. The first live meeting will be at **December 16, 2021, 17:00 (UTC)** on YouTube. ABP core team members will present some of the new features coming with ABP 5.0. + +**Join this event on the Kommunity platform: https://kommunity.com/volosoft/events/abp-community-talks-4afca9c9** + +See you in the event! diff --git a/docs/en/Blog-Posts/2021-12-15 v5_0_Release_Stable/community-talks.png b/docs/en/Blog-Posts/2021-12-15 v5_0_Release_Stable/community-talks.png new file mode 100644 index 00000000000..4056d1afb8b Binary files /dev/null and b/docs/en/Blog-Posts/2021-12-15 v5_0_Release_Stable/community-talks.png differ diff --git a/docs/en/CLI.md b/docs/en/CLI.md index b8f69b1ee44..7db562a66e8 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -29,6 +29,7 @@ Here, the list of all available commands before explaining their details: * **`help`**: Shows help on the usage of the ABP CLI. * **`new`**: Generates a new solution based on the ABP [startup templates](Startup-Templates/Index.md). * **`update`**: Automatically updates all ABP related NuGet and NPM packages in a solution. +* **`clean`**: Deletes all `BIN` and `OBJ` folders in the current folder. * **`add-package`**: Adds an ABP package to a project. * **`add-module`**: Adds a [multi-package application module](https://docs.abp.io/en/abp/latest/Modules/Index) to a solution. * **`list-modules`**: Lists names of open-source application modules. @@ -145,6 +146,17 @@ abp update [options] * `--check-all`: Check the new version of each package separately. Default is `false`. * `--version` or `-v`: Specifies the version to use for update. If not specified, latest version is used. +### clean + +Deletes all `BIN` and `OBJ` folders in the current folder. + +Usage: + +````bash +abp clean +```` + + ### add-package Adds an ABP package to a project by, diff --git a/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md b/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md index 1a07d744e7f..5880406ffb0 100644 --- a/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md +++ b/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md @@ -241,8 +241,9 @@ private void ConfigureElsa(ServiceConfigurationContext context, IConfiguration c .WithExposedHeaders("Content-Disposition")) ); - //register controllers inside elsa - context.Services.AddAssemblyOf(); + //Uncomment the below line if your abp version is lower than v4.4 to register controllers of Elsa . + //See https://github.com/abpframework/abp/pull/9299 (we will no longer need to specify this line of code from v4.4) + // context.Services.AddAssemblyOf(); //Disable antiforgery validation for elsa Configure(options => @@ -269,11 +270,7 @@ public override void OnApplicationInitialization(ApplicationInitializationContex } ``` -* In here we've specified the Elsa Server Api's assembly by using the `AddAssemblyOf<>` extension method to register the required services (controllers). These services required for the dashboard (if we create a workflow by using **Elsa Workflow Designer** it calls some services under the hook, therefore we need to be assured about these services get registered). - -* With [v4.4](https://github.com/abpframework/abp/pull/9299), we will no longer need to specify this line of code. - -> **Note:** `AddAssemblyOf<>` extension method can help you to register all your services by convention. You can check [here](https://docs.abp.io/en/abp/latest/Dependency-Injection#conventional-registration) for more information about conventional registration. +* These services required for the dashboard. * We don't need to register our workflows one by one anymore. Because now we use `.AddWorkflowsFrom()`, and this registers workflows on our behalf. @@ -371,12 +368,14 @@ namespace ElsaDemo.Permissions - + - + + + ``` diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/POST.md b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/POST.md new file mode 100644 index 00000000000..6abf984298c --- /dev/null +++ b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/POST.md @@ -0,0 +1,1671 @@ +# Many to Many Relationship with ABP and EF Core + +## Introduction + +In this article, we'll create a **BookStore** application like in [the ABP tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Part-1?UI=MVC&DB=EF) and add an extra `Category` feature to demonstrate how we can manage the many-to-many relationship with ABP-based applications (by following DDD rules). + +You can see the ER Diagram of our application below. This diagram will be helpful for us to demonstrate the relations between our entities. + +![ER-Diagram](./er-diagram.png) + +When we've examined the ER Diagram, we can see the one-to-many relationship between the **Author** and the **Book** tables. Also, the many-to-many relationship (**BookCategory** table) between the **Book** and the **Category** tables. (There can be more than one category on each book and vice-versa in our scenario). + +### Source Code + +You can find the source code of the application at https://github.com/EngincanV/ABP-Many-to-Many-Relationship-Demo . + +### Demo of the Final Application + +At the end of this article, we will have created an application same as in the gif below. + +![Demo of The Final Application](./application-final-demo.gif) + +## Creating the Solution + +In this article, we will create a new startup template with EF Core as a database provider and MVC for UI framework. + +* We can create a new startup template by using the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI): + +```bash +abp new BookStore -t app --version 5.0.0-beta.2 +``` + +* Our project boilerplate will be ready after the download is finished. Then, we can open the solution and start developing. + +## Starting the Development + +Let's start with creating our Domain Entities. + +### Step 1 - (Creating the Domain Entities) + +We can create a folder-structure under the `BookStore.Domain` project like in the image below. + +![Domain-Layer-Folder-Structure](./domain-file-structure.png) + +Open the entity classes and add the following codes to each of these classes. + +* **Author.cs** + +```csharp +using System; +using JetBrains.Annotations; +using Volo.Abp; +using Volo.Abp.Domain.Entities.Auditing; + +namespace BookStore.Authors +{ + public class Author : FullAuditedAggregateRoot + { + public string Name { get; private set; } + + public DateTime BirthDate { get; set; } + + public string ShortBio { get; set; } + + /* This constructor is for deserialization / ORM purpose */ + private Author() + { + } + + public Author(Guid id, [NotNull] string name, DateTime birthDate, [CanBeNull] string shortBio = null) + : base(id) + { + SetName(name); + BirthDate = birthDate; + ShortBio = shortBio; + } + + public void SetName([NotNull] string name) + { + Name = Check.NotNullOrWhiteSpace( + name, + nameof(name), + maxLength: AuthorConsts.MaxNameLength + ); + } + } +} +``` + +> We'll create the `AuthorConsts` class later in this step. + +* **Book.cs** + +```csharp +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using Volo.Abp; +using Volo.Abp.Domain.Entities.Auditing; + +namespace BookStore.Books +{ + public class Book : FullAuditedAggregateRoot + { + public Guid AuthorId { get; set; } + + public string Name { get; private set; } + + public DateTime PublishDate { get; set; } + + public float Price { get; set; } + + public ICollection Categories { get; private set; } + + private Book() + { + } + + public Book(Guid id, Guid authorId, string name, DateTime publishDate, float price) + : base(id) + { + AuthorId = authorId; + SetName(name); + PublishDate = publishDate; + Price = price; + + Categories = new Collection(); + } + + public void SetName(string name) + { + Name = Check.NotNullOrWhiteSpace(name, nameof(name), BookConsts.MaxNameLength); + } + + public void AddCategory(Guid categoryId) + { + Check.NotNull(categoryId, nameof(categoryId)); + + if (IsInCategory(categoryId)) + { + return; + } + + Categories.Add(new BookCategory(bookId: Id, categoryId)); + } + + public void RemoveCategory(Guid categoryId) + { + Check.NotNull(categoryId, nameof(categoryId)); + + if (!IsInCategory(categoryId)) + { + return; + } + + Categories.RemoveAll(x => x.CategoryId == categoryId); + } + + public void RemoveAllCategoriesExceptGivenIds(List categoryIds) + { + Check.NotNullOrEmpty(categoryIds, nameof(categoryIds)); + + Categories.RemoveAll(x => !categoryIds.Contains(x.CategoryId)); + } + + public void RemoveAllCategories() + { + Categories.RemoveAll(x => x.BookId == Id); + } + + private bool IsInCategory(Guid categoryId) + { + return Categories.Any(x => x.CategoryId == categoryId); + } + } +} +``` + +* In our scenario, a book can have more than one category and a category can have more than one book so we need to create a many-to-many relationship between them. + +* For achieving this, we will create a **join entity** named `BookCategory`, and this class will simply have variables named `BookId` and `CategoryId`. + +* To manage this **join entity**, we can add it as a sub-collection to the **Book** entity, as we do above. We add this sub-collection +to **Book** class instead of **Category** class, because a book can have tens (or mostly hundreds) of categories but on the other perspective a category can have more than a hundred (or even way much) books inside of it. + +* It is a significant performance problem to load thousands of items whenever you query a category. Therefore it makes much more sense to add that sub-collection to the `Book` entity. + +> Don't forget: **Aggregate is a pattern in Domain-Driven Design. A DDD aggregate is a cluster of domain objects that can be treated as a single unit.** (See the full [description](https://martinfowler.com/bliki/DDD_Aggregate.html)) + +* Notice that, `BookCategory` is not an **Aggregate Root** so we are not violating one of the base rules about Aggregate Root (Rule: **"Reference Other Aggregates Only by ID"**). + +* If we examine the methods in the `Book` class (such as **RemoveAllCategories**, **RemoveAllCategoriesExceptGivenIds** and **AddCategory**) we will manage our sub-collection `Categories` (**BookCategory** - join table/entity) through them. (Adds or removes categories for books) + +> We'll create the `BookCategory` and `BookConsts` classes later in this step. + +* **BookCategory.cs** + +```csharp +using System; +using Volo.Abp.Domain.Entities; + +namespace BookStore.Books +{ + public class BookCategory : Entity + { + public Guid BookId { get; protected set; } + + public Guid CategoryId { get; protected set; } + + /* This constructor is for deserialization / ORM purpose */ + private BookCategory() + { + } + + public BookCategory(Guid bookId, Guid categoryId) + { + BookId = bookId; + CategoryId = categoryId; + } + + public override object[] GetKeys() + { + return new object[] {BookId, CategoryId}; + } + } +} +``` + +* Here, as you can notice, we've defined the `BookCategory` as the **Join Table/Entity** for our many-to-many relationship and ensured the required properties (BookId and CategoryId) were set in the constructor method of this class to create this object. + +* And also we've derived this class from the `Entity` class and therefore we've had to override the **GetKeys** method of this class to define the **Composite Key**. + +> The composite key is composed of `BookId` and `CategoryId` in our case. And they are unique together. + +> For more information about **Entities with Composite Keys**, you can read the relevant section from [Entities documentation](https://docs.abp.io/en/abp/latest/Entities#entities-with-composite-keys). + +* **BookManager.cs** + +```csharp +using System; +using System.Linq; +using System.Threading.Tasks; +using BookStore.Categories; +using JetBrains.Annotations; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Domain.Services; + +namespace BookStore.Books +{ + public class BookManager : DomainService + { + private readonly IBookRepository _bookRepository; + private readonly IRepository _categoryRepository; + + public BookManager(IBookRepository bookRepository, IRepository categoryRepository) + { + _bookRepository = bookRepository; + _categoryRepository = categoryRepository; + } + + public async Task CreateAsync(Guid authorId, string name, DateTime publishDate, float price, [CanBeNull]string[] categoryNames) + { + var book = new Book(GuidGenerator.Create(), authorId, name, publishDate, price); + + await SetCategoriesAsync(book, categoryNames); + + await _bookRepository.InsertAsync(book); + } + + public async Task UpdateAsync( + Book book, + Guid authorId, + string name, + DateTime publishDate, + float price, + [CanBeNull] string[] categoryNames + ) + { + book.AuthorId = authorId; + book.SetName(name); + book.PublishDate = publishDate; + book.Price = price; + + await SetCategoriesAsync(book, categoryNames); + + await _bookRepository.UpdateAsync(book); + } + + private async Task SetCategoriesAsync(Book book, [CanBeNull] string[] categoryNames) + { + if (categoryNames == null || !categoryNames.Any()) + { + book.RemoveAllCategories(); + return; + } + + var query = (await _categoryRepository.GetQueryableAsync()) + .Where(x => categoryNames.Contains(x.Name)) + .Select(x => x.Id) + .Distinct(); + + var categoryIds = await AsyncExecuter.ToListAsync(query); + if (!categoryIds.Any()) + { + return; + } + + book.RemoveAllCategoriesExceptGivenIds(categoryIds); + + foreach (var categoryId in categoryIds) + { + book.AddCategory(categoryId); + } + } + } +} +``` + +* If we examine the codes in the `BookManager` class, we can see that we've managed the `BookCategory` class (our join table/entity) by using some methods that we've defined in the `Book` class such as **RemoveAllCategories**, **RemoveAllCategoriesExceptGivenIds** and **AddCategory**. + +* These methods basically add or remove categories related to the book by conditions. + +* In the `CreateAsync` method, if the category names are specified, we'll retrieve their ids from the database and by using the **AddCategory** method that we've defined in the `Book` class, we'll add them. + +* In the `UpdateAsync` method, the same logic is also valid. But in this case, the user might want to remove some categories from books, so if the user sends us an empty **categoryNames** array, we remove all categories from the book he wants to update. If the user sends us some category names, we remove the excluded ones and add the new ones according to the **categoryNames** array. + +* **BookWithDetails.cs** + +```csharp +using System; +using Volo.Abp.Auditing; + +namespace BookStore.Books +{ + public class BookWithDetails : IHasCreationTime + { + public Guid Id { get; set; } + + public string Name { get; set; } + + public DateTime PublishDate { get; set; } + + public float Price { get; set; } + + public string AuthorName { get; set; } + + public string[] CategoryNames { get; set; } + + public DateTime CreationTime { get; set; } + } +} +``` + +We will use this class to retrieve books with their sub-categories and author names. + +* **IBookRepository.cs** + +```csharp +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace BookStore.Books +{ + public interface IBookRepository : IRepository + { + Task> GetListAsync( + string sorting, + int skipCount, + int maxResultCount, + CancellationToken cancellationToken = default + ); + + Task GetAsync(Guid id, CancellationToken cancellationToken = default); + } +} +``` + +We need to create two methods named **GetListAsync** and **GetAsync** and specify their return type as `BookWithDetails`. So by implementing these methods, we will return the book/books by their details (author name and categories). + +* **Category.cs** + +```csharp +using System; +using Volo.Abp; +using Volo.Abp.Domain.Entities.Auditing; + +namespace BookStore.Categories +{ + public class Category : AuditedAggregateRoot + { + public string Name { get; private set; } + + /* This constructor is for deserialization / ORM purpose */ + private Category() + { + } + + public Category(Guid id, string name) : base(id) + { + SetName(name); + } + + public Category SetName(string name) + { + Name = Check.NotNullOrWhiteSpace(name, nameof(name), CategoryConsts.MaxNameLength); + return this; + } + } +} +``` + +After defining our entities we can seed initial data to our database by using the [Data Seeding](https://docs.abp.io/en/abp/5.0/Data-Seeding#data-seeding) system of the ABP framework. We will create initial data for both the `Category` and `Author` entities because we will not create CRUD pages for these entities. + +> We will create only CRUD pages for the Book entity therefore we don't need to add initial data for the Book entity. We can create a new book by using the create modal of the Book page. (We will create it in the sixth step.) + +Create a class named `BookStoreDataSeederContributor` in your `*.Domain` project and update with the following code: + +* **BookStoreDataSeederContributor.cs** + +```csharp +using System; +using System.Threading.Tasks; +using BookStore.Authors; +using BookStore.Categories; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Guids; + +namespace BookStore +{ + public class BookStoreDataSeederContributor : IDataSeedContributor, ITransientDependency + { + private readonly IGuidGenerator _guidGenerator; + private readonly IRepository _categoryRepository; + private readonly IRepository _authorRepository; + + public BookStoreDataSeederContributor( + IGuidGenerator guidGenerator, + IRepository categoryRepository, + IRepository authorRepository + ) + { + _guidGenerator = guidGenerator; + _categoryRepository = categoryRepository; + _authorRepository = authorRepository; + } + + public async Task SeedAsync(DataSeedContext context) + { + await SeedCategoriesAsync(); + await SeedAuthorsAsync(); + } + + private async Task SeedCategoriesAsync() + { + if (await _categoryRepository.GetCountAsync() <= 0) + { + await _categoryRepository.InsertAsync( + new Category(_guidGenerator.Create(), "History") + ); + + await _categoryRepository.InsertAsync( + new Category(_guidGenerator.Create(), "Unknown") + ); + + await _categoryRepository.InsertAsync( + new Category(_guidGenerator.Create(), "Adventure") + ); + + await _categoryRepository.InsertAsync( + new Category(_guidGenerator.Create(), "Action") + ); + + await _categoryRepository.InsertAsync( + new Category(_guidGenerator.Create(), "Crime") + ); + + await _categoryRepository.InsertAsync( + new Category(_guidGenerator.Create(), "Dystopia") + ); + } + } + + private async Task SeedAuthorsAsync() + { + if (await _authorRepository.GetCountAsync() <= 0) + { + await _authorRepository.InsertAsync( + new Author( + _guidGenerator.Create(), + "George Orwell", + new DateTime(1903, 06, 25), + "Orwell produced literary criticism and poetry, fiction and polemical journalism; and is best known for the allegorical novella Animal Farm (1945) and the dystopian novel Nineteen Eighty-Four (1949)." + ) + ); + + await _authorRepository.InsertAsync( + new Author( + _guidGenerator.Create(), + "Dan Brown", + new DateTime(1964, 06, 22), + "Daniel Gerhard Brown (born June 22, 1964) is an American author best known for his thriller novels" + ) + ); + } + } + } +} +``` + +### Step 2 - (Define Consts) + +We can create a folder-structure under the `BookStore.Domain.Shared` project like in the image below. + +![Domain Shared File Structure](./domain-shared-file-structure.png) + +* **AuthorConsts.cs** + +```csharp +namespace BookStore.Authors +{ + public class AuthorConsts + { + public const int MaxNameLength = 128; + + public const int MaxShortBioLength = 256; + } +} +``` + +* **BookConsts.cs** + +```csharp +namespace BookStore.Books +{ + public class BookConsts + { + public const int MaxNameLength = 128; + } +} +``` + +* **CategoryConsts.cs** + +```csharp +namespace BookStore.Categories +{ + public class CategoryConsts + { + public const int MaxNameLength = 64; + } +} +``` + +In these classes, we've defined max text length for our entity properties that we will use in the **Database Integration** section to specify limits for our properties. (E.g. varchar(128) for BookName) + +### Step 3 - (Database Integration) + +After defining our entities, we can configure them for the database integration. +Open the `BookStoreDbContext` class in the `BookStore.EntityFrameworkCore` project and update the following code blocks. + +```csharp +namespace BookStore.EntityFrameworkCore +{ + [ReplaceDbContext(typeof(IIdentityDbContext))] + [ReplaceDbContext(typeof(ITenantManagementDbContext))] + [ConnectionStringName("Default")] + public class BookStoreDbContext : + AbpDbContext, + IIdentityDbContext, + ITenantManagementDbContext + { + //... + + //DbSet properties for our Aggregate Roots + public DbSet Authors { get; set; } + public DbSet Books { get; set; } + public DbSet Categories { get; set; } + + //NOTE: We don't need to add DbSet, because we will be query it via using the Book entity + // public DbSet BookCategories { get; set; } + + //... + + protected override void OnModelCreating(ModelBuilder builder) + { + //... + + /* Configure your own tables/entities inside here */ + builder.Entity(b => + { + b.ToTable(BookStoreConsts.DbTablePrefix + "Authors" + BookStoreConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Name) + .HasMaxLength(AuthorConsts.MaxNameLength) + .IsRequired(); + + b.Property(x => x.ShortBio) + .HasMaxLength(AuthorConsts.MaxShortBioLength) + .IsRequired(); + }); + + builder.Entity(b => + { + b.ToTable(BookStoreConsts.DbTablePrefix + "Books" + BookStoreConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Name) + .HasMaxLength(BookConsts.MaxNameLength) + .IsRequired(); + + //one-to-many relationship with Author table + b.HasOne().WithMany().HasForeignKey(x => x.AuthorId).IsRequired(); + + //many-to-many relationship with Category table => BookCategories + b.HasMany(x => x.Categories).WithOne().HasForeignKey(x => x.BookId).IsRequired(); + }); + + builder.Entity(b => + { + b.ToTable(BookStoreConsts.DbTablePrefix + "Categories" + BookStoreConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Name) + .HasMaxLength(CategoryConsts.MaxNameLength) + .IsRequired(); + }); + + builder.Entity(b => + { + b.ToTable(BookStoreConsts.DbTablePrefix + "BookCategories" + BookStoreConsts.DbSchema); + b.ConfigureByConvention(); + + //define composite key + b.HasKey(x => new { x.BookId, x.CategoryId }); + + //many-to-many configuration + b.HasOne().WithMany(x => x.Categories).HasForeignKey(x => x.BookId).IsRequired(); + b.HasOne().WithMany().HasForeignKey(x => x.CategoryId).IsRequired(); + + b.HasIndex(x => new { x.BookId, x.CategoryId }); + }); + } + } +} +``` + +* In this class, we've defined the **DbSet** properties for our **Aggregate Roots** (**Book**, **Author** and **Category**). Notice, we didn't define the **DbSet** for the `BookCategory` class (our join table/entity). Because, the `Book` aggregate is responsible for managing it via sub-collection. + +* After that, we can use the **FluentAPI** to configure our tables in the `OnModelCreating` method of this class. + +```csharp +builder.Entity(b => +{ + //... + + //one-to-many relationship with Author table + b.HasOne().WithMany().HasForeignKey(x => x.AuthorId).IsRequired(); + + //many-to-many relationship with Category table => BookCategories + b.HasMany(x => x.Categories).WithOne().HasForeignKey(x => x.BookId).IsRequired(); +}); +``` + +Here, we have provided the one-to-many relationship between the **Book** and the **Author** in the above code-block. + +```csharp +builder.Entity(b => +{ + //... + + //define composite key + b.HasKey(x => new { x.BookId, x.CategoryId }); + + //many-to-many configuration + b.HasOne().WithMany(x => x.Categories).HasForeignKey(x => x.BookId).IsRequired(); + b.HasOne().WithMany().HasForeignKey(x => x.CategoryId).IsRequired(); + + b.HasIndex(x => new { x.BookId, x.CategoryId }); +}); +``` + +Here, firstly we've defined the composite key for our `BookCategory` entity. `BookId` and `CategoryId` are together as composite keys for the `BookCategory` table. Then we've configured the many-to-many relationship between the `Book` and the `Category` tables like in the above code-block. + +#### Implementing the `IBookRepository` Interface + +After making the relevant configurations for the database integration, we can now implement the `IBookRepository` interface. To do this, create a folder named `Books` in the `BookStore.EntityFrameworkCore` project and inside of this folder, create a class named `EfCoreBookRepository` and update this class with the following code: + +```csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Threading; +using System.Threading.Tasks; +using BookStore.Authors; +using BookStore.Categories; +using BookStore.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace BookStore.Books +{ + public class EfCoreBookRepository : EfCoreRepository, IBookRepository + { + public EfCoreBookRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public async Task> GetListAsync( + string sorting, + int skipCount, + int maxResultCount, + CancellationToken cancellationToken = default + ) + { + var query = await ApplyFilterAsync(); + + return await query + .OrderBy(!string.IsNullOrWhiteSpace(sorting) ? sorting : nameof(Book.Name)) + .PageBy(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public async Task GetAsync(Guid id, CancellationToken cancellationToken = default) + { + var query = await ApplyFilterAsync(); + + return await query + .Where(x => x.Id == id) + .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + } + + private async Task> ApplyFilterAsync() + { + var dbContext = await GetDbContextAsync(); + + return (await GetDbSetAsync()) + .Include(x => x.Categories) + .Join(dbContext.Set(), book => book.AuthorId, author => author.Id, + (book, author) => new {book, author}) + .Select(x => new BookWithDetails + { + Id = x.book.Id, + Name = x.book.Name, + Price = x.book.Price, + PublishDate = x.book.PublishDate, + CreationTime = x.book.CreationTime, + AuthorName = x.author.Name, + CategoryNames = (from bookCategories in x.book.Categories + join category in dbContext.Set() on bookCategories.CategoryId equals category.Id + select category.Name).ToArray() + }); + } + + public override Task> WithDetailsAsync() + { + return base.WithDetailsAsync(x => x.Categories); + } + } +} +``` + +* Here, we've implemented our custom repository methods and returned the book with details (author name and categories). + +### Step 4 - (Database Migration) + +* We've integrated our entities with the database in the previous step, now we can create a new database migration and apply it to the database. So let's do that. + +* Open the `BookStore.EntityFrameworkCore` project in the terminal. And create a new database migration by using the following command: + +```bash +dotnet ef migrations add +``` + +* Then, run the `BookStore.DbMigrator` application to create the database. + +### Step 5 - (Create Application Services) + +* Let's start with defining our DTOs and application service interfaces in the `BookStore.Application.Contracts` layer. We can create a folder-structure like in the image below: + +![Application Contracts Folder Structure](./application-contracts-folder-structure.png) + +* We can use the [`CrudAppService`](https://docs.abp.io/en/abp/latest/Application-Services#crud-application-services) base class of the ABP Framework to create application services to **Get**, **Create**, **Update** and **Delete** authors and categories. + +* **AuthorDto.cs** + +```csharp +using System; +using Volo.Abp.Application.Dtos; + +namespace BookStore.Authors +{ + public class AuthorDto : EntityDto + { + public string Name { get; set; } + + public DateTime BirthDate { get; set; } + + public string ShortBio { get; set; } + } +} +``` + +* **AuthorLookupDto.cs** + +```csharp +using System; +using Volo.Abp.Application.Dtos; + +namespace BookStore.Authors +{ + public class AuthorLookupDto : EntityDto + { + public string Name { get; set; } + } +} +``` + +We will use this DTO class as output DTO to get all the authors and list them in a select box in the book creation model. (Like in the image below.) + +![Book Create Modal](./book-creation-modal.png) + +* **CreateUpdateAuthorDto.cs** + +```csharp +using System; + +namespace BookStore.Authors +{ + public class CreateUpdateAuthorDto + { + public string Name { get; set; } + + public DateTime BirthDate { get; set; } + + public string ShortBio { get; set; } + } +} +``` + +* **IAuthorAppService.cs** + +```csharp +using System; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace BookStore.Authors +{ + public interface IAuthorAppService : + ICrudAppService + { + } +} +``` + +* **BookDto.cs** + +```csharp +using System; +using Volo.Abp.Application.Dtos; + +namespace BookStore.Books +{ + public class BookDto : EntityDto + { + public string AuthorName { get; set; } + + public string Name { get; set; } + + public DateTime PublishDate { get; set; } + + public float Price { get; set; } + + public string[] CategoryNames { get; set; } + } +} +``` + +When listing the Book/Books we will retrieve them with all their details (author name and category names). + +* **BookGetListInput.cs** + +```csharp +using Volo.Abp.Application.Dtos; + +namespace BookStore.Books +{ + public class BookGetListInput : PagedAndSortedResultRequestDto + { + } +} +``` + +* **CreateUpdateBookDto.cs** + +```csharp +using System; + +namespace BookStore.Books +{ + public class CreateUpdateBookDto + { + public Guid AuthorId { get; set; } + + public string Name { get; set; } + + public DateTime PublishDate { get; set; } + + public float Price { get; set; } + + public string[] CategoryNames { get; set; } + } +} +``` + +To create or update a book we will use this input DTO. + +* **IBookAppService.cs** + +```csharp +using System; +using System.Threading.Tasks; +using BookStore.Authors; +using BookStore.Categories; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace BookStore.Books +{ + public interface IBookAppService : IApplicationService + { + Task> GetListAsync(BookGetListInput input); + + Task GetAsync(Guid id); + + Task CreateAsync(CreateUpdateBookDto input); + + Task UpdateAsync(Guid id, CreateUpdateBookDto input); + + Task DeleteAsync(Guid id); + + Task> GetAuthorLookupAsync(); + + Task> GetCategoryLookupAsync(); + } +} +``` + +* We will create custom application service method for managing Books instead of using the `CrudAppService`'s methods. + +* Also we will create two additional methods and they are `GetAuthorLookupAsync` and `GetCategoryLookupAsync`. We will use these two methods to retrieve all the authors and categories without pagination and list them as a select box item in create/update modals for the Book page. +(You can see the usage of these two methods in the gif below.) + +![New Book](./book-create.gif) + +* **CategoryDto.cs** + +```csharp +using System; +using Volo.Abp.Application.Dtos; + +namespace BookStore.Categories +{ + public class CategoryDto : EntityDto + { + public string Name { get; set; } + } +} +``` + +* **CategoryLookupDto.cs** + +```csharp +using System; +using Volo.Abp.Application.Dtos; + +namespace BookStore.Categories +{ + public class CategoryLookupDto : EntityDto + { + public string Name { get; set; } + } +} +``` + +We will use this DTO class as an output DTO to get all categories without pagination and list them in a select box in the book create/update modals. + +* **CreateUpdateCategoryDto.cs** + +```csharp +namespace BookStore.Categories +{ + public class CreateUpdateCategoryDto + { + public string Name { get; set; } + } +} +``` + +* **ICategoryAppService.cs** + +```csharp +using System; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace BookStore.Categories +{ + public interface ICategoryAppService : + ICrudAppService + { + } +} +``` + +After creating the DTOs and application service interfaces, now we can define the implementation of those interfaces. So, we can create a folder-structure like in the image below for the `BookStore.Application` layer. Open the application service classes and add the following codes to each of these classes. + +![Application Folder Structure](./application-folder-structure.png) + +* **AuthorAppService.cs** + +```csharp +using System; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace BookStore.Authors +{ + public class AuthorAppService : + CrudAppService, + IAuthorAppService + { + public AuthorAppService(IRepository repository) : base(repository) + { + } + } +} +``` + +* **CategoryAppService.cs** + +```csharp +using System; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace BookStore.Categories +{ + public class CategoryAppService : + CrudAppService, + ICategoryAppService + { + public CategoryAppService(IRepository repository) : base(repository) + { + } + } +} +``` + +Thanks to the `CrudAppService`, we don't need to manually implement the crud methods for **AuthorAppService** and **CategoryAppService**. + +* **BookAppService.cs** + +```csharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using BookStore.Authors; +using BookStore.Categories; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Domain.Repositories; + +namespace BookStore.Books +{ + public class BookAppService : BookStoreAppService, IBookAppService + { + private readonly IBookRepository _bookRepository; + private readonly BookManager _bookManager; + private readonly IRepository _authorRepository; + private readonly IRepository _categoryRepository; + + public BookAppService( + IBookRepository bookRepository, + BookManager bookManager, + IRepository authorRepository, + IRepository categoryRepository + ) + { + _bookRepository = bookRepository; + _bookManager = bookManager; + _authorRepository = authorRepository; + _categoryRepository = categoryRepository; + } + + public async Task> GetListAsync(BookGetListInput input) + { + var books = await _bookRepository.GetListAsync(input.Sorting, input.SkipCount, input.MaxResultCount); + var totalCount = await _bookRepository.CountAsync(); + + return new PagedResultDto(totalCount, ObjectMapper.Map, List>(books)); + } + + public async Task GetAsync(Guid id) + { + var book = await _bookRepository.GetAsync(id); + + return ObjectMapper.Map(book); + } + + public async Task CreateAsync(CreateUpdateBookDto input) + { + await _bookManager.CreateAsync( + input.AuthorId, + input.Name, + input.PublishDate, + input.Price, + input.CategoryNames + ); + } + + public async Task UpdateAsync(Guid id, CreateUpdateBookDto input) + { + var book = await _bookRepository.GetAsync(id, includeDetails: true); //return type is: Book (not BookWithDetails) Because, we don't need author name + + await _bookManager.UpdateAsync( + book, + input.AuthorId, + input.Name, + input.PublishDate, + input.Price, + input.CategoryNames + ); + } + + public async Task DeleteAsync(Guid id) + { + await _bookRepository.DeleteAsync(id); + } + + public async Task> GetAuthorLookupAsync() + { + var authors = await _authorRepository.GetListAsync(); + + return new ListResultDto( + ObjectMapper.Map, List>(authors) + ); + } + + public async Task> GetCategoryLookupAsync() + { + var categories = await _categoryRepository.GetListAsync(); + + return new ListResultDto( + ObjectMapper.Map, List>(categories) + ); + } + } +} +``` + +* As you can notice here, we've used our **Domain Service** class named `BookManager` in the **CreateAsync** and **UpdateAsync** methods. (Defined them in step 1) + +* As you may remember, in these methods, new categories are added to the book or removed from the sub-collection (**Categories** (`BookCategory`)) according to the relevant category names. + +* After implementing the application services, we need to define the mappings for our services to work. So open the `BookStoreApplicationAutoMapperProfile` class and update it with the following code: + +```csharp +using AutoMapper; +using BookStore.Authors; +using BookStore.Books; +using BookStore.Categories; + +namespace BookStore +{ + public class BookStoreApplicationAutoMapperProfile : Profile + { + public BookStoreApplicationAutoMapperProfile() + { + CreateMap(); + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + CreateMap(); + + CreateMap(); + } + } +} + +``` + +### Step 6 - (UI) + +The only thing we need to do is, by using the application service methods that we've defined in the previous step to create the UI. + +![Web Folder Structure](./web-folder-structure.png) + +> To keep the article shorter, I'll just show you how to create the Book page (with Create/Edit modals). If you want to implement it to other pages, you can access the source code of the application at https://github.com/EngincanV/ABP-Many-to-Many-Relationship-Demo and copy-paste the relevant code-blocks to your application. + +#### Book Page + +* Create a razor page named **Index.cshtml** under the **Pages/Books** folder of the `BookStore.Web` project and paste the following code to that page. + +* **Index.cshtml** + +```html +@page +@model BookStore.Web.Pages.Books.Index + +@section scripts +{ + +} + + + + + + Books + + + + + + + + + + +``` + +In here we've added a **New Book** button and a table with an id named "BooksTable". We'll create an `Index.js` file and by using [datatable.js](https://datatables.net) we will fill the table with our records. + +* **Index.js** + +```js +$(function () { + var createModal = new abp.ModalManager(abp.appPath + 'Books/CreateModal'); + var editModal = new abp.ModalManager(abp.appPath + 'Books/EditModal'); + + var bookService = bookStore.books.book; + + var dataTable = $('#BooksTable').DataTable( + abp.libs.datatables.normalizeConfiguration({ + serverSide: true, + paging: true, + order: [[1, "asc"]], + searching: false, + scrollX: true, + ajax: abp.libs.datatables.createAjax(bookService.getList), + columnDefs: [ + { + title: 'Actions', + rowAction: { + items: + [ + { + text: 'Edit', + action: function (data) { + editModal.open({ id: data.record.id }); + } + }, + { + text: 'Delete', + confirmMessage: function (data) { + return "Are you sure to delete the book '" + data.record.name +"'?"; + }, + action: function (data) { + bookService + .delete(data.record.id) + .then(function() { + abp.notify.info("Successfully deleted!"); + dataTable.ajax.reload(); + }); + } + } + ] + } + }, + { + title: 'Name', + data: "name" + }, + { + title: 'Publish Date', + data: "publishDate", + render: function (data) { + return luxon + .DateTime + .fromISO(data, { + locale: abp.localization.currentCulture.name + }).toLocaleString(); + } + }, + { + title: 'Author Name', + data: "authorName" + }, + { + title: 'Price', + data: "price" + }, + { + title: 'Categories', + data: "categoryNames", + render: function (data) { + return data.join(", "); + } + } + ] + }) + ); + + createModal.onResult(function () { + dataTable.ajax.reload(); + }); + + editModal.onResult(function () { + dataTable.ajax.reload(); + }); + + $('#NewBookButton').click(function (e) { + e.preventDefault(); + createModal.open(); + }); +}); + +``` + +> `abp.libs.datatables.normalizeConfiguration` is a helper function defined by the ABP Framework. It simplifies the Datatables configuration by providing conventional default values for missing options. + +* Let's examine what we've done in the `Index.js` file. + +* Firstly, we've defined our `createModal` and `editModal` modals by using the [ABP Modals](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Modals). Then, we've created the DataTable and fetched our books by using the dynamic JavaScript proxy function (`bookStore.books.book.getList`) (It sends a request to the **GetListAsync** method that we've defined in the `BookAppService` under the hook) and we've shown them in the table with an id named "BooksTable". + +* Now let's run the application and navigate to the **/Books** route to see how our Book page looks. + +![Demo](./demo.png) + +We need to see a page similar to the image above. Our app is working properly, we can continue developing. + +> If you are stuck in any point, you can examine the [source codes](https://github.com/EngincanV/ABP-Many-to-Many-Relationship-Demo). + +#### Model Classes and Mapping Configurations + +Create a folder named **Models** and add a class named `CategoryViewModel` inside of it. We will use this view modal class to determine which categories are selected or not in our Create/Edit modals. + +* **CategoryViewModel.cs** + +```csharp +using System; +using System.ComponentModel.DataAnnotations; +using Microsoft.AspNetCore.Mvc; + +namespace BookStore.Web.Models +{ + public class CategoryViewModel + { + [HiddenInput] + public Guid Id { get; set; } + + public bool IsSelected { get; set; } + + [Required] + [HiddenInput] + public string Name { get; set; } + } +} +``` + +Then, we can open the `BookStoreWebAutoMapperProfile` class and define the required mappings as follows: + +```csharp +using AutoMapper; +using BookStore.Authors; +using BookStore.Books; +using BookStore.Categories; +using BookStore.Web.Models; +using BookStore.Web.Pages.Books; +using Volo.Abp.AutoMapper; + +namespace BookStore.Web +{ + public class BookStoreWebAutoMapperProfile : Profile + { + public BookStoreWebAutoMapperProfile() + { + CreateMap() + .Ignore(x => x.IsSelected); + + CreateMap(); + + CreateMap(); + + CreateMap(); + } + } +} +``` + +#### Create/Edit Modals + +After creating our index page for Books and configuring mappings, let's continue with creating the Create/Edit modals for Books. + +Create a razor page named **CreateModal.cshtml** (and **CreateModal.cshtml.cs**). + +* **CreateModal.cshtml** + +```html +@page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@model BookStore.Web.Pages.Books.CreateModal + +@{ + Layout = null; +} + +
+ + + + + +
+ + + + + + +
+
+ +
+ @for (var i = 0; i < Model.Categories.Count; i++) + { + var category = Model.Categories[i]; + + + } +
+
+
+
+ +
+
+``` + +* **CreateModal.cshtml.cs** + +```csharp +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using BookStore.Books; +using BookStore.Categories; +using BookStore.Web.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Rendering; + +namespace BookStore.Web.Pages.Books +{ + public class CreateModal : BookStorePageModel + { + [BindProperty] + public CreateUpdateBookDto Book { get; set; } + + [BindProperty] + public List Categories { get; set; } + + public List AuthorList { get; set; } + + private readonly IBookAppService _bookAppService; + + public CreateModal(IBookAppService bookAppService) + { + _bookAppService = bookAppService; + } + + public async Task OnGetAsync() + { + Book = new CreateUpdateBookDto(); + + //Get all authors and fill the select list + var authorLookup = await _bookAppService.GetAuthorLookupAsync(); + AuthorList = authorLookup.Items + .Select(x => new SelectListItem(x.Name, x.Id.ToString())) + .ToList(); + + //Get all categories + var categoryLookupDto = await _bookAppService.GetCategoryLookupAsync(); + Categories = ObjectMapper.Map, List>(categoryLookupDto.Items.ToList()); + } + + public async Task OnPostAsync() + { + ValidateModel(); + + var selectedCategories = Categories.Where(x => x.IsSelected).ToList(); + if (selectedCategories.Any()) + { + var categoryNames = selectedCategories.Select(x => x.Name).ToArray(); + Book.CategoryNames = categoryNames; + } + + await _bookAppService.CreateAsync(Book); + return NoContent(); + } + } +} +``` + +Here, we've got all categories and authors inside of the `OnGetAsync` method. And use them inside of the create modal to list them so the user can choose when creating a new book. + +![Create Book Modal](./book-creation-modal.png) + +* When the user submits the form, the `OnPostAsync` method runs. Inside of this method, we get the selected categories and pass them into the **CategoryNames** array of the Book object and call the `IBookAppService.CreateAsync` method to create a new book. + +Create a razor page named **EditModal.cshtml** (and **EditModal.cshtml.cs**). + +* **EditModal.cshtml** + +```html +@page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@model BookStore.Web.Pages.Books.EditModal + +@{ + Layout = null; +} + +
+ + + + + +
+ + + + + + + +
+
+ +
+ @for (var i = 0; i < Model.Categories.Count; i++) + { + var category = Model.Categories[i]; + + + } +
+
+
+
+ +
+
+``` + +* **EditModal.cshtml.cs** + +```csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using BookStore.Books; +using BookStore.Categories; +using BookStore.Web.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Rendering; + +namespace BookStore.Web.Pages.Books +{ + public class EditModal : BookStorePageModel + { + [HiddenInput] + [BindProperty(SupportsGet = true)] + public Guid Id { get; set; } + + [BindProperty] + public CreateUpdateBookDto EditingBook { get; set; } + + [BindProperty] + public List Categories { get; set; } + + public List AuthorList { get; set; } + + private readonly IBookAppService _bookAppService; + + public EditModal(IBookAppService bookAppService) + { + _bookAppService = bookAppService; + } + + public async Task OnGetAsync() + { + var bookDto = await _bookAppService.GetAsync(Id); + EditingBook = ObjectMapper.Map(bookDto); + + //get all authors + var authorLookup = await _bookAppService.GetAuthorLookupAsync(); + AuthorList = authorLookup.Items + .Select(x => new SelectListItem(x.Name, x.Id.ToString())) + .ToList(); + + //get all categories + var categoryLookupDto = await _bookAppService.GetCategoryLookupAsync(); + Categories = ObjectMapper.Map, List>(categoryLookupDto.Items.ToList()); + + //mark as Selected for Categories in the book + if (EditingBook.CategoryNames != null && EditingBook.CategoryNames.Any()) + { + Categories + .Where(x => EditingBook.CategoryNames.Contains(x.Name)) + .ToList() + .ForEach(x => x.IsSelected = true); + } + } + + public async Task OnPostAsync() + { + ValidateModel(); + + var selectedCategories = Categories.Where(x => x.IsSelected).ToList(); + if (selectedCategories.Any()) + { + var categoryNames = selectedCategories.Select(x => x.Name).ToArray(); + EditingBook.CategoryNames = categoryNames; + } + + await _bookAppService.UpdateAsync(Id, EditingBook); + return NoContent(); + } + } +} +``` + +* As in the `CreateModal.cshtml.cs`, we've got all categories and authors inside of the `OnGetAsync` method. And also we get the book by id and mark the selected categories properties' as `IsSelected = true`. + +* When the user updates the inputs and submits the form, the `OnPostAsync` method runs. Inside of this method, we get the selected categories and pass them into the **CategoryNames** array of the Book object and call the `IBookAppService.UpdateAsync` method to update the book. + +![Edit Book Modal](./book-update-modal.png) + +### Conclusion + +In this article, I've tried to explain how to create a many-to-many relationship by using the ABP framework. (by following DDD principles) + +Thanks for reading this article, I hope it was helpful. diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/application-contracts-folder-structure.png b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/application-contracts-folder-structure.png new file mode 100644 index 00000000000..c0ed5744892 Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/application-contracts-folder-structure.png differ diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/application-final-demo.gif b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/application-final-demo.gif new file mode 100644 index 00000000000..61289a8ffb0 Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/application-final-demo.gif differ diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/application-folder-structure.png b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/application-folder-structure.png new file mode 100644 index 00000000000..0d37a552d49 Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/application-folder-structure.png differ diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/book-create.gif b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/book-create.gif new file mode 100644 index 00000000000..0e534802f2c Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/book-create.gif differ diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/book-creation-modal.png b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/book-creation-modal.png new file mode 100644 index 00000000000..8661e016cd4 Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/book-creation-modal.png differ diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/book-update-modal.png b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/book-update-modal.png new file mode 100644 index 00000000000..d9d312399ae Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/book-update-modal.png differ diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/demo.png b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/demo.png new file mode 100644 index 00000000000..9b954bd7d60 Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/demo.png differ diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/domain-file-structure.png b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/domain-file-structure.png new file mode 100644 index 00000000000..6a5405dafe3 Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/domain-file-structure.png differ diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/domain-shared-file-structure.png b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/domain-shared-file-structure.png new file mode 100644 index 00000000000..22a8de65999 Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/domain-shared-file-structure.png differ diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/er-diagram.png b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/er-diagram.png new file mode 100644 index 00000000000..5948366e0ee Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/er-diagram.png differ diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/web-folder-structure.png b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/web-folder-structure.png new file mode 100644 index 00000000000..ed4a63a06ce Binary files /dev/null and b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/web-folder-structure.png differ diff --git a/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md new file mode 100644 index 00000000000..edaeaf46dbd --- /dev/null +++ b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md @@ -0,0 +1,321 @@ +# Integrating the Syncfusion MVC Components to the ABP MVC UI + +## Introduction + +In this article we will see how we can integrate the Syncfusion MVC Components into our ABP application. + +## Source Code + +You can find the source code of the application at https://github.com/EngincanV/ABP-Syncfusion-Components-Demo. + +## Prerequisites + +* [.NET 6](https://dotnet.microsoft.com/en-us/download/dotnet/6.0) + + * In this article, we will create a new startup template in v5.0.0-rc.2 and if you follow this article from top to bottom and create a new startup template with me, you need to install the [.NET 6 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/6.0) before starting. + +**NOTE:** ABP v5.X stable version has been released. You can replace v5.0.0-rc.2 with the latest stable version in your steps. + +Also, you need to update your ABP CLI to the v5.0.0-rc.2, you can use the command below to update your CLI version: + +```bash +dotnet tool update Volo.Abp.Cli -g --version 5.0.0-rc.2 +``` + +or install it if you haven't installed it before: + +```bash +dotnet tool install Volo.Abp.Cli -g --version 5.0.0-rc.2 +``` + +## Creating the Solution + +In this article, we will create a new startup template with EF Core as a database provider and MVC for the UI framework. But if you already have a project with MVC UI, you don't need to create a new startup template, you can directly implement the following steps to your existing project. + +> If you already have a project with MVC/Razor Pages UI, you can skip this section. + +We can create a new startup template by using the [ABP CLI](https://docs.abp.io/en/abp/latest/CLI): + +```bash +abp new SyncfusionComponentsDemo -t app --preview +``` + +Our project boilerplate will be ready after the download is finished. Then, we can open the solution and start developing. + +## Starting the Development + +### Pre-requisite + +> If you've already had a license from Syncfusion, you can skip this section. + +* The first thing we need to do is create an account to be able to get a license from Syncfusion. + +* So, let's navigate to https://www.syncfusion.com/aspnet-core-ui-controls and click the "Download Free Trial" button. + +* Then fill the form and start your 30-day free trial. + +* After that, navigate to https://www.syncfusion.com/account/manage-trials/downloads to get our license key that will be used in our application. + +![](./manage-trial-1.png) + +Click the "Get License Key" link for "ASP.NET Core (Essential JS 2)". + +![](./manage-trial-2.png) + +Then a modal will be opened like in the above image, select a version and click the "Get License Key" button. + +![](./copy-license-key.png) + +Lastly, copy the generated license key value. + +In order to use the relevant components, Syncfusion needs to check this license key to know that our license is valid. + +### Configurations + +After providing a license key from Syncfusion, we can start with the configuration that needs to be done in our application. + +#### 1-) Install the Syncfusion.EJ2.AspNet.Core package + +We need to install the `Syncfusion.EJ2.AspNet.Core` Nuget package to our Web project (*.Web). + +We can install it via **Visual Studio's Nuget Package Manager**: + +![](./syncfusion-package.png) + +or via dotnet cli: + +```bash +dotnet add package Syncfusion.EJ2.AspNet.Core --version 19.3.0.57 +``` + +> In this article, I've used the package in version 19.3.0.57. + +#### 2-) Register the License Key + +* After installing the package, we need to register our license key to be able to use the Syncfusion Components. + +* To register the license key, open your web module class and update the `ConfigureServices` method as follows: + +```csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + //Register Syncfusion license + Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense(licenseKey: configuration["Syncfusion:LicenseKey"].ToString()); + + ConfigureUrls(configuration); + ConfigureBundles(); + ConfigureAuthentication(context, configuration); + ConfigureAutoMapper(); + ConfigureVirtualFileSystem(hostingEnvironment); + ConfigureLocalizationServices(); + ConfigureNavigationServices(); + ConfigureAutoApiControllers(); + ConfigureSwaggerServices(context.Services); +} +``` + +Instead of writing the license key directly in here we can define it in the **appsettings.json** file and use it here by using the Configuration system of .NET. + + +* Open your **appsettings.json** file and add a new section named "Syncfusion" as below: + +```json +{ + //... + + "Syncfusion": { + "LicenseKey": "" + } +} +``` + +> Replace the ` part with your license key that we've obtained in the previous section.` + +* To be able to use the Syncfusion Components we need to define them in our **_ViewImports.cshtml** file. By doing that we can use the Syncfusion components everywhere in our application. + +* Open your **/Pages/_ViewImports.cshtml** file and add a new tag helper: + +```cshtml +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling +@addTagHelper *, Syncfusion.EJ2 //use Syncfusion components +``` + +#### 3-) Adding Syncfusion styles and scripts to our application + +Firstly, let's install the `@syncfusion/ej2` package from **npm**. + +* Open your **package.json** file and add the `@syncfusion/ej2` package with version **19.3.57**: + +```json +{ + "version": "1.0.0", + "name": "my-app", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.basic": "^5.0.0-rc.2", + "@syncfusion/ej2": "^19.3.57" + } +} +``` + +* Then, open the **abp.resourcemapping.js** file and update the **mappings** section: + +```js +module.exports = { + aliases: { + + }, + mappings: { + "@node_modules/@syncfusion/ej2/dist/ej2.min.js": "@libs/syncfusion/", + "@node_modules/@syncfusion/ej2/material.css": "@libs/syncfusion/" + } +}; +``` + +> ABP copies related packages from **node_modules** folder to the **libs** folder by examining this file. You can read this [document](docs.abp.io/en/abp/latest/UI/AspNetCore/Client-Side-Package-Management#mapping-the-library-resources) for more info. + +* Then run the `abp install-libs` to install the dependencies and copy them into the libs folder by your mappings configuration. After running this command, in your **libs** folder it should be a folder named **syncfusion** folder. + +![](./syncfusion-libs.png) + +The last thing we need to do is, add some style and script files provided by Syncfusion, between our head-body tags. + +* We can do this by creating two view components (one for Styles and the other for Scripts). Let's do that. + +First, create a folder structure as shown below under the **Components** folder. + +![](./component-folder-structure.png) + +Then open the related files and add the following codes to each of these files. + +* **Default.cshtml** (/Components/Syncfusion/Script/Default.cshtml) + +```cshtml +@addTagHelper *, Syncfusion.EJ2 //add this line + + + + + + +``` + +* **SyncfusionScriptComponent.cs** + +```csharp +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace SyncfusionComponentsDemo.Web.Components.Syncfusion.Script +{ + public class SyncfusionScriptComponent : AbpViewComponent + { + public IViewComponentResult Invoke() + { + return View("~/Components/Syncfusion/Script/Default.cshtml"); + } + } +} +``` + +* **Default.cshtml** (/Components/Syncfusion/Style/Default.cshtml) + +```cshtml + + +``` + +* SyncfusionStyleComponent.cs + +```csharp +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace SyncfusionComponentsDemo.Web.Components.Syncfusion.Style +{ + public class SyncfusionStyleComponent : AbpViewComponent + { + public IViewComponentResult Invoke() + { + return View("~/Components/Syncfusion/Style/Default.cshtml"); + } + } +} +``` + +After creating these two components, we can use the [**Layout Hooks**](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Layout-Hooks) system of ABP to inject these two components between head and script tags. + +To do this, open your web module class and update the `ConfigureServices` method as below: + + +```csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + //Register Syncfusion license + var licenseKey = configuration["Syncfusion:LicenseKey"].ToString(); + Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense(licenseKey: licenseKey); + + Configure(options => + { + //Now, the SyncfusionStyleComponent code will be inserted in the head of the page as the last item. + options.Add(LayoutHooks.Head.Last, typeof(SyncfusionStyleComponent)); + + //the SyncfusionScriptComponent will be inserted in the body of the page as the last item. + options.Add(LayoutHooks.Body.Last, typeof(SyncfusionScriptComponent)); + }); + + ConfigureUrls(configuration); + ConfigureBundles(); + ConfigureAuthentication(context, configuration); + ConfigureAutoMapper(); + ConfigureVirtualFileSystem(hostingEnvironment); + ConfigureLocalizationServices(); + ConfigureNavigationServices(); + ConfigureAutoApiControllers(); + ConfigureSwaggerServices(context.Services); +} +``` + +After injecting the Syncfusion style and script into our application, our configurations have been completed. We can try with a simple component to see if it works as we expected. + +* Let's try with the [Calendar](https://www.syncfusion.com/aspnet-core-ui-controls/calendar) component. Open your **Index.cshtml** file and update with the below content: + +```cshtml +@page +@using Microsoft.AspNetCore.Mvc.Localization +@using SyncfusionComponentsDemo.Localization +@using Volo.Abp.Users +@model SyncfusionComponentsDemo.Web.Pages.IndexModel + +@section styles { + +} + +@section scripts { + +} + +
+

Syncfusion - Calendar Component

+ +
+``` + +* Then when we run the application, we need to see the relevant calendar component as below. + +![](./calendar-component.png) + +### Conclusion + +In this article, we've explained how to integrate the **Syncfusion Components** into our applications. After following this article, you can use the Syncfusion components in your application. + +Thanks for reading the article, I hope you've found it useful :) diff --git a/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/calendar-component.png b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/calendar-component.png new file mode 100644 index 00000000000..8e7f36367ad Binary files /dev/null and b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/calendar-component.png differ diff --git a/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/component-folder-structure.png b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/component-folder-structure.png new file mode 100644 index 00000000000..0dabbe0a062 Binary files /dev/null and b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/component-folder-structure.png differ diff --git a/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/copy-license-key.png b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/copy-license-key.png new file mode 100644 index 00000000000..847be0363d7 Binary files /dev/null and b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/copy-license-key.png differ diff --git a/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/manage-trial-1.png b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/manage-trial-1.png new file mode 100644 index 00000000000..8e84229549d Binary files /dev/null and b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/manage-trial-1.png differ diff --git a/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/manage-trial-2.png b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/manage-trial-2.png new file mode 100644 index 00000000000..57ef370bdb0 Binary files /dev/null and b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/manage-trial-2.png differ diff --git a/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/syncfusion-libs.png b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/syncfusion-libs.png new file mode 100644 index 00000000000..d75935d8fd4 Binary files /dev/null and b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/syncfusion-libs.png differ diff --git a/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/syncfusion-package.png b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/syncfusion-package.png new file mode 100644 index 00000000000..6792ea0c325 Binary files /dev/null and b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/syncfusion-package.png differ diff --git a/docs/en/Customizing-Application-Modules-Extending-Entities.md b/docs/en/Customizing-Application-Modules-Extending-Entities.md index c2bcd314d4e..e1cb02e8490 100644 --- a/docs/en/Customizing-Application-Modules-Extending-Entities.md +++ b/docs/en/Customizing-Application-Modules-Extending-Entities.md @@ -63,8 +63,6 @@ You can then use the same extra properties system defined in the previous sectio Another approach can be **creating your own entity** mapped to **the same database table** (or collection for a MongoDB database). -`AppUser` entity in the [application startup template](Startup-Templates/Application.md) already implements this approach. [EF Core Migrations document](Entity-Framework-Core-Migrations.md) describes how to implement it and manage **EF Core database migrations** in such a case. It is also possible for MongoDB, while this time you won't deal with the database migration problems. - ## Creating a New Entity with Its Own Database Table/Collection Mapping your entity to an **existing table** of a depended module has a few disadvantages; diff --git a/docs/en/Getting-Started-Running-Solution.md b/docs/en/Getting-Started-Running-Solution.md index 3f508589a3d..27e6ac3dee8 100644 --- a/docs/en/Getting-Started-Running-Solution.md +++ b/docs/en/Getting-Started-Running-Solution.md @@ -139,7 +139,7 @@ Ensure that the `.IdentityServer` project is the startup project. Run the applic > Use Ctrl+F5 in Visual Studio (instead of F5) to run the application without debugging. If you don't have a debug purpose, this will be faster. -You can login, but you cannot enter to the main application here. This is just the authentication server. +You can login, but you cannot enter to the main application here. This is **just the authentication server**. Ensure that the `.HttpApi.Host` project is the startup project and run the application which will open a Swagger UI: diff --git a/docs/en/Getting-Started.md b/docs/en/Getting-Started.md index b3fd215e359..0304eb23204 100644 --- a/docs/en/Getting-Started.md +++ b/docs/en/Getting-Started.md @@ -15,6 +15,6 @@ This tutorial explains how to **create and run** a new web application using the ABP Framework. Follow the steps below; -1. [Setup your development environment](Getting-Started-Setup-Environment) +1. [Setup your development environment](Getting-Started-Setup-Environment.md) 2. [Creating a new solution](Getting-Started-Create-Solution.md) 3. [Running the solution](Getting-Started-Running-Solution.md) \ No newline at end of file diff --git a/docs/en/Tutorials/Part-2.md b/docs/en/Tutorials/Part-2.md index 7c8efde9d02..4b29231164a 100644 --- a/docs/en/Tutorials/Part-2.md +++ b/docs/en/Tutorials/Part-2.md @@ -10,7 +10,7 @@ In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies: -* **{{DB_Value}}** as the ORM provider. +* **{{DB_Value}}** as the ORM provider. * **{{UI_Value}}** as the UI Framework. This tutorial is organized as the following parts; @@ -80,13 +80,13 @@ You can see the **book list** returned from the server. You can also check the * Let's **create a new book** using the `create` function: ````js -acme.bookStore.books.book.create({ - name: 'Foundation', - type: 7, - publishDate: '1951-05-24', - price: 21.5 - }).then(function (result) { - console.log('successfully created the book with id: ' + result.id); +acme.bookStore.books.book.create({ + name: 'Foundation', + type: 7, + publishDate: '1951-05-24', + price: 21.5 + }).then(function (result) { + console.log('successfully created the book with id: ' + result.id); }); ```` @@ -187,7 +187,7 @@ namespace Acme.BookStore.Web.Pages.Books { public void OnGet() { - + } } } @@ -654,7 +654,7 @@ Open the `Books.razor` and replace the content as the following: > If you see some syntax errors, you can ignore them if your application properly built and run. Visual Studio still has some bugs with Blazor. * Inherited from the `AbpCrudPageBase` which implements all the CRUD details for us. -* `Entities`, `TotalCount`, `PageSize`, `OnDataGridReadAsync` are defined in the base blass. +* `Entities`, `TotalCount`, `PageSize`, `OnDataGridReadAsync` are defined in the base class. * Injected `IStringLocalizer` (as `L` object) and used for localization. While the code above pretty easy to understand, you can check the Blazorise [Card](https://blazorise.com/docs/components/card/) and [DataGrid](https://blazorise.com/docs/extensions/datagrid/) documents to understand them better. diff --git a/docs/en/Tutorials/Part-5.md b/docs/en/Tutorials/Part-5.md index 4a4611809a7..9c2863ca0af 100644 --- a/docs/en/Tutorials/Part-5.md +++ b/docs/en/Tutorials/Part-5.md @@ -10,7 +10,7 @@ In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies: -* **{{DB_Value}}** as the ORM provider. +* **{{DB_Value}}** as the ORM provider. * **{{UI_Value}}** as the UI Framework. This tutorial is organized as the following parts; @@ -142,7 +142,7 @@ Now, you can use the permissions to authorize the book management. ### Application Layer & HTTP API -Open the `BookAppService` class and add set the policy names as the permission names defined above: +Open the `BookAppService` class and set the policy names as the permission names defined above: ````csharp using System; diff --git a/docs/en/Virtual-File-System.md b/docs/en/Virtual-File-System.md index 4fa29f0738f..4a13bf57405 100644 --- a/docs/en/Virtual-File-System.md +++ b/docs/en/Virtual-File-System.md @@ -119,7 +119,7 @@ The Virtual File System is well integrated to ASP.NET Core: ### Static Virtual File Folders -By default, ASP.NET Core only allows the `wwwroot` folder to contain the static files consumed by the clients. When you use the birtual File System, the following folders also can contain static files: +By default, ASP.NET Core only allows the `wwwroot` folder to contain the static files consumed by the clients. When you use the virtual File System, the following folders also can contain static files: * Pages * Views diff --git a/docs/zh-Hans/Background-Workers.md b/docs/zh-Hans/Background-Workers.md index a7563349ab5..3f0e7fb369e 100644 --- a/docs/zh-Hans/Background-Workers.md +++ b/docs/zh-Hans/Background-Workers.md @@ -2,7 +2,6 @@ ## 介绍 -背景工人在应用简单独立的线程在后台运行.一般来说,他们定期运行,以执行一些任务.例子; 后台工作者在应用程序后台运行的简单的独立线程,一般来说它们定期运行执行一些任务.例如; * 后台工作者可以定期**删除过时的日志**. diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md index b310f96b2cf..b2f3825c64d 100644 --- a/docs/zh-Hans/CLI.md +++ b/docs/zh-Hans/CLI.md @@ -29,6 +29,7 @@ dotnet tool update -g Volo.Abp.Cli * **`help`**: 展示ABP CLI的用法帮助信息. * **`new`**:生成基于ABP的[启动模板](Startup-Templates/Index.md). * **`update`**:自动更新的ABP解决方案ABP相关的NuGet和NPM包. +* **`clean`**: 删除当前目录下所有的 `BIN` 和 `OBJ` 子目录. * **`add-package`**: 添加ABP包到项目. * **`add-module`**: 添加[应用模块](https://docs.abp.io/en/abp/latest/Modules/Index)到解决方案. * **`generate-proxy`**: 生成客户端代理以使用HTTP API端点. @@ -129,6 +130,16 @@ abp update [options] * `--check-all`: 分别检查每个包的新版本. 默认是 `false`. * `--version` or `-v`: 指定用于升级的版本. 如果没有指定,则使用最新版本. +### clean + +删除当前目录下所有的 `BIN` 和 `OBJ` 子目录. + +用法: + +````bash +abp clean +```` + ### add-package 通过以下方式将ABP包添加到项目中 diff --git a/docs/zh-Hans/Getting-Started-AspNetCore-Application.md b/docs/zh-Hans/Getting-Started-AspNetCore-Application.md index 1e676d0c671..f55316739c5 100644 --- a/docs/zh-Hans/Getting-Started-AspNetCore-Application.md +++ b/docs/zh-Hans/Getting-Started-AspNetCore-Application.md @@ -1,12 +1,12 @@ -# 在AspNet Core MVC Web Application中使用ABP +# 在ASP.NET Core MVC Web 应用程序中使用ABP -本教程将介绍如何开始以最少的依赖关系开始使用ABP开发. +本教程将介绍如何开始以最少的依赖关系开始使用ABP开发. -通常情况下你需要下载一个 **[启动模板](Getting-Started-AspNetCore-MVC-Template.md)** +通常情况下你希望从 **[启动模板](Getting-Started-AspNetCore-MVC-Template.md)** 开始. ## 创建一个新项目 -1. 使用Visual Studio 2019 (16.4.0+)创建一个新的AspNet Core Web Application: +1. 使用Visual Studio 2022 (17.0.0+)创建一个新的ASP.NET Core Web应用程序: ![](images/create-new-aspnet-core-application-v2.png) @@ -21,7 +21,7 @@ ## 安装 Volo.Abp.AspNetCore.Mvc 包 -Volo.Abp.AspNetCore.Mvc是ABP集成AspNet Core MVC的包,请安装它到你项目中: +Volo.Abp.AspNetCore.Mvc是ABP集成ASP.NET Core MVC的包,请安装它到你项目中: ```` Install-Package Volo.Abp.AspNetCore.Mvc @@ -29,7 +29,7 @@ Install-Package Volo.Abp.AspNetCore.Mvc ## 创建ABP模块 -ABP是一个模块化框架,它需要一个**启动 (根) 模块**继承自``AbpModule``: +ABP是一个模块化框架,它需要一个**启动(根)模块**继承自 `AbpModule`: ````C# using Microsoft.AspNetCore.Builder; @@ -43,21 +43,20 @@ namespace BasicAspNetCoreApplication [DependsOn(typeof(AbpAspNetCoreMvcModule))] public class AppModule : AbpModule { - public override void OnApplicationInitialization( - ApplicationInitializationContext context) + public override void OnApplicationInitialization(ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); var env = context.GetEnvironment(); + // Configure the HTTP request pipeline. if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else { app.UseExceptionHandler("/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); } + app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseConfiguredEndpoints(); @@ -68,49 +67,44 @@ namespace BasicAspNetCoreApplication ``AppModule`` 是应用程序启动模块的好名称. -ABP的包定义了这个模块类,模块可以依赖其它模块.在上面的代码中 ``AppModule`` 依赖于 ``AbpAspNetCoreMvcModule`` (模块存在于[Volo.Abp.AspNetCore.Mvc](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc)包中). 安装新的ABP的包后添加``DependsOn``是很常见的做法. +ABP的包定义了模块类,模块可以依赖其它模块.在上面的代码中 ``AppModule`` 依赖于 ``AbpAspNetCoreMvcModule`` (由[Volo.Abp.AspNetCore.Mvc](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc)包定义). 安装新的ABP的包后添加``DependsOn``特性是很常见的做法. 我们在此模块类中配置ASP.NET Core管道,而不是Startup类中. ### 启动类 -接下来修改启动类集成ABP模块系统: +接下来修改启动类集成到ABP模块系统: ````C# -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; +using BasicAspNetCoreApplication; -namespace BasicAspNetCoreApplication -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - services.AddApplication(); - } +var builder = WebApplication.CreateBuilder(args); - public void Configure(IApplicationBuilder app) - { - app.InitializeApplication(); - } - } -} +builder.Services.ReplaceConfiguration(builder.Configuration); + +builder.Services.AddApplication(); + +var app = builder.Build(); + +app.InitializeApplication(); + +app.Run(); ```` - -``services.AddApplication()``添加了所有``AppModule``模块中定义的全部服务. -``Configure``方法中的``app.InitializeApplication()``完成初始化并启动应用程序. +``services.AddApplication()``添加了从``AppModule``中启动的所有模块中定义的所有服务. + +``app.InitializeApplication()`` 初始化并启动应用程序. ## 运行应用程序! -启动该应用,它将按预期运行. +启动该应用,它将按预期运行. ## 使用 Autofac 依赖注入框架 -虽然AspNet Core的依赖注入(DI)系统适用于基本要求,但[Autofac](https://autofac.org/)提供了属性注入和方法拦截等高级功能,这些功能是ABP执行高级应用程序框架功能所必需的. +虽然ASP.NET Core的依赖注入(DI)系统适用于基本要求,但[Autofac](https://autofac.org/)提供了属性注入和方法拦截等高级功能,这些功能是ABP执行高级应用程序框架功能所必需的. -用Autofac取代AspNet Core的DI系统并集成到ABP非常简单. +用Autofac取代ASP.NET Core的DI系统并集成到ABP非常简单. 1. 安装 [Volo.Abp.Autofac](https://www.nuget.org/packages/Volo.Abp.Autofac) 包 @@ -132,27 +126,21 @@ public class AppModule : AbpModule 3. 修改``Program.cs``以使用Autofac: ````C# -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; +using BasicAspNetCoreApplication; -namespace BasicAspNetCoreApplication -{ - public class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } +var builder = WebApplication.CreateBuilder(args); - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }) - .UseAutofac(); // 添加这一行 - } -} +builder.Host.UseAutofac(); //Add this line + +builder.Services.ReplaceConfiguration(builder.Configuration); + +builder.Services.AddApplication(); + +var app = builder.Build(); + +app.InitializeApplication(); + +app.Run(); ```` ## 源码 diff --git a/docs/zh-Hans/Getting-Started-Create-Solution.md b/docs/zh-Hans/Getting-Started-Create-Solution.md new file mode 100644 index 00000000000..1ef4879a08f --- /dev/null +++ b/docs/zh-Hans/Getting-Started-Create-Solution.md @@ -0,0 +1,73 @@ +# 入门教程 + +````json +//[doc-params] +{ + "UI": ["MVC", "Blazor", "BlazorServer", "NG"], + "DB": ["EF", "Mongo"], + "Tiered": ["Yes", "No"] +} +```` + +> 本文档假设你更喜欢使用 **{{ UI_Value }}** 作为 UI 框架, 使用 **{{ DB_Value }}** 作为数据库提供程序. 对于其他选项, 请更改本文档顶部的首选项. + +## 创建新项目 + +我们将使用 ABP CLI 创建一个新的 ABP 项目. + +> 或者, 你可以使用[ABP Framework 网站](https://abp.io/get-started)页面上的选项轻松的 **创建并下载** 项目. + +使用 ABP CLI 的 `new` 命令创建一个新项目: + +````shell +abp new Acme.BookStore{{if UI == "NG"}} -u angular{{else if UI == "Blazor"}} -u blazor{{else if UI == "BlazorServer"}} -u blazor-server{{end}}{{if DB == "Mongo"}} -d mongodb{{end}}{{if Tiered == "Yes"}}{{if UI == "MVC" || UI == "BlazorServer"}} --tiered{{else}} --separate-identity-server{{end}}{{end}} +```` + +*你可以使用不同级别的命名空间, 例如: BookStore、Acme.BookStore或 Acme.Retail.BookStore.* + +{{ if Tiered == "Yes" }} + +{{ if UI == "MVC" || UI == "BlazorServer" }} + +* `--tified` 参数用于创建认证服务器、 UI 和 API 实际分隔的 N-层解决方案. + +{{ else }} + +* `--separate-identity-server` 参数用于将Identity Server应用程序与API主机应用程序分隔开. 如果未指定, 则服务器上将只有一个端点. + +{{ end }} + +{{ end }} + +> [ABP CLI 文档](./CLI.md) 涵盖了所有可用的命令和选项. + +## 移动端开发 + +如果你想要在你的解决方案中包含 [React Native](https://reactnative.dev/) 项目, 将 `-m react-native` (or `--mobile react-native`) 参数添加到项目创建命令. 这是一个基础的 React Native 启动模板, 用于开发基于你的 ABP 后端的移动应用程序. + +请参阅 [React Native 入门](Getting-Started-React-Native.md) 文档, 了解如何配置和运行 React Native 应用程序. + +### 解决方案结构 + +该解决方案具有分层结构 (基于 [域驱动设计](Domain-Driven-Design.md)), 并包含单元 & 集成测试项目. 请参阅 [应用程序模板文档](Startup-Templates/Application.md) 以详细了解解决方案结构. + +{{ if DB == "Mongo" }} + +#### MongoDB 事务 + +[启动模板](Startup-templates/Index.md) 默认在`.MongoDB`项目中**禁用**事务. 如果你的MongoDB服务器支持事务, 你可以在*YourProjectMongoDbModule*类中的`ConfigureServices`方法开启它: + + ```csharp +Configure(options => +{ + options.TransactionBehavior = UnitOfWorkTransactionBehavior.Auto; +}); + ``` + +> 或者你可以删除该代码, 因为 `Auto` 已经是默认行为. + +{{ end }} + +## 下一步 + +* [运行解决方案](Getting-Started-Running-Solution.md) \ No newline at end of file diff --git a/docs/zh-Hans/Getting-Started-Running-Solution.md b/docs/zh-Hans/Getting-Started-Running-Solution.md new file mode 100644 index 00000000000..91ee846bc2a --- /dev/null +++ b/docs/zh-Hans/Getting-Started-Running-Solution.md @@ -0,0 +1,199 @@ +# 入门教程 + +````json +//[doc-params] +{ + "UI": ["MVC", "Blazor", "BlazorServer", "NG"], + "DB": ["EF", "Mongo"], + "Tiered": ["Yes", "No"] +} +```` + +> 本文档假设你更喜欢使用 **{{ UI_Value }}** 作为 UI 框架, 使用 **{{ DB_Value }}** 作为数据库提供程序. 对于其他选项, 请更改本文档顶部的首选项. + +## 创建数据库 + +### 连接字符串 + +检查在 {{if Tiered == "Yes"}}`.IdentityServer` 和`.HttpApi.Host` 项目{{else}}{{if UI=="MVC"}}`.Web` 项目{{else if UI=="BlazorServer"}}`.Blazor` 项目{{else}}`.HttpApi.Host` 项目{{end}}{{end}} 中 `appsettings.json` 文件里的**连接字符串**. + +{{ if DB == "EF" }} + +````json +"ConnectionStrings": { + "Default": "Server=(LocalDb)\MSSQLLocalDB;Database=BookStore;Trusted_Connection=True" +} +```` + +> **关于连接字符串和数据库管理系统** +> +> 解决方案配置为默认使用 **Entity Framework Core** 与 **MS SQL Server**. 但是, 如果在执行ABP CLI 的`new`命令时使用了`-dbms`参数来选择其他DBMS (如`-dbms MySQL`), 那么连接字符串可能不同. +> +> EF Core 支持 [多种](https://docs.microsoft.com/en-us/ef/core/providers/) 据库提供程序, 因此你可以使用任何受支持的DBMS. 你可以需要时候参阅[Entity Framework 集成文档](Entity-Framework-Core.md) 来学习如何[切换到另一个DBMS](Entity-Framework-Core-Other-DBMS.md). + +### 数据库迁移 + +该解决方案使用[Entity Framework Core Code First 迁移](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli). 带有 `.DbMigrator` 的控制台程序用于 **应用迁移** 和 **初始化种子数据**. 它在**开发**和**生产**环境中都很有用. + +> `.dbMigator` 项目有自己的 `appsettings.json`. 因此, 如果你更改了之前的连接字符串, 那么也应该更改这个连接字符串. + +### 初次迁移 + +`.dbMigator` 应用程序在首次运行时自动**创建初始迁移**. + +**如果你使用的是 Visual Studio, 你可以跳到 *运行 dbMigrator* 部分.** 但是, 其他 IDE (例如 Rider) 在首次运行时可能会遇到问题, 因为它会添加初始迁移并编译项目. 在这种情况下, 请在 `.dbMigration` 项目的文件夹中打开命令行终端, 然后运行以下命令: + +````bash +dotnet run +```` + +下次, 你可以像往常一样在 IDE 中运行它. + +### 运行迁移 + +右键单击 `.dbMigration` 项目, 然后选择 **设置为启动项目** + +![set-as-startup-project](images/set-as-startup-project.png) + + 按F5(或Ctrl + F5) 运行应用程序. 它将具有如下所示的输出: + + ![db-migrator-output](images/db-migrator-output.png) + +> 初始的[种子数据](Data-Seeding.md)在数据库中创建了 `admin` 用户(密码为`1q2w3E*`) 用于登录应用程序. 所以, 对于新数据库至少使用 `.DbMigrator` 一次. + +{{ else if DB == "Mongo" }} + +````json +"ConnectionStrings": { + "Default": "mongodb://localhost:27017/BookStore" +} +```` + +该解决方案配置为在本地计算机中使用 **MongoDB**, 因此你需要启动并运行 MongoDB 服务器实例, 或者将连接字符串更改为另一台 MongoDB 服务器. + +### 种子初始数据 + +该解决方案带有 `.DbMigrator` 的控制台程序用于 **初始化种子数据**. 它在**开发**和**生产**环境中都很有用. + +> `.dbMigator` 项目有自己的 `appsettings.json`. 因此, 如果你更改了之前的连接字符串, 那么也应该更改这个连接字符串. + +右键单击 `.dbMigration` 项目, 然后选择 **设置为启动项目** + +![set-as-startup-project](images/set-as-startup-project.png) + + 按F5(或Ctrl + F5) 运行应用程序. 它将具有如下所示的输出: + + ![db-migrator-output](images/db-migrator-output.png) + +> 初始的[种子数据](Data-Seeding.md)在数据库中创建了 `admin` 用户(密码为`1q2w3E*`) 用于登录应用程序. 所以, 对于新数据库至少使用 `.DbMigrator` 一次. + +{{ end }} + +## 运行应用程序 + +{{ if UI == "MVC" || UI == "BlazorServer" }} + +{{ if Tiered == "Yes" }} + +> 分层解决方案使用 **Redis** 作为分布式缓存. 确保它已安装并在本地计算机上运行. 如果你使用的是远程 Redis 服务器, 请修改项目的 ` appsettings.json` 文件中的配置. + +1. 确保 `.IdentityServer` 项目是启动项目. 运行此应用程序, 它将在浏览器中打开 **登录** 页面. + +> 在 Visual Studio 中使用 Ctrl+F5(而不是F5) 在不进行调试的情况下运行应用程序. 如果你没有调试目的, 这会更快. + +你可以登录, 但不能在这里进入主应用程序. 这 **只是身份验证服务器**. + +2. 确保 `.httpapi.Host` 项目是启动项目, 然后运行应用将在浏览器中打开 **Swagger UI**. + +![swagger-ui](images/swagger-ui.png) + +这是 Web 应用程序使用的 HTTP API. + +3. 最后, 确保 {{if UI=="MVC"}}`.Web`{{else}}`.Blazor`{{end}} 项目是启动项目,然后运行应用程序,它将在浏览器中打开 **欢迎** 页面 + +![mvc-tiered-app-home](images/bookstore-home.png) + +单击 **login** 按钮, 它将重定向到 *身份验证服务器* 以登录到应用程序: + +![bookstore-login](images/bookstore-login.png) + +{{ else # Tiered != "Yes" }} + +确保 {{if UI=="MVC"}}`.Web`{{else}}`.Blazor`{{end}} 项目是启动项目. 运行应用程序将会在浏览器中打开 **login** 页面: + +> 在 Visual Studio 中使用 Ctrl+F5(而不是F5) 在不进行调试的情况下运行应用程序. 如果你没有调试目的, 这会更快. + +![bookstore-login](images/bookstore-login.png) + +{{ end # Tiered }} + +{{ else # UI != MVC || BlazorServer }} + +### 运行 HTTP API 主机(服务器端) + +{{ if Tiered == "Yes" }} + +> 分层解决方案使用 Redis 作为分布式缓存. 确保它已安装并在本地计算机上运行. 如果你使用的是远程 Redis 服务器, 请修改项目的 `appsettings.json` 文件中的配置. + +确保 `.IdentityServer` 项目是启动项目. 运行此应用程序, 它将在浏览器中打开 **登录** 页面. + +> 在 Visual Studio 中使用 Ctrl+F5(而不是F5) 在不进行调试的情况下运行应用程序. 如果你没有调试目的, 这会更快. + +你可以登录, 但不能在这里进入主应用程序. 这 **只是身份验证服务器**. + +确保 `.HttpApi.Host` 项目是启动项目, 然后运行应用程序将打开 Swagger UI 的: + +{{ else # Tiered == "No" }} + +确保 `.HttpApi.Host` 项目是启动项目, 然后运行应用程序将打开 Swagger UI 的: + +> 在 Visual Studio 中使用 Ctrl+F5(而不是F5) 在不进行调试的情况下运行应用程序. 如果你没有调试目的, 这会更快. + +{{ end # Tiered }} + +![swagger-ui](images/swagger-ui.png) + +你可以在这里查看应用程序的API并测试它们. 获取Swagger UI的[更多信息](https://swagger.io/tools/swagger-ui/). + +{{ end # UI }} + +{{ if UI == "Blazor" }} + +### 运行 Blazor 应用程序 (客户端) + +确保 `.Blazor` 项目是启动项目并运行应用程序. + +> 在 Visual Studio 中使用 Ctrl+F5(而不是F5) 在不进行调试的情况下运行应用程序. 如果你没有调试目的, 这会更快. + +应用程序启动后, 单击页头上的 **Login** 链接, 你将重定向到身份验证服务器以输入用户名和密码: + +![bookstore-login](images/bookstore-login.png) + +{{ else if UI == "NG" }} + +### 运行 Angular 应用程序 (客户端) + +转到 `Angular` 文件夹, 打开命令行终端, 键入 `yarn` 命令(我们建议使用 [yarn](https://yarnpkg.com/) 软件包管理器, 而 `npm install` 也可以使用) + +```bash +yarn +``` + +当所有node模块加载完毕后, 执行 `yarn start` (或 `npm start`) 命令: + +```bash +yarn start +``` + +初次构建可能需要更长的时间. 完成后, 它会在默认浏览器中使用 [localhost:4200](http://localhost:4200/) 地址打开 Angular UI. + +![bookstore-login](images/bookstore-login.png) + +{{ end }} + +输入用户名 **admin** 和 密码 **1q2w3E*** 登录应用程序. 应用程序已启动并正在运行. 你可以根据此启动模板开始开发应用程序. + +## 另请参见 + +* [Web 应用程序开发教程](Tutorials/Part-1.md) +* [应用程序启动模板](Startup-Templates/Application.md) diff --git a/docs/zh-Hans/Getting-Started-Setup-Environment.md b/docs/zh-Hans/Getting-Started-Setup-Environment.md new file mode 100644 index 00000000000..c0c2d5d924f --- /dev/null +++ b/docs/zh-Hans/Getting-Started-Setup-Environment.md @@ -0,0 +1,53 @@ +# 入门教程 + +````json +//[doc-params] +{ + "UI": ["MVC", "Blazor", "BlazorServer", "NG"], + "DB": ["EF", "Mongo"], + "Tiered": ["Yes", "No"] +} +```` + +> 本文档假设你更喜欢使用 **{{ UI_Value }}** 作为 UI 框架, 使用 **{{ DB_Value }}** 作为数据库提供程序. 对于其他选项, 请更改本文档顶部的首选项. + +## 设置你的开发环境 + +第一件事! 在创建项目之前, 让我们先设置你的开发环境. + +### 先决条件 + +开发计算机上应安装以下工具: + +* 一个集成开发环境 (比如: [Visual Studio](https://visualstudio.microsoft.com/vs/)) 它需要支持 [.NET 6.0+](https://dotnet.microsoft.com/download/dotnet) 的开发. +{{ if UI != "Blazor" }} +* [Node v12 或 v14](https://nodejs.org/) +* [Yarn v1.20+ (不是v2)](https://classic.yarnpkg.com/en/docs/install) [1](#f-yarn) 或 npm v6+ (已跟随Node一起安装) +{{ end }} +{{ if Tiered == "Yes" }} +* [Redis](https://redis.io/) (启动解决方案使用 Redis 作为 [分布式缓存](Caching.md)). +{{ end }} + +{{ if UI != "Blazor" }} + +1 _Yarn v2 工作方式不同, 不被支持._ [↩](#a-yarn) + +{{ end }} + +### 安装 ABP CLI + +[ABP CLI](./CLI.md) 是一个命令行界面, 用于自动执行基于 ABP 的解决方案的一些常见任务. 首先, 你需要使用以下命令安装 ABP CLI: + +````shell +dotnet tool install -g Volo.Abp.Cli +```` + +如果已安装, 则可以使用以下命令对其进行更新: + +````shell +dotnet tool update -g Volo.Abp.Cli +```` + +## 下一步 + +* [创建新的解决方案](Getting-Started-Create-Solution.md) \ No newline at end of file diff --git a/docs/zh-Hans/Getting-Started.md b/docs/zh-Hans/Getting-Started.md index c6b3bd70df7..1cf1430a359 100644 --- a/docs/zh-Hans/Getting-Started.md +++ b/docs/zh-Hans/Getting-Started.md @@ -1,374 +1,20 @@ -## 入门 +# 入门教程 ````json //[doc-params] { - "UI": ["MVC","NG"], + "UI": ["MVC", "Blazor", "BlazorServer", "NG"], "DB": ["EF", "Mongo"], "Tiered": ["Yes", "No"] } ```` -本教程介绍了如何创建一个新的{{if UI == "MVC"}} ASP.NET Core MVC web {{else if UI == "NG"}} Angular {{end}}. 配置并运行它. +> 本文档假设你更喜欢使用 **{{ UI_Value }}** 作为 UI 框架, 使用 **{{ DB_Value }}** 作为数据库提供程序. 对于其他选项, 请更改本文档顶部的首选项. -## 设置你的开发环境 +## 内容 -创建第一个项目之前,需要正确的设置你的开发环境. +本教程介绍如何使用 ABP 框架 **创建和运行** 新的 Web 应用程序. 请按照以下步骤操作; -### 预先要求 - -你需要安装以下工具: - -* [Visual Studio 2019 (v16.4+)](https://visualstudio.microsoft.com/vs/) for Windows / [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/).[1](#f-editor) -* [.NET Core 3.1+](https://www.microsoft.com/net/download/dotnet-core/) - -* [Node v12 或 v14](https://nodejs.org/en/) -* [Yarn v1.19+](https://classic.yarnpkg.com/) -* [Yarn v1.20+ (not v2)](https://classic.yarnpkg.com/en/docs/install) [2](#f-yarn) 或 npm v6+ (与Node一起安装) -{{ if Tiered == "Yes" }} - -* [Redis](https://redis.io/): 入门解决方案将Redis用作[分布式缓存](Caching.md). 因此你需要安装并运行Redis. - -{{ end }} - -1 _只要支持.NET Core和ASP.NET Core,就可以使用其他编辑器代替Visual Studio._ [↩](#a-editor) - -2 _Yarn v2 的工作方式不同,不受支持._ [↩](#a-yarn) - -### 安装ABP CLI - -[ABP CLI](./CLI.md)是一个命令行页面,用于自动执行一些基于ABP的应用程序的常见任务. - -> ABP CLI是ABP框架一个免费开源的工具. - -你需要使用以下命令安排ABP CLI: - -````shell -dotnet tool install -g Volo.Abp.Cli -```` - -如果你已经安装,你可以使用以下命令更新到最新版本: - -````shell -dotnet tool update -g Volo.Abp.Cli -```` - -## 创建新项目 - -> 本文假设你使用 **{{ UI_Value }}** 做为UI框架 **{{ DB_Value }}** 做为数据库提供程序,对于其它选项,你可以更改文档顶部的首选项. - -### 使用ABP CLI创建一个新项目 - -使用ABP CLI的 `new` 命令创建新项目: - -````shell -abp new Acme.BookStore{{if UI == "NG"}} -u angular {{end}}{{if DB == "Mongo"}} -d mongodb{{end}}{{if Tiered == "Yes" && UI != "NG"}} --tiered {{else if Tiered == "Yes" && UI == "NG"}}--separate-identity-server{{end}} --mobile react-native -```` - -* 此命令还会在解决方案文件夹内创建一个React Native移动应用程序. 如果你不想要它,可以安全地删除它或从`abp new`命令中删除`--mobile react-native`选项, 以使其完全不包含在解决方案中. - -{{ if UI == "NG" }} - -* `-u` 指定UI框架, 本例中是 `angular`. - -{{ if Tiered == "Yes" }} - -* `--separate-identity-server` 参数用于将Identity服务器应用程序与API主机应用程序分隔开. 如果未指定,则服务器上将只有一个端点. - -{{ end }} - -{{ end }} - -{{ if DB == "Mongo" }} - -* `-d` 指定数据库提供程序, 本例中是 `mongodb`. - -{{ end }} - -{{ if Tiered == "Yes" && UI != "NG" }} - -* `--tiered` 参数用于创建n层解决方案,其中身份验证服务器层,UI层和API层在物理上是分离的. - -{{ end }} - -> 你可以使用不同级别的命令空间; 例如. BookStore, Acme.BookStore or Acme.Retail.BookStore. - -#### ABP CLI 命令 & 选项 - -[ABP CLI文档](./CLI.md)涵盖了ABP CLI的所有可用命令和选项. 本文档使用[应用程序启动模板](Startup-Templates/Application.md)创建新的Web应用程序. 有关其他模板,请参见[ABP启动模板](Startup-Templates/Index.md)文档. - -> 或者,您可以从[ABP Framework网站](https://abp.io/get-started)中选择"直接下载"选项卡创建新的解决方案. - -## 解决方案结构 - -{{ if UI == "MVC" }} - -创建项目后你会有以下解决方案目录和文件: - -![](images/solution-files-mvc.png) - -在Visual Studio中打开 `.sln` 文件时,将看到以下解决方案结构: - -{{if DB == "Mongo"}} - -![vs-default-app-solution-structure](images/vs-app-solution-structure-mongodb.png) - -{{else}} - -![vs-default-app-solution-structure](images/vs-app-solution-structure{{if Tiered == "Yes"}}-tiered{{end}}.png) - -{{end}} - -{{ else if UI == "NG" }} - -在创建的解决方案中有三个文件夹: - -![](images/solution-files-non-mvc.png) - -* `angular` 文件夹包含Angular UI应用程序. -* `aspnet-core` 文件夹包含后端应用程序. -* `react-native` 文件夹包含React Native UI 应用程序. - -打开 `aspnet-core` 文件夹下的 `.sln`(`Visual Studio`解决方案)文件: - -![vs-angular-app-backend-solution-structure](images/vs-spa-app-backend-structure{{if DB == "Mongo"}}-mongodb{{end}}.png) - -{{ end }} - -> ###### 关于解决方案中的项目 -> -> 根据你的**UI**,**数据库**和其他选项,你的解决方案的结构可能略有不同. - -该解决方案具有分层结构(基于[Domain Driven Design](Domain-Driven-Design.md)), 并包含配置好的的单元&集成测试项目. - -{{ if DB == "EF" }} - -集成测试项目已配置为可与 **EF Core** & **SQLite 内存** database同时使用. - -{{ else if DB == "Mongo" }} - -集成测试项目已配置为每个测试创建的内存中的**MongoDB**数据库(使用的[Mongo2Go](https://github.com/Mongo2Go/Mongo2Go)库). - -{{ end }} - -> 请参阅[应用程序模板文档](Startup-Templates/Application.md)详细了解解决方案结构. - -{{ if DB == "Mongo" }} - -> [启动模板](Startup-templates/Index.md)默认在 `.MongoDB` 项目中**禁用**了工作单元事务. 如果你的MongoDB服务器支持事务,你可以手动启用工作单元的事务: - - ```csharp - Configure(options => - { - options.TransactionBehavior = UnitOfWorkTransactionBehavior.Enabled; - }); - ``` - -{{ end }} - -## 创建数据库 - -### 连接字符串 - -检查 {{if UI == "MVC"}}{{if Tiered == "Yes"}}`.IdentityServer` 和 `.HttpApi.Host` 项目{{else}}`.Web` 项目{{end}}{{else if UI == "NG" }}`.HttpApi.Host` 项目{{end}}下 `appsettings.json` 文件中的 **链接字符串**: - -{{ if DB == "EF" }} - -````json -"ConnectionStrings": { - "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True" -} -```` - -该解决方案配置为**Entity Framework Core**与**MS SQL Server**一起使用. EF Core支持[各种](https://docs.microsoft.com/en-us/ef/core/providers/)数据库提供程序,因此你可以使用任何受支持的DBMS. 请参阅[Entity Framework集成文档](https://docs.abp.io/en/abp/latest/Entity-Framework-Core)了解如何切换到另一个DBMS. - -### 数据库连接字符串 - -查看`.Web`项目下`appsettings.json`文件中的 **连接字符串**: - -````json -{ - "ConnectionStrings": { - "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True" - } -} -```` - -解决方案使用 **Entity Framework Core** 和 **MS SQL Server**. EF Core支持[各种](https://docs.microsoft.com/zh-cn/ef/core/providers/)数据库提供程序,因此你可以根据实际需要使用其他DBMS. 如果需要,请更改连接字符串. - -### 应用迁移 - -该解决方案使用[Entity Framework Core Code First 迁移](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli). 你需要应用迁移来创建数据库,有两种方法迁移数据库. - -#### 使用DbMigrator应用程序应用迁移 - -该解决方案包含一个控制台应用程序(在此示例中名为`Acme.BookStore.DbMigrator`),可以创建数据库,应用迁移和初始化数据. 它对开发和生产环境都很有用. - -> `.DbMigrator`项目有自己的`appsettings.json`. 因此,如果你更改了上面的连接字符串,则还应更改此字符串. - -右键单击`.DbMigrator`项目并选择 **设置为启动项目**: - -![set-as-startup-project](images/set-as-startup-project.png) - -按F5(或Ctrl + F5)运行应用程序. 它将具有如下所示的输出: - -![set-as-startup-project](images/db-migrator-app.png) - -#### 使用EF Core Update-Database命令 - -Ef Core具有`Update-Database`命令, 可根据需要创建数据库并应用挂起的迁移. 右键单击`.Web`项目并选择**设置为启动项目**: - -{{ if UI == "MVC" }} - -右键单击{{if Tiered == "Yes"}}`.IdentityServer`{{else}}`.Web`{{end}}项目并选择**设置为启动项目**: - -{{ else if UI != "MVC" }} - -右键单击`.HttpApi.Host`项目并选择**设置为启动项目**: - -{{ end }} - -![set-as-startup-project](images/set-as-startup-project.png) - -打开**包管理器控制台(Package Manager Console)**, 选择`.EntityFrameworkCore.DbMigrations`项目作为**默认项目**并运行`Update-Database`命令: - -![package-manager-console-update-database](images/package-manager-console-update-database.png) - -这将基于配置的连接字符串创建新数据库. - -> **使用`.DbMigrator`工具是建议的方法**, 因为它能初始化初始数据能够正确运行Web应用程序. -> -> 如果你只是使用 `Update-Database` 命令,你会得到一个空数据库,所以你无法登录到应用程序因为数据库中没有初始管理用户. 不需要种子数据库时,可以在开发期间使用 `Update-Database` 命令. 但是使用 `.DbMigrator` 应用程序会更简单,你始终可以使用它来迁移模式并为数据库添加种子. - -{{ else if DB == "Mongo" }} - -````json -"ConnectionStrings": { - "Default": "mongodb://localhost:27017/BookStore" -} -```` - -该解决方案被配置为在你的本地计算机中使用 **MongoDB**,因此你需要启动并运行一个MongoDB服务器实例或者将连接字符串更改为另一个MongoDB服务器. - -### 初始化种子数据 - -该解决方案附带一个 `.DbMigrator` 控制台应用程序,该应用程序为初始数据提供了种子. 它对于开发以及生产环境都很有用. - -> `.DbMigrator` 项目有自己的 `appsettings.json`.如果你更改了其他项目的 `appsettings.json`,也应该更改这个. - -右键点击 `.DbMigrator` 并选择 **设置为启动项目**. - -![set-as-startup-project](images/set-as-startup-project.png) - - 按F5(或Ctrl+F5)启动应用程序,你会看到以下输出: - - ![db-migrator-output](images/db-migrator-output.png) - -> 数据库创建后会初始化[种子数据](Data-Seeding.md), 其中包含用于登录的 `admin` 用户. 所以你至少使用 `.DbMigrator` 一次. - -{{ end }} - -### 运行应用程序 - -{{ if UI == "MVC" }} - -{{ if Tiered == "Yes" }} - -确保 `.IdentityServer` 是启动项目,运行应用程序后会在你的浏览器打开一个 **login** 页面. - -> 在Visual Studio中使用Ctrl+F5(而不是F5)运行应用,如果你不用于调试,这会减少启动时间. - -你可以登录,但是不能在这里进入主应用程序,它仅是验证服务器. - -确保 `.HttpApi.Host` 是启动项目,运行应用程序后会在你的浏览器打开一个 **Swagger UI** 页面. - -![swagger-ui](images/swagger-ui.png) - -这里是Web应用程序使用的API应用程序. - -最后确保 `.Web` 是启动项目,运行应用程序后会在你的浏览器打开一个 **welcome** 页面. - -![mvc-tiered-app-home](images/bookstore-home.png) - -点击 **login** 按钮重定向到 `Identity Server` 来登录应用程序. - -![bookstore-login](images/bookstore-login.png) - -{{ else }} - -最后确保 `.Web` 是启动项目,运行应用程序后会在你的浏览器打开一个 **login** 页面. - -> 在Visual Studio中使用Ctrl+F5(而不是F5)运行应用,如果你不用于调试,这会减少启动时间. - -![bookstore-login](images/bookstore-login.png) - -{{ end }} - -{{ else if UI != "MVC" }} - -#### 运行HTTP API Host (服务器端) - -{{ if Tiered == "Yes" }} - -确保 `.IdentityServer` 是启动项目,运行应用程序后会在你的浏览器打开一个 **login** 页面. - -> 在Visual Studio中使用Ctrl+F5(而不是F5)运行应用,如果你不用于调试,这会减少启动时间. - -你可以登录,但是不能在这里进入主应用程序,它仅是验证服务器. - -{{ end }} - -确保 `.HttpApi.Host` 是启动项目,运行应用程序后会在你的浏览器打开一个 **Swagger UI** 页面. - -{{ if Tiered == "No" }} - -> 在Visual Studio中使用Ctrl+F5(而不是F5)运行应用,如果你不用于调试,这会减少启动时间. - -{{ end }} - -![swagger-ui](images/swagger-ui.png) - -你可以看到应用程序的API并进行测试. 更多信息,请参阅[Swagger UI](https://swagger.io/tools/swagger-ui/). - -> ##### Swagger UI 授权 -> -> 大多数的HTTP API都需要身份验证和授权. 如果你要测试授权API, 请手动进入 `/Account/Login` 页面, 输入用户名: `admin` 和密码: `1q2w3E*` 登录到应用程序. 然后你可以访问授权API. - -{{ end }} - -{{ if UI == "NG" }} -#### 运行 Angular 应用程序 (客户端) - -在 `angular` 下打开命令行终端, 输入 `yarn` 命令(我们推荐使用[yarn](https://yarnpkg.com/)包管理, `npm install` 在大多数情况下也可以工作). - -```bash -yarn -``` - -等到所有node模块加载成功, 执行 `yarn start` (或 `npm start`) 命令: - -```bash -yarn start -``` - -等待 `Angular CLI` 使用 `BrowserSync` 启动 `Webpack` dev-server. -它会负责编译你的 `TypeScript`代码, 并自动重新加载浏览器. -完成后 `Angular Live Development Server` 会监听 localhost:4200. -打开你的浏览器并导航到[localhost:4200](http://localhost:4200/). - -![bookstore-login](images/bookstore-login.png) - -{{ end }} - -输入用户名 **admin**,密码 **1q2w3E*** 登录到应用程序,应用程序已经启动并执行,你可以基于此启动模板开始开发应用程序. - -#### 移动开发 - -当你创建一个新的应用程序时. 可以添加`-m react-native`选项以在解决方案中包含 `react-native`项目. 这是一个基础的[React Native](https://reactnative.dev/)启动模板,用于开发与基于ABP的后端集成的移动应用程序. - - -请参阅"[React Native入门](Getting-Started-React-Native.md)"文档了解如何配置和运行React Native应用程序. - -## 下一步是什么? - -[Web应用程序开发教程](Tutorials/Part-1.md) +1. [设置你的开发环境](Getting-Started-Setup-Environment.md) +2. [创建新的解决方案](Getting-Started-Create-Solution.md) +3. [运行解决方案](Getting-Started-Running-Solution.md) \ No newline at end of file diff --git a/docs/zh-Hans/Modules/Identity.md b/docs/zh-Hans/Modules/Identity.md index 420b696a7ce..73f05af7bb8 100644 --- a/docs/zh-Hans/Modules/Identity.md +++ b/docs/zh-Hans/Modules/Identity.md @@ -1,28 +1,320 @@ # 身份管理模块 -身份模块基于Microsoft Identity库用于管理[组织单元](Organization-Units.md), 角色, 用户和他们的权限. +身份模块基于 [Microsoft Identity 库](https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/identity) 用于管理角色,用户及其权限. -> 参阅 [源码](https://github.com/abpframework/abp/tree/dev/modules/identity). 文档很快会被完善. +## 如何安装 -## Identity安全日志 +当你使用 ABP 框架 [创建一个新的解决方案](https://abp.io/get-started) 时,此模块将被预安装(作为 NuGet/NPM 包)。你可以继续用其作为包并轻松地获取更新,也可以将其源代码包含在解决方案中(请参阅 `get-source` [CLI](../CLI.md))以开发自定义模块。 -安全日志可以记录账户的一些重要的操作或者改动, 你可以在在一些功能中保存安全日志. +### 源代码 -你可以注入和使用 `IdentitySecurityLogManager` 或 `ISecurityLogManager` 来保存安全日志. 默认它会创建一个安全日志对象并填充常用的值. 如 `CreationTime`, `ClientIpAddress`, `BrowserInfo`, `current user/tenant`等等. 当然你可以自定义这些值. +可以 [在此处](https://github.com/abpframework/abp/tree/dev/modules/identity) 访问源代码。源代码使用 [MIT](https://choosealicense.com/licenses/mit/) 许可, 所以你可以免费使用和自定义它. + +## 用户界面 + +此模块提供了 [Blazor](../UI/Blazor/Overall.md), [Angular](../UI/Angular/Quick-Start.md) 和 [MVC / Razor Pages](../UI/AspNetCore/Overall.md) 的 UI 可选. + +### 菜单项 + +此模块在 *管理* 菜单下添加了一个 *身份管理* 菜单项: + +![身份模块菜单](../images/identity-module-menu.png) + +这个菜单项和相关页面已获得授权. 这意味着当前用户必须拥有相关权限才能使其可见. `admin` 角色 (和拥有此角色的用户, 如 `admin` 用户) 已经拥有这些权限. 如果你想要使其他角色/用户也启用权限, 请打开 *角色* 或 *用户* 页面的 *权限* 对话框, 并检查如下所示的权限: + +![身分模块权限](../images/identity-module-permissions.png) + +请参阅 [授权文档](../Authorization.md) 以了解权限系统. + +### 页面 + +本节介绍此模块提供的主要页面. + +#### 用户 + +此页用于查看用户列表. 您可以创建/编辑和删除用户, 将角色分配给用户. + +![身分模块用户](../images/identity-module-users.png) + +一个用户可以有零个或多个角色. 用户从其角色继承权限. 此外, 你可以给用户直接分配权限 (通过点击 *操作* 按钮, 然后选择 *权限*) . + +#### 角色 + +角色用于按分组给用户分配权限. + +![身份模块角色](../images/identity-module-roles.png) + +角色除了角色名称之外还有2个属性: + +* `Default`: 如果某个角色被标记为 "default", 那么当新用户 (使用 [账户模块](Account.md)) 注册到应用程序时, 其将被作为默认角色分配给新用户. +* `Public`: 用户的公共角色可以被应用程序中的其他用户看到. 这个功能在身份模块中没有用到, 但被提供作为你可能希望在你自己的应用程序中使用的功能. + +## 其他功能 + +本节包括此模块提供的没有 UI 页面的其他功能. + +### 组织单元 + +组织单元 (OU) 可被用于 **按层级对用户和实体进行分组**. + +#### 组织单元实体 + +组织单元由 **OrganizationUnit** 实体表示. 它的基本属性是: + +- **TenantId**: 组织单元的租户Id. 对于宿主可以是 null. +- **ParentId**: 父级组织单元的Id. 如果这是一个根级组织单元,它可以是 null. +- **Code**: 对于租户唯一的层级字符串编码. +- **DisplayName**: 组织单元的显示名称. + +#### 组织树 + +由于组织单元可以有父级, 因此租户的所有组织单元是一个 **树** 结构. 这个树有一些规则; + +- 可以有多个根级 (`ParentId` 是 `null` 的) . +- 一个组织单元的第一级子项数量有限制 (因为下面解释的固定的组织单元编码单位长度) . + +#### 组织单元编码 + +组织单元编码是通过 `OrganizationUnitManager` 服务自动生成和维护的. 它是一个字符串, 像这样: + +"**00001.00042.00005**" + +通常用这种编码可以轻易地 (递归) 查询出数据库中组织单元的所有子项. 这个编码有一些规则 (当你使用 `OrganizationUnitManager` 时自动被应用的) : + +- 对 [租户](../Multi-Tenancy.md) 是 **唯一的**. +- 同一组织单元的全部子项都具有 **以父级组织单元编码开头的** 编码. +- 如示例中所示, 它是固定长度的且是基于树中组织单元的级别的. +- 尽管组织单元编码是唯一的, 但如果你移动了相关的组织单元, 它也可以被更改. + +请注意, 你必须根据Id引用一个组织单元, 而不是编码, 因为编码后续是可以被更改的. + +#### 组织单元管理 + +`OrganizationUnitManager` 类可以被 [注入](../Dependency-Injection.md) 并用来管理组织单元. 常见用例如下: + +- 创建, 更新和删除组织单元. +- 在组织单元树中移动一个组织单元. +- 获取关于组织单元树及其项的信息. + +### 身份安全日志 + +安全日志系统可以记录账户的一些重要的操作或者改动 (例如 *登录* 和 *更改密码*) . 如果需要, 你也可以保存安全日志. + +你可以注入和使用 `IdentitySecurityLogManager` 或 `ISecurityLogManager` 来写入安全日志. 默认它会创建一个日志对象并填充常用的值, 如 `CreationTime`, `ClientIpAddress`, `BrowserInfo`, `current user/tenant` 等等. 当然你可以覆盖这些值. ```cs await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() { - Identity = "IdentityServer"; - Action = "ChangePassword"; + Identity = "IdentityServer"; + Action = "ChangePassword"; }); ``` -通过配置 `AbpSecurityLogOptions` 来提供应用程序的名称或者禁用安全日志功能. 默认是**启用**状态. +通过配置 `AbpSecurityLogOptions` 来为日志提供应用程序的名称 (如果你有多个应用程序并且想要在日志中区分应用程序) 或者禁用安全日志功能. ```cs Configure(options => { - options.ApplicationName = "AbpSecurityTest"; + options.ApplicationName = "AbpSecurityTest"; }); ``` +## 选项 + +`IdentityOptions` 是由 Microsoft [Identity 库](https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/identity) 提供的标准 [选项类](../Options.md) . 所以, 你可以在 [模块](../Module-Development-Basics.md) 类的 `ConfigureServices` 方法中设置这些选项. + +**例如: 设置所需的密码最小长度** + +````csharp +Configure(options => +{ + options.Password.RequiredLength = 5; +}); +```` + +ABP 允许你在运行时通过使用 [设置系统](../Settings.md) 更进一步地更改这些选项. 你可以 [注入](../Dependency-Injection.md) `ISettingManager` 并使用 `Set...` 方法中的一种来更改用户, 租户或全局所有用户的选项值. + +**例如: 更改当前租户所需的密码最小长度** + +````csharp +public class MyService : ITransientDependency +{ + private readonly ISettingManager _settingManager; + + public MyService(ISettingManager settingManager) + { + _settingManager = settingManager; + } + + public async Task ChangeMinPasswordLength(int minLength) + { + await _settingManager.SetForCurrentTenantAsync( + IdentitySettingNames.Password.RequiredLength, + minLength.ToString() + ); + } +} +```` + +`IdentitySettingNames` 类 (在 `Volo.Abp.Identity.Settings` 命名空间中) 为设置名称定义了一些常量. + +## 分布式事件 + +此模块定义了如下 ETOs (事件传输对象) 以允许你去订阅模块中实体的改动. + +* `UserEto` 在 `IdentityUser` 实体更改完成时发布. +* `IdentityRoleEto` 在 `IdentityRole` 实体更改完成时发布. +* `IdentityClaimTypeEto` 在 `IdentityClaimType` 实体更改完成时发布. +* `OrganizationUnitEto` 在 `OrganizationUnit` 实体更改完成时发布. + +**例如: 当一个新用户被创建时接收通知** + +````csharp +public class MyHandler : + IDistributedEventHandler>, + ITransientDependency +{ + public async Task HandleEventAsync(EntityCreatedEto eventData) + { + UserEto user = eventData.Entity; + // TODO: ... + } +} +```` + +`UserEto` 和 `IdentityRoleEto` 默认自动发布事件. 你应该自己配置其他的 Eto. 请参阅 [分布式事件总线文档](../Distributed-Event-Bus.md) 了解预定义事件的详细信息. + +> 订阅分布式事件对于分布式场景 (如微服务架构) 特别有用. 如果你正在构建单体式应用程序, 或者在运行了身份模块的同一进程内监听事件, 那么订阅 [本地事件](../Local-Event-Bus.md) 更高效, 更简单. + +## 内部构件 + +本节包括模块的一些内部详细信息, 您不是那么需要, 但在一些情况下可能需要使用. + +### 领域层 + +#### 聚合 + +##### 用户 + +用户通常是一个登录并使用应用程序的人. + +* `IdentityUser` (聚合根): 表示系统中的一个用户. + * `IdentityUserRole` (集合): 分配给用户的角色. + * `IdentityUserClaim` (集合): 用户的自定义声明. + * `IdentityUserLogin` (集合): 用户的外部登录. + * `IdentityUserToken` (集合): 用户的令牌 (用于 Microsoft Identity 服务). + +##### 角色 + +角色通常是分配给用户的一组权限. + +* `IdentityRole` (聚合根): 表示系统中的角色. + * `IdentityRoleClaim` (集合): 角色的自定义声明. + +##### 声明类型 + +声明类型是可以被分配给系统中其他实体 (如角色和用户) 的自定义声明的定义. + +* `IdentityClaimType` (聚合根): 表示声明类型的定义. 它包括一些用于定义声明类型和验证规则的属性 (例如, 必须的, 正则表达式, 描述, 值类型) . + +##### 身份安全日志 + +`IdentitySecurityLog` 对象表示系统中与授权相关的操作 (如 *登录*) . + +* `IdentitySecurityLog` (聚合根): 表示系统中的安全日志. + +##### 组织单元 + +组织单元是一个有层级结构的实体. + +* ```OrganizationUnit``` (聚合根): 表示系统中的组织单元. + * ```Roles``` (集合): 组织单元的角色. + +#### 仓储 + +此模块定义了以下自定义仓储: + +* `IIdentityUserRepository` +* `IIdentityRoleRepository` +* `IIdentityClaimTypeRepository` +* ```IIdentitySecurityLogRepository``` +* ```IOrganizationUnitRepository``` + +#### 领域服务 + +##### 用户管理 + +`IdentityUserManager` 常用于管理用户, 他们的权限, 声明, 密码, 电子邮件等等. 它派生自 Microsoft Identity 的 `UserManager` 类, 其中 `T` 是 `IdentityUser`. + +##### 角色管理 + +`IdentityRoleManager` 常用于管理角色和他们的声明. 它派生自 Microsoft Identity 的 `RoleManager` 类, 其中 `T` 是 `IdentityRole`. + +##### 声明类型管理 + +`IdenityClaimTypeManager` 常用于对聚合根 `IdentityClaimType` 执行某些操作. + +##### 组织单元管理 + +```OrganizationUnitManager``` 常用于对聚合根 `OrganizationUnit` 执行某些操作. + +##### 安全日志管理 + +```IdentitySecurityLogManager``` 常用于保存安全日志. + +### 服务层 + +#### 应用服务 + +* `IdentityUserAppService` (实现 `IIdentityUserAppService`): 实现了用户管理 UI 的用例. +* `IdentityRoleAppService` (实现 `IIdentityRoleAppService`): 实现了角色管理 UI 的用例. +* `IdentityClaimTypeAppService` (实现 `IIdentityClaimTypeAppService`): 实现了声明类型管理 UI 的用例. +* `IdentitySettingsAppService` (实现 `IIdentitySettingsAppService`): 用于获取和更新身份模块的设置. +* `IdentityUserLookupAppService` (实现 `IIdentityUserLookupAppService`): 用于根据 `id` 或 `userName` 获取用户信息. 它旨在由ABP内部使用. +* `ProfileAppService` (实现 `IProfileAppService`): 用于更改用户的简介和密码. +* ```IdentitySecurityLogAppService``` (实现 ```IIdentitySecurityLogAppService```): 实现了安全日志 UI 的用例. +* ```OrganizationUnitAppService``` (实现 ```OrganizationUnitAppService```): 实现了组织单元管理 UI 的用例. + +### 数据库提供程序 + +此模块为数据库提供 [Entity Framework Core](../Entity-Framework-Core.md) 和 [MongoDB](../MongoDB.md) 两种选择. + +#### EF Core + +NuGet 包 [Volo.Abp.Identity.EntityFrameworkCore](https://www.nuget.org/packages/Volo.Abp.Identity.EntityFrameworkCore) 实现了 EF Core 的集成. + +##### 数据库表 + +* **AbpRoles** + * AbpRoleClaims +* **AbpUsers** + * AbpUserClaims + * AbpUserLogins + * AbpUserRoles + * AbpUserTokens +* **AbpClaimTypes** +* **AbpOrganizationUnits** + * AbpOrganizationUnitRoles + * AbpUserOrganizationUnits +* **AbpSecurityLogs** + +#### MongoDB + +NuGet 包 [Volo.Abp.Identity.MongoDB](https://www.nuget.org/packages/Volo.Abp.Identity.MongoDB) 实现了 MongoDB 的集成. + +##### 数据库集合 + +* **AbpRoles** +* **AbpUsers** +* **AbpClaimTypes** +* **AbpOrganizationUnits** +* **AbpSecurityLogs** + +#### 常用数据库属性 + +你可以设置 `AbpIdentityDbProperties` 中的以下属性来更改数据库选项: + +* `DbTablePrefix` (`Abp` 作为默认值) 是表/集合名称的前缀. +* `DbSchema` (`null` 作为默认值) 是数据库架构. +* `ConnectionStringName` (`AbpIdentity` 作为默认值) 是此模块的 [连接字符串](../Connection-Strings.md) 名称. + +它们是静态属性. 你需要在开始运行应用程序前设置它们 (通常在 `Program.cs` 中). diff --git a/docs/zh-Hans/Modules/IdentityServer.md b/docs/zh-Hans/Modules/IdentityServer.md index cb82a640d5d..1359c04e531 100644 --- a/docs/zh-Hans/Modules/IdentityServer.md +++ b/docs/zh-Hans/Modules/IdentityServer.md @@ -1 +1,173 @@ -TODO... \ No newline at end of file +# 身份服务器模块 + +身份服务器模块提供了一个 [IdentityServer](https://github.com/IdentityServer/IdentityServer4) (IDS) 的完全集成, 该框架提供高级身份验证功能, 如单点登录和API访问控制.此模块将客户端,资源以及其他 IDS 相关的对象保存到数据库中. + +## 如何安装 + +当你使用 ABP 框架 [创建一个新的解决方案](https://abp.io/get-started) 时, 此模块将被预安装(作为 NuGet/NPM 包).你可以继续用其作为包并轻松地获取更新, 也可以将其源代码包含在解决方案中(请参阅 `get-source` [CLI](../CLI.md))以开发自定义模块. + +### 源代码 + +可以 [在此处](https://github.com/abpframework/abp/tree/dev/modules/identityserver) 访问源代码.源代码使用 [MIT](https://choosealicense.com/licenses/mit/) 许可, 所以你可以免费使用和自定义它. + +## 用户界面 + +此模块使用了领域逻辑和数据库集成, 但没有提供任何 UI.如果你需要动态添加客户端和资源, 管理 UI 是非常有用的.在这种情况下, 你可以自己构建管理 UI, 或者考虑购买为此模块提供了管理 UI 的 [ABP 商业版](https://commercial.abp.io/). + +## 与其他模块的关系 + +此模块基于 [身份模块](Identity.md) 并且[账户模块](Account.md) 有一个 [集成包](https://www.nuget.org/packages/Volo.Abp.Account.Web.IdentityServer). + +## 选项 + +### AbpIdentityServerBuilderOptions + +`AbpIdentityServerBuilderOptions` 在你的身份服务器 [模块](https://docs.abp.io/zh-Hans/abp/latest/Module-Development-Basics) 中的 `PreConfigureServices` 方法中配置.例如: + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(builder => + { + //Set options here... + }); +} +```` + +`AbpIdentityServerBuilderOptions` 属性: + +* `UpdateJwtSecurityTokenHandlerDefaultInboundClaimTypeMap` (默认值:true):更新 `JwtSecurityTokenHandler.DefaultInboundClaimTypeMap` 使其与身份服务器声明兼容. +* `UpdateAbpClaimTypes` (默认值:true):更新 `AbpClaimTypes` 与身份服务器声明兼容. +* `IntegrateToAspNetIdentity` (默认值:true):集成到 ASP.NET Identity. +* `AddDeveloperSigningCredential` (默认值:true):设置为 false 禁止调用 IIdentityServerBuilder 中的 `AddDeveloperSigningCredential()`. + +`IIdentityServerBuilder` 可以在你的身份服务器 [模块](https://docs.abp.io/zh-Hans/abp/latest/Module-Development-Basics) 中的 `PreConfigureServices` 方法中配置.例如: + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(builder => + { + builder.AddSigningCredential(...); + }); +} +```` + +## 内部结构 + +### 领域层 + +#### 聚合 + +##### API 资源 + +需要 API 资源来允许客户端请求访问令牌. + +* `ApiResource` (聚合根):表示系统中的 API 资源. + * `ApiSecret` (集合):API 资源的密钥. + * `ApiScope` (集合):API 资源的作用域. + * `ApiResourceClaim` (集合):API 资源的声明. + +##### 客户端 + +客户端表示可以从你的身份服务器请求令牌的应用程序. + +* `Client` (聚合根):表示一个身份服务器的客户端应用程序. + * `ClientScope` (集合):客户端的作用域. + * `ClientSecret` (集合):客户端的密钥. + * `ClientGrantType` (集合):客户端的授权类型. + * `ClientCorsOrigin` (集合):客户端的 CORS 源. + * `ClientRedirectUri` (集合):客户端的重定向 URIs. + * `ClientPostLogoutRedirectUri` (集合):客户端的登出重定向 URIs. + * `ClientIdPRestriction` (集合):客户端的提供程序约束. + * `ClientClaim` (集合):客户端的声明. + * `ClientProperty` (集合):客户端的自定义属性. + +##### 持续化授权 + +持续化授权存储了授权码,刷新令牌和用户准许. + +* `PersistedGrant` (聚合根):表示为身份服务器持续化授权. + +##### 身份资源 + +身份资源是用户的用户 ID ,名称或邮件地址等数据. + +* `IdentityResource` (聚合根):表示与身份服务器的身份资源. + * `IdentityClaim` (集合):身份资源的声明. + +#### 仓储 + +为此模块定义了以下自定义仓储: + +* `IApiResourceRepository` +* `IClientRepository` +* `IPersistentGrantRepository` +* `IIdentityResourceRepository` + +#### 领域服务 + +此模块不包含任何领域服务, 但重写了下面的服务; + +* `AbpProfileService` (当 `AbpIdentityServerBuilderOptions.IntegrateToAspNetIdentity` 为 true 时使用) +* `AbpClaimsService` +* `AbpCorsPolicyService` + +### 设置 + +此模块未定义任何设置. + +### 应用层 + +#### 应用服务 + +* `ApiResourceAppService` (实现 `IApiResourceAppService`):实现了 API 资源管理 UI 的用例. +* `IdentityServerClaimTypeAppService` (实现 `IIdentityServerClaimTypeAppService`):用于获取声明列表. +* `ApiResourceAppService` (实现 `IApiResourceAppService`):实现了 API 管理资源 UI 的用例. +* `IdentityResourceAppService` (实现 `IIdentityResourceAppService`):实现了身份资源管理 UI 的用例. + +### 数据库提供程序 + +#### 公共 + +##### 表/集合 前缀 & 架构 + +所有表/集合都使用 `IdentityServer` 作为默认前缀.如果你需要改变表的前缀或设置一个架构名称(如果你的数据库提供程序支持), 请设置 `AbpIdentityServerDbProperties` 类的静态属性. + +##### 连接字符串 + +此模块使用 `AbpIdentityServer` 作为连接字符串的名称.如果你没有用这个名称定义连接字符串, 它将回退到 `Default` 连接字符串. + +有关详细信息, 请参阅 [连接字符串](https://docs.abp.io/zh-Hans/abp/latest/Connection-Strings) 文档. + +#### EF Core + +##### 表 + +* **IdentityServerApiResources** + * IdentityServerApiSecrets + * IdentityServerApiScopes + * IdentityServerApiScopeClaims + * IdentityServerApiClaims +* **IdentityServerClients** + * IdentityServerClientScopes + * IdentityServerClientSecrets + * IdentityServerClientGrantTypes + * IdentityServerClientCorsOrigins + * IdentityServerClientRedirectUris + * IdentityServerClientPostLogoutRedirectUris + * IdentityServerClientIdPRestrictions + * IdentityServerClientClaims + * IdentityServerClientProperties +* **IdentityServerPersistedGrants** +* **IdentityServerIdentityResources** + * IdentityServerIdentityClaims + +#### MongoDB + +##### 集合 + +* **IdentityServerApiResources** +* **IdentityServerClients** +* **IdentityServerPersistedGrants** +* **IdentityServerIdentityResources** diff --git a/docs/zh-Hans/Tutorials/Part-1.md b/docs/zh-Hans/Tutorials/Part-1.md index 3ff216fb76d..927463e100e 100644 --- a/docs/zh-Hans/Tutorials/Part-1.md +++ b/docs/zh-Hans/Tutorials/Part-1.md @@ -2,32 +2,15 @@ ````json //[doc-params] { - "UI": ["MVC","NG"], + "UI": ["MVC","Blazor","BlazorServer","NG"], "DB": ["EF","Mongo"] } ```` -{{ -if UI == "MVC" - UI_Text="mvc" -else if UI == "NG" - UI_Text="angular" -else - UI_Text="?" -end -if DB == "EF" - DB_Text="Entity Framework Core" -else if DB == "Mongo" - DB_Text="MongoDB" -else - DB_Text="?" -end -}} - ## 关于本教程 在本系列教程中, 你将构建一个名为 `Acme.BookStore` 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开发的: -* **{{DB_Text}}** 做为ORM提供程序. +* **{{DB_Text}}** 做为数据库提供程序. * **{{UI_Value}}** 做为UI框架. 本教程分为以下部分: @@ -40,16 +23,29 @@ end - [Part 6: 作者: 领域层](Part-6.md) - [Part 7: 作者: 数据库集成](Part-7.md) - [Part 8: 作者: 应用服务层](Part-8.md) -- [Part 9: 作者: 用户页面](Part-9.md) +- [Part 9: 作者: 用户界面](Part-9.md) - [Part 10: 图书到作者的关系](Part-10.md) ## 下载源码 -本教程根据你的**UI** 和 **Database**偏好有多个版,我们准备了两种可供下载的源码组合: +本教程根据你的**UI** 和 **数据库**偏好有多个版本,我们准备了几种可供下载的源码组合: * [MVC (Razor Pages) UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Mvc-EfCore) +* [Blazor UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore) * [Angular UI 与 MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb) +> 如果你在Windows中遇到 "文件名太长" or "解压错误", 很可能与Windows最大文件路径限制有关. Windows文件路径的最大长度为250字符. 为了解决这个问题,参阅 [在Windows 10中启用长路径](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later). + +> 如果你遇到与Git相关的长路径错误, 尝试使用下面的命令在Windows中启用长路径. 参阅 https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path +> `git config --system core.longpaths true` + +{{if UI == "MVC" && DB == "EF"}} + +### 视频教程 + +本章也被录制为视频教程 **发布在YouTube**. + +{{end}} ## 创建解决方案 在开始开发之前,请按照[入门教程](../Getting-Started.md)创建名为 `Acme.BookStore` 的新解决方案. @@ -58,12 +54,12 @@ end 启动模板中的**领域层**分为两个项目: - - `Acme.BookStore.Domain`包含你的[实体](https://docs.abp.io/zh-Hans/abp/latest/Entities), [领域服务](https://docs.abp.io/zh-Hans/abp/latest/Domain-Services)和其他核心域对象. + - `Acme.BookStore.Domain`包含你的[实体](../Entities.md), [领域服务](../Domain-Services.md)和其他核心域对象. - `Acme.BookStore.Domain.Shared`包含可与客户共享的常量,枚举或其他域相关对象. -在解决方案的**领域层**(`Acme.BookStore.Domain`项目)中定义你的实体. +在解决方案的**领域层**(`Acme.BookStore.Domain`项目)中定义你的实体. -该应用程序的主要实体是`Book`. 在`Acme.BookStore.Domain`项目中创建一个 `Books` 文件夹并在其中添加一个名为 `Book` 的类,如下所示: +该应用程序的主要实体是`Book`. 在`Acme.BookStore.Domain`项目中创建一个 `Books` 文件夹(命名空间),并在其中添加名为 `Book` 的类,如下所示: ````csharp using System; @@ -84,15 +80,15 @@ namespace Acme.BookStore.Books } ```` -* ABP为实体提供了两个基本的基类: `AggregateRoot`和`Entity`. **Aggregate Root**是[**领域驱动设计**](./Domain-Driven-Design.md) 概念之一. 可以视为直接查询和处理的根实体(请参阅[实体文档](../Entities.md)). -* `Book`实体继承了`AuditedAggregateRoot`,`AuditedAggregateRoot`类在`AggregateRoot`类的基础上添加了一些审计属性(`CreationTime`, `CreatorId`, `LastModificationTime` 等). ABP框架自动为你管理这些属性. -* `Guid`是`Book`实体的主键类型. +* ABP为实体提供了两个基本的基类: `AggregateRoot`和`Entity`. **Aggregate Root**是[**领域驱动设计**](../Domain-Driven-Design.md) 概念之一. 可以视为直接查询和处理的根实体(请参阅[实体文档](../Entities.md)). +* `Book`实体继承了`AuditedAggregateRoot`,`AuditedAggregateRoot`类在`AggregateRoot`类的基础上添加了一些基础[审计](../Audit-Logging.md)属性(例如`CreationTime`, `CreatorId`, `LastModificationTime` 等). ABP框架自动为你管理这些属性. +* `Guid`是`Book`实体的**主键类型**. > 为了保持简单,本教程将实体属性保留为 **public get/set** . 如果你想了解关于DDD最佳实践,请参阅[实体文档](../Entities.md). ### BookType枚举 -上面所用到了 `BookType` 枚举,在 `Acme.BookStore.Domain.Shared` 项目创建 `BookType`. +`Book`实体使用了`BookType`枚举. 在`Acme.BookStore.Domain.Shared`项目中创建`Books`文件夹(命名空间),并在其中添加`BookType`: ````csharp namespace Acme.BookStore.Books @@ -150,28 +146,37 @@ public class BookStoreMongoDbContext : AbpMongoDbContext ### 将Book实体映射到数据库表 -在 `Acme.BookStore.EntityFrameworkCore` 项目中打开 `BookStoreDbContextModelCreatingExtensions.cs` 文件,添加 `Book` 实体的映射代码. 最终类应为: + +打开`BookStoreDbContext`类的`OnModelCreating`方法,为`Book`实体添加映射代码: ````csharp using Acme.BookStore.Books; -using Microsoft.EntityFrameworkCore; -using Volo.Abp; -using Volo.Abp.EntityFrameworkCore.Modeling; +... namespace Acme.BookStore.EntityFrameworkCore { - public static class BookStoreDbContextModelCreatingExtensions + public class BookStoreDbContext : + AbpDbContext, + IIdentityDbContext, + ITenantManagementDbContext { - public static void ConfigureBookStore(this ModelBuilder builder) + ... + + protected override void OnModelCreating(ModelBuilder builder) { - Check.NotNull(builder, nameof(builder)); + base.OnModelCreating(builder); + + /* Include modules to your migration db context */ + + builder.ConfigurePermissionManagement(); + ... /* Configure your own tables/entities inside here */ builder.Entity(b => { b.ToTable(BookStoreConsts.DbTablePrefix + "Books", - BookStoreConsts.DbSchema); + BookStoreConsts.DbSchema); b.ConfigureByConvention(); //auto configure for the base class props b.Property(x => x.Name).IsRequired().HasMaxLength(128); }); @@ -180,14 +185,14 @@ namespace Acme.BookStore.EntityFrameworkCore } ```` -* `BookStoreConsts` 含有用于表的架构和表前缀的常量值. 你不必使用它,但建议在单点控制表前缀. -* `ConfigureByConvention()` 方法优雅的配置/映射继承的属性,应始终对你所有的实体使用它. +* `BookStoreConsts` 含有用于表的架构和表前缀的常量值. 使用它不是强制的,但建议在统一的地方控制表前缀. +* `ConfigureByConvention()` 方法优雅的配置/映射继承的属性,应对所有的实体使用它. ### 添加数据迁移 -启动模板使用[EF Core Code First Migrations](https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/)创建和维护数据库架构. 我们应该创建一个新的迁移并且应用到数据库. +本示例使用[EF Core Code First Migrations](https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/).因为我们修改了数据库映射配置,我们必须创建一个新的迁移并且应用到数据库. -在 `Acme.BookStore.EntityFrameworkCore.DbMigrations` 目录打开命令行终端输入以下命令: +在 `Acme.BookStore.EntityFrameworkCore` 目录打开命令行终端输入以下命令: ```bash dotnet ef migrations add Created_Book_Entity @@ -205,7 +210,7 @@ dotnet ef migrations add Created_Book_Entity > >在运行应用程序之前最好将初始数据添加到数据库中. 本节介绍ABP框架的[数据种子系统](../Data-Seeding.md). 如果你不想创建种子数据可以跳过本节,但是建议你遵循它来学习这个有用的ABP Framework功能。 -在 `*.Domain` 项目下创建派生 `IDataSeedContributor` 的类,并且拷贝以下代码: +在 `*.Domain` 项目下创建 `IDataSeedContributor` 的派生类,并且拷贝以下代码: ```csharp using System; @@ -258,7 +263,7 @@ namespace Acme.BookStore } ``` -* 如果数据库中当前没有图书,则此代码使用 `IRepository`(默认为[repository](../Repositories.md))将两本书插入数据库. +* 如果数据库中当前没有图书,则此代码使用 `IRepository`(默认[repository](../Repositories.md))将两本书插入数据库. ### 更新数据库 @@ -279,7 +284,7 @@ namespace Acme.BookStore ### BookDto -`CrudAppService` 基类需要定义实体的基本DTO. 在 `Acme.BookStore.Application.Contracts` 项目中创建一个名为 `BookDto` 的DTO类: +`CrudAppService` 基类需要定义实体的基本DTO. 在 `Acme.BookStore.Application.Contracts` 项目中创建 `Books` 文件夹(命名空间), 并在其中添加名为 `BookDto` 的DTO类: ````C# using System; @@ -300,9 +305,9 @@ namespace Acme.BookStore } ```` -* **DTO**类被用来在 **表示层** 和 **应用层** **传递数据**.查看[DTO文档](https://docs.abp.io/zh-Hans/abp/latest/Data-Transfer-Objects)查看更多信息. -* 为了在页面上展示书籍信息,`BookDto`被用来将书籍数据传递到表示层. -* `BookDto`继承自 `AuditedEntityDto`.跟上面定义的 `Book` 实体一样具有一些审计属性. +* **DTO**类被用来在 **表示层** 和 **应用层** **传递数据**.参阅[DTO文档](https://docs.abp.io/zh-Hans/abp/latest/Data-Transfer-Objects). +* 为了在用户界面上展示书籍信息,`BookDto`被用来将书籍数据传递到表示层. +* `BookDto`继承自 `AuditedEntityDto`.与上面定义的 `Book` 实体一样具有一些审计属性. 在将书籍返回到表示层时,需要将`Book`实体转换为`BookDto`对象. [AutoMapper](https://automapper.org)库可以在定义了正确的映射时自动执行此转换. 启动模板配置了AutoMapper,因此你只需在`Acme.BookStore.Application`项目的`BookStoreApplicationAutoMapperProfile`类中定义映射: @@ -322,12 +327,11 @@ namespace Acme.BookStore } ```` -> 参阅 [对象对对象映射](../Object-To-Object-Mapping.md) 文档了解详情. +> 参阅 [对象到对象映射](../Object-To-Object-Mapping.md) 文档了解详情. ### CreateUpdateBookDto -在`Acme.BookStore.Application.Contracts`项目中创建一个名为 `CreateUpdateBookDto` 的DTO类: - +在`Acme.BookStore.Application.Contracts`项目中创建 `Books` 文件夹(命名空间),并在其中添加名为 `CreateUpdateBookDto` 的DTO类: ````csharp using System; using System.ComponentModel.DataAnnotations; @@ -354,7 +358,7 @@ namespace Acme.BookStore.Books ```` * 这个DTO类被用于在创建或更新书籍的时候从用户界面获取图书信息. -* 它定义了数据注释属性(如`[Required]`)来定义属性的验证. DTO由ABP框架[自动验证](https://docs.abp.io/zh-Hans/abp/latest/Validation). +* 它定义了数据注释特性(如`[Required]`)来定义属性的验证规则. DTO由ABP框架[自动验证](https://docs.abp.io/zh-Hans/abp/latest/Validation). 就像上面的`BookDto`一样,创建一个从`CreateUpdateBookDto`对象到`Book`实体的映射,最终映射配置类如下: @@ -378,7 +382,7 @@ namespace Acme.BookStore ### IBookAppService -下一步是为应用程序定义接口,在`Acme.BookStore.Application.Contracts`项目中定义一个名为`IBookAppService`的接口: +下一步是为应用程序定义接口,在`Acme.BookStore.Application.Contracts`项目创建 `Books` 文件夹(命名空间),并在其中添加名为`IBookAppService`的接口: ````csharp using System; @@ -400,12 +404,12 @@ namespace Acme.BookStore.Books ```` * 框架定义应用程序服务的接口**不是必需的**. 但是,它被建议作为最佳实践. -* `ICrudAppService`定义了常见的**CRUD**方法:`GetAsync`,`GetListAsync`,`CreateAsync`,`UpdateAsync`和`DeleteAsync`. 你可以从空的`IApplicationService`接口继承并手动定义自己的方法(将在下一部分中完成). -* `ICrudAppService`有一些变体, 你可以在每个方法中使用单独的DTO,也可以分别单独指定(例如使用不同的DTO进行创建和更新). +* `ICrudAppService`定义了常见的**CRUD**方法:`GetAsync`,`GetListAsync`,`CreateAsync`,`UpdateAsync`和`DeleteAsync`. 从这个接口扩展不是必需的,你可以从空的`IApplicationService`接口继承并手动定义自己的方法(将在下一部分中完成). +* `ICrudAppService`有一些变体, 你可以在每个方法中使用单独的DTO(例如使用不同的DTO进行创建和更新). ### BookAppService -在`Acme.BookStore.Application`项目中创建名为 `BookAppService` 的 `IBookAppService` 实现: +是时候实现`IBookAppService`接口了.在`Acme.BookStore.Application`项目中创建 `Books` 文件夹(命名空间),并在其中添加名为 `BookAppService` 的类: ````csharp using System; @@ -439,19 +443,20 @@ namespace Acme.BookStore.Books ### 自动生成API Controllers -你通常创建**Controller**以将应用程序服务公开为**HTTP API**端点. 因此允许浏览器或第三方客户端通过AJAX调用它们. +在典型的ASP.NET Core应用程序中,你创建**API Controller**以将应用程序服务公开为**HTTP API**端点. 这将允许浏览器或第三方客户端通过HTTP调用它们. -ABP可以[**自动**](../API/Auto-API-Controllers.md)按照惯例将你的应用程序服务配置为MVC API控制器. +ABP可以[**自动**](../API/Auto-API-Controllers.md)按照约定将你的应用程序服务配置为MVC API控制器. ### Swagger UI 启动模板配置为使用[Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)运行[swagger UI](https://swagger.io/tools/swagger-ui/). 运行应用程序并在浏览器中输入`https://localhost:XXXX/swagger/`(用你自己的端口替换XXXX)作为URL. +使用`CTRL+F5`运行应用程序 ({{if UI=="MVC"}}`Acme.BookStore.Web`{{else}}`Acme.BookStore.HttpApi.Host`{{end}})并使用浏览器访问`https://localhost:/swagger/` on your browser. 使用你自己的端口号替换 ``. -你会看到一些内置的接口和`Book`的接口,它们都是REST风格的: +你会看到一些内置的服务端点和`Book`服务,它们都是REST风格的端点: -![bookstore-swagger](images/bookstore-swagger.png) +![bookstore-swagger](./images/bookstore-swagger.png) -Swagger有一个很好的UI来测试API. +Swagger有一个很好的UI来测试API. 你可以尝试执行`[GET] /api/app/book` API来获取书籍列表, 服务端会返回以下JSON结果: diff --git a/docs/zh-Hans/Tutorials/Part-2.md b/docs/zh-Hans/Tutorials/Part-2.md index 231ca226fa9..fe0dd84c452 100644 --- a/docs/zh-Hans/Tutorials/Part-2.md +++ b/docs/zh-Hans/Tutorials/Part-2.md @@ -2,26 +2,10 @@ ````json //[doc-params] { - "UI": ["MVC","NG"], + "UI": ["MVC","Blazor","BlazorServer","NG"], "DB": ["EF","Mongo"] } ```` - -{{ -if UI == "MVC" - DB="ef" - DB_Text="Entity Framework Core" - UI_Text="mvc" -else if UI == "NG" - DB="mongodb" - DB_Text="MongoDB" - UI_Text="angular" -else - DB ="?" - UI_Text="?" -end -}} - ## 关于本教程 在本系列教程中, 你将构建一个名为 `Acme.BookStore` 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开发的: @@ -44,16 +28,30 @@ end ## 下载源码 -本教程根据你的**UI** 和 **Database**偏好有多个版,我们准备了两种可供下载的源码组合: +本教程根据你的**UI** 和 **数据库**偏好有多个版本,我们准备了几种可供下载的源码组合: * [MVC (Razor Pages) UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Mvc-EfCore) +* [Blazor UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore) * [Angular UI 与 MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb) +> 如果你在Windows中遇到 "文件名太长" or "解压错误", 很可能与Windows最大文件路径限制有关. Windows文件路径的最大长度为250字符. 为了解决这个问题,参阅 [在Windows 10中启用长路径](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later). + +> 如果你遇到与Git相关的长路径错误, 尝试使用下面的命令在Windows中启用长路径. 参阅 https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path +> `git config --system core.longpaths true` + +{{if UI == "MVC" && DB == "EF"}} + +### 视频教程 + +本章也被录制为视频教程 **发布在YouTube**. + +{{end}} + {{if UI == "MVC"}} ## 动态JavaScript代理 -通常在 **JavaScript** 端通过AJAX调用HTTP API端点. 你可以使用 `$.ajax` 或其他工具来调用端点. 但是ABP提供了更好的方法. +在 **JavaScript** 端通过AJAX调用HTTP API端点是常见的做法. 你可以使用 `$.ajax` 或其他工具来调用端点. 但是ABP提供了更好的方法. ABP**动态**为所有API端点创建 **[JavaScript代理](../UI/AspNetCore/Dynamic-JavaScript-Proxies.md)**. 所以你可以像调用**Javascript本地方法**一样使用任何**端点**. @@ -79,21 +77,21 @@ acme.bookStore.books.book.getList({}).done(function (result) { console.log(resul ![bookstore-getlist-result-network](images/bookstore-getlist-result-network.png) -Let's **create a new book** using the `create` function: - 让我们使用 `create` 函数**创建一本书**: ````js -acme.bookStore.books.book.create({ - name: 'Foundation', - type: 7, - publishDate: '1951-05-24', - price: 21.5 - }).then(function (result) { - console.log('successfully created the book with id: ' + result.id); +acme.bookStore.books.book.create({ + name: 'Foundation', + type: 7, + publishDate: '1951-05-24', + price: 21.5 + }).then(function (result) { + console.log('successfully created the book with id: ' + result.id); }); ```` +> 如果你下载了本教程的源代码并按照示例中的步骤操作,你需要传递`authorId`参数给创建方法以**创建一本新书**. + 您应该在控制台中看到类似以下的消息: ````text @@ -102,7 +100,7 @@ successfully created the book with id: 439b0ea8-923e-8e1e-5d97-39f2c7ac4246 检查数据库中的 `Books` 表你会看到新的一行. 你可以自己尝试使用 `get`, `update` 和 `delete` 函数. -我们将利用这些动态代理功能在接下来的章节来与服务器通信. +在接下来的章节,我们将利用这些动态代理函数与服务器通信. {{end}} @@ -112,7 +110,7 @@ successfully created the book with id: 439b0ea8-923e-8e1e-5d97-39f2c7ac4246 本地化文本位于 `Acme.BookStore.Domain.Shared` 项目的 `Localization/BookStore` 文件夹下: -![bookstore-localization-files](./images/bookstore-localization-files-v2.png) +![bookstore-localization-files](images/bookstore-localization-files-v2.png) 打开 `en.json` (*英文翻译*)文件并更改内容,如下所示: @@ -154,7 +152,7 @@ successfully created the book with id: 439b0ea8-923e-8e1e-5d97-39f2c7ac4246 * 为按钮项添加 `Menu:` 前缀. * 使用 `Enum::` 命名约定来本地化枚举成员. 当您这样做时ABP可以在某些适当的情况下自动将枚举本地化. -如果未在本地化文件中定义文本,则文本将**回退**到本地化键(作为ASP.NET Core的标准行为). +如果未在本地化文件中定义文本,则文本将**回退**到本地化键(ASP.NET Core的标准行为). > ABP本地化系统建立在[ASP.NET Core标准本地化](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization)系统之上,并以多种方式进行了扩展. 有关详细信息请参见[本地化文档](../Localization.md). @@ -162,7 +160,7 @@ successfully created the book with id: 439b0ea8-923e-8e1e-5d97-39f2c7ac4246 ## 创建图书页面 -是时候创建可见的和可用的东西了! 代替经典的MVC,我们将使用微软推荐的[Razor Pages UI](https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/razor-pages/razor-pages-start). +是时候创建可见的和可用的东西了! 我们将使用微软推荐的[Razor Pages UI](https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/razor-pages/razor-pages-start),而不是经典的MVC. 在 `Acme.BookStore.Web` 项目的 `Pages` 文件夹下创建一个名为新的 `Books` 的文件夹. 然后在文件夹右键选择 **添加 > Razor Page** 菜单. 输入名称 `Index`: @@ -189,13 +187,13 @@ namespace Acme.BookStore.Web.Pages.Books { public void OnGet() { - + } } } ``` -### 将Book页面添加到主菜单 +### 将图书页面添加到主菜单 打开 `Menus` 文件夹中的 `BookStoreMenuContributor` 类,在 `ConfigureMainMenuAsync` 方法的底部添加如下代码: @@ -223,9 +221,7 @@ context.Menu.AddItem( ### 图书列表 -We will use the [Datatables.net](https://datatables.net/) jQuery library to show the book list. Datatables library completely work via AJAX, it is fast, popular and provides a good user experience. - -我们将使用[Datatables.net](https://datatables.net/)JQuery插件来显示页面上的表格列表. [Datatables](https://datatables.net/)可以完全通过AJAX工作,速度快,并提供良好的用户体验. +我们将使用[Datatables.net](https://datatables.net/)JQuery插件来显示图书列表. [Datatables](https://datatables.net/)可以完全通过AJAX工作,速度快,并提供良好的用户体验. > Datatables插件在启动模板中配置,因此你可以直接在任何页面中使用它,无需在页面中引用样式和脚本文件. @@ -261,7 +257,7 @@ We will use the [Datatables.net](https://datatables.net/) jQuery library to show 在 `Pages/Books/` 文件夹中创建 `index.js`文件 -![bookstore-index-js-file](./images/bookstore-index-js-file-v3.png) +![bookstore-index-js-file](images/bookstore-index-js-file-v3.png) `index.js` 的内容如下: @@ -321,8 +317,8 @@ $(function () { ```` * `abp.localization.getResource` 获取一个函数,该函数用于使用服务器端定义的相同JSON文件对文本进行本地化. 通过这种方式你可以与客户端共享本地化值. -* `abp.libs.datatables.normalizeConfiguration`是另一个辅助方法.不是必须的, 但是它通过为缺少的选项提供常规值来简化数据表配置. -* `abp.libs.datatables.createAjax`是帮助ABP的动态JavaScript API代理跟[Datatable](https://datatables.net/)的格式相适应的辅助方法. +* `abp.libs.datatables.normalizeConfiguration`是一个辅助方法.不是必须的, 但是它通过为缺省的选项提供约定的值来简化[Datatables](https://datatables.net/)配置. +* `abp.libs.datatables.createAjax`是另一个辅助方法,用来适配ABP的动态JavaScript API代理和[Datatable](https://datatables.net/)期望的参数格式. * `acme.bookStore.books.book.getList` 是动态JavaScript代理函数(上面已经介绍过了) * [luxon](https://moment.github.io/luxon/) 库也是该解决方案中预先配置的标准库,你可以轻松地执行日期/时间操作. @@ -334,15 +330,13 @@ $(function () { ![Book list](images/bookstore-book-list-3.png) -这是一个完全正常工作的服务端分页,排序和本地化的图书列表. - -{{end}} +这是一个可以正常工作的,服务端分页,排序和本地化的图书列表. {{if UI == "NG"}} ## 安装NPM包 ->注意: 本教程基于ABP Framework v3.0.3+. 如果你的项目版本较旧,请升级您的解决方案. 如果要升级现有的v2.x项目,请参阅[迁移指南](../UI/Angular/Migration-Guide-v3.md). +>注意: 本教程基于ABP Framework v3.1.0+. 如果你的项目版本较旧,请升级您的解决方案. 如果要升级现有的v2.x项目,请参阅[迁移指南](../UI/Angular/Migration-Guide-v3.md). 在 `angular` 目录下打开命令行窗口,选择 `yarn` 命令安装NPM包: @@ -357,9 +351,7 @@ yarn - [Ng Bootstrap](https://ng-bootstrap.github.io/#/home) 用做UI组件库. - [ngx-datatable](https://swimlane.gitbook.io/ngx-datatable/) 用做 datatable 类库. -### BookModule - -运行以下命令创建一个名为 `BookModule` 的新模块: +运行以下命令在angular应用程序根目录创建一个名为 `BookModule` 的新模块: ```bash yarn ng generate module book --module app --routing --route books @@ -417,7 +409,7 @@ const routes: Routes = [ ]; ```` -现在打开 `src/app/route.provider.ts` 以下替换 `configureRoutes` 函数: +现在打开 `src/app/route.provider.ts` 替换 `configureRoutes` 函数为以下代码: ```js function configureRoutes(routes: RoutesService) { @@ -450,27 +442,31 @@ function configureRoutes(routes: RoutesService) { `RoutesService` 是ABP框架提供的用于配置主菜单和路由的服务. -* `path` 路由的URL. +* `path` 路由的URL. * `name` 菜单项的名称(参阅[本地化文档](../UI/Angular/Localization.md)了解更多). -* `iconClass` 菜单项的图标(你可以使用默认的[Font Awesome](https://fontawesome.com/)图标). -* `order` 菜单项的排序.我们定义了101,它显示在 "Administration" 项的后面. -* `layout` BooksModule路由的布局. 可以定义 `eLayoutType.application`, `eLayoutType.account` 或 `eLayoutType.empty`. +* `iconClass` 菜单项的图标(你可以使用默认的[Font Awesome](https://fontawesome.com/)图标). +* `order` 菜单项的排序. +* `layout` BooksModule路由的布局. (有三个预定义的布局类型: `eLayoutType.application`, `eLayoutType.account` 或 `eLayoutType.empty`). + +更多信息请参阅[RoutesService 文档](../UI/Angular/Modifying-the-Menu.md#via-routesservice). -更多信息请参阅[RoutesService 文档](https://docs.abp.io/en/abp/latest/UI/Angular/Modifying-the-Menu.md#via-routesservice). +### 生成服务代理 -### 生成代理 +[ABP CLI](../CLI.md) 提供 `generate-proxy` 命令为HTTP APIs生成客户端代理.有了这些代理,在客户端使用HTTP APIs变得更加方便. 运行 `generate-proxy` 命令前, 你的 host 必须正在运行. -ABP CLI提供了 `generate-proxy` 命令为你的服务HTTP API生成客户端代理简化客户端使用服务的成本. 运行 `generate-proxy` 命令前你的host必须正在运行. 参阅 [CLI 文档](../CLI.md). +> **警告**: 使用IIS Express时有一个问题; 它不允许从另一个进程连接应用程序. 如果你使用Visual Studio, 在运行按钮的下拉框中选择`Acme.BookStore.HttpApi.Host`,不要选择IIS Express, 如下图: -在 `angular` 文件夹下运行以下命令: +![vs-run-without-iisexpress](images/vs-run-without-iisexpress.png) + +启动host应用程序后,在 `angular` 文件夹下运行以下命令: ```bash abp generate-proxy -t ng ``` -生成的文件如下: +这个命令将在`/src/app/proxy/books`文件夹下产生以下文件: -![Generated files](./images/generated-proxies-2.png) +![Generated files](images/generated-proxies-3.png) ### BookComponent @@ -479,8 +475,7 @@ abp generate-proxy -t ng ```js import { ListService, PagedResultDto } from '@abp/ng.core'; import { Component, OnInit } from '@angular/core'; -import { BookDto } from './models'; -import { BookService } from './services'; +import { BookService, BookDto } from '@proxy/books'; @Component({ selector: 'app-book', @@ -494,7 +489,7 @@ export class BookComponent implements OnInit { constructor(public readonly list: ListService, private bookService: BookService) {} ngOnInit() { - const bookStreamCreator = (query) => this.bookService.getListByInput(query); + const bookStreamCreator = (query) => this.bookService.getList(query); this.list.hookToQuery(bookStreamCreator).subscribe((response) => { this.book = response; @@ -503,8 +498,8 @@ export class BookComponent implements OnInit { } ``` -* 我们注入了生成的 `BookService`. -* 我们实现了 [ListService](https://docs.abp.io/en/abp/latest/UI/Angular/List-Service),它是一个公用服务,提供了简单的分页,排序和搜索. +* 我们引入并注入了生成的 `BookService`. +* 我们使用 [ListService](../UI/Angular/List-Service.md),它是一个工具服务,提供了易用的分页,排序和搜索. 打开 `/src/app/book/book.component.html` 用以下内容替换它: @@ -545,9 +540,138 @@ export class BookComponent implements OnInit { 现在你可以在浏览器看到最终结果: -![Book list final result](./images/bookstore-book-list.png) +![图书列表最终结果](images/bookstore-book-list.png) -{{end}} +{{else if UI == "Blazor" || UI == "BlazorServer"}} + +## 创建图书页面 + +是时候创建可见和可用的东西了! 右击`Acme.BookStore.Blazor`项目下的`Pages`文件夹,新建一个名为`Books.razor`的**razor组件**. + +![blazor-add-books-component](images/blazor-add-books-component.png) + +用以下内容替换这个组件的内容: + +````html +@page "/books" + +

Books

+ +@code { + +} +```` + +### 将图书页面添加到主菜单 + +打开`Blazor`项目中的`BookStoreMenuContributor`类,在 `ConfigureMainMenuAsync` 方法的底部添加如下代码: + +````csharp +context.Menu.AddItem( + new ApplicationMenuItem( + "BooksStore", + l["Menu:BookStore"], + icon: "fa fa-book" + ).AddItem( + new ApplicationMenuItem( + "BooksStore.Books", + l["Menu:Books"], + url: "/books" + ) + ) +); +```` + +运行项目,使用用户名 `admin` 和密码 `1q2w3E*` 登录到应用程序. 看到新菜单项已添加到顶部栏: + +![blazor-menu-bookstore](images/blazor-menu-bookstore.png) + +点击BookStore下的Books子菜单项就会跳转到空的图书页面. + +### 图书列表 + +我们将使用[Blazorise library](https://blazorise.com/)作为UI组件.它是一个强大的库,支持主要的HTML/CSS框架,包括Bootstrap. + +ABP提供了一个通用的基类,`AbpCrudPageBase<...>`,用来创建CRUD风格的页面.这个基类兼容用来构建`IBookAppService`的`ICrudAppService`.所以我们从`AbpCrudPageBase`继承,获得标准CRUD的默认实现. + +打开`Books.razor` 并把内容修改成下面这样: + +````xml +@page "/books" +@using Volo.Abp.Application.Dtos +@using Acme.BookStore.Books +@using Acme.BookStore.Localization +@using Microsoft.Extensions.Localization +@inject IStringLocalizer L +@inherits AbpCrudPageBase + + + +

@L["Books"]

+
+ + + + + + + @L[$"Enum:BookType:{(int)context.Type}"] + + + + + @context.PublishDate.ToShortDateString() + + + + + + + @context.CreationTime.ToLongDateString() + + + + + +
+```` + +> 如果你可以编译并运行成功,但看到一些语法错误.你可以忽略这些错误,因为Visual Studio处理Blazor还有一些bug. + +* `AbpCrudPageBase`实现了所有的CRUD细节,我们从它继承. +* `Entities`, `TotalCount`, `PageSize`, `OnDataGridReadAsync`定义在基类中. +* 注入`IStringLocalizer` (作为`L`对象),用于本地化. + +虽然上面的代码非常容易理解,你仍然可以查看Blazorise [Card](https://blazorise.com/docs/components/card/)和[DataGrid](https://blazorise.com/docs/extensions/datagrid/)文档以更好地理解它们. + +#### 关于AbpCrudPageBase + +对于图书页面,我们将持续从`AbpCrudPageBase`获得益处. 你可以只注入`IBookAppService`并自己执行所有的服务端调用(感谢ABP的[动态C# HTTP API客户端代理](../API/Dynamic-CSharp-API-Clients.md)系统). + +## 运行最终应用程序 + +你可以运行应用程序!该部分的最终用户界面如下所示: + +![blazor-bookstore-book-list](images/blazor-bookstore-book-list.png) + +这是一个可以正常工作的,服务端分页,排序和本地化的图书列表. + +{{end # UI }} ## 下一章 diff --git a/docs/zh-Hans/Tutorials/Part-3.md b/docs/zh-Hans/Tutorials/Part-3.md index 90dd1326c3f..6a9740730d8 100644 --- a/docs/zh-Hans/Tutorials/Part-3.md +++ b/docs/zh-Hans/Tutorials/Part-3.md @@ -2,27 +2,10 @@ ````json //[doc-params] { - "UI": ["MVC","NG"], + "UI": ["MVC","Blazor","BlazorServer","NG"], "DB": ["EF","Mongo"] } ```` -{{ -if UI == "MVC" - UI_Text="mvc" -else if UI == "NG" - UI_Text="angular" -else - UI_Text="?" -end -if DB == "EF" - DB_Text="Entity Framework Core" -else if DB == "Mongo" - DB_Text="MongoDB" -else - DB_Text="?" -end -}} - ## 关于本教程 在本系列教程中, 你将构建一个名为 `Acme.BookStore` 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开发的: @@ -45,16 +28,30 @@ end ## 下载源码 -本教程根据你的**UI** 和 **Database**偏好有多个版,我们准备了两种可供下载的源码组合: +本教程根据你的**UI** 和 **数据库**偏好有多个版本,我们准备了几种可供下载的源码组合: * [MVC (Razor Pages) UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Mvc-EfCore) +* [Blazor UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore) * [Angular UI 与 MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb) +> 如果你在Windows中遇到 "文件名太长" or "解压错误", 很可能与Windows最大文件路径限制有关. Windows文件路径的最大长度为250字符. 为了解决这个问题,参阅 [在Windows 10中启用长路径](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later). + +> 如果你遇到与Git相关的长路径错误, 尝试使用下面的命令在Windows中启用长路径. 参阅 https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path +> `git config --system core.longpaths true` + +{{if UI == "MVC" && DB == "EF"}} + +### 视频教程 + +本章也被录制为视频教程 **发布在YouTube**. + +{{end}} + {{if UI == "MVC"}} ## 创建新书籍 -通过本节, 你将会了解如何创建一个 modal form 来实现新增书籍的功能. 最终成果如下图所示: +通过本节, 你将会了解如何创建一个 modal form 实现新增书籍的功能. model dialog将如下图所示: ![bookstore-create-dialog](./images/bookstore-create-dialog-2.png) @@ -66,7 +63,7 @@ end #### CreateModal.cshtml.cs -打开 `CreateModal.cshtml.cs` 代码文件,用如下代码替换 `CreateModalModel` 类的实现: +打开 `CreateModal.cshtml.cs` 代码文件(`CreateModalModel` 类),替换成以下代码: ````C# using System.Threading.Tasks; @@ -101,10 +98,10 @@ namespace Acme.BookStore.Web.Pages.Books } ```` -* 该类派生于 `BookStorePageModel` 而非默认的 `PageModel`. `BookStorePageModel` 继承了 `PageModel` 并且添加了一些可以被你的page model类使用的通用属性和方法. +* 该类派生于 `BookStorePageModel` 而非默认的 `PageModel`. `BookStorePageModel` 间接继承了 `PageModel` 并且添加了一些可以被你的page model类使用的通用属性和方法. * `Book` 属性上的 `[BindProperty]` 特性将post请求提交上来的数据绑定到该属性上. * 该类通过构造函数注入了 `IBookAppService` 应用服务,并且在 `OnPostAsync` 处理程序中调用了服务的 `CreateAsync` 方法. -* 它在 `OnGet` 方法中创建一个新的 `CreateUpdateBookDto` 对象。 ASP.NET Core不需要像这样创建一个新实例就可以正常工作. 但是它不会为你创建实例,并且如果你的类在类构造函数中具有一些默认值分配或代码执行,它们将无法工作. 对于这种情况,我们为某些 `CreateUpdateBookDto` 属性设置了默认值. +* 它在 `OnGet` 方法中创建一个新的 `CreateUpdateBookDto` 对象。 ASP.NET Core不需要像这样创建一个新实例就可以正常工作. 但是它不会为你创建实例,并且如果你的类在类构造函数中赋值一些默认值或执行一些代码,它们将无法工作. 对于这种情况,我们为某些 `CreateUpdateBookDto` 属性设置了默认值. #### CreateModal.cshtml @@ -134,10 +131,9 @@ namespace Acme.BookStore.Web.Pages.Books * 这个 modal 使用 `abp-dynamic-form` [tag Helper](../UI/AspNetCore/Tag-Helpers/Dynamic-Forms.md) 根据 `CreateBookViewModel` 类自动构建了表单. * `abp-model` 指定了 `Book` 属性为模型对象. -* `data-ajaxForm` 设置了表单通过AJAX提交,而不是经典的页面回发. * `abp-form-content` tag helper 作为表单控件渲染位置的占位符 (这是可选的,只有你在 `abp-dynamic-form` 中像本示例这样添加了其他内容才需要). -> 提示: 就像在本示例中一样,`Layout` 应该为 `null`,因为当通过AJAX加载模态时,我们不希望包括所有布局. +> 提示: 就像在本示例中一样,`Layout` 应该为 `null`,因为当通过AJAX加载模态窗口时,我们不希望包括所有布局. ### 添加 "New book" 按钮 @@ -195,9 +191,9 @@ namespace Acme.BookStore.Web.Pages.Books 如下图所示,只是在表格 **右上方** 添加了 **New book** 按钮: -![bookstore-new-book-button](./images/bookstore-new-book-button-2.png) +![bookstore-new-book-button](images/bookstore-new-book-button-2.png) -打开 `Pages/book/index.js` 在 `datatable` 配置代码后面添加如下代码: +打开 `Pages/Book/Index.js` 在 `datatable` 配置代码后面添加如下代码: ````js var createModal = new abp.ModalManager(abp.appPath + 'Books/CreateModal'); @@ -212,9 +208,9 @@ $('#NewBookButton').click(function (e) { }); ```` -* `abp.ModalManager` 是一个在客户端打开和管理modal的辅助类.它基于Twitter Bootstrap的标准modal组件通过简化的API抽象隐藏了许多细节. +* `abp.ModalManager` 是一个在客户端管理modal的辅助类.它内部使用了Twitter Bootstrap的标准modal组件,但通过简化的API抽象了许多细节. * `createModal.onResult(...)` 用于在创建书籍后刷新数据表格. -* `createModal.open();` 用于打开模态创建新书籍. +* `createModal.open();` 用于打开modal创建新书籍. `Index.js` 的内容最终如下所示: @@ -335,8 +331,8 @@ namespace Acme.BookStore.Web.Pages.Books } ```` -* `[HiddenInput]` 和 `[BindProperty]` 是标准的 ASP.NET Core MVC 特性.这里启用 `SupportsGet` 从Http请求的查询字符串中获取Id的值. -* 在 `OnGetAsync` 方法中,将 `BookAppService.GetAsync` 方法返回的 `BookDto` 映射成 `CreateUpdateBookDto` 并赋值给Book属性. +* `[HiddenInput]` 和 `[BindProperty]` 是标准的 ASP.NET Core MVC 特性.这里启用 `SupportsGet` 从Http请求的查询字符串参数中获取Id的值. +* 在 `OnGetAsync` 方法中, 我们从 `BookAppService` 获得 `BookDto` ,并将它映射成DTO对象 `CreateUpdateBookDto`. * `OnPostAsync` 方法直接使用 `BookAppService.UpdateAsync` 来更新实体. ### BookDto 到 CreateUpdateBookDto 对象映射 @@ -391,10 +387,10 @@ namespace Acme.BookStore.Web 这个页面内容和 `CreateModal.cshtml` 非常相似,除了以下几点: -* 它包含`id`属性的`abp-input`, 用于存储编辑书的 `id` (它是隐藏的Input) +* 它包含`id`属性的`abp-input`, 用于存储被编辑书籍的 `id` (它是隐藏的Input) * 此页面指定的post地址是`Books/EditModal`. -### 为表格添加 "操作(Actions)" 下拉菜单 +### 为表格添加 "操作(Actions)" 下拉菜单 我们将为表格每行添加下拉按钮 ("Actions"): @@ -516,9 +512,9 @@ $(function () { } ```` -* `confirmMessage` 用来在实际执行 `action` 之前向用户进行确认. -* 通过javascript代理方法 `acme.bookStore.books.book.delete(...)` 执行一个AJAX请求来删除一个book实体. -* `abp.notify.info` 用来在执行删除操作后显示一个toastr通知信息. +* `confirmMessage` 执行 `action` 前向用户进行确认. +* `acme.bookStore.books.book.delete(...)` 执行一个AJAX请求删除一个book. +* `abp.notify.info` 执行删除操作后显示一个通知信息. 由于我们使用了两个新的本地化文本(`BookDeletionConfirmationMessage`和`SuccesslyDeleted`),因此你需要将它们添加到本地化文件(`Acme.BookStore.Domain.Shared`项目的`Localization/BookStore`文件夹下的`en.json`): @@ -640,7 +636,7 @@ $(function () { ## 创建新书籍 -下面的章节中,你将学习到如何创建一个新的模态对话框来新增书籍. +下面的章节中,你将学习到如何创建一个新的模态窗口新增书籍. ### BookComponent @@ -649,8 +645,7 @@ $(function () { ```js import { ListService, PagedResultDto } from '@abp/ng.core'; import { Component, OnInit } from '@angular/core'; -import { BookDto } from './models'; -import { BookService } from './services'; +import { BookService, BookDto } from '@proxy/books'; @Component({ selector: 'app-book', @@ -666,7 +661,7 @@ export class BookComponent implements OnInit { constructor(public readonly list: ListService, private bookService: BookService) {} ngOnInit() { - const bookStreamCreator = (query) => this.bookService.getListByInput(query); + const bookStreamCreator = (query) => this.bookService.getList(query); this.list.hookToQuery(bookStreamCreator).subscribe((response) => { this.book = response; @@ -680,7 +675,8 @@ export class BookComponent implements OnInit { } ``` -* 我们定义了一个名为 `isModalOpen` 的变量和 `createBook` 方法. +* 我们定义了一个名为 `isModalOpen` 的属性和 `createBook` 方法. + 打开 `/src/app/book/book.component.html` 做以下更改: @@ -690,9 +686,9 @@ export class BookComponent implements OnInit {
{%{{{ '::Menu:Books' | abpLocalization }}}%}
-
+
- +
- +
@@ -726,11 +722,11 @@ export class BookComponent implements OnInit { ``` * 添加了 `New book` 按钮到卡片头部. -* 添加了 `abp-modal` 渲染模态框,允许用户创建新书. `abp-modal` 是显示模态框的预构建组件. 你也可以使用其它方法显示模态框,但 `abp-modal` 提供了一些附加的好处. +* 添加了 `abp-modal` 渲染模态框,允许用户创建新书. `abp-modal` 是显示模态框的预构建组件. 你也可以使用其它方法显示模态框,但 `abp-modal` 提供了一些额外的好处. 你可以打开浏览器,点击**New book**按钮看到模态框. -![Empty modal for new book](./images/bookstore-empty-new-book-modal.png) +![Empty modal for new book](images/bookstore-empty-new-book-modal.png) ### 添加响应式表单 @@ -741,8 +737,7 @@ export class BookComponent implements OnInit { ```js import { ListService, PagedResultDto } from '@abp/ng.core'; import { Component, OnInit } from '@angular/core'; -import { BookDto, BookType } from './models'; // add BookType -import { BookService } from './services'; +import { BookService, BookDto, bookTypeOptions } from '@proxy/books'; // add bookTypeOptions import { FormGroup, FormBuilder, Validators } from '@angular/forms'; // add this @Component({ @@ -756,12 +751,8 @@ export class BookComponent implements OnInit { form: FormGroup; // add this line - bookType = BookType; // add this line - // add bookTypes as a list of BookType enum members - bookTypes = Object.keys(this.bookType).filter( - (key) => typeof this.bookType[key] === 'number' - ); + bookTypes = bookTypeOptions; isModalOpen = false; @@ -772,7 +763,7 @@ export class BookComponent implements OnInit { ) {} ngOnInit() { - const bookStreamCreator = (query) => this.bookService.getListByInput(query); + const bookStreamCreator = (query) => this.bookService.getList(query); this.list.hookToQuery(bookStreamCreator).subscribe((response) => { this.book = response; @@ -800,7 +791,7 @@ export class BookComponent implements OnInit { return; } - this.bookService.createByInput(this.form.value).subscribe(() => { + this.bookService.create(this.form.value).subscribe(() => { this.isModalOpen = false; this.form.reset(); this.list.get(); @@ -809,12 +800,11 @@ export class BookComponent implements OnInit { } ``` -* 导入了 `FormGroup, FormBuilder and Validators`. +* 从` @angular/forms `导入了 `FormGroup, FormBuilder and Validators`. * 添加了 `form: FormGroup` 变量. -* 添加了 `bookType` 属性,你可以从模板中获取 `BookType` 枚举成员. * 添加了 `bookTypes` 属性作为 `BookType` 枚举成员列表. 将在表单选项中使用. -* 我们注入了 `fb: FormBuilder` 服务到构造函数. [FormBuilder](https://angular.io/api/forms/FormBuilder) 服务为生成控件提供了方便的方法. 它减少了构建复杂表单所需的样板文件的数量. -* 我们添加了 `buildForm` 方法到文件末尾, 在 `createBook` 方法调用 `buildForm()` 方法. 该方法创建一个响应式表单去创建新书. +* 我们注入了 `FormBuilder` 到构造函数. [FormBuilder](https://angular.io/api/forms/FormBuilder) 提供了简便的方法生成表单控件. 它减少了构建复杂表单所需的样板文件的数量. +* 我们添加了 `buildForm` 方法到文件末尾, 在 `createBook` 方法调用 `buildForm()` 方法. * 添加了`save` 方法. 打开 `/src/app/book/book.component.html`,使用以下内容替换 ` `: @@ -836,7 +826,7 @@ export class BookComponent implements OnInit { * @@ -897,13 +887,12 @@ export class BookModule { } * 我们导入了 `NgbDatepickerModule` 来使用日期选择器. -打开 `/src/app/book/book.component.ts` 使用以内内容替换: +打开 `/src/app/book/book.component.ts` 使用以下内容替换: ```js import { ListService, PagedResultDto } from '@abp/ng.core'; import { Component, OnInit } from '@angular/core'; -import { BookDto, BookType } from './models'; -import { BookService } from './services'; +import { BookService, BookDto, bookTypeOptions } from '@proxy/books'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; // added this line @@ -923,11 +912,7 @@ export class BookComponent implements OnInit { form: FormGroup; - bookType = BookType; - - bookTypes = Object.keys(this.bookType).filter( - (key) => typeof this.bookType[key] === 'number' - ); + bookTypes = bookTypeOptions; isModalOpen = false; @@ -938,7 +923,7 @@ export class BookComponent implements OnInit { ) {} ngOnInit() { - const bookStreamCreator = (query) => this.bookService.getListByInput(query); + const bookStreamCreator = (query) => this.bookService.getList(query); this.list.hookToQuery(bookStreamCreator).subscribe((response) => { this.book = response; @@ -964,7 +949,7 @@ export class BookComponent implements OnInit { return; } - this.bookService.createByInput(this.form.value).subscribe(() => { + this.bookService.create(this.form.value).subscribe(() => { this.isModalOpen = false; this.form.reset(); this.list.get(); @@ -974,11 +959,11 @@ export class BookComponent implements OnInit { ``` * 导入了 `NgbDateNativeAdapter` 和 `NgbDateAdapter`. -* 我们添加了一个新的 `NgbDateAdapter` 提供程序,它将Datepicker值转换为 `Date` 类型. 有关更多详细信息,请参见[datepicker adapters](https://ng-bootstrap.github.io/#/components/datepicker/overview). +* 我们添加了一个新的 `NgbDateAdapter` 提供程序,它将Datepicker值转换为 `Date` 类型. 更多详细信息,请参见[datepicker adapters](https://ng-bootstrap.github.io/#/components/datepicker/overview). 现在你可以打开浏览器看到以下变化: -![Save button to the modal](./images/bookstore-new-book-form-v2.png) +![Save button to the modal](images/bookstore-new-book-form-v2.png) ## 更新书籍 @@ -987,8 +972,7 @@ export class BookComponent implements OnInit { ```js import { ListService, PagedResultDto } from '@abp/ng.core'; import { Component, OnInit } from '@angular/core'; -import { BookDto, BookType, CreateUpdateBookDto } from './models'; -import { BookService } from './services'; +import { BookService, BookDto, bookTypeOptions } from '@proxy/books'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap'; @@ -1001,15 +985,11 @@ import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap export class BookComponent implements OnInit { book = { items: [], totalCount: 0 } as PagedResultDto; - selectedBook = new BookDto(); // declare selectedBook + selectedBook = {} as BookDto; // declare selectedBook form: FormGroup; - bookType = BookType; - - bookTypes = Object.keys(this.bookType).filter( - (key) => typeof this.bookType[key] === 'number' - ); + bookTypes = bookTypeOptions; isModalOpen = false; @@ -1020,7 +1000,7 @@ export class BookComponent implements OnInit { ) {} ngOnInit() { - const bookStreamCreator = (query) => this.bookService.getListByInput(query); + const bookStreamCreator = (query) => this.bookService.getList(query); this.list.hookToQuery(bookStreamCreator).subscribe((response) => { this.book = response; @@ -1028,14 +1008,14 @@ export class BookComponent implements OnInit { } createBook() { - this.selectedBook = new BookDto(); // reset the selected book + this.selectedBook = {} as BookDto; // reset the selected book this.buildForm(); this.isModalOpen = true; } // Add editBook method editBook(id: string) { - this.bookService.getById(id).subscribe((book) => { + this.bookService.get(id).subscribe((book) => { this.selectedBook = book; this.buildForm(); this.isModalOpen = true; @@ -1061,8 +1041,8 @@ export class BookComponent implements OnInit { } const request = this.selectedBook.id - ? this.bookService.updateByIdAndInput(this.form.value, this.selectedBook.id) - : this.bookService.createByInput(this.form.value); + ? this.bookService.update(this.selectedBook.id, this.form.value) + : this.bookService.create(this.form.value); request.subscribe(() => { this.isModalOpen = false; @@ -1074,10 +1054,10 @@ export class BookComponent implements OnInit { ``` * 我们声明了类型为 `BookDto` 的 `selectedBook` 变量. -* 我们添加了 `editBook` 方法, 根据给定图书 `Id` 设置 `selectedBook` 对象. +* 我们添加了 `editBook` 方法, 根据给定书籍 `Id` 设置 `selectedBook` 对象. * 我们替换了 `buildForm` 方法使用 `selectedBook` 数据创建表单. * 我们替换了 `createBook` 方法,设置 `selectedBook` 为空对象. -* 我们替换了 `save` 方法. +* 我们修改了 `save` 方法,同时处理新建和更新操作. ### 添加 "Actions" 下拉框到表格 @@ -1111,7 +1091,7 @@ export class BookComponent implements OnInit { 在表格的第一列添加了一个 "Actions" 下拉菜单,如下图所示: -![Action buttons](./images/bookstore-actions-buttons.png) +![Action buttons](images/bookstore-actions-buttons.png) 同时如下所示更改 `ng-template #abpHeader` 部分: @@ -1147,13 +1127,13 @@ constructor( delete(id: string) { this.confirmation.warn('::AreYouSureToDelete', '::AreYouSure').subscribe((status) => { if (status === Confirmation.Status.confirm) { - this.bookService.deleteById(id).subscribe(() => this.list.get()); + this.bookService.delete(id).subscribe(() => this.list.get()); } }); } ``` -* 我们注入了 `ConfirmationService`. +* 我们引入了 `ConfirmationService`. * 我们注入了 `ConfirmationService` 到构造函数. * 添加了 `delete` 方法. @@ -1161,6 +1141,7 @@ delete(id: string) { ### 添加删除按钮: + 打开 `/src/app/book/book.component.html` 修改 `ngbDropdownMenu` 添加删除按钮: ```html @@ -1174,14 +1155,445 @@ delete(id: string) { 最终操作下拉框UI看起来如下: -![bookstore-final-actions-dropdown](./images/bookstore-final-actions-dropdown.png) +![bookstore-final-actions-dropdown](images/bookstore-final-actions-dropdown.png) + +点击 `delete` 操作调用 `delete` 方法,然后显示一个确认弹层如下图所示. + +![bookstore-confirmation-popup](images/bookstore-confirmation-popup.png) + +{{end}} + +{{if UI == "Blazor" || UI == "BlazorServer"}} + +## 创建新书籍 + +通过本节, 你将会了解如何创建一个模态窗口实现新增书籍的功能. 因为我们已经从 `AbpCrudPageBase` 继承, 所以只需要开发视图部分. + +### 添加 "New Button" 按钮 + +打开 `Books.razor` 替换 `` 部分为以下代码: + +````xml + + + +

@L["Books"]

+
+ + + +
+
+```` + +如下图所示,卡片头 **右侧** 添加了 **New book** 按钮: + +![blazor-add-book-button](images/blazor-add-book-button.png) + +现在, 我们可以添加点击按钮后打开的模态窗口了. + +### 书籍创建模态窗口 + +打开 `Books.razor`, 添加以下代码到页面底部: + +````xml + + + +
+ + @L["NewBook"] + + + + + + + @L["Name"] + + + + + + + + + @L["Type"] + + + + @L["PublishDate"] + + + + @L["Price"] + + + + + + + + +
+
+
+```` + +这段代码需要一个服务; 在文件顶部, `@inherits...` 行前, 注入 `AbpBlazorMessageLocalizerHelper`: + +````csharp +@inject AbpBlazorMessageLocalizerHelper LH +```` + +* 表单实现了验证功能, `AbpBlazorMessageLocalizerHelper` 用于本地化验证消息. +* `CreateModal` 对象, `CloseCreateModalAsync` 和 `CreateEntityAsync` 方法定义在基类中. 参阅 [Blazorise文档](https://blazorise.com/docs/) 以深入理解 `Modal` 和其它组件. + +这就是全部了. 运行应用程序, 尝试添加一本新书. + +![blazor-new-book-modal](images/blazor-new-book-modal.png) + +## 更新书籍 + +编辑书籍与新建书籍很类似. -点击 `delete` 动作调用 `delete` 方法,然后无法显示一个确认弹层如下图所示. +### 操作下拉菜单 -![bookstore-confirmation-popup](./images/bookstore-confirmation-popup.png) +打开 `Books.razor` , 在 `DataGridColumns` 中添加以下 `DataGridEntityActionsColumn` 作为第一项: + +````xml + + + + + + + +```` + +* `OpenEditModalAsync` 定义在基类中, 它接收实体(书籍)参数, 编辑这个实体. + +`DataGridEntityActionsColumn` 组件用于显示 `DataGrid` 每一行中的"操作" 下拉菜单. 如果其中只有唯一的操作, `DataGridEntityActionsColumn` 显示 **唯一按钮**, 而不是下拉菜单. + +![blazor-edit-book-action](images/blazor-edit-book-action-2.png) + +### 编辑模态窗口 + +我们现在可以定义一个模态窗口编辑书籍. 加入下面的代码到 `Books.razor` 页面的底部: + +````xml + + + +
+ + @EditingEntity.Name + + + + + + + @L["Name"] + + + + + + + + + @L["Type"] + + + + @L["PublishDate"] + + + + @L["Price"] + + + + + + + + +
+
+
+```` + +### AutoMapper 配置 + +基类 `AbpCrudPageBase` 使用 [对象到对象映射](../Object-To-Object-Mapping.md) 系统将 `BookDto` 对象转化为`CreateUpdateBookDto` 对象. 因此, 我们需要定义映射. + +打开 `Acme.BookStore.Blazor` 项目中的 `BookStoreBlazorAutoMapperProfile `, 替换成以下内容: + +````csharp +using Acme.BookStore.Books; +using AutoMapper; + +namespace Acme.BookStore.Blazor +{ + public class BookStoreBlazorAutoMapperProfile : Profile + { + public BookStoreBlazorAutoMapperProfile() + { + CreateMap(); + } + } +} +```` + +* `CreateMap();` 行用于定义映射. + +### 测试编辑模态窗口 + +你可以运行程序并尝试编辑一本书. + +![blazor-edit-book-modal](images/blazor-edit-book-modal.png) + +> 提示: 尝试保留 *Name* 字段为空并提交表单, 将显示验证错误消息. + +## 删除书籍 + +打开 `Books.razor` 页面, 在 `EntityActions` 中的"编辑" 操作下面加入以下的 `EntityAction`: + +````xml + +```` + +* `DeleteEntityAsync` 定义在基类中. 通过向服务器发起请求删除实体. +* `ConfirmationMessage` 执行操作前显示确认消息的回调函数. +* `GetDeleteConfirmationMessage` 定义在基类中. 你可以覆写这个方法 (或传递其它值给 `ConfirmationMessage` 参数) 以定制本地化消息. + +因为"操作" 按钮现在有了两个操作, 变成了下拉菜单: + +![blazor-edit-book-action](images/blazor-delete-book-action.png) + +运行程序并尝试删除一本书. + +## 完整的 CRUD UI 代码 + +下面是完整的创建图书管理CRUD页面的代码, 这些代码在上面是分成两部分开发的: + +````xml +@page "/books" +@using Volo.Abp.Application.Dtos +@using Acme.BookStore.Books +@using Acme.BookStore.Localization +@using Microsoft.Extensions.Localization +@using Volo.Abp.AspNetCore.Components.Web +@inject IStringLocalizer L +@inject AbpBlazorMessageLocalizerHelper LH +@inherits AbpCrudPageBase + + + + + +

@L["Books"]

+
+ + + +
+
+ + + + + + + + + + + + + + + @L[$"Enum:BookType:{(int) context.Type}"] + + + + + @context.PublishDate.ToShortDateString() + + + + + + + @context.CreationTime.ToLongDateString() + + + + + +
+ + + + +
+ + @L["NewBook"] + + + + + + + @L["Name"] + + + + + + + + + @L["Type"] + + + + @L["PublishDate"] + + + + @L["Price"] + + + + + + + + +
+
+
+ + + + +
+ + @EditingEntity.Name + + + + + + + @L["Name"] + + + + + + + + + @L["Type"] + + + + @L["PublishDate"] + + + + @L["Price"] + + + + + + + + +
+
+
+```` {{end}} ## 下一章 -查看本教程的[下一章](Part-4.md). +查看本教程的[下一章](Part-4.md). \ No newline at end of file diff --git a/docs/zh-Hans/Tutorials/Part-4.md b/docs/zh-Hans/Tutorials/Part-4.md index 151c7aab900..e570880a228 100644 --- a/docs/zh-Hans/Tutorials/Part-4.md +++ b/docs/zh-Hans/Tutorials/Part-4.md @@ -2,27 +2,10 @@ ````json //[doc-params] { - "UI": ["MVC","NG"], + "UI": ["MVC","Blazor","BlazorServer","NG"], "DB": ["EF","Mongo"] } ```` -{{ -if UI == "MVC" - UI_Text="mvc" -else if UI == "NG" - UI_Text="angular" -else - UI_Text="?" -end -if DB == "EF" - DB_Text="Entity Framework Core" -else if DB == "Mongo" - DB_Text="MongoDB" -else - DB_Text="?" -end -}} - ## 关于本教程 在本系列教程中, 你将构建一个名为 `Acme.BookStore` 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开发的: @@ -45,16 +28,32 @@ end ## 下载源码 -本教程根据你的**UI** 和 **Database**偏好有多个版,我们准备了两种可供下载的源码组合: +本教程根据你的**UI** 和 **数据库**偏好有多个版本,我们准备了几种可供下载的源码组合: * [MVC (Razor Pages) UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Mvc-EfCore) +* [Blazor UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore) * [Angular UI 与 MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb) +> 如果你在Windows中遇到 "文件名太长" or "解压错误", 很可能与Windows最大文件路径限制有关. Windows文件路径的最大长度为250字符. 为了解决这个问题,参阅 [在Windows 10中启用长路径](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later). + +> 如果你遇到与Git相关的长路径错误, 尝试使用下面的命令在Windows中启用长路径. 参阅 https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path +> `git config --system core.longpaths true` + +{{if UI == "MVC" && DB == "EF"}} + +### 视频教程 + +本章也被录制为视频教程 **发布在YouTube**. + +{{end}} + ## 解决方案中的测试项目 这一部分涵盖了 **服务器端** 测试. 解决方案中有多个测试项目: -![bookstore-test-projects-v2](./images/bookstore-test-projects-{{UI_Text}}.png) +![bookstore-test-projects-v2](./images/bookstore-test-projects-mvc.png) + +> 根据你选择的UI和数据库, 测试项目略微有所不同. 例如, 如果选择MongoDB, 那么 `Acme.BookStore.EntityFrameworkCore.Tests` 会变为 `Acme.BookStore.MongoDB.Tests`. 每个项目用于测试相关的应用程序项目.测试项目使用以下库进行测试: @@ -64,11 +63,11 @@ end {{if DB=="EF"}} -> 测试项目配置为使用 **SQLite内存** 作为数据库. 创建一个单独的数据库实例并使用数据种子系统进行初始化种子数据,为每个测试准备一个新的数据库. +> 测试项目配置为使用 **SQLite内存** 作为数据库. 创建一个单独的数据库实例并使用[数据种子系统](../Data-Seeding.md)初始化种子数据,为每个测试准备一个新的数据库. {{else if DB=="Mongo"}} -> **[Mongo2Go](https://github.com/Mongo2Go/Mongo2Go)**库用于模拟MongoDB数据库. 创建一个单独的数据库实例并使用数据种子系统进行初始化种子数据,为每个测试准备一个新的数据库. +> **[Mongo2Go](https://github.com/Mongo2Go/Mongo2Go)**库用于模拟MongoDB数据库. 创建一个单独的数据库实例并使用[数据种子系统](../Data-Seeding.md)初始化种子数据,为每个测试准备一个新的数据库. {{end}} @@ -78,12 +77,15 @@ end ## 测试 BookAppService -在 `Acme.BookStore.Application.Tests` 项目中创建一个名叫 `BookAppService_Tests` 的测试类: +在 `Acme.BookStore.Application.Tests` 项目的 `Books` 命名空间(文件夹)中创建一个名叫 `BookAppService_Tests` 的测试类: ````csharp +using System; +using System.Linq; using System.Threading.Tasks; using Shouldly; using Volo.Abp.Application.Dtos; +using Volo.Abp.Validation; using Xunit; namespace Acme.BookStore.Books @@ -129,7 +131,7 @@ public async Task Should_Create_A_Valid_Book() { Name = "New test book 42", Price = 10, - PublishDate = System.DateTime.Now, + PublishDate = DateTime.Now, Type = BookType.ScienceFiction } ); @@ -201,7 +203,7 @@ namespace Acme.BookStore.Books result.TotalCount.ShouldBeGreaterThan(0); result.Items.ShouldContain(b => b.Name == "1984"); } - + [Fact] public async Task Should_Create_A_Valid_Book() { @@ -211,7 +213,7 @@ namespace Acme.BookStore.Books { Name = "New test book 42", Price = 10, - PublishDate = System.DateTime.Now, + PublishDate = DateTime.Now, Type = BookType.ScienceFiction } ); @@ -220,7 +222,7 @@ namespace Acme.BookStore.Books result.Id.ShouldNotBe(Guid.Empty); result.Name.ShouldBe("New test book 42"); } - + [Fact] public async Task Should_Not_Create_A_Book_Without_Name() { @@ -244,7 +246,7 @@ namespace Acme.BookStore.Books } ```` -打开**测试资源管理器**(测试 -> Windows -> 测试资源管理器)并**执行**所有测试: +打开**测试资源管理器**(测试 -> Windows -> 测试资源管理器)并**执行所有**测试: ![bookstore-appservice-tests](./images/bookstore-appservice-tests.png) @@ -252,4 +254,4 @@ namespace Acme.BookStore.Books ## 下一章 -查看本教程的[下一章](Part-5.md). \ No newline at end of file +查看本教程的[下一章](Part-5.md). diff --git a/docs/zh-Hans/Tutorials/Part-5.md b/docs/zh-Hans/Tutorials/Part-5.md index 602306c484d..be687a6cb92 100644 --- a/docs/zh-Hans/Tutorials/Part-5.md +++ b/docs/zh-Hans/Tutorials/Part-5.md @@ -1 +1,635 @@ -TODO.. \ No newline at end of file +# Web应用程序开发教程 - 第五章: 授权 +````json +//[doc-params] +{ + "UI": ["MVC","Blazor","BlazorServer","NG"], + "DB": ["EF","Mongo"] +} +```` +## 关于本教程 + +在本系列教程中, 你将构建一个名为 `Acme.BookStore` 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开发的: + +* **{{DB_Text}}** 做为ORM提供程序. +* **{{UI_Value}}** 做为UI框架. + +本教程分为以下部分: + +- [Part 1: 创建服务端](Part-1.md) +- [Part 2: 图书列表页面](Part-2.md) +- [Part 3: 创建,更新和删除图书](Part-2.md) +- [Part 4: 集成测试](Part-4.md) +- **Part 5: 授权**(本章) +- [Part 6: 作者: 领域层](Part-6.md) +- [Part 7: 作者: 数据库集成](Part-7.md) +- [Part 8: 作者: 应用服务层](Part-8.md) +- [Part 9: 作者: 用户页面](Part-9.md) +- [Part 10: 图书到作者的关系](Part-10.md) + +## 下载源码 + +本教程根据你的**UI** 和 **数据库**偏好有多个版本,我们准备了几种可供下载的源码组合: + +* [MVC (Razor Pages) UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Mvc-EfCore) +* [Blazor UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore) +* [Angular UI 与 MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb) + +> 如果你在Windows中遇到 "文件名太长" or "解压错误", 很可能与Windows最大文件路径限制有关. Windows文件路径的最大长度为250字符. 为了解决这个问题,参阅 [在Windows 10中启用长路径](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later). + +> 如果你遇到与Git相关的长路径错误, 尝试使用下面的命令在Windows中启用长路径. 参阅 https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path +> `git config --system core.longpaths true` + +{{if UI == "MVC" && DB == "EF"}} + +### 视频教程 + +本章也被录制为视频教程 **发布在YouTube**. + +{{end}} + +## 权限 + +ABP框架提供了一个基于ASP.NET Core[授权基础架构](https://docs.microsoft.com/en-us/aspnet/core/security/authorization/introduction)的[授权系统](../Authorization.md). 基于标准授权基础架构的一个主要功能是添加了 **权限系统**, 这个系统允许定义权限并且根据角色, 用户或客户端启用/禁用权限. + +### 权限名称 + +权限必须有唯一的名称 (一个 `字符串`). 最好的方法是把它定义为一个 `常量`, 这样我们就可以重用这个权限名称了. + +打开 `Acme.BookStore.Application.Contracts` 项目中的 `BookStorePermissions` 类 (位于 `Permissions` 文件夹) 并替换为以下代码: + +````csharp +namespace Acme.BookStore.Permissions +{ + public static class BookStorePermissions + { + public const string GroupName = "BookStore"; + + public static class Books + { + public const string Default = GroupName + ".Books"; + public const string Create = Default + ".Create"; + public const string Edit = Default + ".Edit"; + public const string Delete = Default + ".Delete"; + } + } +} +```` + +权限名称具有层次结构. 例如, "创建图书" 权限被定义为 `BookStore.Books.Create`. ABP不强制必须如此, 但这是一种有益的做法. + +### 权限定义 + +在使用权限前必须定义它们. + +打开 `Acme.BookStore.Application.Contracts` 项目中的 `BookStorePermissionDefinitionProvider` 类 (位于 `Permissions` 文件夹) 并替换为以下代码: + +````csharp +using Acme.BookStore.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace Acme.BookStore.Permissions +{ + public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider + { + public override void Define(IPermissionDefinitionContext context) + { + var bookStoreGroup = context.AddGroup(BookStorePermissions.GroupName, L("Permission:BookStore")); + + var booksPermission = bookStoreGroup.AddPermission(BookStorePermissions.Books.Default, L("Permission:Books")); + booksPermission.AddChild(BookStorePermissions.Books.Create, L("Permission:Books.Create")); + booksPermission.AddChild(BookStorePermissions.Books.Edit, L("Permission:Books.Edit")); + booksPermission.AddChild(BookStorePermissions.Books.Delete, L("Permission:Books.Delete")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} +```` + +这个类定义了一个 **权限组** (在UI上分组权限, 下文会看到) 和 权限组中的**4个权限**. 而且, **创建**, **编辑** 和 **删除** 是 `BookStorePermissions.Books.Default` 权限的子权限. **仅当父权限被选择**时, 子权限才能被选择. + +最后, 编辑本地化文件 (`Acme.BookStore.Domain.Shared` 项目的 `Localization/BookStore` 文件夹中的 `en.json`) 定义上面使用的本地化键: + +````json +"Permission:BookStore": "Book Store", +"Permission:Books": "Book Management", +"Permission:Books.Create": "Creating new books", +"Permission:Books.Edit": "Editing the books", +"Permission:Books.Delete": "Deleting the books" +```` + +> 本地化键名可以是任意的, 并没有强制的规则. 但我们推荐上面使用的约定. + +### 权限管理界面 + +完成权限定义后, 可以在**权限管理模态窗口**看到它们. + +在*管理 -> Identity -> 角色* 页面, 选择admin角色的 *权限* 操作, 打开权限管理模态窗口: + +![bookstore-permissions-ui](images/bookstore-permissions-ui.png) + +授予你希望的权限并保存. + +> **提示**: 如果运行 `Acme.BookStore.DbMigrator` 应用程序, 新权限会被自动授予admin. + +## 授权 + +现在, 你可以使用权限授权图书管理. + +### 应用层 和 HTTP API + +打开 the `BookAppService` 类, 设置策略名称为上面定义的权限名称. + +````csharp +using System; +using Acme.BookStore.Permissions; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace Acme.BookStore.Books +{ + public class BookAppService : + CrudAppService< + Book, //The Book entity + BookDto, //Used to show books + Guid, //Primary key of the book entity + PagedAndSortedResultRequestDto, //Used for paging/sorting + CreateUpdateBookDto>, //Used to create/update a book + IBookAppService //implement the IBookAppService + { + public BookAppService(IRepository repository) + : base(repository) + { + GetPolicyName = BookStorePermissions.Books.Default; + GetListPolicyName = BookStorePermissions.Books.Default; + CreatePolicyName = BookStorePermissions.Books.Create; + UpdatePolicyName = BookStorePermissions.Books.Edit; + DeletePolicyName = BookStorePermissions.Books.Delete; + } + } +} +```` + +加入代码到构造器. 基类中的 `CrudAppService` 自动在CRUD操作中使用这些权限. 这不仅实现了 **应用服务** 的安全性, 也实现了 **HTTP API** 安全性, 因为如前解释的, HTTP API 自动使用这些服务. (参阅 [自动 API controllers](../API/Auto-API-Controllers.md)). + +> 在稍后开发作者管理功能时, 你将会看到声明式授权, 使用 `[Authorize(...)]` 特性. + +{{if UI == "MVC"}} + +### Razor 页面 + +虽然安全的 HTTP API和应用服务阻止未授权用户使用服务, 但他们依然可以导航到图书管理页面. 虽然当页面发起第一个访问服务器的AJAX请求时会收到授权异常, 但为了更好的用户体验和安全性, 我们应该对页面进行授权. + +打开 `BookStoreWebModule` 在 `ConfigureServices` 方法中加入以下代码: + +````csharp +Configure(options => +{ + options.Conventions.AuthorizePage("/Books/Index", BookStorePermissions.Books.Default); + options.Conventions.AuthorizePage("/Books/CreateModal", BookStorePermissions.Books.Create); + options.Conventions.AuthorizePage("/Books/EditModal", BookStorePermissions.Books.Edit); +}); +```` + +现在未授权用户会被重定向至**登录页面**. + +#### 隐藏新建图书按钮 + +图书管理页面有一个 *新建图书* 按钮, 当用户没有 *图书新建* 权限时就不可见的. + +![bookstore-new-book-button-small](images/bookstore-new-book-button-small.png) + +打开 the `Pages/Books/Index.cshtml` 文件, 替换内容为以下代码: + +````html +@page +@using Acme.BookStore.Localization +@using Acme.BookStore.Permissions +@using Acme.BookStore.Web.Pages.Books +@using Microsoft.AspNetCore.Authorization +@using Microsoft.Extensions.Localization +@model IndexModel +@inject IStringLocalizer L +@inject IAuthorizationService AuthorizationService +@section scripts +{ + +} + + + + + + @L["Books"] + + + @if (await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Create)) + { + + } + + + + + + + +```` + +* 加入 `@inject IAuthorizationService AuthorizationService` 以访问授权服务. +* 使用 `@if (await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Create))` 检查图书创建权限, 条件显示 *新建图书* 按钮. + +### JavaScript端 + +图书管理页面中的图书表格每行都有操作按钮. 操作按钮包括 *编辑* 和 *删除* 操作: + +![bookstore-edit-delete-actions](images/bookstore-edit-delete-actions.png) + +如果用户没有权限, 应该隐藏相关的操作. 表格行中的操作有一个 `visible` 属性, 可以设置为 `false` 隐藏操作项. + +打开 `Acme.BookStore.Web` 项目中的 `Pages/Books/Index.js`, 为 `编辑` 操作加入 `visible` 属性: + +````js +{ + text: l('Edit'), + visible: abp.auth.isGranted('BookStore.Books.Edit'), //CHECK for the PERMISSION + action: function (data) { + editModal.open({ id: data.record.id }); + } +} +```` + +对 `Delete` 操作进行同样的操作: + +````js +visible: abp.auth.isGranted('BookStore.Books.Delete') +```` + +* `abp.auth.isGranted(...)` 检查前面定义的权限. +* `visible` 也可以是一个返回 `bool` 值的函数. 这个函数可以稍后根据某些条件计算. + +### 菜单项 + +即使我们在图书管理页面的所有层都控制了权限, 应用程序的主菜单依然会显示. 我们应该隐藏用户没有权限的菜单项. + +打开 `BookStoreMenuContributor` 类, 找到下面的代码: + +````csharp +context.Menu.AddItem( + new ApplicationMenuItem( + "BooksStore", + l["Menu:BookStore"], + icon: "fa fa-book" + ).AddItem( + new ApplicationMenuItem( + "BooksStore.Books", + l["Menu:Books"], + url: "/Books" + ) + ) +); +```` + +替换为以下代码: + +````csharp +var bookStoreMenu = new ApplicationMenuItem( + "BooksStore", + l["Menu:BookStore"], + icon: "fa fa-book" +); + +context.Menu.AddItem(bookStoreMenu); + +//CHECK the PERMISSION +if (await context.IsGrantedAsync(BookStorePermissions.Books.Default)) +{ + bookStoreMenu.AddItem(new ApplicationMenuItem( + "BooksStore.Books", + l["Menu:Books"], + url: "/Books" + )); +} +```` + +你需要为 `ConfigureMenuAsync` 方法加入 `async` 关键字, 并重新组织返回值. 最终的 `BookStoreMenuContributor` 类应该如下: + +````csharp +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using Acme.BookStore.Localization; +using Acme.BookStore.MultiTenancy; +using Acme.BookStore.Permissions; +using Volo.Abp.TenantManagement.Web.Navigation; +using Volo.Abp.UI.Navigation; + +namespace Acme.BookStore.Web.Menus +{ + public class BookStoreMenuContributor : IMenuContributor + { + public async Task ConfigureMenuAsync(MenuConfigurationContext context) + { + if (context.Menu.Name == StandardMenus.Main) + { + await ConfigureMainMenuAsync(context); + } + } + + private async Task ConfigureMainMenuAsync(MenuConfigurationContext context) + { + if (!MultiTenancyConsts.IsEnabled) + { + var administration = context.Menu.GetAdministration(); + administration.TryRemoveMenuItem(TenantManagementMenuNames.GroupName); + } + + var l = context.GetLocalizer(); + + context.Menu.Items.Insert(0, new ApplicationMenuItem("BookStore.Home", l["Menu:Home"], "~/")); + + var bookStoreMenu = new ApplicationMenuItem( + "BooksStore", + l["Menu:BookStore"], + icon: "fa fa-book" + ); + + context.Menu.AddItem(bookStoreMenu); + + //CHECK the PERMISSION + if (await context.IsGrantedAsync(BookStorePermissions.Books.Default)) + { + bookStoreMenu.AddItem(new ApplicationMenuItem( + "BooksStore.Books", + l["Menu:Books"], + url: "/Books" + )); + } + } + } +} +```` + +{{else if UI == "NG"}} + +### Angular Guard 配置 + +UI的第一步是防止未认证用户看见"图书"菜单项并进入图书管理页面. + +打开 `/src/app/book/book-routing.module.ts` 替换为以下代码: + +````js +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { AuthGuard, PermissionGuard } from '@abp/ng.core'; +import { BookComponent } from './book.component'; + +const routes: Routes = [ + { path: '', component: BookComponent, canActivate: [AuthGuard, PermissionGuard] }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class BookRoutingModule {} +```` + +* 从 `@abp/ng.core` 引入 `AuthGuard` 和 `PermissionGuard`. +* 在路由定义中添加 `canActivate: [AuthGuard, PermissionGuard]`. + +打开 `/src/app/route.provider.ts`, 在 `/books` 路由中添加 `requiredPolicy: 'BookStore.Books'`. `/books` 路由应该如以下配置: + +````js +{ + path: '/books', + name: '::Menu:Books', + parentName: '::Menu:BookStore', + layout: eLayoutType.application, + requiredPolicy: 'BookStore.Books', +} +```` + +### 隐藏新建图书按钮 + +当用户没有 *图书新建* 权限时, 图书管理页面上的 *新建图书* 按钮应该不可见. + +![bookstore-new-book-button-small](images/bookstore-new-book-button-small.png) + +打开 `/src/app/book/book.component.html` 文件, 替换创建按钮的HTML内容如下: + +````html + + +```` + +* 加入 `*abpPermission="'BookStore.Books.Create'"`, 当用户没有权限时隐藏按钮. + +### 隐藏编辑和删除操作 + +图书管理页面中的图书表格每行都有操作按钮. 操作按钮包括 *编辑* 和 *删除* 操作: + +![bookstore-edit-delete-actions](images/bookstore-edit-delete-actions.png) + +如果用户没有权限, 应该隐藏相关的操作. + +打开 `/src/app/book/book.component.html` 文件, 替换编辑和删除按钮的内容如下: + +````html + + + + + +```` + +* 加入 `*abpPermission="'BookStore.Books.Create'"`, 当用户没有编辑权限时隐藏按钮. +* 加入 `*abpPermission="'BookStore.Books.Delete'"`, 当用户没有删除权限时隐藏按钮. + +{{else if UI == "Blazor"}} + +### Razor验证组件 + +打开 `Acme.BookStore.Blazor` 项目中的 `/Pages/Books.razor` 文件, 在` @page` 指令和命名空间引入(`@using` 行)后添加 `Authorize` 特性, 如下所示: + +````html +@page "/books" +@attribute [Authorize(BookStorePermissions.Books.Default)] +@using Acme.BookStore.Permissions +@using Microsoft.AspNetCore.Authorization +... +```` + +添加这个特性阻止未登录用户或未授权用户访问这个页面. 用户重试后, 会被重定向到登录页面. + +### 显示/隐藏操作 + +图书管理页面上的每一种图书都有 *新建* 按钮和 *编辑*, *删除* 操作. 如果用户没有相关权限, 这些按钮/操作应该被隐藏. + +基类 `AbpCrudPageBase` 已经具有这些操作需要的功能. + +#### 设置策略 (权限) 名称 + +加入以下代码到 `Books.razor` 文件结尾: + +````csharp +@code +{ + public Books() // Constructor + { + CreatePolicyName = BookStorePermissions.Books.Create; + UpdatePolicyName = BookStorePermissions.Books.Edit; + DeletePolicyName = BookStorePermissions.Books.Delete; + } +} +```` + +基类 `AbpCrudPageBase` 自动检查相关操作的权限. 如果需要手动检查, 它也定义了相应的属性. + +* `HasCreatePermission`: True, 如果用户具有新建实体的权限. +* `HasUpdatePermission`: True, 如果用户具有编辑/更新实体的权限. +* `HasDeletePermission`: True, 如果用户具有删除实体的权限. + +> **Blazor 提示**: 当添加少量代码到 `@code` 是没有问题的. 当添加的代码变长时, 建议使用代码后置方法以便于维护. 我们将在作者部分使用这个方法. + +#### 隐藏新建图书按钮 + +检查 *新建图书* 按钮权限: + +````xml +@if (HasCreatePermission) +{ + +} +```` + +#### 隐藏编辑/删除操作 + +`EntityAction` 组件定义了 `Visible` 属性 (参数) 以条件显示操作. + +更新 `EntityActions` 部分: + +````xml + + + + +```` + +#### 关于权限缓存 + +你可以运行和测试权限. 从admin角色中移除一个图书相关权限, 观察到相关按钮/操作从UI上消失. + +在客户端, **ABP框架缓存当前用户的权限** . 所以, 当你修改了你的权限, 你需要手工 **刷新页面**. 如果不刷新并试图使用被禁的操作, 你会从服务器收到一个HTTP 403 (forbidden) 响应. + +> 修改角色或用户的权限在服务端立即生效. 所以, 缓存系统不会导致安全问题. + +### 菜单项 + +即使我们在图书管理页面的所有层都控制了权限, 应用程序的主菜单依然会显示. 我们应该隐藏用户没有权限的菜单项. + +打开 `Acme.BookStore.Blazor` 项目中的 `BookStoreMenuContributor` 类, 找到以下代码: + +````csharp +context.Menu.AddItem( + new ApplicationMenuItem( + "BooksStore", + l["Menu:BookStore"], + icon: "fa fa-book" + ).AddItem( + new ApplicationMenuItem( + "BooksStore.Books", + l["Menu:Books"], + url: "/books" + ) + ) +); +```` + +替换为以下代码: + +````csharp +var bookStoreMenu = new ApplicationMenuItem( + "BooksStore", + l["Menu:BookStore"], + icon: "fa fa-book" +); + +context.Menu.AddItem(bookStoreMenu); + +//CHECK the PERMISSION +if (await context.IsGrantedAsync(BookStorePermissions.Books.Default)) +{ + bookStoreMenu.AddItem(new ApplicationMenuItem( + "BooksStore.Books", + l["Menu:Books"], + url: "/books" + )); +} +```` + +你需要为 `ConfigureMenuAsync` 方法加入 `async` 关键字并重新整理返回值. 最终的 `ConfigureMainMenuAsync` 方法如下: + +````csharp +private async Task ConfigureMainMenuAsync(MenuConfigurationContext context) +{ + var l = context.GetLocalizer(); + + context.Menu.Items.Insert( + 0, + new ApplicationMenuItem( + "BookStore.Home", + l["Menu:Home"], + "/", + icon: "fas fa-home" + ) + ); + + var bookStoreMenu = new ApplicationMenuItem( + "BooksStore", + l["Menu:BookStore"], + icon: "fa fa-book" + ); + + context.Menu.AddItem(bookStoreMenu); + + //CHECK the PERMISSION + if (await context.IsGrantedAsync(BookStorePermissions.Books.Default)) + { + bookStoreMenu.AddItem(new ApplicationMenuItem( + "BooksStore.Books", + l["Menu:Books"], + url: "/books" + )); + } +} +```` + +{{end}} + +## 下一章 + +查看本教程的[下一章](Part-6.md). diff --git a/docs/zh-Hans/Tutorials/Part-6.md b/docs/zh-Hans/Tutorials/Part-6.md index 602306c484d..6030c8f3b97 100644 --- a/docs/zh-Hans/Tutorials/Part-6.md +++ b/docs/zh-Hans/Tutorials/Part-6.md @@ -1 +1,278 @@ -TODO.. \ No newline at end of file +# Web应用程序开发教程 - 第六章: 作者: 领域层 +````json +//[doc-params] +{ + "UI": ["MVC","Blazor","BlazorServer","NG"], + "DB": ["EF","Mongo"] +} +```` +## 关于本教程 + +在本系列教程中, 你将构建一个名为 `Acme.BookStore` 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开发的: + +* **{{DB_Text}}** 做为ORM提供程序. +* **{{UI_Value}}** 做为UI框架. + +本教程分为以下部分: + +- [Part 1: 创建服务端](Part-1.md) +- [Part 2: 图书列表页面](Part-2.md) +- [Part 3: 创建,更新和删除图书](Part-2.md) +- [Part 4: 集成测试](Part-4.md) +- [Part 5: 授权](Part-5.md) +- **Part 6: 作者: 领域层**(本章) +- [Part 7: 作者: 数据库集成](Part-7.md) +- [Part 8: 作者: 应用服务层](Part-8.md) +- [Part 9: 作者: 用户页面](Part-9.md) +- [Part 10: 图书到作者的关系](Part-10.md) + +## 下载源码 + +本教程根据你的**UI** 和 **数据库**偏好有多个版本,我们准备了几种可供下载的源码组合: + +* [MVC (Razor Pages) UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Mvc-EfCore) +* [Blazor UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore) +* [Angular UI 与 MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb) + +> 如果你在Windows中遇到 "文件名太长" or "解压错误", 很可能与Windows最大文件路径限制有关. Windows文件路径的最大长度为250字符. 为了解决这个问题,参阅 [在Windows 10中启用长路径](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later). + +> 如果你遇到与Git相关的长路径错误, 尝试使用下面的命令在Windows中启用长路径. 参阅 https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path +> `git config --system core.longpaths true` + +## 简介 + +在前面的章节中, 我们使用 ABP 框架轻松地构建了一些服务; + +* 使用 [CrudAppService](../Application-Services.md) 基类, 而不是为标准的增删改查操作手工开发应用服务. +* 使用 [generic repositories](../Repositories.md) 自动完成数据层功能. + +对于 "作者" 部分; + +* 我们将要展示在需要的情况下, 如何 **手工做一些事情**. +* 我们将要实现一些 **领域驱动设计 (DDD) 最佳实践**. + +> **开发将会逐层完成, 一次聚焦一层. 在真实项目中, 你会逐个功能(垂直)开发, 如同前面的教程. 通过这种方式, 你可以体验这两种方式** + +## 作者实体 + +在 `Acme.BookStore.Domain` 项目中创建 `Authors` 文件夹 (命名空间), 在其中加入 `Author` 类: + +````csharp +using System; +using JetBrains.Annotations; +using Volo.Abp; +using Volo.Abp.Domain.Entities.Auditing; + +namespace Acme.BookStore.Authors +{ + public class Author : FullAuditedAggregateRoot + { + public string Name { get; private set; } + public DateTime BirthDate { get; set; } + public string ShortBio { get; set; } + + private Author() + { + /* This constructor is for deserialization / ORM purpose */ + } + + internal Author( + Guid id, + [NotNull] string name, + DateTime birthDate, + [CanBeNull] string shortBio = null) + : base(id) + { + SetName(name); + BirthDate = birthDate; + ShortBio = shortBio; + } + + internal Author ChangeName([NotNull] string name) + { + SetName(name); + return this; + } + + private void SetName([NotNull] string name) + { + Name = Check.NotNullOrWhiteSpace( + name, + nameof(name), + maxLength: AuthorConsts.MaxNameLength + ); + } + } +} +```` + +* 由 `FullAuditedAggregateRoot` 继承使得实体支持[软删除](../Data-Filtering.md) (指实体被删除时, 它并没有从数据库中被删除, 而只是被标记删除), 实体也具有了 [审计](../Entities.md) 属性. +* `Name` 属性的 `private set` 限制从类的外部设置这个属性. 有两种方法设置名字 (两种都进行了验证): + * 当新建一个作者时, 通过构造器. + * 使用 `ChangeName` 方法更新名字. +* `构造器` 和 `ChangeName` 方法的访问级别是 `internal`, 强制这些方法只能在领域层由 `AuthorManager` 使用. 稍后将对此进行解释. +* `Check` 类是一个ABP框架工具类, 用于检查方法参数 (如果参数非法会抛出 `ArgumentException`). + +`AuthorConsts` 是一个简单的类, 它位于 `Acme.BookStore.Domain.Shared` 项目的 `Authors` 命名空间 (文件夹)中: + +````csharp +namespace Acme.BookStore.Authors +{ + public static class AuthorConsts + { + public const int MaxNameLength = 64; + } +} +```` + +在 `Acme.BookStore.Domain.Shared` 项目中创建这个类, 因为[数据传输类](../Data-Transfer-Objects.md) (DTOs) 稍后会再一次用到它. + +## AuthorManager: 领域服务 + +`Author` 构造器和 `ChangeName` 方法的访问级别是 `internal`, 所以它们只能在领域层使用. 在 `Acme.BookStore.Domain` 项目中的 `Authors` 文件夹 (命名空间)创建 `AuthorManager` 类: + +````csharp +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Volo.Abp; +using Volo.Abp.Domain.Services; + +namespace Acme.BookStore.Authors +{ + public class AuthorManager : DomainService + { + private readonly IAuthorRepository _authorRepository; + + public AuthorManager(IAuthorRepository authorRepository) + { + _authorRepository = authorRepository; + } + + public async Task CreateAsync( + [NotNull] string name, + DateTime birthDate, + [CanBeNull] string shortBio = null) + { + Check.NotNullOrWhiteSpace(name, nameof(name)); + + var existingAuthor = await _authorRepository.FindByNameAsync(name); + if (existingAuthor != null) + { + throw new AuthorAlreadyExistsException(name); + } + + return new Author( + GuidGenerator.Create(), + name, + birthDate, + shortBio + ); + } + + public async Task ChangeNameAsync( + [NotNull] Author author, + [NotNull] string newName) + { + Check.NotNull(author, nameof(author)); + Check.NotNullOrWhiteSpace(newName, nameof(newName)); + + var existingAuthor = await _authorRepository.FindByNameAsync(newName); + if (existingAuthor != null && existingAuthor.Id != author.Id) + { + throw new AuthorAlreadyExistsException(newName); + } + + author.ChangeName(newName); + } + } +} +```` + +* `AuthorManager` 强制使用一种可控的方式创建作者和修改作者的名字. 应用层 (后面会介绍) 将会使用这些方法. + +> **DDD 提示**: 如非必须并且用于执行核心业务规则, 不要引入领域服务方法. 对于这个场景, 我们使用这个服务保证名字的唯一性. + +两个方法都检查是否存在同名用户, 如果存在, 抛出业务异常 `AuthorAlreadyExistsException`, 这个异常定义在 `Acme.BookStore.Domain` 项目 (`Authors` 文件夹中): + +````csharp +using Volo.Abp; + +namespace Acme.BookStore.Authors +{ + public class AuthorAlreadyExistsException : BusinessException + { + public AuthorAlreadyExistsException(string name) + : base(BookStoreDomainErrorCodes.AuthorAlreadyExists) + { + WithData("name", name); + } + } +} +```` + +`BusinessException` 是一个特殊的异常类型. 在需要时抛出领域相关异常是一个好的实践. ABP框架会自动处理它, 并且它也容易本地化. `WithData(...)` 方法提供额外的数据给异常对象, 这些数据将会在本地化中或出于其它一些目的被使用. + +打开 `Acme.BookStore.Domain.Shared` 项目中的 `BookStoreDomainErrorCodes` 并修改为: + +````csharp +namespace Acme.BookStore +{ + public static class BookStoreDomainErrorCodes + { + public const string AuthorAlreadyExists = "BookStore:00001"; + } +} +```` + +这里定义了一个字符串, 表示应用程序抛出的错误码, 这个错误码可以被客户端应用程序处理. 为了用户, 你可能希望本地化它. 打开 `Acme.BookStore.Domain.Shared` 项目中的 `Localization/BookStore/en.json` , 加入以下项: + +````json +"BookStore:00001": "There is already an author with the same name: {name}" +```` + +当 `AuthorAlreadyExistsException` 被抛出, 终端用户将会在UI上看到组织好的错误消息. + +## IAuthorRepository + +`AuthorManager` 注入了 `IAuthorRepository`, 所以我们需要定义它. 在 `Acme.BookStore.Domain` 项目的 `Authors` 文件夹 (命名空间) 中创建这个新接口: + +````csharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace Acme.BookStore.Authors +{ + public interface IAuthorRepository : IRepository + { + Task FindByNameAsync(string name); + + Task> GetListAsync( + int skipCount, + int maxResultCount, + string sorting, + string filter = null + ); + } +} +```` + +* `IAuthorRepository` 扩展了标准 `IRepository` 接口, 所以所有的标准 [repository](../Repositories.md) 方法对于 `IAuthorRepository` 都是可用的. +* `FindByNameAsync` 在 `AuthorManager` 中用来根据姓名查询用户. +* `GetListAsync` 用于应用层以获得一个排序的, 经过过滤的作者列表, 显示在UI上. + +我们会在下一章实现这个repository. + +> 这两个方法似乎 **看上去没有必要**, 因为标准repositories已经是 `IQueryable`, 你可以直接使用它们, 而不是自定义方法. 在实际应用程序中, 这么做是没问题的. 但在这个 **学习指南**中, 解释如何在需要时创建自定义repository方法是有价值的. + +## 结论 + +这一章覆盖了图书管理程序作者相关功能的领域层. 在这一章中创建/更新的文件在下图中被高亮: + +![bookstore-author-domain-layer](images/bookstore-author-domain-layer.png) + +## 下一章 + +查看本教程的[下一章](Part-7.md). diff --git a/docs/zh-Hans/Tutorials/Part-7.md b/docs/zh-Hans/Tutorials/Part-7.md index 602306c484d..95b016e4519 100644 --- a/docs/zh-Hans/Tutorials/Part-7.md +++ b/docs/zh-Hans/Tutorials/Part-7.md @@ -1 +1,238 @@ -TODO.. \ No newline at end of file +# Web应用程序开发教程 - 第七章: 数据库集成 +````json +//[doc-params] +{ + "UI": ["MVC","Blazor","BlazorServer","NG"], + "DB": ["EF","Mongo"] +} +```` +## 关于本教程 + +在本系列教程中, 你将构建一个名为 `Acme.BookStore` 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开发的: + +* **{{DB_Text}}** 做为ORM提供程序. +* **{{UI_Value}}** 做为UI框架. + +本教程分为以下部分: + +- [Part 1: 创建服务端](Part-1.md) +- [Part 2: 图书列表页面](Part-2.md) +- [Part 3: 创建,更新和删除图书](Part-2.md) +- [Part 4: 集成测试](Part-4.md) +- [Part 5: 授权](Part-5.md) +- [Part 6: 作者: 领域层](Part-6.md) +- **Part 7: 数据库集成**(本章) +- [Part 8: 作者: 应用服务层](Part-8.md) +- [Part 9: 作者: 用户页面](Part-9.md) +- [Part 10: 图书到作者的关系](Part-10.md) + +## 下载源码 + +本教程根据你的**UI** 和 **数据库**偏好有多个版本,我们准备了几种可供下载的源码组合: + +* [MVC (Razor Pages) UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Mvc-EfCore) +* [Blazor UI 与 EF Core](https://github.com/abpframework/abp-samples/tree/master/BookStore-Blazor-EfCore) +* [Angular UI 与 MongoDB](https://github.com/abpframework/abp-samples/tree/master/BookStore-Angular-MongoDb) + +> 如果你在Windows中遇到 "文件名太长" or "解压错误", 很可能与Windows最大文件路径限制有关. Windows文件路径的最大长度为250字符. 为了解决这个问题,参阅 [在Windows 10中启用长路径](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later). + +> 如果你遇到与Git相关的长路径错误, 尝试使用下面的命令在Windows中启用长路径. 参阅 https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path +> `git config --system core.longpaths true` + +## 简介 + +这章阐述如何为前一章介绍的 `作者` 实体配置数据库集成. + +{{if DB=="EF"}} + +## DB Context + +打开 `Acme.BookStore.EntityFrameworkCore` 项目中的 `BookStoreDbContext` 加入 `DbSet` 属性: + +````csharp +public DbSet Authors { get; set; } +```` + +定位到相同项目中的 `BookStoreDbContext` 类中的 `OnModelCreating` 方法, 加入以下代码到方法的结尾: + +````csharp +builder.Entity(b => +{ + b.ToTable(BookStoreConsts.DbTablePrefix + "Authors", + BookStoreConsts.DbSchema); + + b.ConfigureByConvention(); + + b.Property(x => x.Name) + .IsRequired() + .HasMaxLength(AuthorConsts.MaxNameLength); + + b.HasIndex(x => x.Name); +}); +```` + +这和前面的 `Book` 实体做的一样, 所以不再赘述. + +## 创建数据库迁移 + +配置启动解决方案为使用 [Entity Framework Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). 因为我们还没有修改数据库映射配置,所以需要创建一个新的迁移并对数据库应用变更. + +打开命令行终端, 切换当前目录为 `Acme.BookStore.EntityFrameworkCore` 项目目录, 输入以下命令: + +````bash +dotnet ef migrations add Added_Authors +```` + +这会在项目中添加一个迁移类: + +![bookstore-efcore-migration-authors](./images/bookstore-efcore-migration-authors.png) + +你可以在同一个命令行终端中使用以下命令对数据库应用更改: + +````bash +dotnet ef database update +```` + +> 如果你使用 Visual Studio, 可能希望在 *Package Manager Console (PMC)* 使用 `Add-Migration Added_Authors -c BookStoreMigrationsDbContext` 和 `Update-Database -c BookStoreMigrationsDbContext` 命令. 如果这样, 保证 {{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer"}}`Acme.BookStore.Blazor`{{else if UI=="Blazor" || UI=="NG"}}`Acme.BookStore.HttpApi.Host`{{end}} 是启动项目并且在PMC中 `Acme.BookStore.EntityFrameworkCore` 是 *默认项目* . + +{{else if DB=="Mongo"}} + +## DB Context + +打开 `Acme.BookStore.MongoDB` 项目 `MongoDb 文件夹`中的 `BookStoreMongoDbContext`, 在类中加入以下属性: + +````csharp +public IMongoCollection Authors => Collection(); +```` + +{{end}} + +## 实现 IAuthorRepository + +{{if DB=="EF"}} + +在 `Acme.BookStore.EntityFrameworkCore` 项目 (`Authors` 文件夹)中创建一个新类 `EfCoreAuthorRepository`, 粘贴以下代码: + +````csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Threading.Tasks; +using Acme.BookStore.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace Acme.BookStore.Authors +{ + public class EfCoreAuthorRepository + : EfCoreRepository, + IAuthorRepository + { + public EfCoreAuthorRepository( + IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task FindByNameAsync(string name) + { + var dbSet = await GetDbSetAsync(); + return await dbSet.FirstOrDefaultAsync(author => author.Name == name); + } + + public async Task> GetListAsync( + int skipCount, + int maxResultCount, + string sorting, + string filter = null) + { + var dbSet = await GetDbSetAsync(); + return await dbSet + .WhereIf( + !filter.IsNullOrWhiteSpace(), + author => author.Name.Contains(filter) + ) + .OrderBy(sorting) + .Skip(skipCount) + .Take(maxResultCount) + .ToListAsync(); + } + } +} +```` + +* 继承自 `EfCoreRepository`, 所以继承了标准repository的方法实现. +* `WhereIf` 是ABP 框架的快捷扩展方法. 它仅当第一个条件满足时, 执行 `Where` 查询. (根据名字查询, 仅当 filter 不为空). 你可以不使用这个方法, 但这些快捷方法可以提高效率. +* `sorting` 可以是一个字符串, 如 `Name`, `Name ASC` 或 `Name DESC`. 通过使用 [System.Linq.Dynamic.Core](https://www.nuget.org/packages/System.Linq.Dynamic.Core) NuGet 包是可能的. + +> 参阅 [EF Core 集成文档](../Entity-Framework-Core.md) 获得基于EF Core的repositories的更多信息. + +{{else if DB=="Mongo"}} + +在 `Acme.BookStore.MongoDB` 项目 (`Authors` 文件夹)中创建一个新类 `MongoDbAuthorRepository`, 粘贴以下代码: + +```csharp +using System; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Collections.Generic; +using System.Threading.Tasks; +using Acme.BookStore.MongoDB; +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using Volo.Abp.Domain.Repositories.MongoDB; +using Volo.Abp.MongoDB; + +namespace Acme.BookStore.Authors +{ + public class MongoDbAuthorRepository + : MongoDbRepository, + IAuthorRepository + { + public MongoDbAuthorRepository( + IMongoDbContextProvider dbContextProvider + ) : base(dbContextProvider) + { + } + + public async Task FindByNameAsync(string name) + { + var queryable = await GetMongoQueryableAsync(); + return await queryable.FirstOrDefaultAsync(author => author.Name == name); + } + + public async Task> GetListAsync( + int skipCount, + int maxResultCount, + string sorting, + string filter = null) + { + var queryable = await GetMongoQueryableAsync(); + return await queryable + .WhereIf>( + !filter.IsNullOrWhiteSpace(), + author => author.Name.Contains(filter) + ) + .OrderBy(sorting) + .As>() + .Skip(skipCount) + .Take(maxResultCount) + .ToListAsync(); + } + } +} +``` + +* 继承自 `MongoDbRepository`, 所以继承了标准repository的方法实现. +* `WhereIf` 是ABP 框架的快捷扩展方法. 它仅当第一个条件满足时, 执行 `Where` 查询. (根据名字查询, 仅当 filter 不为空). 你可以不使用这个方法, 但这些快捷方法可以提高效率. +* `sorting` 可以是一个字符串, 如 `Name`, `Name ASC` 或 `Name DESC`. 通过使用 [System.Linq.Dynamic.Core](https://www.nuget.org/packages/System.Linq.Dynamic.Core) NuGet 包是可能的. + +> 参阅 [MongoDB 集成文档](../MongoDB.md) 获得基于MongoDB的repositories的更多信息. + +{{end}} + +## 下一章 + +查看本教程的[下一章](Part-8.md). diff --git a/docs/zh-Hans/Tutorials/images/blazor-add-book-button.png b/docs/zh-Hans/Tutorials/images/blazor-add-book-button.png new file mode 100644 index 00000000000..58a607d3b1e Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/blazor-add-book-button.png differ diff --git a/docs/zh-Hans/Tutorials/images/blazor-add-books-component.png b/docs/zh-Hans/Tutorials/images/blazor-add-books-component.png new file mode 100644 index 00000000000..ec0412d31ec Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/blazor-add-books-component.png differ diff --git a/docs/zh-Hans/Tutorials/images/blazor-bookstore-book-list.png b/docs/zh-Hans/Tutorials/images/blazor-bookstore-book-list.png new file mode 100644 index 00000000000..18bb26ccb10 Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/blazor-bookstore-book-list.png differ diff --git a/docs/zh-Hans/Tutorials/images/blazor-delete-book-action.png b/docs/zh-Hans/Tutorials/images/blazor-delete-book-action.png new file mode 100644 index 00000000000..f2b0b83f301 Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/blazor-delete-book-action.png differ diff --git a/docs/zh-Hans/Tutorials/images/blazor-edit-book-action-2.png b/docs/zh-Hans/Tutorials/images/blazor-edit-book-action-2.png new file mode 100644 index 00000000000..c3e2b1e0e1c Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/blazor-edit-book-action-2.png differ diff --git a/docs/zh-Hans/Tutorials/images/blazor-edit-book-modal.png b/docs/zh-Hans/Tutorials/images/blazor-edit-book-modal.png new file mode 100644 index 00000000000..e63e796d34b Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/blazor-edit-book-modal.png differ diff --git a/docs/zh-Hans/Tutorials/images/blazor-menu-bookstore.png b/docs/zh-Hans/Tutorials/images/blazor-menu-bookstore.png new file mode 100644 index 00000000000..f9f334aa1d5 Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/blazor-menu-bookstore.png differ diff --git a/docs/zh-Hans/Tutorials/images/blazor-new-book-modal.png b/docs/zh-Hans/Tutorials/images/blazor-new-book-modal.png new file mode 100644 index 00000000000..dd284a0ffd6 Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/blazor-new-book-modal.png differ diff --git a/docs/zh-Hans/Tutorials/images/bookstore-efcore-migration-authors.png b/docs/zh-Hans/Tutorials/images/bookstore-efcore-migration-authors.png new file mode 100644 index 00000000000..2cfb29f86f8 Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/bookstore-efcore-migration-authors.png differ diff --git a/docs/zh-Hans/Tutorials/images/bookstore-efcore-migration.png b/docs/zh-Hans/Tutorials/images/bookstore-efcore-migration.png index 9714e795e20..5c034f6e801 100644 Binary files a/docs/zh-Hans/Tutorials/images/bookstore-efcore-migration.png and b/docs/zh-Hans/Tutorials/images/bookstore-efcore-migration.png differ diff --git a/docs/zh-Hans/Tutorials/images/generated-proxies-3.png b/docs/zh-Hans/Tutorials/images/generated-proxies-3.png new file mode 100644 index 00000000000..2a94f4e389b Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/generated-proxies-3.png differ diff --git a/docs/zh-Hans/Tutorials/images/vs-run-without-iisexpress.png b/docs/zh-Hans/Tutorials/images/vs-run-without-iisexpress.png new file mode 100644 index 00000000000..03c30e2b481 Binary files /dev/null and b/docs/zh-Hans/Tutorials/images/vs-run-without-iisexpress.png differ diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 37f57388c06..74a44c84455 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -5,11 +5,25 @@ "path": "Tutorials/Todo/Index.md" }, { - "text": "入门", + "text": "入门教程", "items": [ { "text": "Web应用程序", - "path": "Getting-Started.md" + "path": "Getting-Started.md", + "items": [ + { + "text": "1: 设置你的开发环境", + "path": "Getting-Started-Setup-Environment.md" + }, + { + "text": "2: 创建新的解决方案", + "path": "Getting-Started-Create-Solution.md" + }, + { + "text": "3: 运行解决方案", + "path": "Getting-Started-Running-Solution.md" + } + ] }, { "text": "控制台应用程序", diff --git a/docs/zh-Hans/images/create-aspnet-core-application.png b/docs/zh-Hans/images/create-aspnet-core-application.png index 5813cf38e9a..b8b98f5c326 100644 Binary files a/docs/zh-Hans/images/create-aspnet-core-application.png and b/docs/zh-Hans/images/create-aspnet-core-application.png differ diff --git a/docs/zh-Hans/images/identity-module-menu.png b/docs/zh-Hans/images/identity-module-menu.png new file mode 100644 index 00000000000..ce2ee7e3e92 Binary files /dev/null and b/docs/zh-Hans/images/identity-module-menu.png differ diff --git a/docs/zh-Hans/images/identity-module-permissions.png b/docs/zh-Hans/images/identity-module-permissions.png new file mode 100644 index 00000000000..dfe0a9a0223 Binary files /dev/null and b/docs/zh-Hans/images/identity-module-permissions.png differ diff --git a/docs/zh-Hans/images/identity-module-roles.png b/docs/zh-Hans/images/identity-module-roles.png new file mode 100644 index 00000000000..53df1cdc6da Binary files /dev/null and b/docs/zh-Hans/images/identity-module-roles.png differ diff --git a/docs/zh-Hans/images/identity-module-users.png b/docs/zh-Hans/images/identity-module-users.png new file mode 100644 index 00000000000..33edb4cb782 Binary files /dev/null and b/docs/zh-Hans/images/identity-module-users.png differ diff --git a/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/AbpApiVersioningAbstractionsModule.cs b/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/AbpApiVersioningAbstractionsModule.cs index b4f679c9279..70d960c8d5e 100644 --- a/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/AbpApiVersioningAbstractionsModule.cs +++ b/framework/src/Volo.Abp.ApiVersioning.Abstractions/Volo/Abp/ApiVersioning/AbpApiVersioningAbstractionsModule.cs @@ -1,13 +1,12 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace Volo.Abp.ApiVersioning +namespace Volo.Abp.ApiVersioning; + +public class AbpApiVersioningAbstractionsModule : AbpModule { - public class AbpApiVersioningAbstractionsModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(NullRequestedApiVersion.Instance); - } + context.Services.AddSingleton(NullRequestedApiVersion.Instance); } } 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 3d8a31c694e..96c2ef33cda 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 @@ -1,7 +1,6 @@ -namespace Volo.Abp.ApiVersioning +namespace Volo.Abp.ApiVersioning; + +public interface IRequestedApiVersion { - 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 721fa918157..0589c662ef1 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 @@ -1,14 +1,13 @@ -namespace Volo.Abp.ApiVersioning +namespace Volo.Abp.ApiVersioning; + +public class NullRequestedApiVersion : IRequestedApiVersion { - public class NullRequestedApiVersion : IRequestedApiVersion - { - public static NullRequestedApiVersion Instance = new NullRequestedApiVersion(); + public static NullRequestedApiVersion Instance = new NullRequestedApiVersion(); - public string Current => null; + public string Current => null; + + private NullRequestedApiVersion() + { - private NullRequestedApiVersion() - { - - } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/AspNetCore/Builder/ApplicationBuilderAbpJwtTokenMiddlewareExtension.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/AspNetCore/Builder/ApplicationBuilderAbpJwtTokenMiddlewareExtension.cs index 4ff54f39bf2..8171013854d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/AspNetCore/Builder/ApplicationBuilderAbpJwtTokenMiddlewareExtension.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Microsoft/AspNetCore/Builder/ApplicationBuilderAbpJwtTokenMiddlewareExtension.cs @@ -1,25 +1,24 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; -namespace Microsoft.AspNetCore.Builder +namespace Microsoft.AspNetCore.Builder; + +public static class ApplicationBuilderAbpJwtTokenMiddlewareExtension { - public static class ApplicationBuilderAbpJwtTokenMiddlewareExtension + public static IApplicationBuilder UseJwtTokenMiddleware(this IApplicationBuilder app, string schema = JwtBearerDefaults.AuthenticationScheme) { - public static IApplicationBuilder UseJwtTokenMiddleware(this IApplicationBuilder app, string schema = JwtBearerDefaults.AuthenticationScheme) + return app.Use(async (ctx, next) => { - return app.Use(async (ctx, next) => + if (ctx.User.Identity?.IsAuthenticated != true) { - if (ctx.User.Identity?.IsAuthenticated != true) + var result = await ctx.AuthenticateAsync(schema); + if (result.Succeeded && result.Principal != null) { - var result = await ctx.AuthenticateAsync(schema); - if (result.Succeeded && result.Principal != null) - { - ctx.User = result.Principal; - } + ctx.User = result.Principal; } + } - await next(); - }); - } + await next(); + }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo/Abp/AspNetCore/Authentication/JwtBearer/AbpAspNetCoreAuthenticationJwtBearerModule.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo/Abp/AspNetCore/Authentication/JwtBearer/AbpAspNetCoreAuthenticationJwtBearerModule.cs index 8698e2283d8..1fa5077a91b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo/Abp/AspNetCore/Authentication/JwtBearer/AbpAspNetCoreAuthenticationJwtBearerModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo/Abp/AspNetCore/Authentication/JwtBearer/AbpAspNetCoreAuthenticationJwtBearerModule.cs @@ -1,11 +1,10 @@ using Volo.Abp.Modularity; using Volo.Abp.Security; -namespace Volo.Abp.AspNetCore.Authentication.JwtBearer +namespace Volo.Abp.AspNetCore.Authentication.JwtBearer; + +[DependsOn(typeof(AbpSecurityModule))] +public class AbpAspNetCoreAuthenticationJwtBearerModule : AbpModule { - [DependsOn(typeof(AbpSecurityModule))] - public class AbpAspNetCoreAuthenticationJwtBearerModule : AbpModule - { - } } diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Microsoft/AspNetCore/Authentication/OAuth/Claims/AbpClaimActionCollectionExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Microsoft/AspNetCore/Authentication/OAuth/Claims/AbpClaimActionCollectionExtensions.cs index 2ad72955afd..01dc489c545 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Microsoft/AspNetCore/Authentication/OAuth/Claims/AbpClaimActionCollectionExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Microsoft/AspNetCore/Authentication/OAuth/Claims/AbpClaimActionCollectionExtensions.cs @@ -1,57 +1,56 @@ using Volo.Abp.AspNetCore.Authentication.OAuth.Claims; using Volo.Abp.Security.Claims; -namespace Microsoft.AspNetCore.Authentication.OAuth.Claims +namespace Microsoft.AspNetCore.Authentication.OAuth.Claims; + +public static class AbpClaimActionCollectionExtensions { - public static class AbpClaimActionCollectionExtensions + public static void MapAbpClaimTypes(this ClaimActionCollection claimActions) { - public static void MapAbpClaimTypes(this ClaimActionCollection claimActions) + if (AbpClaimTypes.UserName != "name") + { + claimActions.MapJsonKey(AbpClaimTypes.UserName, "name"); + claimActions.DeleteClaim("name"); + claimActions.RemoveDuplicate(AbpClaimTypes.UserName); + } + + if (AbpClaimTypes.Email != "email") + { + claimActions.MapJsonKey(AbpClaimTypes.Email, "email"); + claimActions.DeleteClaim("email"); + claimActions.RemoveDuplicate(AbpClaimTypes.Email); + } + + if (AbpClaimTypes.EmailVerified != "email_verified") + { + claimActions.MapJsonKey(AbpClaimTypes.EmailVerified, "email_verified"); + } + + if (AbpClaimTypes.PhoneNumber != "phone_number") { - if (AbpClaimTypes.UserName != "name") - { - claimActions.MapJsonKey(AbpClaimTypes.UserName, "name"); - claimActions.DeleteClaim("name"); - claimActions.RemoveDuplicate(AbpClaimTypes.UserName); - } - - if (AbpClaimTypes.Email != "email") - { - claimActions.MapJsonKey(AbpClaimTypes.Email, "email"); - claimActions.DeleteClaim("email"); - claimActions.RemoveDuplicate(AbpClaimTypes.Email); - } - - if (AbpClaimTypes.EmailVerified != "email_verified") - { - claimActions.MapJsonKey(AbpClaimTypes.EmailVerified, "email_verified"); - } - - if (AbpClaimTypes.PhoneNumber != "phone_number") - { - claimActions.MapJsonKey(AbpClaimTypes.PhoneNumber, "phone_number"); - } - - if (AbpClaimTypes.PhoneNumberVerified != "phone_number_verified") - { - claimActions.MapJsonKey(AbpClaimTypes.PhoneNumberVerified, "phone_number_verified"); - } - - if (AbpClaimTypes.Role != "role") - { - claimActions.MapJsonKeyMultiple(AbpClaimTypes.Role, "role"); - } - - claimActions.RemoveDuplicate(AbpClaimTypes.Name); + claimActions.MapJsonKey(AbpClaimTypes.PhoneNumber, "phone_number"); } - public static void MapJsonKeyMultiple(this ClaimActionCollection claimActions, string claimType, string jsonKey) + if (AbpClaimTypes.PhoneNumberVerified != "phone_number_verified") { - claimActions.Add(new MultipleClaimAction(claimType, jsonKey)); + claimActions.MapJsonKey(AbpClaimTypes.PhoneNumberVerified, "phone_number_verified"); } - - public static void RemoveDuplicate(this ClaimActionCollection claimActions, string claimType) + + if (AbpClaimTypes.Role != "role") { - claimActions.Add(new RemoveDuplicateClaimAction(claimType)); + claimActions.MapJsonKeyMultiple(AbpClaimTypes.Role, "role"); } + + claimActions.RemoveDuplicate(AbpClaimTypes.Name); + } + + public static void MapJsonKeyMultiple(this ClaimActionCollection claimActions, string claimType, string jsonKey) + { + claimActions.Add(new MultipleClaimAction(claimType, jsonKey)); + } + + public static void RemoveDuplicate(this ClaimActionCollection claimActions, string claimType) + { + claimActions.Add(new RemoveDuplicateClaimAction(claimType)); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/AbpAspNetCoreAuthenticationOAuthModule.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/AbpAspNetCoreAuthenticationOAuthModule.cs index cff3f437b7d..b73c78782ee 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/AbpAspNetCoreAuthenticationOAuthModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/AbpAspNetCoreAuthenticationOAuthModule.cs @@ -1,11 +1,10 @@ using Volo.Abp.Modularity; using Volo.Abp.Security; -namespace Volo.Abp.AspNetCore.Authentication.OAuth +namespace Volo.Abp.AspNetCore.Authentication.OAuth; + +[DependsOn(typeof(AbpSecurityModule))] +public class AbpAspNetCoreAuthenticationOAuthModule : AbpModule { - [DependsOn(typeof(AbpSecurityModule))] - public class AbpAspNetCoreAuthenticationOAuthModule : AbpModule - { - } } 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 66ca78026d6..1910af63d5f 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 @@ -3,51 +3,50 @@ using System.Text.Json; using Microsoft.AspNetCore.Authentication.OAuth.Claims; -namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims +namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims; + +public class MultipleClaimAction : ClaimAction { - public class MultipleClaimAction : ClaimAction + public MultipleClaimAction(string claimType, string jsonKey) + : base(claimType, jsonKey) { - public MultipleClaimAction(string claimType, string jsonKey) - : base(claimType, jsonKey) - { - } + } - public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer) - { - JsonElement prop; + public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer) + { + JsonElement prop; - if (!userData.TryGetProperty(ValueType, out prop)) - return; - - if (prop.ValueKind == JsonValueKind.Null) - { - return; - } + if (!userData.TryGetProperty(ValueType, out prop)) + return; - Claim claim; - switch (prop.ValueKind) - { - case JsonValueKind.String: - claim = new Claim(ClaimType, prop.GetString(), ValueType, issuer); + if (prop.ValueKind == JsonValueKind.Null) + { + return; + } + + Claim claim; + switch (prop.ValueKind) + { + case JsonValueKind.String: + claim = new Claim(ClaimType, prop.GetString(), ValueType, issuer); + if (!identity.Claims.Any(c => c.Type == claim.Type && c.Value == claim.Value)) + { + identity.AddClaim(claim); + } + break; + case JsonValueKind.Array: + foreach (var arramItem in prop.EnumerateArray()) + { + claim = new Claim(ClaimType, arramItem.GetString(), ValueType, issuer); if (!identity.Claims.Any(c => c.Type == claim.Type && c.Value == claim.Value)) { identity.AddClaim(claim); } - break; - case JsonValueKind.Array: - foreach (var arramItem in prop.EnumerateArray()) - { - claim = new Claim(ClaimType, arramItem.GetString(), ValueType, issuer); - if (!identity.Claims.Any(c => c.Type == claim.Type && c.Value == claim.Value)) - { - identity.AddClaim(claim); - } - } - break; - default: - throw new AbpException("Unhandled JsonValueKind: " + prop.ValueKind); - } + } + break; + default: + throw new AbpException("Unhandled JsonValueKind: " + prop.ValueKind); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/RemoveDuplicateClaimAction.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/RemoveDuplicateClaimAction.cs index ab3e4027c26..80773ed481f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/RemoveDuplicateClaimAction.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/RemoveDuplicateClaimAction.cs @@ -5,36 +5,35 @@ using System.Text.Json; using Microsoft.AspNetCore.Authentication.OAuth.Claims; -namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims +namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims; + +public class RemoveDuplicateClaimAction : ClaimAction { - public class RemoveDuplicateClaimAction : ClaimAction + public RemoveDuplicateClaimAction(string claimType) + : base(claimType, ClaimValueTypes.String) { - public RemoveDuplicateClaimAction(string claimType) - : base(claimType, ClaimValueTypes.String) + } + + /// + public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer) + { + var claims = identity.Claims.Where(c => c.Type == ClaimType).ToArray(); + if (claims.Length < 2) { + return; } - /// - public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer) + var previousValues = new List(); + foreach (var claim in claims) { - var claims = identity.Claims.Where(c => c.Type == ClaimType).ToArray(); - if (claims.Length < 2) + if (claim.Value.IsIn(previousValues)) { - return; + identity.RemoveClaim(claim); } - - var previousValues = new List(); - foreach (var claim in claims) + else { - if (claim.Value.IsIn(previousValues)) - { - identity.RemoveClaim(claim); - } - else - { - previousValues.Add(claim.Value); - } + previousValues.Add(claim.Value); } } } -} \ No newline at end of file +} 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 acd42335122..02b292a9846 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 @@ -7,59 +7,58 @@ using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Volo.Abp.AspNetCore.MultiTenancy; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class AbpOpenIdConnectExtensions { - public static class AbpOpenIdConnectExtensions - { - public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder) - => builder.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, _ => { }); + public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder) + => builder.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, _ => { }); - public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, Action configureOptions) - => builder.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, configureOptions); + public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, Action configureOptions) + => builder.AddAbpOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, configureOptions); - public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, Action configureOptions) - => builder.AddAbpOpenIdConnect(authenticationScheme, OpenIdConnectDefaults.DisplayName, configureOptions); + public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, Action configureOptions) + => builder.AddAbpOpenIdConnect(authenticationScheme, OpenIdConnectDefaults.DisplayName, configureOptions); - public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action configureOptions) + public static AuthenticationBuilder AddAbpOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action configureOptions) + { + return builder.AddOpenIdConnect(authenticationScheme, displayName, options => { - return builder.AddOpenIdConnect(authenticationScheme, displayName, options => - { - options.ClaimActions.MapAbpClaimTypes(); + options.ClaimActions.MapAbpClaimTypes(); - configureOptions?.Invoke(options); + configureOptions?.Invoke(options); - options.Events ??= new OpenIdConnectEvents(); - var authorizationCodeReceived = options.Events.OnAuthorizationCodeReceived ?? (_ => Task.CompletedTask); + options.Events ??= new OpenIdConnectEvents(); + var authorizationCodeReceived = options.Events.OnAuthorizationCodeReceived ?? (_ => Task.CompletedTask); - options.Events.OnAuthorizationCodeReceived = receivedContext => - { - SetAbpTenantId(receivedContext); - return authorizationCodeReceived.Invoke(receivedContext); - }; + options.Events.OnAuthorizationCodeReceived = receivedContext => + { + SetAbpTenantId(receivedContext); + return authorizationCodeReceived.Invoke(receivedContext); + }; - options.Events.OnRemoteFailure = remoteFailureContext => + options.Events.OnRemoteFailure = remoteFailureContext => + { + if (remoteFailureContext.Failure is OpenIdConnectProtocolException && + remoteFailureContext.Failure.Message.Contains("access_denied")) { - if (remoteFailureContext.Failure is OpenIdConnectProtocolException && - remoteFailureContext.Failure.Message.Contains("access_denied")) - { - remoteFailureContext.HandleResponse(); - remoteFailureContext.Response.Redirect($"{remoteFailureContext.Request.PathBase}/"); - } - return Task.CompletedTask; - }; - }); - } + remoteFailureContext.HandleResponse(); + remoteFailureContext.Response.Redirect($"{remoteFailureContext.Request.PathBase}/"); + } + return Task.CompletedTask; + }; + }); + } - private static void SetAbpTenantId(AuthorizationCodeReceivedContext receivedContext) - { - var tenantKey = receivedContext.HttpContext.RequestServices - .GetRequiredService>().Value.TenantKey; + private static void SetAbpTenantId(AuthorizationCodeReceivedContext receivedContext) + { + var tenantKey = receivedContext.HttpContext.RequestServices + .GetRequiredService>().Value.TenantKey; - if (receivedContext.Request.Cookies.ContainsKey(tenantKey)) - { - receivedContext.TokenEndpointRequest.SetParameter(tenantKey, - receivedContext.Request.Cookies[tenantKey]); - } + if (receivedContext.Request.Cookies.ContainsKey(tenantKey)) + { + receivedContext.TokenEndpointRequest.SetParameter(tenantKey, + receivedContext.Request.Cookies[tenantKey]); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/AbpAspNetCoreAuthenticationOpenIdConnectModule.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/AbpAspNetCoreAuthenticationOpenIdConnectModule.cs index 13a8fd5c045..8670fbea173 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/AbpAspNetCoreAuthenticationOpenIdConnectModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/AbpAspNetCoreAuthenticationOpenIdConnectModule.cs @@ -2,13 +2,12 @@ using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.Authentication.OpenIdConnect +namespace Volo.Abp.AspNetCore.Authentication.OpenIdConnect; + +[DependsOn( + typeof(AbpMultiTenancyModule), + typeof(AbpAspNetCoreAuthenticationOAuthModule))] +public class AbpAspNetCoreAuthenticationOpenIdConnectModule : AbpModule { - [DependsOn( - typeof(AbpMultiTenancyModule), - typeof(AbpAspNetCoreAuthenticationOAuthModule))] - public class AbpAspNetCoreAuthenticationOpenIdConnectModule : AbpModule - { - } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/AbpAspNetCoreComponentsServerThemingModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/AbpAspNetCoreComponentsServerThemingModule.cs index 72462b97d61..dab511b5954 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/AbpAspNetCoreComponentsServerThemingModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/AbpAspNetCoreComponentsServerThemingModule.cs @@ -4,34 +4,33 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages; using Volo.Abp.Modularity; -namespace Volo.Abp.AspNetCore.Components.Server.Theming +namespace Volo.Abp.AspNetCore.Components.Server.Theming; + +[DependsOn( + typeof(AbpAspNetCoreComponentsServerModule), + typeof(AbpAspNetCoreMvcUiPackagesModule), + typeof(AbpAspNetCoreComponentsWebThemingModule), + typeof(AbpAspNetCoreMvcUiBundlingModule) + )] +public class AbpAspNetCoreComponentsServerThemingModule : AbpModule { - [DependsOn( - typeof(AbpAspNetCoreComponentsServerModule), - typeof(AbpAspNetCoreMvcUiPackagesModule), - typeof(AbpAspNetCoreComponentsWebThemingModule), - typeof(AbpAspNetCoreMvcUiBundlingModule) - )] - public class AbpAspNetCoreComponentsServerThemingModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(options => { - Configure(options => - { - options - .StyleBundles - .Add(BlazorStandardBundles.Styles.Global, bundle => - { - bundle.AddContributors(typeof(BlazorGlobalStyleContributor)); - }); - - options - .ScriptBundles - .Add(BlazorStandardBundles.Scripts.Global, bundle => - { - bundle.AddContributors(typeof(BlazorGlobalScriptContributor)); - }); - }); - } + options + .StyleBundles + .Add(BlazorStandardBundles.Styles.Global, bundle => + { + bundle.AddContributors(typeof(BlazorGlobalStyleContributor)); + }); + + options + .ScriptBundles + .Add(BlazorStandardBundles.Scripts.Global, bundle => + { + bundle.AddContributors(typeof(BlazorGlobalScriptContributor)); + }); + }); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalBundles.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalBundles.cs index 7112fd342d6..d65efa0c3fa 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalBundles.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalBundles.cs @@ -1,15 +1,14 @@ -namespace Volo.Abp.AspNetCore.Components.Server.Theming.Bundling +namespace Volo.Abp.AspNetCore.Components.Server.Theming.Bundling; + +public class BlazorStandardBundles { - public class BlazorStandardBundles + public static class Styles { - public static class Styles - { - public static string Global = "Blazor.Global"; - } + public static string Global = "Blazor.Global"; + } - public static class Scripts - { - public static string Global = "Blazor.Global"; - } + public static class Scripts + { + public static string Global = "Blazor.Global"; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalScriptContributor.cs index 6a0542f717d..8977acc869a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalScriptContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalScriptContributor.cs @@ -1,14 +1,13 @@ using System.Collections.Generic; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; -namespace Volo.Abp.AspNetCore.Components.Server.Theming.Bundling +namespace Volo.Abp.AspNetCore.Components.Server.Theming.Bundling; + +public class BlazorGlobalScriptContributor : BundleContributor { - public class BlazorGlobalScriptContributor : BundleContributor + public override void ConfigureBundle(BundleConfigurationContext context) { - public override void ConfigureBundle(BundleConfigurationContext context) - { - context.Files.AddIfNotContains("/_framework/blazor.server.js"); - context.Files.AddIfNotContains("/_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/abp.js"); - } + context.Files.AddIfNotContains("/_framework/blazor.server.js"); + context.Files.AddIfNotContains("/_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/abp.js"); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalStyleContributor.cs index 9e712ffba77..3223be417cd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalStyleContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalStyleContributor.cs @@ -4,19 +4,18 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.FontAwesome; using Volo.Abp.Modularity; -namespace Volo.Abp.AspNetCore.Components.Server.Theming.Bundling +namespace Volo.Abp.AspNetCore.Components.Server.Theming.Bundling; + +[DependsOn( + typeof(BootstrapStyleContributor), + typeof(FontAwesomeStyleContributor) +)] +public class BlazorGlobalStyleContributor : BundleContributor { - [DependsOn( - typeof(BootstrapStyleContributor), - typeof(FontAwesomeStyleContributor) - )] - public class BlazorGlobalStyleContributor : BundleContributor + public override void ConfigureBundle(BundleConfigurationContext context) { - public override void ConfigureBundle(BundleConfigurationContext context) - { - context.Files.AddIfNotContains("/_content/Blazorise/blazorise.css"); - context.Files.AddIfNotContains("/_content/Blazorise.Bootstrap5/blazorise.bootstrap5.css"); - context.Files.AddIfNotContains("/_content/Blazorise.Snackbar/blazorise.snackbar.css"); - } + context.Files.AddIfNotContains("/_content/Blazorise/blazorise.css"); + context.Files.AddIfNotContains("/_content/Blazorise.Bootstrap5/blazorise.bootstrap5.css"); + context.Files.AddIfNotContains("/_content/Blazorise.Snackbar/blazorise.snackbar.css"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs index 91b672b0734..dfa515c1b89 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Hosting; using Volo.Abp.AspNetCore.Auditing; using Volo.Abp.AspNetCore.Components.Web; using Volo.Abp.AspNetCore.Mvc; @@ -12,49 +13,54 @@ using Volo.Abp.Http.Client; using Volo.Abp.Modularity; -namespace Volo.Abp.AspNetCore.Components.Server +namespace Volo.Abp.AspNetCore.Components.Server; + +[DependsOn( + typeof(AbpHttpClientModule), + typeof(AbpAspNetCoreComponentsWebModule), + typeof(AbpAspNetCoreSignalRModule), + typeof(AbpEventBusModule), + typeof(AbpAspNetCoreMvcContractsModule) + )] +public class AbpAspNetCoreComponentsServerModule : AbpModule { - [DependsOn( - typeof(AbpHttpClientModule), - typeof(AbpAspNetCoreComponentsWebModule), - typeof(AbpAspNetCoreSignalRModule), - typeof(AbpEventBusModule), - typeof(AbpAspNetCoreMvcContractsModule) - )] - public class AbpAspNetCoreComponentsServerModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var serverSideBlazorBuilder = context.Services.AddServerSideBlazor(options => { - var serverSideBlazorBuilder = context.Services.AddServerSideBlazor(); - context.Services.ExecutePreConfiguredActions(serverSideBlazorBuilder); - - Configure(options => + if (context.Services.GetHostingEnvironment().IsDevelopment()) { - options.IgnoredUrls.AddIfNotContains("/_blazor"); - }); + options.DetailedErrors = true; + } + }); + context.Services.ExecutePreConfiguredActions(serverSideBlazorBuilder); - Configure(options => - { - options.IgnoredUrls.AddIfNotContains("/_blazor"); - }); + Configure(options => + { + options.IgnoredUrls.AddIfNotContains("/_blazor"); + }); - Configure(options => + Configure(options => + { + options.IgnoredUrls.AddIfNotContains("/_blazor"); + }); + + Configure(options => + { + options.EndpointConfigureActions.Add(endpointContext => { - options.EndpointConfigureActions.Add(endpointContext => - { - endpointContext.Endpoints.MapBlazorHub(); - endpointContext.Endpoints.MapFallbackToPage("/_Host"); - }); + endpointContext.Endpoints.MapBlazorHub(); + endpointContext.Endpoints.MapFallbackToPage("/_Host"); }); - } + }); + } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - context.GetEnvironment().WebRootFileProvider = - new CompositeFileProvider( - new ManifestEmbeddedFileProvider(typeof(IServerSideBlazorBuilder).Assembly), - context.GetEnvironment().WebRootFileProvider - ); - } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + context.GetEnvironment().WebRootFileProvider = + new CompositeFileProvider( + new ManifestEmbeddedFileProvider(typeof(IServerSideBlazorBuilder).Assembly), + context.GetEnvironment().WebRootFileProvider + ); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Configuration/BlazorServerCurrentApplicationConfigurationCacheResetService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Configuration/BlazorServerCurrentApplicationConfigurationCacheResetService.cs index 1e3cd857e5d..02de9d8bf79 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Configuration/BlazorServerCurrentApplicationConfigurationCacheResetService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Configuration/BlazorServerCurrentApplicationConfigurationCacheResetService.cs @@ -4,26 +4,25 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace Volo.Abp.AspNetCore.Components.Server.Configuration +namespace Volo.Abp.AspNetCore.Components.Server.Configuration; + +[Dependency(ReplaceServices = true)] +public class BlazorServerCurrentApplicationConfigurationCacheResetService : + ICurrentApplicationConfigurationCacheResetService, + ITransientDependency { - [Dependency(ReplaceServices = true)] - public class BlazorServerCurrentApplicationConfigurationCacheResetService : - ICurrentApplicationConfigurationCacheResetService, - ITransientDependency - { - private readonly ILocalEventBus _localEventBus; + private readonly ILocalEventBus _localEventBus; - public BlazorServerCurrentApplicationConfigurationCacheResetService( - ILocalEventBus localEventBus) - { - _localEventBus = localEventBus; - } + public BlazorServerCurrentApplicationConfigurationCacheResetService( + ILocalEventBus localEventBus) + { + _localEventBus = localEventBus; + } - public async Task ResetAsync() - { - await _localEventBus.PublishAsync( - new CurrentApplicationConfigurationCacheResetEventData() - ); - } + public async Task ResetAsync() + { + await _localEventBus.PublishAsync( + new CurrentApplicationConfigurationCacheResetEventData() + ); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Extensibility/BlazorServerLookupApiRequestService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Extensibility/BlazorServerLookupApiRequestService.cs index 952a2d6de43..2071e40f0bc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Extensibility/BlazorServerLookupApiRequestService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/Extensibility/BlazorServerLookupApiRequestService.cs @@ -13,78 +13,77 @@ using Volo.Abp.Http.Client.Authentication; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.Components.Server.Extensibility +namespace Volo.Abp.AspNetCore.Components.Server.Extensibility; + +public class BlazorServerLookupApiRequestService : ILookupApiRequestService, ITransientDependency { - public class BlazorServerLookupApiRequestService : ILookupApiRequestService, ITransientDependency + public IHttpClientFactory HttpClientFactory { get; } + public IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; } + public IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; } + public ICurrentTenant CurrentTenant { get; } + public IHttpContextAccessor HttpContextAccessor { get; } + public NavigationManager NavigationManager { get; } + + public BlazorServerLookupApiRequestService(IHttpClientFactory httpClientFactory, + IRemoteServiceHttpClientAuthenticator httpClientAuthenticator, + ICurrentTenant currentTenant, + IHttpContextAccessor httpContextAccessor, + NavigationManager navigationManager, + IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider) { - public IHttpClientFactory HttpClientFactory { get; } - public IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; } - public IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; } - public ICurrentTenant CurrentTenant { get; } - public IHttpContextAccessor HttpContextAccessor { get; } - public NavigationManager NavigationManager { get; } + HttpClientFactory = httpClientFactory; + HttpClientAuthenticator = httpClientAuthenticator; + CurrentTenant = currentTenant; + HttpContextAccessor = httpContextAccessor; + NavigationManager = navigationManager; + RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider; + } - public BlazorServerLookupApiRequestService(IHttpClientFactory httpClientFactory, - IRemoteServiceHttpClientAuthenticator httpClientAuthenticator, - ICurrentTenant currentTenant, - IHttpContextAccessor httpContextAccessor, - NavigationManager navigationManager, - IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider) - { - HttpClientFactory = httpClientFactory; - HttpClientAuthenticator = httpClientAuthenticator; - CurrentTenant = currentTenant; - HttpContextAccessor = httpContextAccessor; - NavigationManager = navigationManager; - RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider; - } + public async Task SendAsync(string url) + { + var client = HttpClientFactory.CreateClient(); + var requestMessage = new HttpRequestMessage(HttpMethod.Get, url); - public async Task SendAsync(string url) + var uri = new Uri(url, UriKind.RelativeOrAbsolute); + if (!uri.IsAbsoluteUri) { - var client = HttpClientFactory.CreateClient(); - var requestMessage = new HttpRequestMessage(HttpMethod.Get, url); - - var uri = new Uri(url, UriKind.RelativeOrAbsolute); - if (!uri.IsAbsoluteUri) + var baseUrl = string.Empty; + try { - var baseUrl = string.Empty; - try - { - //Blazor tiered -- mode - var remoteServiceConfig = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Default"); - baseUrl = remoteServiceConfig.BaseUrl; - client.BaseAddress = new Uri(baseUrl); - AddHeaders(requestMessage); - await HttpClientAuthenticator.Authenticate(new RemoteServiceHttpClientAuthenticateContext(client, - requestMessage, new RemoteServiceConfiguration(baseUrl), string.Empty)); - } - catch (AbpException) // Blazor-Server mode. + //Blazor tiered -- mode + var remoteServiceConfig = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Default"); + baseUrl = remoteServiceConfig.BaseUrl; + client.BaseAddress = new Uri(baseUrl); + AddHeaders(requestMessage); + await HttpClientAuthenticator.Authenticate(new RemoteServiceHttpClientAuthenticateContext(client, + requestMessage, new RemoteServiceConfiguration(baseUrl), string.Empty)); + } + catch (AbpException) // Blazor-Server mode. + { + baseUrl = NavigationManager.BaseUri; + client.BaseAddress = new Uri(baseUrl); + foreach (var header in HttpContextAccessor.HttpContext.Request.Headers) { - baseUrl = NavigationManager.BaseUri; - client.BaseAddress = new Uri(baseUrl); - foreach (var header in HttpContextAccessor.HttpContext.Request.Headers) - { - requestMessage.Headers.Add(header.Key, header.Value.ToArray()); - } + requestMessage.Headers.Add(header.Key, header.Value.ToArray()); } } - - var response = await client.SendAsync(requestMessage); - return await response.Content.ReadAsStringAsync(); } - protected virtual void AddHeaders(HttpRequestMessage requestMessage) + var response = await client.SendAsync(requestMessage); + return await response.Content.ReadAsStringAsync(); + } + + protected virtual void AddHeaders(HttpRequestMessage requestMessage) + { + if (CurrentTenant.Id.HasValue) { - if (CurrentTenant.Id.HasValue) - { - requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString()); - } + requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString()); + } - var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name; - if (!currentCulture.IsNullOrEmpty()) - { - requestMessage.Headers.AcceptLanguage.Add(new(currentCulture)); - } + var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name; + if (!currentCulture.IsNullOrEmpty()) + { + requestMessage.Headers.AcceptLanguage.Add(new(currentCulture)); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/AbpAspNetCoreComponentsWebThemingModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/AbpAspNetCoreComponentsWebThemingModule.cs index e5c71c8496c..e2a0617b906 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/AbpAspNetCoreComponentsWebThemingModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/AbpAspNetCoreComponentsWebThemingModule.cs @@ -2,14 +2,13 @@ using Volo.Abp.Modularity; using Volo.Abp.UI.Navigation; -namespace Volo.Abp.AspNetCore.Components.Web.Theming +namespace Volo.Abp.AspNetCore.Components.Web.Theming; + +[DependsOn( + typeof(AbpBlazoriseUIModule), + typeof(AbpUiNavigationModule) + )] +public class AbpAspNetCoreComponentsWebThemingModule : AbpModule { - [DependsOn( - typeof(AbpBlazoriseUIModule), - typeof(AbpUiNavigationModule) - )] - public class AbpAspNetCoreComponentsWebThemingModule : AbpModule - { - - } -} \ No newline at end of file + +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs index 7806aa4b445..594909cd52a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs @@ -5,69 +5,68 @@ using Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; using Volo.Abp.BlazoriseUI; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Layout +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Layout; + +public partial class PageHeader : ComponentBase { - public partial class PageHeader : ComponentBase - { - protected List ToolbarItemRenders { get; set; } - - public IPageToolbarManager PageToolbarManager { get; set; } - - [Parameter] - public string Title { get; set; } + protected List ToolbarItemRenders { get; set; } - [Parameter] - public bool BreadcrumbShowHome { get; set; } = true; + public IPageToolbarManager PageToolbarManager { get; set; } - [Parameter] - public bool BreadcrumbShowCurrent { get; set; } = true; + [Parameter] + public string Title { get; set; } - [Parameter] - public RenderFragment ChildContent { get; set; } + [Parameter] + public bool BreadcrumbShowHome { get; set; } = true; - [Parameter] - public List BreadcrumbItems { get; set; } - - [Parameter] - public PageToolbar Toolbar { get; set; } + [Parameter] + public bool BreadcrumbShowCurrent { get; set; } = true; - public PageHeader() - { - BreadcrumbItems = new List(); - ToolbarItemRenders = new List(); - } + [Parameter] + public RenderFragment ChildContent { get; set; } + + [Parameter] + public List BreadcrumbItems { get; set; } + + [Parameter] + public PageToolbar Toolbar { get; set; } + + public PageHeader() + { + BreadcrumbItems = new List(); + ToolbarItemRenders = new List(); + } - protected override async Task OnParametersSetAsync() + protected override async Task OnParametersSetAsync() + { + await base.OnParametersSetAsync(); + if (Toolbar != null) { - await base.OnParametersSetAsync(); - if (Toolbar!=null) - { - var toolbarItems = await PageToolbarManager.GetItemsAsync(Toolbar); - ToolbarItemRenders.Clear(); + var toolbarItems = await PageToolbarManager.GetItemsAsync(Toolbar); + ToolbarItemRenders.Clear(); - foreach (var item in toolbarItems) + foreach (var item in toolbarItems) + { + var sequence = 0; + ToolbarItemRenders.Add(builder => { - var sequence = 0; - ToolbarItemRenders.Add(builder => + builder.OpenComponent(sequence, item.ComponentType); + if (item.Arguments != null) { - builder.OpenComponent(sequence, item.ComponentType); - if (item.Arguments != null) + foreach (var argument in item.Arguments) { - foreach (var argument in item.Arguments) - { - sequence++; - builder.AddAttribute(sequence, argument.Key, argument.Value); - } + sequence++; + builder.AddAttribute(sequence, argument.Key, argument.Value); } - builder.CloseComponent(); - }); - } + } + builder.CloseComponent(); + }); } } + } - protected override async Task OnInitializedAsync() - { - await base.OnInitializedAsync(); - } + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/IPageToolbarContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/IPageToolbarContributor.cs index dd04c0a1ff5..426fdde4c9e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/IPageToolbarContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/IPageToolbarContributor.cs @@ -1,9 +1,8 @@ using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public interface IPageToolbarContributor { - public interface IPageToolbarContributor - { - Task ContributeAsync(PageToolbarContributionContext context); - } + Task ContributeAsync(PageToolbarContributionContext context); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/IPageToolbarManager.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/IPageToolbarManager.cs index 507fa8070b1..87e256b1ce7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/IPageToolbarManager.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/IPageToolbarManager.cs @@ -1,9 +1,8 @@ using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public interface IPageToolbarManager { - public interface IPageToolbarManager - { - Task GetItemsAsync(PageToolbar toolbar); - } + Task GetItemsAsync(PageToolbar toolbar); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbar.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbar.cs index 84a9bae7c42..f1fb792996e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbar.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbar.cs @@ -1,12 +1,11 @@ -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public class PageToolbar { - public class PageToolbar - { - public PageToolbarContributorList Contributors { get; set; } + public PageToolbarContributorList Contributors { get; set; } - public PageToolbar() - { - Contributors = new PageToolbarContributorList(); - } + public PageToolbar() + { + Contributors = new PageToolbarContributorList(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributionContext.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributionContext.cs index 5544510b717..057777cfdf9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributionContext.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributionContext.cs @@ -1,21 +1,20 @@ using JetBrains.Annotations; using System; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public class PageToolbarContributionContext { - public class PageToolbarContributionContext - { - [NotNull] - public IServiceProvider ServiceProvider { get; } + [NotNull] + public IServiceProvider ServiceProvider { get; } - [NotNull] - public PageToolbarItemList Items { get; } + [NotNull] + public PageToolbarItemList Items { get; } - public PageToolbarContributionContext( - [NotNull] IServiceProvider serviceProvider) - { - ServiceProvider = Check.NotNull(serviceProvider, nameof(serviceProvider)); - Items = new PageToolbarItemList(); - } + public PageToolbarContributionContext( + [NotNull] IServiceProvider serviceProvider) + { + ServiceProvider = Check.NotNull(serviceProvider, nameof(serviceProvider)); + Items = new PageToolbarItemList(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributor.cs index 3c5196c449b..87521c592f0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributor.cs @@ -1,9 +1,8 @@ using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public abstract class PageToolbarContributor : IPageToolbarContributor { - public abstract class PageToolbarContributor : IPageToolbarContributor - { - public abstract Task ContributeAsync(PageToolbarContributionContext context); - } + public abstract Task ContributeAsync(PageToolbarContributionContext context); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributorList.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributorList.cs index 984f4618dc0..02ef1bfb001 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributorList.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarContributorList.cs @@ -1,8 +1,7 @@ using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public class PageToolbarContributorList : List { - public class PageToolbarContributorList : List - { - } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarDictionary.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarDictionary.cs index 2368ab9cafc..65c2e8a25d1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarDictionary.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarDictionary.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public class PageToolbarDictionary : Dictionary { - public class PageToolbarDictionary : Dictionary - { - } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarExtensions.cs index 3879e27e3c1..dd2063d0cfd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarExtensions.cs @@ -5,67 +5,66 @@ using Volo.Abp.BlazoriseUI.Components; using Volo.Abp.Localization; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public static class PageToolbarExtensions { - public static class PageToolbarExtensions + public static PageToolbar AddComponent( + this PageToolbar toolbar, + Dictionary arguments = null, + int order = 0, + string requiredPolicyName = null) { - public static PageToolbar AddComponent( - this PageToolbar toolbar, - Dictionary arguments = null, - int order = 0, - string requiredPolicyName = null) - { - return toolbar.AddComponent( - typeof(TComponent), + return toolbar.AddComponent( + typeof(TComponent), + arguments, + order, + requiredPolicyName + ); + } + + public static PageToolbar AddComponent( + this PageToolbar toolbar, + Type componentType, + Dictionary arguments = null, + int order = 0, + string requiredPolicyName = null) + { + toolbar.Contributors.Add( + new SimplePageToolbarContributor( + componentType, arguments, order, requiredPolicyName - ); - } - - public static PageToolbar AddComponent( - this PageToolbar toolbar, - Type componentType, - Dictionary arguments = null, - int order = 0, - string requiredPolicyName = null) - { - toolbar.Contributors.Add( - new SimplePageToolbarContributor( - componentType, - arguments, - order, - requiredPolicyName - ) - ); + ) + ); - return toolbar; - } + return toolbar; + } - public static PageToolbar AddButton( - this PageToolbar toolbar, - string text, - Func clicked, - object icon = null, - Color color = Color.Primary, - bool disabled = false, - int order = 0, - string requiredPolicyName = null) - { - toolbar.AddComponent( - new Dictionary - { + public static PageToolbar AddButton( + this PageToolbar toolbar, + string text, + Func clicked, + object icon = null, + Color color = Color.Primary, + bool disabled = false, + int order = 0, + string requiredPolicyName = null) + { + toolbar.AddComponent( + new Dictionary + { { nameof(ToolbarButton.Color), color}, { nameof(ToolbarButton.Text), text}, { nameof(ToolbarButton.Disabled), disabled}, { nameof(ToolbarButton.Icon), icon}, { nameof(ToolbarButton.Clicked),clicked}, - }, - order, - requiredPolicyName - ); + }, + order, + requiredPolicyName + ); - return toolbar; - } + return toolbar; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarItem.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarItem.cs index 0e1650a803b..f62d7704039 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarItem.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarItem.cs @@ -2,26 +2,25 @@ using System; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public class PageToolbarItem { - public class PageToolbarItem - { - [NotNull] - public Type ComponentType { get; } + [NotNull] + public Type ComponentType { get; } - [CanBeNull] - public Dictionary Arguments { get; set; } + [CanBeNull] + public Dictionary Arguments { get; set; } - public int Order { get; set; } + public int Order { get; set; } - public PageToolbarItem( - [NotNull] Type componentType, - [CanBeNull] Dictionary arguments = null, - int order = 0) - { - ComponentType = Check.NotNull(componentType, nameof(componentType)); - Arguments = arguments; - Order = order; - } + public PageToolbarItem( + [NotNull] Type componentType, + [CanBeNull] Dictionary arguments = null, + int order = 0) + { + ComponentType = Check.NotNull(componentType, nameof(componentType)); + Arguments = arguments; + Order = order; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarItemList.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarItemList.cs index 7042b2ed059..4be5e6fab1f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarItemList.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarItemList.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public class PageToolbarItemList : List { - public class PageToolbarItemList : List - { - } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarManager.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarManager.cs index adcd72f25e3..05531096d4f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarManager.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/PageToolbarManager.cs @@ -5,36 +5,35 @@ using System.Threading.Tasks; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public class PageToolbarManager : IPageToolbarManager, ITransientDependency { - public class PageToolbarManager : IPageToolbarManager, ITransientDependency + protected IHybridServiceScopeFactory ServiceScopeFactory { get; } + + public PageToolbarManager( + IHybridServiceScopeFactory serviceScopeFactory) { - protected IHybridServiceScopeFactory ServiceScopeFactory { get; } + ServiceScopeFactory = serviceScopeFactory; + } - public PageToolbarManager( - IHybridServiceScopeFactory serviceScopeFactory) + public virtual async Task GetItemsAsync(PageToolbar toolbar) + { + if (toolbar == null || !toolbar.Contributors.Any()) { - ServiceScopeFactory = serviceScopeFactory; + return Array.Empty(); } - public virtual async Task GetItemsAsync(PageToolbar toolbar) + using (var scope = ServiceScopeFactory.CreateScope()) { - if (toolbar == null || !toolbar.Contributors.Any()) - { - return Array.Empty(); - } + var context = new PageToolbarContributionContext(scope.ServiceProvider); - using (var scope = ServiceScopeFactory.CreateScope()) + foreach (var contributor in toolbar.Contributors) { - var context = new PageToolbarContributionContext(scope.ServiceProvider); - - foreach (var contributor in toolbar.Contributors) - { - await contributor.ContributeAsync(context); - } - - return context.Items.OrderBy(i => i.Order).ToArray(); + await contributor.ContributeAsync(context); } + + return context.Items.OrderBy(i => i.Order).ToArray(); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/SimplePageToolbarContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/SimplePageToolbarContributor.cs index 82afe19f7fc..d31b12e73ce 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/SimplePageToolbarContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/PageToolbars/SimplePageToolbarContributor.cs @@ -4,50 +4,49 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; + +public class SimplePageToolbarContributor : IPageToolbarContributor { - public class SimplePageToolbarContributor : IPageToolbarContributor - { - public Type ComponentType { get; } + public Type ComponentType { get; } - public Dictionary Arguments { get; set; } + public Dictionary Arguments { get; set; } - public int Order { get; } + public int Order { get; } - public string RequiredPolicyName { get; } + public string RequiredPolicyName { get; } - public SimplePageToolbarContributor( - Type componentType, - Dictionary arguments = null, - int order = 0, - string requiredPolicyName = null) - { - ComponentType = componentType; - Arguments = arguments; - Order = order; - RequiredPolicyName = requiredPolicyName; - } + public SimplePageToolbarContributor( + Type componentType, + Dictionary arguments = null, + int order = 0, + string requiredPolicyName = null) + { + ComponentType = componentType; + Arguments = arguments; + Order = order; + RequiredPolicyName = requiredPolicyName; + } - public async Task ContributeAsync(PageToolbarContributionContext context) + public async Task ContributeAsync(PageToolbarContributionContext context) + { + if (await ShouldAddComponentAsync(context)) { - if (await ShouldAddComponentAsync(context)) - { - context.Items.Add(new PageToolbarItem(ComponentType, Arguments, Order)); - } + context.Items.Add(new PageToolbarItem(ComponentType, Arguments, Order)); } + } - protected virtual async Task ShouldAddComponentAsync(PageToolbarContributionContext context) + protected virtual async Task ShouldAddComponentAsync(PageToolbarContributionContext context) + { + if (RequiredPolicyName != null) { - if (RequiredPolicyName != null) + var authorizationService = context.ServiceProvider.GetRequiredService(); + if (!await authorizationService.IsGrantedAsync(RequiredPolicyName)) { - var authorizationService = context.ServiceProvider.GetRequiredService(); - if (!await authorizationService.IsGrantedAsync(RequiredPolicyName)) - { - return false; - } + return false; } - - return true; } + + return true; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Routing/AbpRouterOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Routing/AbpRouterOptions.cs index 9655d411862..ce3b2746e45 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Routing/AbpRouterOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Routing/AbpRouterOptions.cs @@ -1,16 +1,15 @@ using System.Reflection; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Routing +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Routing; + +public class AbpRouterOptions { - public class AbpRouterOptions - { - public Assembly AppAssembly { get; set; } + public Assembly AppAssembly { get; set; } - public RouterAssemblyList AdditionalAssemblies { get; } + public RouterAssemblyList AdditionalAssemblies { get; } - public AbpRouterOptions() - { - AdditionalAssemblies = new RouterAssemblyList(); - } + public AbpRouterOptions() + { + AdditionalAssemblies = new RouterAssemblyList(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Routing/RouterAssemblyList.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Routing/RouterAssemblyList.cs index ea1153ff1f8..ad9d5ea404f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Routing/RouterAssemblyList.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Routing/RouterAssemblyList.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using System.Reflection; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Routing +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Routing; + +public class RouterAssemblyList : List { - public class RouterAssemblyList : List - { - - } -} \ No newline at end of file + +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/AbpToolbarOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/AbpToolbarOptions.cs index a2bae7460da..b713386359c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/AbpToolbarOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/AbpToolbarOptions.cs @@ -1,16 +1,15 @@ using System.Collections.Generic; using JetBrains.Annotations; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; + +public class AbpToolbarOptions { - public class AbpToolbarOptions - { - [NotNull] - public List Contributors { get; } + [NotNull] + public List Contributors { get; } - public AbpToolbarOptions() - { - Contributors = new List(); - } + public AbpToolbarOptions() + { + Contributors = new List(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarConfigurationContext.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarConfigurationContext.cs index 8ebe76bcb4c..e2bfaf06d01 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarConfigurationContext.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarConfigurationContext.cs @@ -5,25 +5,24 @@ using Microsoft.Extensions.Localization; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; + +public interface IToolbarConfigurationContext : IServiceProviderAccessor { - public interface IToolbarConfigurationContext : IServiceProviderAccessor - { - Toolbar Toolbar { get; } + Toolbar Toolbar { get; } - IAuthorizationService AuthorizationService { get; } + IAuthorizationService AuthorizationService { get; } - IStringLocalizerFactory StringLocalizerFactory { get; } + IStringLocalizerFactory StringLocalizerFactory { get; } - Task IsGrantedAsync(string policyName); + Task IsGrantedAsync(string policyName); - [CanBeNull] - IStringLocalizer GetDefaultLocalizer(); + [CanBeNull] + IStringLocalizer GetDefaultLocalizer(); - [NotNull] - public IStringLocalizer GetLocalizer(); + [NotNull] + public IStringLocalizer GetLocalizer(); - [NotNull] - public IStringLocalizer GetLocalizer(Type resourceType); - } + [NotNull] + public IStringLocalizer GetLocalizer(Type resourceType); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarContributor.cs index 6a5de9c1c95..c56f964265a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarContributor.cs @@ -1,9 +1,8 @@ using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; + +public interface IToolbarContributor { - public interface IToolbarContributor - { - Task ConfigureToolbarAsync(IToolbarConfigurationContext context); - } -} \ No newline at end of file + Task ConfigureToolbarAsync(IToolbarConfigurationContext context); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarManager.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarManager.cs index 0550ce75b69..df36b9ca329 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarManager.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/IToolbarManager.cs @@ -1,9 +1,8 @@ using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; + +public interface IToolbarManager { - public interface IToolbarManager - { - Task GetAsync(string name); - } + Task GetAsync(string name); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/StandardToolbars.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/StandardToolbars.cs index 7cda0d8897b..9c84d8165e8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/StandardToolbars.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/StandardToolbars.cs @@ -1,7 +1,6 @@ -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; + +public static class StandardToolbars { - public static class StandardToolbars - { - public const string Main = "Main"; - } -} \ No newline at end of file + public const string Main = "Main"; +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/Toolbar.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/Toolbar.cs index b25cc608b63..cd02da35c21 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/Toolbar.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/Toolbar.cs @@ -1,18 +1,17 @@ using System.Collections.Generic; using JetBrains.Annotations; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; + +public class Toolbar { - public class Toolbar - { - public string Name { get; } + public string Name { get; } - public List Items { get; } + public List Items { get; } - public Toolbar([NotNull] string name) - { - Name = Check.NotNull(name, nameof(name)); - Items = new List(); - } + public Toolbar([NotNull] string name) + { + Name = Check.NotNull(name, nameof(name)); + Items = new List(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarConfigurationContext.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarConfigurationContext.cs index fab4eb8f6c6..f773ba14e15 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarConfigurationContext.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarConfigurationContext.cs @@ -6,48 +6,47 @@ using Microsoft.Extensions.Localization; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; + +public class ToolbarConfigurationContext : IToolbarConfigurationContext { - public class ToolbarConfigurationContext : IToolbarConfigurationContext - { - public IServiceProvider ServiceProvider { get; } + public IServiceProvider ServiceProvider { get; } - private readonly IAbpLazyServiceProvider _lazyServiceProvider; + private readonly IAbpLazyServiceProvider _lazyServiceProvider; - public IAuthorizationService AuthorizationService => _lazyServiceProvider.LazyGetRequiredService(); + public IAuthorizationService AuthorizationService => _lazyServiceProvider.LazyGetRequiredService(); - public IStringLocalizerFactory StringLocalizerFactory => _lazyServiceProvider.LazyGetRequiredService(); + public IStringLocalizerFactory StringLocalizerFactory => _lazyServiceProvider.LazyGetRequiredService(); - public Toolbar Toolbar { get; } + public Toolbar Toolbar { get; } - public ToolbarConfigurationContext(Toolbar toolbar, IServiceProvider serviceProvider) - { - Toolbar = toolbar; - ServiceProvider = serviceProvider; - _lazyServiceProvider = ServiceProvider.GetRequiredService(); - } + public ToolbarConfigurationContext(Toolbar toolbar, IServiceProvider serviceProvider) + { + Toolbar = toolbar; + ServiceProvider = serviceProvider; + _lazyServiceProvider = ServiceProvider.GetRequiredService(); + } - public Task IsGrantedAsync(string policyName) - { - return AuthorizationService.IsGrantedAsync(policyName); - } + public Task IsGrantedAsync(string policyName) + { + return AuthorizationService.IsGrantedAsync(policyName); + } - [CanBeNull] - public IStringLocalizer GetDefaultLocalizer() - { - return StringLocalizerFactory.CreateDefaultOrNull(); - } + [CanBeNull] + public IStringLocalizer GetDefaultLocalizer() + { + return StringLocalizerFactory.CreateDefaultOrNull(); + } - [NotNull] - public IStringLocalizer GetLocalizer() - { - return StringLocalizerFactory.Create(); - } + [NotNull] + public IStringLocalizer GetLocalizer() + { + return StringLocalizerFactory.Create(); + } - [NotNull] - public IStringLocalizer GetLocalizer(Type resourceType) - { - return StringLocalizerFactory.Create(resourceType); - } + [NotNull] + public IStringLocalizer GetLocalizer(Type resourceType) + { + return StringLocalizerFactory.Create(resourceType); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarItem.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarItem.cs index d6bfcd1fb83..966145a4ee3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarItem.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarItem.cs @@ -1,23 +1,21 @@ using System; using JetBrains.Annotations; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; + +public class ToolbarItem { - public class ToolbarItem - { - public Type ComponentType - { - get => _componentType; - set => _componentType = Check.NotNull(value, nameof(value)); - } - private Type _componentType; + public Type ComponentType { + get => _componentType; + set => _componentType = Check.NotNull(value, nameof(value)); + } + private Type _componentType; - public int Order { get; set; } + public int Order { get; set; } - public ToolbarItem([NotNull] Type componentType, int order = 0) - { - Order = order; - ComponentType = Check.NotNull(componentType, nameof(componentType)); - } + public ToolbarItem([NotNull] Type componentType, int order = 0) + { + Order = order; + ComponentType = Check.NotNull(componentType, nameof(componentType)); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarManager.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarManager.cs index 86bdfc751e3..b4746fe85f8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarManager.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Toolbars/ToolbarManager.cs @@ -4,36 +4,35 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; + +public class ToolbarManager : IToolbarManager, ITransientDependency { - public class ToolbarManager : IToolbarManager, ITransientDependency + protected AbpToolbarOptions Options { get; } + protected IServiceProvider ServiceProvider { get; } + + public ToolbarManager( + IOptions options, + IServiceProvider serviceProvider) { - protected AbpToolbarOptions Options { get; } - protected IServiceProvider ServiceProvider { get; } + ServiceProvider = serviceProvider; + Options = options.Value; + } - public ToolbarManager( - IOptions options, - IServiceProvider serviceProvider) - { - ServiceProvider = serviceProvider; - Options = options.Value; - } + public async Task GetAsync(string name) + { + var toolbar = new Toolbar(name); - public async Task GetAsync(string name) + using (var scope = ServiceProvider.CreateScope()) { - var toolbar = new Toolbar(name); + var context = new ToolbarConfigurationContext(toolbar, scope.ServiceProvider); - using (var scope = ServiceProvider.CreateScope()) + foreach (var contributor in Options.Contributors) { - var context = new ToolbarConfigurationContext(toolbar, scope.ServiceProvider); - - foreach (var contributor in Options.Contributors) - { - await contributor.ConfigureToolbarAsync(context); - } + await contributor.ConfigureToolbarAsync(context); } - - return toolbar; } + + return toolbar; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreApplicationCreationOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreApplicationCreationOptions.cs index 4eab62f819d..27efa5f9985 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreApplicationCreationOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreApplicationCreationOptions.cs @@ -1,13 +1,12 @@ -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +public class AbpAspNetCoreApplicationCreationOptions { - public class AbpAspNetCoreApplicationCreationOptions - { - public AbpApplicationCreationOptions ApplicationCreationOptions { get; } + public AbpApplicationCreationOptions ApplicationCreationOptions { get; } - public AbpAspNetCoreApplicationCreationOptions( - AbpApplicationCreationOptions applicationCreationOptions) - { - ApplicationCreationOptions = applicationCreationOptions; - } + public AbpAspNetCoreApplicationCreationOptions( + AbpApplicationCreationOptions applicationCreationOptions) + { + ApplicationCreationOptions = applicationCreationOptions; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebModule.cs index ddcd839e3d1..28984ce5d04 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebModule.cs @@ -5,22 +5,21 @@ using Volo.Abp.Modularity; using Volo.Abp.UI; -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +[DependsOn( + typeof(AbpUiModule), + typeof(AbpAspNetCoreComponentsModule) + )] +public class AbpAspNetCoreComponentsWebModule : AbpModule { - [DependsOn( - typeof(AbpUiModule), - typeof(AbpAspNetCoreComponentsModule) - )] - public class AbpAspNetCoreComponentsWebModule : AbpModule + public override void PreConfigureServices(ServiceConfigurationContext context) { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - } + } - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.Replace(ServiceDescriptor.Transient()); - } + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.Replace(ServiceDescriptor.Transient()); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorClientHttpMessageHandler.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorClientHttpMessageHandler.cs index 450481a6469..eb8bee99bd3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorClientHttpMessageHandler.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorClientHttpMessageHandler.cs @@ -9,90 +9,89 @@ using Volo.Abp.AspNetCore.Components.Progression; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDependency { - public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDependency - { - private readonly IJSRuntime _jsRuntime; + private readonly IJSRuntime _jsRuntime; - private readonly ICookieService _cookieService; + private readonly ICookieService _cookieService; - private readonly NavigationManager _navigationManager; + private readonly NavigationManager _navigationManager; - private readonly IUiPageProgressService _uiPageProgressService; + private readonly IUiPageProgressService _uiPageProgressService; - private const string AntiForgeryCookieName = "XSRF-TOKEN"; + private const string AntiForgeryCookieName = "XSRF-TOKEN"; - private const string AntiForgeryHeaderName = "RequestVerificationToken"; + private const string AntiForgeryHeaderName = "RequestVerificationToken"; - public AbpBlazorClientHttpMessageHandler( - IJSRuntime jsRuntime, - ICookieService cookieService, - NavigationManager navigationManager, - IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor) - { - _jsRuntime = jsRuntime; - _cookieService = cookieService; - _navigationManager = navigationManager; - _uiPageProgressService = clientScopeServiceProviderAccessor.ServiceProvider.GetRequiredService(); - } + public AbpBlazorClientHttpMessageHandler( + IJSRuntime jsRuntime, + ICookieService cookieService, + NavigationManager navigationManager, + IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor) + { + _jsRuntime = jsRuntime; + _cookieService = cookieService; + _navigationManager = navigationManager; + _uiPageProgressService = clientScopeServiceProviderAccessor.ServiceProvider.GetRequiredService(); + } - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + try { - try + await _uiPageProgressService.Go(null, options => { - await _uiPageProgressService.Go(null, options => - { - options.Type = UiPageProgressType.Info; - }); + options.Type = UiPageProgressType.Info; + }); - await SetLanguageAsync(request, cancellationToken); - await SetAntiForgeryTokenAsync(request); + await SetLanguageAsync(request, cancellationToken); + await SetAntiForgeryTokenAsync(request); - return await base.SendAsync(request, cancellationToken); - } - finally - { - await _uiPageProgressService.Go(-1); - } + return await base.SendAsync(request, cancellationToken); } - - private async Task SetLanguageAsync(HttpRequestMessage request, CancellationToken cancellationToken) + finally { - var selectedLanguage = await _jsRuntime.InvokeAsync( - "localStorage.getItem", - cancellationToken, - "Abp.SelectedLanguage" - ); + await _uiPageProgressService.Go(-1); + } + } - if (!selectedLanguage.IsNullOrWhiteSpace()) - { - request.Headers.AcceptLanguage.Clear(); - request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(selectedLanguage)); - } + private async Task SetLanguageAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var selectedLanguage = await _jsRuntime.InvokeAsync( + "localStorage.getItem", + cancellationToken, + "Abp.SelectedLanguage" + ); + + if (!selectedLanguage.IsNullOrWhiteSpace()) + { + request.Headers.AcceptLanguage.Clear(); + request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(selectedLanguage)); } + } - private async Task SetAntiForgeryTokenAsync(HttpRequestMessage request) + private async Task SetAntiForgeryTokenAsync(HttpRequestMessage request) + { + if (request.Method == HttpMethod.Get || request.Method == HttpMethod.Head || + request.Method == HttpMethod.Trace || request.Method == HttpMethod.Options) { - if (request.Method == HttpMethod.Get || request.Method == HttpMethod.Head || - request.Method == HttpMethod.Trace || request.Method == HttpMethod.Options) - { - return; - } + return; + } - var selfUri = new Uri(_navigationManager.Uri); + var selfUri = new Uri(_navigationManager.Uri); - if (request.RequestUri.Host != selfUri.Host || request.RequestUri.Port != selfUri.Port) - { - return; - } + if (request.RequestUri.Host != selfUri.Host || request.RequestUri.Port != selfUri.Port) + { + return; + } - var token = await _cookieService.GetAsync(AntiForgeryCookieName); + var token = await _cookieService.GetAsync(AntiForgeryCookieName); - if (!token.IsNullOrWhiteSpace()) - { - request.Headers.Add(AntiForgeryHeaderName, token); - } + if (!token.IsNullOrWhiteSpace()) + { + request.Headers.Add(AntiForgeryHeaderName, token); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorMessageLocalizerHelper.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorMessageLocalizerHelper.cs index 5b5a838e17c..52efbc6d11f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorMessageLocalizerHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorMessageLocalizerHelper.cs @@ -3,46 +3,45 @@ using JetBrains.Annotations; using Microsoft.Extensions.Localization; -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +public class AbpBlazorMessageLocalizerHelper { - public class AbpBlazorMessageLocalizerHelper + private readonly IStringLocalizer stringLocalizer; + + public AbpBlazorMessageLocalizerHelper(IStringLocalizer stringLocalizer) { - private readonly IStringLocalizer stringLocalizer; + this.stringLocalizer = stringLocalizer; + } - public AbpBlazorMessageLocalizerHelper(IStringLocalizer stringLocalizer) + public string Localize(string message, [CanBeNull] IEnumerable arguments) + { + try { - this.stringLocalizer = stringLocalizer; + return arguments?.Count() > 0 + ? stringLocalizer[message, LocalizeMessageArguments(arguments)?.ToArray()] + : stringLocalizer[message]; } - - public string Localize(string message, [CanBeNull] IEnumerable arguments) + catch { - try - { - return arguments?.Count() > 0 - ? stringLocalizer[message, LocalizeMessageArguments(arguments)?.ToArray()] - : stringLocalizer[message]; - } - catch - { - return stringLocalizer[message]; - } + return stringLocalizer[message]; } + } - private IEnumerable LocalizeMessageArguments(IEnumerable arguments) + private IEnumerable LocalizeMessageArguments(IEnumerable arguments) + { + foreach (var argument in arguments) { - foreach (var argument in arguments) - { - // first try to localize with "DisplayName:{Name}" - var localization = stringLocalizer[$"DisplayName:{argument}"]; + // first try to localize with "DisplayName:{Name}" + var localization = stringLocalizer[$"DisplayName:{argument}"]; - if (localization.ResourceNotFound) - { - // then try to localize with just "{Name}" - localization = stringLocalizer[argument]; - } - - yield return localization; + if (localization.ResourceNotFound) + { + // then try to localize with just "{Name}" + localization = stringLocalizer[argument]; } + + yield return localization; } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpUtilsService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpUtilsService.cs index b80e927154a..082dd7c32fb 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpUtilsService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpUtilsService.cs @@ -2,50 +2,49 @@ using Microsoft.JSInterop; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +public class AbpUtilsService : IAbpUtilsService, ITransientDependency { - public class AbpUtilsService : IAbpUtilsService, ITransientDependency - { - protected IJSRuntime JsRuntime { get; } - - public AbpUtilsService(IJSRuntime jsRuntime) - { - JsRuntime = jsRuntime; - } - - public ValueTask AddClassToTagAsync(string tagName, string className) - { - return JsRuntime.InvokeVoidAsync("abp.utils.addClassToTag", tagName, className); - } - - public ValueTask RemoveClassFromTagAsync(string tagName, string className) - { - return JsRuntime.InvokeVoidAsync("abp.utils.removeClassFromTag", tagName, className); - } - - public ValueTask HasClassOnTagAsync(string tagName, string className) - { - return JsRuntime.InvokeAsync("abp.utils.hasClassOnTag", tagName, className); - } - - public ValueTask ReplaceLinkHrefByIdAsync(string linkId, string hrefValue) - { - return JsRuntime.InvokeVoidAsync("abp.utils.replaceLinkHrefById", linkId, hrefValue); - } - - public ValueTask ToggleFullscreenAsync() - { - return JsRuntime.InvokeVoidAsync("abp.utils.toggleFullscreen"); - } - - public ValueTask RequestFullscreenAsync() - { - return JsRuntime.InvokeVoidAsync("abp.utils.requestFullscreen"); - } - - public ValueTask ExitFullscreenAsync() - { - return JsRuntime.InvokeVoidAsync("abp.utils.exitFullscreen"); - } + protected IJSRuntime JsRuntime { get; } + + public AbpUtilsService(IJSRuntime jsRuntime) + { + JsRuntime = jsRuntime; + } + + public ValueTask AddClassToTagAsync(string tagName, string className) + { + return JsRuntime.InvokeVoidAsync("abp.utils.addClassToTag", tagName, className); + } + + public ValueTask RemoveClassFromTagAsync(string tagName, string className) + { + return JsRuntime.InvokeVoidAsync("abp.utils.removeClassFromTag", tagName, className); + } + + public ValueTask HasClassOnTagAsync(string tagName, string className) + { + return JsRuntime.InvokeAsync("abp.utils.hasClassOnTag", tagName, className); + } + + public ValueTask ReplaceLinkHrefByIdAsync(string linkId, string hrefValue) + { + return JsRuntime.InvokeVoidAsync("abp.utils.replaceLinkHrefById", linkId, hrefValue); + } + + public ValueTask ToggleFullscreenAsync() + { + return JsRuntime.InvokeVoidAsync("abp.utils.toggleFullscreen"); + } + + public ValueTask RequestFullscreenAsync() + { + return JsRuntime.InvokeVoidAsync("abp.utils.requestFullscreen"); + } + + public ValueTask ExitFullscreenAsync() + { + return JsRuntime.InvokeVoidAsync("abp.utils.exitFullscreen"); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Alerts/AlertManager.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Alerts/AlertManager.cs index aef46b97dde..218e3cbdea4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Alerts/AlertManager.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Alerts/AlertManager.cs @@ -1,15 +1,14 @@ using Volo.Abp.AspNetCore.Components.Alerts; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web.Alerts +namespace Volo.Abp.AspNetCore.Components.Web.Alerts; + +public class AlertManager : IAlertManager, IScopedDependency { - public class AlertManager : IAlertManager, IScopedDependency - { - public AlertList Alerts { get; } + public AlertList Alerts { get; } - public AlertManager() - { - Alerts = new AlertList(); - } + public AlertManager() + { + Alerts = new AlertList(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/ICurrentApplicationConfigurationCacheResetService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/ICurrentApplicationConfigurationCacheResetService.cs index b1da30825df..c3e33a9e410 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/ICurrentApplicationConfigurationCacheResetService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/ICurrentApplicationConfigurationCacheResetService.cs @@ -1,9 +1,8 @@ using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web.Configuration +namespace Volo.Abp.AspNetCore.Components.Web.Configuration; + +public interface ICurrentApplicationConfigurationCacheResetService { - public interface ICurrentApplicationConfigurationCacheResetService - { - Task ResetAsync(); - } -} \ No newline at end of file + Task ResetAsync(); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/NullCurrentApplicationConfigurationCacheResetService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/NullCurrentApplicationConfigurationCacheResetService.cs index 6eeb0e94717..bb91d707750 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/NullCurrentApplicationConfigurationCacheResetService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Configuration/NullCurrentApplicationConfigurationCacheResetService.cs @@ -1,13 +1,12 @@ using System.Threading.Tasks; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web.Configuration +namespace Volo.Abp.AspNetCore.Components.Web.Configuration; + +public class NullCurrentApplicationConfigurationCacheResetService : ICurrentApplicationConfigurationCacheResetService, ISingletonDependency { - public class NullCurrentApplicationConfigurationCacheResetService : ICurrentApplicationConfigurationCacheResetService, ISingletonDependency + public Task ResetAsync() { - public Task ResetAsync() - { - return Task.CompletedTask; - } + return Task.CompletedTask; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/CookieOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/CookieOptions.cs index 2781d9ead3c..283f665642e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/CookieOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/CookieOptions.cs @@ -1,11 +1,10 @@ using System; -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +public class CookieOptions { - public class CookieOptions - { - public DateTimeOffset? ExpireDate { get; set; } - public string Path { get; set; } - public bool Secure { get; set; } - } -} \ No newline at end of file + public DateTimeOffset? ExpireDate { get; set; } + public string Path { get; set; } + public bool Secure { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/CookieService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/CookieService.cs index ed682261a38..1b61acb459d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/CookieService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/CookieService.cs @@ -2,31 +2,30 @@ using Microsoft.JSInterop; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +[Dependency(ReplaceServices = true)] +public class CookieService : ICookieService, ITransientDependency { - [Dependency(ReplaceServices = true)] - public class CookieService : ICookieService, ITransientDependency - { - public IJSRuntime JsRuntime { get; } + public IJSRuntime JsRuntime { get; } - public CookieService(IJSRuntime jsRuntime) - { - JsRuntime = jsRuntime; - } + public CookieService(IJSRuntime jsRuntime) + { + JsRuntime = jsRuntime; + } - public async ValueTask SetAsync(string key, string value, CookieOptions options) - { - await JsRuntime.InvokeVoidAsync("abp.utils.setCookieValue", key, value, options?.ExpireDate?.ToString("r"), options?.Path, options?.Secure); - } + public async ValueTask SetAsync(string key, string value, CookieOptions options) + { + await JsRuntime.InvokeVoidAsync("abp.utils.setCookieValue", key, value, options?.ExpireDate?.ToString("r"), options?.Path, options?.Secure); + } - public async ValueTask GetAsync(string key) - { - return await JsRuntime.InvokeAsync("abp.utils.getCookieValue", key); - } + public async ValueTask GetAsync(string key) + { + return await JsRuntime.InvokeAsync("abp.utils.getCookieValue", key); + } - public async ValueTask DeleteAsync(string key, string path = null) - { - await JsRuntime.InvokeVoidAsync("abp.utils.deleteCookie", key); - } + public async ValueTask DeleteAsync(string key, string path = null) + { + await JsRuntime.InvokeVoidAsync("abp.utils.deleteCookie", key); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/DefaultServerUrlProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/DefaultServerUrlProvider.cs index 629a19d9f56..281ee3cd736 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/DefaultServerUrlProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/DefaultServerUrlProvider.cs @@ -1,13 +1,12 @@ using System.Threading.Tasks; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +public class DefaultServerUrlProvider : IServerUrlProvider, ISingletonDependency { - public class DefaultServerUrlProvider : IServerUrlProvider, ISingletonDependency + public Task GetBaseUrlAsync(string remoteServiceName = null) { - public Task GetBaseUrlAsync(string remoteServiceName = null) - { - return Task.FromResult("/"); - } + return Task.FromResult("/"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/DependencyInjection/ComponentsClientScopeServiceProviderAccessor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/DependencyInjection/ComponentsClientScopeServiceProviderAccessor.cs index 5ced9d658e1..f5e07865a70 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/DependencyInjection/ComponentsClientScopeServiceProviderAccessor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/DependencyInjection/ComponentsClientScopeServiceProviderAccessor.cs @@ -1,12 +1,11 @@ using System; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web.DependencyInjection +namespace Volo.Abp.AspNetCore.Components.Web.DependencyInjection; + +public class ComponentsClientScopeServiceProviderAccessor : + IClientScopeServiceProviderAccessor, + ISingletonDependency { - public class ComponentsClientScopeServiceProviderAccessor : - IClientScopeServiceProviderAccessor, - ISingletonDependency - { - public IServiceProvider ServiceProvider { get; set; } - } + public IServiceProvider ServiceProvider { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/AbpExceptionHandlingLogger.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/AbpExceptionHandlingLogger.cs index 755947a4814..cf66f107a07 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/AbpExceptionHandlingLogger.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/AbpExceptionHandlingLogger.cs @@ -3,64 +3,63 @@ using Microsoft.Extensions.Logging; using Volo.Abp.AspNetCore.Components.ExceptionHandling; -namespace Volo.Abp.AspNetCore.Components.Web.ExceptionHandling +namespace Volo.Abp.AspNetCore.Components.Web.ExceptionHandling; + +public class AbpExceptionHandlingLogger : ILogger { - public class AbpExceptionHandlingLogger : ILogger + private readonly IServiceCollection _serviceCollection; + private IUserExceptionInformer _userExceptionInformer; + + public AbpExceptionHandlingLogger(IServiceCollection serviceCollection) { - private readonly IServiceCollection _serviceCollection; - private IUserExceptionInformer _userExceptionInformer; + _serviceCollection = serviceCollection; + } - public AbpExceptionHandlingLogger(IServiceCollection serviceCollection) + public virtual void Log( + LogLevel logLevel, + EventId eventId, + TState state, + Exception exception, + Func formatter) + { + if (exception == null) { - _serviceCollection = serviceCollection; + return; } - public virtual void Log( - LogLevel logLevel, - EventId eventId, - TState state, - Exception exception, - Func formatter) + if (logLevel != LogLevel.Critical && logLevel != LogLevel.Error) { - if (exception == null) - { - return; - } - - if (logLevel != LogLevel.Critical && logLevel != LogLevel.Error) - { - return; - } - - TryInitialize(); - - if (_userExceptionInformer == null) - { - return; - } - - _userExceptionInformer.Inform(new UserExceptionInformerContext(exception)); + return; } - protected virtual void TryInitialize() - { - var serviceProvider = _serviceCollection.GetServiceProviderOrNull(); - if (serviceProvider == null) - { - return; - } - - _userExceptionInformer = serviceProvider.GetRequiredService(); - } + TryInitialize(); - public virtual bool IsEnabled(LogLevel logLevel) + if (_userExceptionInformer == null) { - return logLevel == LogLevel.Critical || logLevel == LogLevel.Error; + return; } - public virtual IDisposable BeginScope(TState state) + _userExceptionInformer.Inform(new UserExceptionInformerContext(exception)); + } + + protected virtual void TryInitialize() + { + var serviceProvider = _serviceCollection.GetServiceProviderOrNull(); + if (serviceProvider == null) { - return NullDisposable.Instance; + return; } + + _userExceptionInformer = serviceProvider.GetRequiredService(); + } + + public virtual bool IsEnabled(LogLevel logLevel) + { + return logLevel == LogLevel.Critical || logLevel == LogLevel.Error; + } + + public virtual IDisposable BeginScope(TState state) + { + return NullDisposable.Instance; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/AbpExceptionHandlingLoggerProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/AbpExceptionHandlingLoggerProvider.cs index 85b16d08baa..3f895502fa6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/AbpExceptionHandlingLoggerProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/AbpExceptionHandlingLoggerProvider.cs @@ -1,38 +1,37 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -namespace Volo.Abp.AspNetCore.Components.Web.ExceptionHandling +namespace Volo.Abp.AspNetCore.Components.Web.ExceptionHandling; + +public class AbpExceptionHandlingLoggerProvider : ILoggerProvider { - public class AbpExceptionHandlingLoggerProvider : ILoggerProvider - { - private AbpExceptionHandlingLogger _logger; - private static readonly object SyncObj = new object(); - private readonly IServiceCollection _serviceCollection; + private AbpExceptionHandlingLogger _logger; + private static readonly object SyncObj = new object(); + private readonly IServiceCollection _serviceCollection; - public AbpExceptionHandlingLoggerProvider(IServiceCollection serviceCollection) - { - _serviceCollection = serviceCollection; - } + public AbpExceptionHandlingLoggerProvider(IServiceCollection serviceCollection) + { + _serviceCollection = serviceCollection; + } - public ILogger CreateLogger(string categoryName) + public ILogger CreateLogger(string categoryName) + { + if (_logger == null) { - if (_logger == null) + lock (SyncObj) { - lock (SyncObj) + if (_logger == null) { - if (_logger == null) - { - _logger = new AbpExceptionHandlingLogger(_serviceCollection); - } + _logger = new AbpExceptionHandlingLogger(_serviceCollection); } } - - return _logger; } - public void Dispose() - { + return _logger; + } + + public void Dispose() + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs index ecbeb16e812..0f0da11bdf7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs @@ -9,65 +9,64 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Http; -namespace Volo.Abp.AspNetCore.Components.Web.ExceptionHandling +namespace Volo.Abp.AspNetCore.Components.Web.ExceptionHandling; + +[Dependency(ReplaceServices = true)] +public class UserExceptionInformer : IUserExceptionInformer, IScopedDependency { - [Dependency(ReplaceServices = true)] - public class UserExceptionInformer : IUserExceptionInformer, IScopedDependency + public ILogger Logger { get; set; } + protected IUiMessageService MessageService { get; } + protected IExceptionToErrorInfoConverter ExceptionToErrorInfoConverter { get; } + + protected AbpExceptionHandlingOptions Options { get; } + + public UserExceptionInformer( + IUiMessageService messageService, + IExceptionToErrorInfoConverter exceptionToErrorInfoConverter, + IOptions options) + { + MessageService = messageService; + ExceptionToErrorInfoConverter = exceptionToErrorInfoConverter; + Options = options.Value; + Logger = NullLogger.Instance; + } + + public void Inform(UserExceptionInformerContext context) { - public ILogger Logger { get; set; } - protected IUiMessageService MessageService { get; } - protected IExceptionToErrorInfoConverter ExceptionToErrorInfoConverter { get; } + //TODO: Create sync versions of the MessageService APIs. - protected AbpExceptionHandlingOptions Options { get; } + var errorInfo = GetErrorInfo(context); - public UserExceptionInformer( - IUiMessageService messageService, - IExceptionToErrorInfoConverter exceptionToErrorInfoConverter, - IOptions options) + if (errorInfo.Details.IsNullOrEmpty()) { - MessageService = messageService; - ExceptionToErrorInfoConverter = exceptionToErrorInfoConverter; - Options = options.Value; - Logger = NullLogger.Instance; + MessageService.Error(errorInfo.Message); } - - public void Inform(UserExceptionInformerContext context) + else { - //TODO: Create sync versions of the MessageService APIs. + MessageService.Error(errorInfo.Details, errorInfo.Message); + } + } - var errorInfo = GetErrorInfo(context); + public async Task InformAsync(UserExceptionInformerContext context) + { + var errorInfo = GetErrorInfo(context); - if (errorInfo.Details.IsNullOrEmpty()) - { - MessageService.Error(errorInfo.Message); - } - else - { - MessageService.Error(errorInfo.Details, errorInfo.Message); - } + if (errorInfo.Details.IsNullOrEmpty()) + { + await MessageService.Error(errorInfo.Message); } - - public async Task InformAsync(UserExceptionInformerContext context) + else { - var errorInfo = GetErrorInfo(context); - - if (errorInfo.Details.IsNullOrEmpty()) - { - await MessageService.Error(errorInfo.Message); - } - else - { - await MessageService.Error(errorInfo.Details, errorInfo.Message); - } + await MessageService.Error(errorInfo.Details, errorInfo.Message); } + } - protected virtual RemoteServiceErrorInfo GetErrorInfo(UserExceptionInformerContext context) + protected virtual RemoteServiceErrorInfo GetErrorInfo(UserExceptionInformerContext context) + { + return ExceptionToErrorInfoConverter.Convert(context.Exception, options => { - return ExceptionToErrorInfoConverter.Convert(context.Exception, options => - { - options.SendExceptionsDetailsToClients = Options.SendExceptionsDetailsToClients; - options.SendStackTraceToClients = Options.SendStackTraceToClients; - }); - } + options.SendExceptionsDetailsToClients = Options.SendExceptionsDetailsToClients; + options.SendStackTraceToClients = Options.SendStackTraceToClients; + }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/EntityActions/EntityAction.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/EntityActions/EntityAction.cs index 61bea5c27ac..2f800c72579 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/EntityActions/EntityAction.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/EntityActions/EntityAction.cs @@ -1,20 +1,19 @@ using System; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions +namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions; + +public class EntityAction : IEquatable { - public class EntityAction : IEquatable + public string Text { get; set; } + public Func Clicked { get; set; } + public Func ConfirmationMessage { get; set; } + public bool Primary { get; set; } + public object Color { get; set; } + public string Icon { get; set; } + public Func Visible { get; set; } + public bool Equals(EntityAction other) { - public string Text { get; set; } - public Func Clicked { get; set; } - public Func ConfirmationMessage { get; set; } - public bool Primary { get; set; } - public object Color { get; set; } - public string Icon { get; set; } - public Func Visible { get; set; } - public bool Equals(EntityAction other) - { - return string.Equals(Text, other?.Text, StringComparison.OrdinalIgnoreCase); - } + return string.Equals(Text, other?.Text, StringComparison.OrdinalIgnoreCase); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/EntityActions/EntityActionDictionary.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/EntityActions/EntityActionDictionary.cs index 36117abb375..0781870b69b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/EntityActions/EntityActionDictionary.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/EntityActions/EntityActionDictionary.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions +namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions; + +public class EntityActionDictionary : Dictionary> { - public class EntityActionDictionary : Dictionary> + public List Get() { - public List Get() - { - return this.GetOrAdd(typeof(T).FullName, () => new List()); - } + return this.GetOrAdd(typeof(T).FullName, () => new List()); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/ILookupApiRequestService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/ILookupApiRequestService.cs index 2351606306e..f4b3e26e47d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/ILookupApiRequestService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/ILookupApiRequestService.cs @@ -1,10 +1,9 @@ using System.Threading.Tasks; using JetBrains.Annotations; -namespace Volo.Abp.AspNetCore.Components.Web.Extensibility +namespace Volo.Abp.AspNetCore.Components.Web.Extensibility; + +public interface ILookupApiRequestService { - public interface ILookupApiRequestService - { - Task SendAsync([NotNull]string url); - } -} \ No newline at end of file + Task SendAsync([NotNull] string url); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs index 2121b8a1287..9a6a40a17ad 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs @@ -4,25 +4,24 @@ using System.Globalization; using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions; -namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns +namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns; + +public class TableColumn { - public class TableColumn - { - public string Title { get; set; } - public string Data { get; set; } - [CanBeNull] - public string DisplayFormat { get; set; } - public IFormatProvider DisplayFormatProvider { get; set; } = CultureInfo.CurrentCulture; - [CanBeNull] - public Type Component { get; set; } - public List Actions { get; set; } - [CanBeNull] - public Func ValueConverter { get; set; } - public bool Sortable { get; set; } + public string Title { get; set; } + public string Data { get; set; } + [CanBeNull] + public string DisplayFormat { get; set; } + public IFormatProvider DisplayFormatProvider { get; set; } = CultureInfo.CurrentCulture; + [CanBeNull] + public Type Component { get; set; } + public List Actions { get; set; } + [CanBeNull] + public Func ValueConverter { get; set; } + public bool Sortable { get; set; } - public TableColumn() - { - Actions = new List(); - } + public TableColumn() + { + Actions = new List(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumnDictionary.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumnDictionary.cs index a68ad437d45..7eda70177c6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumnDictionary.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumnDictionary.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns +namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns; + +public class TableColumnDictionary : Dictionary> { - public class TableColumnDictionary : Dictionary> + public List Get() { - public List Get() - { - return this.GetOrAdd(typeof(T).FullName, () => new List()); - } + return this.GetOrAdd(typeof(T).FullName, () => new List()); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/IAbpUtilsService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/IAbpUtilsService.cs index a149691ba4d..732ce11b4bf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/IAbpUtilsService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/IAbpUtilsService.cs @@ -1,21 +1,20 @@ using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +public interface IAbpUtilsService { - public interface IAbpUtilsService - { - ValueTask AddClassToTagAsync(string tagName, string className); + ValueTask AddClassToTagAsync(string tagName, string className); - ValueTask RemoveClassFromTagAsync(string tagName, string className); + ValueTask RemoveClassFromTagAsync(string tagName, string className); - ValueTask HasClassOnTagAsync(string tagName, string className); + ValueTask HasClassOnTagAsync(string tagName, string className); - ValueTask ReplaceLinkHrefByIdAsync(string linkId, string hrefValue); + ValueTask ReplaceLinkHrefByIdAsync(string linkId, string hrefValue); - ValueTask ToggleFullscreenAsync(); + ValueTask ToggleFullscreenAsync(); - ValueTask RequestFullscreenAsync(); + ValueTask RequestFullscreenAsync(); - ValueTask ExitFullscreenAsync(); - } + ValueTask ExitFullscreenAsync(); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ICookieService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ICookieService.cs index 8f397bf5548..afb124644e6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ICookieService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ICookieService.cs @@ -1,11 +1,10 @@ using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +public interface ICookieService { - public interface ICookieService - { - public ValueTask SetAsync(string key, string value, CookieOptions options = null); - public ValueTask GetAsync(string key); - public ValueTask DeleteAsync(string key, string path = null); - } -} \ No newline at end of file + public ValueTask SetAsync(string key, string value, CookieOptions options = null); + public ValueTask GetAsync(string key); + public ValueTask DeleteAsync(string key, string path = null); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/IServerUrlProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/IServerUrlProvider.cs index fffec2f606e..f5266a9f187 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/IServerUrlProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/IServerUrlProvider.cs @@ -1,9 +1,8 @@ using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Web +namespace Volo.Abp.AspNetCore.Components.Web; + +public interface IServerUrlProvider { - public interface IServerUrlProvider - { - Task GetBaseUrlAsync(string remoteServiceName = null); - } -} \ No newline at end of file + Task GetBaseUrlAsync(string remoteServiceName = null); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Messages/SimpleUiMessageService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Messages/SimpleUiMessageService.cs index cc82625b4c7..647be65b413 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Messages/SimpleUiMessageService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Messages/SimpleUiMessageService.cs @@ -4,40 +4,39 @@ using Volo.Abp.AspNetCore.Components.Messages; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web.Messages +namespace Volo.Abp.AspNetCore.Components.Web.Messages; + +public class SimpleUiMessageService : IUiMessageService, ITransientDependency { - public class SimpleUiMessageService : IUiMessageService, ITransientDependency + protected IJSRuntime JsRuntime { get; } + + public SimpleUiMessageService(IJSRuntime jsRuntime) + { + JsRuntime = jsRuntime; + } + + public async Task Info(string message, string title = null, Action options = null) + { + await JsRuntime.InvokeVoidAsync("alert", message); + } + + public async Task Success(string message, string title = null, Action options = null) + { + await JsRuntime.InvokeVoidAsync("alert", message); + } + + public async Task Warn(string message, string title = null, Action options = null) + { + await JsRuntime.InvokeVoidAsync("alert", message); + } + + public async Task Error(string message, string title = null, Action options = null) + { + await JsRuntime.InvokeVoidAsync("alert", message); + } + + public async Task Confirm(string message, string title = null, Action options = null) { - protected IJSRuntime JsRuntime { get; } - - public SimpleUiMessageService(IJSRuntime jsRuntime) - { - JsRuntime = jsRuntime; - } - - public async Task Info(string message, string title = null, Action options = null) - { - await JsRuntime.InvokeVoidAsync("alert", message); - } - - public async Task Success(string message, string title = null, Action options = null) - { - await JsRuntime.InvokeVoidAsync("alert", message); - } - - public async Task Warn(string message, string title = null, Action options = null) - { - await JsRuntime.InvokeVoidAsync("alert", message); - } - - public async Task Error(string message, string title = null, Action options = null) - { - await JsRuntime.InvokeVoidAsync("alert", message); - } - - public async Task Confirm(string message, string title = null, Action options = null) - { - return await JsRuntime.InvokeAsync("confirm", message); - } + return await JsRuntime.InvokeAsync("confirm", message); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs index 787bf5cb6eb..bb053eac212 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs @@ -5,39 +5,38 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Web.Security +namespace Volo.Abp.AspNetCore.Components.Web.Security; + +[ExposeServices( + typeof(AbpComponentsClaimsCache), + typeof(IAsyncInitialize) +)] +public class AbpComponentsClaimsCache : IScopedDependency, IAsyncInitialize { - [ExposeServices( - typeof(AbpComponentsClaimsCache), - typeof(IAsyncInitialize) - )] - public class AbpComponentsClaimsCache : IScopedDependency, IAsyncInitialize - { - public ClaimsPrincipal Principal { get; private set; } + public ClaimsPrincipal Principal { get; private set; } - [CanBeNull] - private readonly AuthenticationStateProvider _authenticationStateProvider; + [CanBeNull] + private readonly AuthenticationStateProvider _authenticationStateProvider; - public AbpComponentsClaimsCache( - IClientScopeServiceProviderAccessor serviceProviderAccessor) + public AbpComponentsClaimsCache( + IClientScopeServiceProviderAccessor serviceProviderAccessor) + { + _authenticationStateProvider = serviceProviderAccessor.ServiceProvider.GetService(); + if (_authenticationStateProvider != null) { - _authenticationStateProvider = serviceProviderAccessor.ServiceProvider.GetService(); - if (_authenticationStateProvider != null) + _authenticationStateProvider.AuthenticationStateChanged += async (task) => { - _authenticationStateProvider.AuthenticationStateChanged += async (task) => - { - Principal = (await task).User; - }; - } + Principal = (await task).User; + }; } + } - public virtual async Task InitializeAsync() + public virtual async Task InitializeAsync() + { + if (_authenticationStateProvider != null) { - if (_authenticationStateProvider != null) - { - var authenticationState = await _authenticationStateProvider.GetAuthenticationStateAsync(); - Principal = authenticationState.User; - } + var authenticationState = await _authenticationStateProvider.GetAuthenticationStateAsync(); + Principal = authenticationState.User; } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/AbpAspNetCoreComponentsWebAssemblyThemingModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/AbpAspNetCoreComponentsWebAssemblyThemingModule.cs index a19df06bc70..38eff974b8c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/AbpAspNetCoreComponentsWebAssemblyThemingModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/AbpAspNetCoreComponentsWebAssemblyThemingModule.cs @@ -1,14 +1,13 @@ using Volo.Abp.AspNetCore.Components.Web.Theming; using Volo.Abp.Modularity; -namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming +namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming; + +[DependsOn( + typeof(AbpAspNetCoreComponentsWebThemingModule), + typeof(AbpAspNetCoreComponentsWebAssemblyModule) +)] +public class AbpAspNetCoreComponentsWebAssemblyThemingModule : AbpModule { - [DependsOn( - typeof(AbpAspNetCoreComponentsWebThemingModule), - typeof(AbpAspNetCoreComponentsWebAssemblyModule) - )] - public class AbpAspNetCoreComponentsWebAssemblyThemingModule : AbpModule - { - } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/ComponentsComponentsBundleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/ComponentsComponentsBundleContributor.cs index 69933bd95f5..61f42e82223 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/ComponentsComponentsBundleContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/ComponentsComponentsBundleContributor.cs @@ -1,31 +1,30 @@ using Volo.Abp.Bundling; -namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming +namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming; + +public class ComponentsComponentsBundleContributor : IBundleContributor { - public class ComponentsComponentsBundleContributor : IBundleContributor + public void AddScripts(BundleContext context) { - public void AddScripts(BundleContext context) - { - context.Add("_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"); - context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/abp.js"); - context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/lang-utils.js"); - } + context.Add("_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"); + context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/abp.js"); + context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/lang-utils.js"); + } - public void AddStyles(BundleContext context) + public void AddStyles(BundleContext context) + { + context.BundleDefinitions.Insert(0, new BundleDefinition + { + Source = "_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/bootstrap/css/bootstrap.min.css" + }); + context.BundleDefinitions.Insert(1, new BundleDefinition { - context.BundleDefinitions.Insert(0, new BundleDefinition - { - Source = "_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/bootstrap/css/bootstrap.min.css" - }); - context.BundleDefinitions.Insert(1, new BundleDefinition - { - Source = "_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/fontawesome/css/all.css" - }); + Source = "_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/fontawesome/css/all.css" + }); - context.Add("_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/flag-icon/css/flag-icon.css"); - context.Add("_content/Blazorise/blazorise.css"); - context.Add("_content/Blazorise.Bootstrap5/blazorise.bootstrap5.css"); - context.Add("_content/Blazorise.Snackbar/blazorise.snackbar.css"); - } + context.Add("_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/flag-icon/css/flag-icon.css"); + context.Add("_content/Blazorise/blazorise.css"); + context.Add("_content/Blazorise.Bootstrap5/blazorise.bootstrap5.css"); + context.Add("_content/Blazorise.Snackbar/blazorise.snackbar.css"); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyHostBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyHostBuilderExtensions.cs index f05feacae8f..5c77dcff493 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyHostBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/AspNetCore/Components/WebAssembly/Hosting/AbpWebAssemblyHostBuilderExtensions.cs @@ -13,74 +13,97 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Modularity; -namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting +namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting; + +public static class AbpWebAssemblyHostBuilderExtensions { - public static class AbpWebAssemblyHostBuilderExtensions + public async static Task AddApplicationAsync( + [NotNull] this WebAssemblyHostBuilder builder, + Action options) + where TStartupModule : IAbpModule { - public static IAbpApplicationWithExternalServiceProvider AddApplication( - [NotNull] this WebAssemblyHostBuilder builder, - Action options) - where TStartupModule : IAbpModule + Check.NotNull(builder, nameof(builder)); + + // Related this commit(https://github.com/dotnet/aspnetcore/commit/b99d805bc037fcac56afb79abeb7d5a43141c85e) + // Microsoft.AspNetCore.Blazor.BuildTools has been removed in net 5.0. + // This call may be removed when we find a suitable solution. + // System.Runtime.CompilerServices.AsyncStateMachineAttribute + Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(); + + builder.Services.AddSingleton(builder.Configuration); + builder.Services.AddSingleton(builder); + + var application = await builder.Services.AddApplicationAsync(opts => { - Check.NotNull(builder, nameof(builder)); + options?.Invoke(new AbpWebAssemblyApplicationCreationOptions(builder, opts)); + }); - // Related this commit(https://github.com/dotnet/aspnetcore/commit/b99d805bc037fcac56afb79abeb7d5a43141c85e) - // Microsoft.AspNetCore.Blazor.BuildTools has been removed in net 5.0. - // This call may be removed when we find a suitable solution. - // System.Runtime.CompilerServices.AsyncStateMachineAttribute - Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(); + return application; + } - builder.Services.AddSingleton(builder.Configuration); - builder.Services.AddSingleton(builder); + public static IAbpApplicationWithExternalServiceProvider AddApplication( + [NotNull] this WebAssemblyHostBuilder builder, + Action options) + where TStartupModule : IAbpModule + { + Check.NotNull(builder, nameof(builder)); - var application = builder.Services.AddApplication(opts => - { - options?.Invoke(new AbpWebAssemblyApplicationCreationOptions(builder, opts)); - }); + // Related this commit(https://github.com/dotnet/aspnetcore/commit/b99d805bc037fcac56afb79abeb7d5a43141c85e) + // Microsoft.AspNetCore.Blazor.BuildTools has been removed in net 5.0. + // This call may be removed when we find a suitable solution. + // System.Runtime.CompilerServices.AsyncStateMachineAttribute + Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(); - return application; - } + builder.Services.AddSingleton(builder.Configuration); + builder.Services.AddSingleton(builder); - public static async Task InitializeAsync( - [NotNull] this IAbpApplicationWithExternalServiceProvider application, - [NotNull] IServiceProvider serviceProvider) + var application = builder.Services.AddApplication(opts => { - Check.NotNull(application, nameof(application)); - Check.NotNull(serviceProvider, nameof(serviceProvider)); + options?.Invoke(new AbpWebAssemblyApplicationCreationOptions(builder, opts)); + }); - ((ComponentsClientScopeServiceProviderAccessor) serviceProvider - .GetRequiredService()).ServiceProvider = serviceProvider; + return application; + } - application.Initialize(serviceProvider); - await InitializeModulesAsync(serviceProvider); - await SetCurrentLanguageAsync(serviceProvider); + public async static Task InitializeApplicationAsync( + [NotNull] this IAbpApplicationWithExternalServiceProvider application, + [NotNull] IServiceProvider serviceProvider) + { + Check.NotNull(application, nameof(application)); + Check.NotNull(serviceProvider, nameof(serviceProvider)); + + ((ComponentsClientScopeServiceProviderAccessor)serviceProvider + .GetRequiredService()).ServiceProvider = serviceProvider; + + await application.InitializeAsync(serviceProvider); + await InitializeModulesAsync(serviceProvider); + await SetCurrentLanguageAsync(serviceProvider); + } + + private async static Task InitializeModulesAsync(IServiceProvider serviceProvider) + { + foreach (var service in serviceProvider.GetServices()) + { + await service.InitializeAsync(); } + } - private static async Task InitializeModulesAsync(IServiceProvider serviceProvider) + private async static Task SetCurrentLanguageAsync(IServiceProvider serviceProvider) + { + var configurationClient = serviceProvider.GetRequiredService(); + var utilsService = serviceProvider.GetRequiredService(); + var configuration = await configurationClient.GetAsync(); + var cultureName = configuration.Localization?.CurrentCulture?.CultureName; + if (!cultureName.IsNullOrEmpty()) { - foreach (var service in serviceProvider.GetServices()) - { - await service.InitializeAsync(); - } + var culture = new CultureInfo(cultureName); + CultureInfo.DefaultThreadCurrentCulture = culture; + CultureInfo.DefaultThreadCurrentUICulture = culture; } - private static async Task SetCurrentLanguageAsync(IServiceProvider serviceProvider) + if (CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft) { - var configurationClient = serviceProvider.GetRequiredService(); - var utilsService = serviceProvider.GetRequiredService(); - var configuration = await configurationClient.GetAsync(); - var cultureName = configuration.Localization?.CurrentCulture?.CultureName; - if (!cultureName.IsNullOrEmpty()) - { - var culture = new CultureInfo(cultureName); - CultureInfo.DefaultThreadCurrentCulture = culture; - CultureInfo.DefaultThreadCurrentUICulture = culture; - } - - if (CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft) - { - await utilsService.AddClassToTagAsync("body", "rtl"); - } + await utilsService.AddClassToTagAsync("body", "rtl"); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpWebAssemblyServiceCollectionExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpWebAssemblyServiceCollectionExtensions.cs index 2f541265d1a..bbcf1d5a838 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpWebAssemblyServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpWebAssemblyServiceCollectionExtensions.cs @@ -2,16 +2,15 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Volo.Abp; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class AbpWebAssemblyServiceCollectionExtensions { - public static class AbpWebAssemblyServiceCollectionExtensions + public static WebAssemblyHostBuilder GetHostBuilder( + [NotNull] this IServiceCollection services) { - public static WebAssemblyHostBuilder GetHostBuilder( - [NotNull] this IServiceCollection services) - { - Check.NotNull(services, nameof(services)); + Check.NotNull(services, nameof(services)); - return services.GetSingletonInstance(); - } + return services.GetSingletonInstance(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs index 170bd9c327d..56dd8106a30 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs @@ -7,31 +7,30 @@ using Volo.Abp.Modularity; using Volo.Abp.UI; -namespace Volo.Abp.AspNetCore.Components.WebAssembly +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +[DependsOn( + typeof(AbpAspNetCoreMvcClientCommonModule), + typeof(AbpUiModule), + typeof(AbpAspNetCoreComponentsWebModule) + )] +public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule { - [DependsOn( - typeof(AbpAspNetCoreMvcClientCommonModule), - typeof(AbpUiModule), - typeof(AbpAspNetCoreComponentsWebModule) - )] - public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule + public override void PreConfigureServices(ServiceConfigurationContext context) { - public override void PreConfigureServices(ServiceConfigurationContext context) + PreConfigure(options => { - PreConfigure(options => + options.ProxyClientBuildActions.Add((_, builder) => { - options.ProxyClientBuildActions.Add((_, builder) => - { - builder.AddHttpMessageHandler(); - }); + builder.AddHttpMessageHandler(); }); - } + }); + } - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services - .GetHostBuilder().Logging - .AddProvider(new AbpExceptionHandlingLoggerProvider(context.Services)); - } + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services + .GetHostBuilder().Logging + .AddProvider(new AbpExceptionHandlingLoggerProvider(context.Services)); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpWebAssemblyApplicationCreationOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpWebAssemblyApplicationCreationOptions.cs index 54fdf7edb47..6ffe5fe17ee 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpWebAssemblyApplicationCreationOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpWebAssemblyApplicationCreationOptions.cs @@ -1,19 +1,18 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -namespace Volo.Abp.AspNetCore.Components.WebAssembly +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +public class AbpWebAssemblyApplicationCreationOptions { - public class AbpWebAssemblyApplicationCreationOptions - { - public WebAssemblyHostBuilder HostBuilder { get; } + public WebAssemblyHostBuilder HostBuilder { get; } - public AbpApplicationCreationOptions ApplicationCreationOptions { get; } + public AbpApplicationCreationOptions ApplicationCreationOptions { get; } - public AbpWebAssemblyApplicationCreationOptions( - WebAssemblyHostBuilder hostBuilder, - AbpApplicationCreationOptions applicationCreationOptions) - { - HostBuilder = hostBuilder; - ApplicationCreationOptions = applicationCreationOptions; - } + public AbpWebAssemblyApplicationCreationOptions( + WebAssemblyHostBuilder hostBuilder, + AbpApplicationCreationOptions applicationCreationOptions) + { + HostBuilder = hostBuilder; + ApplicationCreationOptions = applicationCreationOptions; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ApplicationConfigurationCache.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ApplicationConfigurationCache.cs index ffbcf4e9730..b55d8d8a56d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ApplicationConfigurationCache.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ApplicationConfigurationCache.cs @@ -1,20 +1,19 @@ using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.WebAssembly +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +public class ApplicationConfigurationCache : ISingletonDependency { - public class ApplicationConfigurationCache : ISingletonDependency - { - protected ApplicationConfigurationDto Configuration { get; set; } + protected ApplicationConfigurationDto Configuration { get; set; } - public virtual ApplicationConfigurationDto Get() - { - return Configuration; - } + public virtual ApplicationConfigurationDto Get() + { + return Configuration; + } - public void Set(ApplicationConfigurationDto configuration) - { - Configuration = configuration; - } + public void Set(ApplicationConfigurationDto configuration) + { + Configuration = configuration; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Extensibility/WebAssemblyLookupApiRequestService.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Extensibility/WebAssemblyLookupApiRequestService.cs index 594aa32bae4..b8eadacdd6e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Extensibility/WebAssemblyLookupApiRequestService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Extensibility/WebAssemblyLookupApiRequestService.cs @@ -11,57 +11,56 @@ using Microsoft.Extensions.Options; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.Components.WebAssembly.Extensibility +namespace Volo.Abp.AspNetCore.Components.WebAssembly.Extensibility; + +public class WebAssemblyLookupApiRequestService : ILookupApiRequestService, ITransientDependency { - public class WebAssemblyLookupApiRequestService : ILookupApiRequestService, ITransientDependency + public IHttpClientFactory HttpClientFactory { get; } + public IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; } + public IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; } + public ICurrentTenant CurrentTenant { get; } + + public WebAssemblyLookupApiRequestService(IHttpClientFactory httpClientFactory, + IRemoteServiceHttpClientAuthenticator httpClientAuthenticator, + ICurrentTenant currentTenant, + IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider) + { + HttpClientFactory = httpClientFactory; + HttpClientAuthenticator = httpClientAuthenticator; + CurrentTenant = currentTenant; + RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider; + } + + public async Task SendAsync(string url) { - public IHttpClientFactory HttpClientFactory { get; } - public IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; } - public IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; } - public ICurrentTenant CurrentTenant { get; } + var client = HttpClientFactory.CreateClient(); + var requestMessage = new HttpRequestMessage(HttpMethod.Get, url); + AddHeaders(requestMessage); - public WebAssemblyLookupApiRequestService(IHttpClientFactory httpClientFactory, - IRemoteServiceHttpClientAuthenticator httpClientAuthenticator, - ICurrentTenant currentTenant, - IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider) + var uri = new Uri(url, UriKind.RelativeOrAbsolute); + if (!uri.IsAbsoluteUri) { - HttpClientFactory = httpClientFactory; - HttpClientAuthenticator = httpClientAuthenticator; - CurrentTenant = currentTenant; - RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider; + var remoteServiceConfig = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Default"); + client.BaseAddress = new Uri(remoteServiceConfig.BaseUrl); + await HttpClientAuthenticator.Authenticate(new RemoteServiceHttpClientAuthenticateContext(client, requestMessage, new RemoteServiceConfiguration(remoteServiceConfig.BaseUrl), string.Empty)); } - public async Task SendAsync(string url) - { - var client = HttpClientFactory.CreateClient(); - var requestMessage = new HttpRequestMessage(HttpMethod.Get, url); - AddHeaders(requestMessage); + var response = await client.SendAsync(requestMessage); - var uri = new Uri(url, UriKind.RelativeOrAbsolute); - if (!uri.IsAbsoluteUri) - { - var remoteServiceConfig = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Default"); - client.BaseAddress = new Uri(remoteServiceConfig.BaseUrl); - await HttpClientAuthenticator.Authenticate(new RemoteServiceHttpClientAuthenticateContext(client, requestMessage, new RemoteServiceConfiguration(remoteServiceConfig.BaseUrl), string.Empty)); - } + return await response.Content.ReadAsStringAsync(); + } - var response = await client.SendAsync(requestMessage); - - return await response.Content.ReadAsStringAsync(); - } - - protected virtual void AddHeaders(HttpRequestMessage requestMessage) + protected virtual void AddHeaders(HttpRequestMessage requestMessage) + { + if (CurrentTenant.Id.HasValue) { - if (CurrentTenant.Id.HasValue) - { - requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString()); - } + requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString()); + } - var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name; - if (!currentCulture.IsNullOrEmpty()) - { - requestMessage.Headers.AcceptLanguage.Add(new (currentCulture)); - } + var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name; + if (!currentCulture.IsNullOrEmpty()) + { + requestMessage.Headers.AcceptLanguage.Add(new(currentCulture)); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs index c7b659a8598..4dbd188a471 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs @@ -5,63 +5,62 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.Components.WebAssembly +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +[ExposeServices( + typeof(WebAssemblyCachedApplicationConfigurationClient), + typeof(ICachedApplicationConfigurationClient), + typeof(IAsyncInitialize) + )] +public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency { - [ExposeServices( - typeof(WebAssemblyCachedApplicationConfigurationClient), - typeof(ICachedApplicationConfigurationClient), - typeof(IAsyncInitialize) - )] - public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency - { - protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; } + protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; } - protected ApplicationConfigurationCache Cache { get; } + protected ApplicationConfigurationCache Cache { get; } - protected ICurrentTenantAccessor CurrentTenantAccessor { get; } + protected ICurrentTenantAccessor CurrentTenantAccessor { get; } - public WebAssemblyCachedApplicationConfigurationClient( - AbpApplicationConfigurationClientProxy applicationConfigurationAppService, - ApplicationConfigurationCache cache, - ICurrentTenantAccessor currentTenantAccessor) - { - ApplicationConfigurationAppService = applicationConfigurationAppService; - Cache = cache; - CurrentTenantAccessor = currentTenantAccessor; - } + public WebAssemblyCachedApplicationConfigurationClient( + AbpApplicationConfigurationClientProxy applicationConfigurationAppService, + ApplicationConfigurationCache cache, + ICurrentTenantAccessor currentTenantAccessor) + { + ApplicationConfigurationAppService = applicationConfigurationAppService; + Cache = cache; + CurrentTenantAccessor = currentTenantAccessor; + } - public virtual async Task InitializeAsync() - { - var configurationDto = await ApplicationConfigurationAppService.GetAsync(); + public virtual async Task InitializeAsync() + { + var configurationDto = await ApplicationConfigurationAppService.GetAsync(); - Cache.Set(configurationDto); + Cache.Set(configurationDto); - CurrentTenantAccessor.Current = new BasicTenantInfo( - configurationDto.CurrentTenant.Id, - configurationDto.CurrentTenant.Name - ); - } + CurrentTenantAccessor.Current = new BasicTenantInfo( + configurationDto.CurrentTenant.Id, + configurationDto.CurrentTenant.Name + ); + } - public virtual Task GetAsync() - { - return Task.FromResult(GetConfigurationByChecking()); - } + public virtual Task GetAsync() + { + return Task.FromResult(GetConfigurationByChecking()); + } - public virtual ApplicationConfigurationDto Get() - { - return GetConfigurationByChecking(); - } + public virtual ApplicationConfigurationDto Get() + { + return GetConfigurationByChecking(); + } - private ApplicationConfigurationDto GetConfigurationByChecking() + private ApplicationConfigurationDto GetConfigurationByChecking() + { + var configuration = Cache.Get(); + if (configuration == null) { - var configuration = Cache.Get(); - if (configuration == null) - { - throw new AbpException( - $"{nameof(WebAssemblyCachedApplicationConfigurationClient)} should be initialized before using it."); - } - - return configuration; + throw new AbpException( + $"{nameof(WebAssemblyCachedApplicationConfigurationClient)} should be initialized before using it."); } + + return configuration; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs index 36438871c1a..9f1eb5d0b97 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs @@ -4,21 +4,20 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Security.Claims; -namespace Volo.Abp.AspNetCore.Components.WebAssembly +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +public class WebAssemblyCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ITransientDependency { - public class WebAssemblyCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ITransientDependency - { - protected AbpComponentsClaimsCache ClaimsCache { get; } + protected AbpComponentsClaimsCache ClaimsCache { get; } - public WebAssemblyCurrentPrincipalAccessor( - IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor) - { - ClaimsCache = clientScopeServiceProviderAccessor.ServiceProvider.GetRequiredService(); - } + public WebAssemblyCurrentPrincipalAccessor( + IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor) + { + ClaimsCache = clientScopeServiceProviderAccessor.ServiceProvider.GetRequiredService(); + } - protected override ClaimsPrincipal GetClaimsPrincipal() - { - return ClaimsCache.Principal; - } + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return ClaimsCache.Principal; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentTenantAccessor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentTenantAccessor.cs index eb0ee781ad4..e24746f85a8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentTenantAccessor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentTenantAccessor.cs @@ -1,11 +1,10 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.Components.WebAssembly +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +[Dependency(ReplaceServices = true)] +public class WebAssemblyCurrentTenantAccessor : ICurrentTenantAccessor, ISingletonDependency { - [Dependency(ReplaceServices = true)] - public class WebAssemblyCurrentTenantAccessor : ICurrentTenantAccessor, ISingletonDependency - { - public BasicTenantInfo Current { get; set; } - } + public BasicTenantInfo Current { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyServerUrlProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyServerUrlProvider.cs index 477dba54182..2fb133a10d4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyServerUrlProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyServerUrlProvider.cs @@ -4,26 +4,25 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Http.Client; -namespace Volo.Abp.AspNetCore.Components.WebAssembly +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +[Dependency(ReplaceServices = true)] +public class WebAssemblyServerUrlProvider : IServerUrlProvider, ITransientDependency { - [Dependency(ReplaceServices = true)] - public class WebAssemblyServerUrlProvider : IServerUrlProvider, ITransientDependency + protected IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; } + + public WebAssemblyServerUrlProvider( + IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider) + { + RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider; + } + + public async Task GetBaseUrlAsync(string remoteServiceName = null) { - protected IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; } + var remoteServiceConfiguration = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync( + remoteServiceName ?? RemoteServiceConfigurationDictionary.DefaultName + ); - public WebAssemblyServerUrlProvider( - IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider) - { - RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider; - } - - public async Task GetBaseUrlAsync(string remoteServiceName = null) - { - var remoteServiceConfiguration = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync( - remoteServiceName ?? RemoteServiceConfigurationDictionary.DefaultName - ); - - return remoteServiceConfiguration.BaseUrl.EnsureEndsWith('/'); - } + return remoteServiceConfiguration.BaseUrl.EnsureEndsWith('/'); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo.Abp.AspNetCore.Components.csproj b/framework/src/Volo.Abp.AspNetCore.Components/Volo.Abp.AspNetCore.Components.csproj index 1b81b8e6d9b..628661a1846 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo.Abp.AspNetCore.Components.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo.Abp.AspNetCore.Components.csproj @@ -15,7 +15,7 @@
- + diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpAspNetCoreComponentsModule.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpAspNetCoreComponentsModule.cs index 08c7ed8e9fa..b73432b38a5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpAspNetCoreComponentsModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpAspNetCoreComponentsModule.cs @@ -6,20 +6,20 @@ using Volo.Abp.Modularity; using Volo.Abp.ObjectMapping; using Volo.Abp.Security; +using Volo.Abp.Timing; -namespace Volo.Abp.AspNetCore.Components +namespace Volo.Abp.AspNetCore.Components; + +[DependsOn( + typeof(AbpObjectMappingModule), + typeof(AbpSecurityModule), + typeof(AbpTimingModule) + )] +public class AbpAspNetCoreComponentsModule : AbpModule { - [DependsOn( - typeof(AbpObjectMappingModule), - typeof(AbpSecurityModule), - typeof(AbpLocalizationModule) - )] - public class AbpAspNetCoreComponentsModule : AbpModule + public override void PreConfigureServices(ServiceConfigurationContext context) { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - DynamicProxyIgnoreTypes.Add(); - context.Services.AddConventionalRegistrar(new AbpWebAssemblyConventionalRegistrar()); - } + DynamicProxyIgnoreTypes.Add(); + context.Services.AddConventionalRegistrar(new AbpWebAssemblyConventionalRegistrar()); } } 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 163b2217fad..66acd8f171c 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 @@ -11,167 +11,168 @@ using Volo.Abp.AspNetCore.Components.Messages; using Volo.Abp.AspNetCore.Components.Notifications; using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectMapping; +using Volo.Abp.Timing; using Volo.Abp.Users; -namespace Volo.Abp.AspNetCore.Components +namespace Volo.Abp.AspNetCore.Components; + +public abstract class AbpComponentBase : OwningComponentBase { - public abstract class AbpComponentBase : OwningComponentBase - { - protected IStringLocalizerFactory StringLocalizerFactory => LazyGetRequiredService(ref _stringLocalizerFactory); - private IStringLocalizerFactory _stringLocalizerFactory; + protected IStringLocalizerFactory StringLocalizerFactory => LazyGetRequiredService(ref _stringLocalizerFactory); + private IStringLocalizerFactory _stringLocalizerFactory; - protected IStringLocalizer L - { - get + protected IStringLocalizer L { + get { + if (_localizer == null) { - if (_localizer == null) - { - _localizer = CreateLocalizer(); - } - - return _localizer; + _localizer = CreateLocalizer(); } + + return _localizer; } - private IStringLocalizer _localizer; + } + private IStringLocalizer _localizer; - protected Type LocalizationResource - { - get => _localizationResource; - set - { - _localizationResource = value; - _localizer = null; - } + protected Type LocalizationResource { + get => _localizationResource; + set { + _localizationResource = value; + _localizer = null; } - private Type _localizationResource = typeof(DefaultResource); + } + private Type _localizationResource = typeof(DefaultResource); - protected ILogger Logger => _lazyLogger.Value; - private Lazy _lazyLogger => new Lazy(() => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance, true); + protected ILogger Logger => _lazyLogger.Value; + private Lazy _lazyLogger => new Lazy(() => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance, true); - protected ILoggerFactory LoggerFactory => LazyGetRequiredService(ref _loggerFactory); - private ILoggerFactory _loggerFactory; + protected ILoggerFactory LoggerFactory => LazyGetRequiredService(ref _loggerFactory); + private ILoggerFactory _loggerFactory; - protected IAuthorizationService AuthorizationService => LazyGetRequiredService(ref _authorizationService); - private IAuthorizationService _authorizationService; + protected IAuthorizationService AuthorizationService => LazyGetRequiredService(ref _authorizationService); + private IAuthorizationService _authorizationService; - protected ICurrentUser CurrentUser => LazyGetRequiredService(ref _currentUser); - private ICurrentUser _currentUser; - - protected IUiMessageService Message => LazyGetNonScopedRequiredService(ref _message); - private IUiMessageService _message; + protected ICurrentUser CurrentUser => LazyGetRequiredService(ref _currentUser); + private ICurrentUser _currentUser; - protected IUiNotificationService Notify => LazyGetNonScopedRequiredService(ref _notify); - private IUiNotificationService _notify; - - protected IUserExceptionInformer UserExceptionInformer => LazyGetNonScopedRequiredService(ref _userExceptionInformer); - private IUserExceptionInformer _userExceptionInformer; + protected ICurrentTenant CurrentTenant => LazyGetRequiredService(ref _currentTenant); + private ICurrentTenant _currentTenant; - protected IAlertManager AlertManager => LazyGetNonScopedRequiredService(ref _alertManager); - private IAlertManager _alertManager; + protected IUiMessageService Message => LazyGetNonScopedRequiredService(ref _message); + private IUiMessageService _message; - protected AlertList Alerts => AlertManager.Alerts; + protected IUiNotificationService Notify => LazyGetNonScopedRequiredService(ref _notify); + private IUiNotificationService _notify; - protected IObjectMapper ObjectMapper - { - get - { - if (_objectMapper != null) - { - return _objectMapper; - } - - if (ObjectMapperContext == null) - { - return LazyGetRequiredService(ref _objectMapper); - } - - return LazyGetRequiredService( - typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext), - ref _objectMapper - ); - } - } + protected IUserExceptionInformer UserExceptionInformer => LazyGetNonScopedRequiredService(ref _userExceptionInformer); + private IUserExceptionInformer _userExceptionInformer; - private IObjectMapper _objectMapper; + protected IAlertManager AlertManager => LazyGetNonScopedRequiredService(ref _alertManager); + private IAlertManager _alertManager; - protected Type ObjectMapperContext { get; set; } + protected IClock Clock => LazyGetNonScopedRequiredService(ref _clock); + private IClock _clock; - protected TService LazyGetRequiredService(ref TService reference) => LazyGetRequiredService(typeof(TService), ref reference); + protected AlertList Alerts => AlertManager.Alerts; - protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference) - { - if (reference == null) + protected IObjectMapper ObjectMapper { + get { + if (_objectMapper != null) { - reference = (TRef)ScopedServices.GetRequiredService(serviceType); + return _objectMapper; } - return reference; - } - - protected TService LazyGetService(ref TService reference) => LazyGetService(typeof(TService), ref reference); - - protected TRef LazyGetService(Type serviceType, ref TRef reference) - { - if (reference == null) + if (ObjectMapperContext == null) { - reference = (TRef)ScopedServices.GetService(serviceType); + return LazyGetRequiredService(ref _objectMapper); } - return reference; + return LazyGetRequiredService( + typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext), + ref _objectMapper + ); } + } - protected TService LazyGetNonScopedRequiredService(ref TService reference) => LazyGetNonScopedRequiredService(typeof(TService), ref reference); + private IObjectMapper _objectMapper; - protected TRef LazyGetNonScopedRequiredService(Type serviceType, ref TRef reference) - { - if (reference == null) - { - reference = (TRef)NonScopedServices.GetRequiredService(serviceType); - } + protected Type ObjectMapperContext { get; set; } + + protected TService LazyGetRequiredService(ref TService reference) => LazyGetRequiredService(typeof(TService), ref reference); - return reference; + protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference) + { + if (reference == null) + { + reference = (TRef)ScopedServices.GetRequiredService(serviceType); } - - protected TService LazyGetNonScopedService(ref TService reference) => LazyGetNonScopedService(typeof(TService), ref reference); - protected TRef LazyGetNonScopedService(Type serviceType, ref TRef reference) + return reference; + } + + protected TService LazyGetService(ref TService reference) => LazyGetService(typeof(TService), ref reference); + + protected TRef LazyGetService(Type serviceType, ref TRef reference) + { + if (reference == null) { - if (reference == null) - { - reference = (TRef)NonScopedServices.GetService(serviceType); - } + reference = (TRef)ScopedServices.GetService(serviceType); + } + + return reference; + } + + protected TService LazyGetNonScopedRequiredService(ref TService reference) => LazyGetNonScopedRequiredService(typeof(TService), ref reference); - return reference; + protected TRef LazyGetNonScopedRequiredService(Type serviceType, ref TRef reference) + { + if (reference == null) + { + reference = (TRef)NonScopedServices.GetRequiredService(serviceType); } - [Inject] - protected IServiceProvider NonScopedServices { get; set; } + return reference; + } + + protected TService LazyGetNonScopedService(ref TService reference) => LazyGetNonScopedService(typeof(TService), ref reference); - protected virtual IStringLocalizer CreateLocalizer() + protected TRef LazyGetNonScopedService(Type serviceType, ref TRef reference) + { + if (reference == null) { - if (LocalizationResource != null) - { - return StringLocalizerFactory.Create(LocalizationResource); - } + reference = (TRef)NonScopedServices.GetService(serviceType); + } - var localizer = StringLocalizerFactory.CreateDefaultOrNull(); - if (localizer == null) - { - throw new AbpException($"Set {nameof(LocalizationResource)} or define the default localization resource type (by configuring the {nameof(AbpLocalizationOptions)}.{nameof(AbpLocalizationOptions.DefaultResourceType)}) to be able to use the {nameof(L)} object!"); - } + return reference; + } - return localizer; + [Inject] + protected IServiceProvider NonScopedServices { get; set; } + + protected virtual IStringLocalizer CreateLocalizer() + { + if (LocalizationResource != null) + { + return StringLocalizerFactory.Create(LocalizationResource); } - - protected async Task HandleErrorAsync(Exception exception) + + var localizer = StringLocalizerFactory.CreateDefaultOrNull(); + if (localizer == null) { - Logger.LogException(exception); - await InvokeAsync(async () => - { - await UserExceptionInformer.InformAsync(new UserExceptionInformerContext(exception)); - StateHasChanged(); - }); + throw new AbpException($"Set {nameof(LocalizationResource)} or define the default localization resource type (by configuring the {nameof(AbpLocalizationOptions)}.{nameof(AbpLocalizationOptions.DefaultResourceType)}) to be able to use the {nameof(L)} object!"); } + + return localizer; + } + + protected async Task HandleErrorAsync(Exception exception) + { + Logger.LogException(exception); + await InvokeAsync(async () => + { + await UserExceptionInformer.InformAsync(new UserExceptionInformerContext(exception)); + StateHasChanged(); + }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertList.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertList.cs index 866095a9b9e..6ea0031352c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertList.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertList.cs @@ -5,33 +5,32 @@ using System.Text; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Alerts +namespace Volo.Abp.AspNetCore.Components.Alerts; + +public class AlertList : ObservableCollection { - public class AlertList : ObservableCollection + public void Add(AlertType type, string text, string title = null, bool dismissible = true) { - public void Add(AlertType type, string text, string title = null, bool dismissible = true) - { - Add(new AlertMessage(type, text, title, dismissible)); - } + Add(new AlertMessage(type, text, title, dismissible)); + } - public void Info(string text, string title = null, bool dismissible = true) - { - Add(new AlertMessage(AlertType.Info, text, title, dismissible)); - } + public void Info(string text, string title = null, bool dismissible = true) + { + Add(new AlertMessage(AlertType.Info, text, title, dismissible)); + } - public void Warning(string text, string title = null, bool dismissible = true) - { - Add(new AlertMessage(AlertType.Warning, text, title, dismissible)); - } + public void Warning(string text, string title = null, bool dismissible = true) + { + Add(new AlertMessage(AlertType.Warning, text, title, dismissible)); + } - public void Danger(string text, string title = null, bool dismissible = true) - { - Add(new AlertMessage(AlertType.Danger, text, title, dismissible)); - } + public void Danger(string text, string title = null, bool dismissible = true) + { + Add(new AlertMessage(AlertType.Danger, text, title, dismissible)); + } - public void Success(string text, string title = null, bool dismissible = true) - { - Add(new AlertMessage(AlertType.Success, text, title, dismissible)); - } + public void Success(string text, string title = null, bool dismissible = true) + { + Add(new AlertMessage(AlertType.Success, text, title, dismissible)); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertMessage.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertMessage.cs index 1b6a7dd21d8..7a38e422a09 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertMessage.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertMessage.cs @@ -1,30 +1,28 @@ using JetBrains.Annotations; -namespace Volo.Abp.AspNetCore.Components.Alerts +namespace Volo.Abp.AspNetCore.Components.Alerts; + +public class AlertMessage { - public class AlertMessage - { - [NotNull] - public string Text - { - get => _text; - set => _text = Check.NotNullOrWhiteSpace(value, nameof(value)); - } - private string _text; + [NotNull] + public string Text { + get => _text; + set => _text = Check.NotNullOrWhiteSpace(value, nameof(value)); + } + private string _text; - public AlertType Type { get; set; } + public AlertType Type { get; set; } - [CanBeNull] - public string Title { get; set; } + [CanBeNull] + public string Title { get; set; } - public bool Dismissible { get; set; } + public bool Dismissible { get; set; } - public AlertMessage(AlertType type, [NotNull] string text, string title = null, bool dismissible = true) - { - Type = type; - Text = Check.NotNullOrWhiteSpace(text, nameof(text)); - Title = title; - Dismissible = dismissible; - } + public AlertMessage(AlertType type, [NotNull] string text, string title = null, bool dismissible = true) + { + Type = type; + Text = Check.NotNullOrWhiteSpace(text, nameof(text)); + Title = title; + Dismissible = dismissible; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertType.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertType.cs index 4703158b12c..6149f9bb242 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertType.cs @@ -4,18 +4,17 @@ using System.Text; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Alerts +namespace Volo.Abp.AspNetCore.Components.Alerts; + +public enum AlertType { - public enum AlertType - { - Default, - Primary, - Secondary, - Success, - Danger, - Warning, - Info, - Light, - Dark - } + Default, + Primary, + Secondary, + Success, + Danger, + Warning, + Info, + Light, + Dark } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/IAlertManager.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/IAlertManager.cs index 542b576b015..0e6344baafb 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/IAlertManager.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/IAlertManager.cs @@ -4,10 +4,9 @@ using System.Text; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Alerts +namespace Volo.Abp.AspNetCore.Components.Alerts; + +public interface IAlertManager { - public interface IAlertManager - { - AlertList Alerts { get; } - } + AlertList Alerts { get; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/AbpWebAssemblyConventionalRegistrar.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/AbpWebAssemblyConventionalRegistrar.cs index 3929f6c4cc4..776c80108a0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/AbpWebAssemblyConventionalRegistrar.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/AbpWebAssemblyConventionalRegistrar.cs @@ -3,23 +3,22 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.DependencyInjection +namespace Volo.Abp.AspNetCore.Components.DependencyInjection; + +public class AbpWebAssemblyConventionalRegistrar : DefaultConventionalRegistrar { - public class AbpWebAssemblyConventionalRegistrar : DefaultConventionalRegistrar + protected override bool IsConventionalRegistrationDisabled(Type type) { - protected override bool IsConventionalRegistrationDisabled(Type type) - { - return !IsComponent(type) || base.IsConventionalRegistrationDisabled(type); - } + return !IsComponent(type) || base.IsConventionalRegistrationDisabled(type); + } - private static bool IsComponent(Type type) - { - return typeof(ComponentBase).IsAssignableFrom(type); - } + private static bool IsComponent(Type type) + { + return typeof(ComponentBase).IsAssignableFrom(type); + } - protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type) - { - return ServiceLifetime.Transient; - } + protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type) + { + return ServiceLifetime.Transient; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/ServiceProviderComponentActivator.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/ServiceProviderComponentActivator.cs index 3841f48c4a4..001659395e1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/ServiceProviderComponentActivator.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/ServiceProviderComponentActivator.cs @@ -1,32 +1,31 @@ using System; using Microsoft.AspNetCore.Components; -namespace Volo.Abp.AspNetCore.Components.DependencyInjection +namespace Volo.Abp.AspNetCore.Components.DependencyInjection; + +public class ServiceProviderComponentActivator : IComponentActivator { - public class ServiceProviderComponentActivator : IComponentActivator + public IServiceProvider ServiceProvider { get; } + + public ServiceProviderComponentActivator(IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + } + + public IComponent CreateInstance(Type componentType) { - public IServiceProvider ServiceProvider { get; } + var instance = ServiceProvider.GetService(componentType); - public ServiceProviderComponentActivator(IServiceProvider serviceProvider) + if (instance == null) { - ServiceProvider = serviceProvider; + instance = Activator.CreateInstance(componentType); } - public IComponent CreateInstance(Type componentType) + if (!(instance is IComponent component)) { - var instance = ServiceProvider.GetService(componentType); - - if (instance == null) - { - instance = Activator.CreateInstance(componentType); - } - - if (!(instance is IComponent component)) - { - throw new ArgumentException($"The type {componentType.FullName} does not implement {nameof(IComponent)}.", nameof(componentType)); - } - - return component; + throw new ArgumentException($"The type {componentType.FullName} does not implement {nameof(IComponent)}.", nameof(componentType)); } + + return component; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/IUserExceptionInformer.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/IUserExceptionInformer.cs index aaab5057eb1..26b04b805ef 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/IUserExceptionInformer.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/IUserExceptionInformer.cs @@ -1,11 +1,10 @@ using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.ExceptionHandling +namespace Volo.Abp.AspNetCore.Components.ExceptionHandling; + +public interface IUserExceptionInformer { - public interface IUserExceptionInformer - { - void Inform(UserExceptionInformerContext context); - - Task InformAsync(UserExceptionInformerContext context); - } + void Inform(UserExceptionInformerContext context); + + Task InformAsync(UserExceptionInformerContext context); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/NullUserExceptionInformer.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/NullUserExceptionInformer.cs index 56522bef01b..3a23390f513 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/NullUserExceptionInformer.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/NullUserExceptionInformer.cs @@ -1,18 +1,17 @@ using System.Threading.Tasks; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.ExceptionHandling +namespace Volo.Abp.AspNetCore.Components.ExceptionHandling; + +public class NullUserExceptionInformer : IUserExceptionInformer, ISingletonDependency { - public class NullUserExceptionInformer : IUserExceptionInformer, ISingletonDependency + public void Inform(UserExceptionInformerContext context) { - public void Inform(UserExceptionInformerContext context) - { - - } - public Task InformAsync(UserExceptionInformerContext context) - { - return Task.CompletedTask; - } } -} \ No newline at end of file + + public Task InformAsync(UserExceptionInformerContext context) + { + return Task.CompletedTask; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/UserExceptionInformerContext.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/UserExceptionInformerContext.cs index d174a984886..978e6b82e92 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/UserExceptionInformerContext.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/ExceptionHandling/UserExceptionInformerContext.cs @@ -1,16 +1,15 @@ using System; using JetBrains.Annotations; -namespace Volo.Abp.AspNetCore.Components.ExceptionHandling +namespace Volo.Abp.AspNetCore.Components.ExceptionHandling; + +public class UserExceptionInformerContext { - public class UserExceptionInformerContext - { - [NotNull] - public Exception Exception { get; } + [NotNull] + public Exception Exception { get; } - public UserExceptionInformerContext(Exception exception) - { - Exception = exception; - } + public UserExceptionInformerContext(Exception exception) + { + Exception = exception; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/IUiMessageService.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/IUiMessageService.cs index 4f43cb90d65..86e878d2a92 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/IUiMessageService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/IUiMessageService.cs @@ -1,18 +1,17 @@ using System; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Messages +namespace Volo.Abp.AspNetCore.Components.Messages; + +public interface IUiMessageService { - public interface IUiMessageService - { - Task Info(string message, string title = null, Action options = null); + Task Info(string message, string title = null, Action options = null); - Task Success(string message, string title = null, Action options = null); + Task Success(string message, string title = null, Action options = null); - Task Warn(string message, string title = null, Action options = null); + Task Warn(string message, string title = null, Action options = null); - Task Error(string message, string title = null, Action options = null); + Task Error(string message, string title = null, Action options = null); - Task Confirm(string message, string title = null, Action options = null); - } + Task Confirm(string message, string title = null, Action options = null); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageEventArgs.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageEventArgs.cs index 51ef8ed5585..4d73fb28121 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageEventArgs.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageEventArgs.cs @@ -1,35 +1,34 @@ using System; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Messages +namespace Volo.Abp.AspNetCore.Components.Messages; + +public class UiMessageEventArgs : EventArgs { - public class UiMessageEventArgs : EventArgs + public UiMessageEventArgs(UiMessageType messageType, string message, string title, UiMessageOptions options) { - public UiMessageEventArgs(UiMessageType messageType, string message, string title, UiMessageOptions options) - { - MessageType = messageType; - Message = message; - Title = title; - Options = options; - } + MessageType = messageType; + Message = message; + Title = title; + Options = options; + } - public UiMessageEventArgs(UiMessageType messageType, string message, string title, UiMessageOptions options, TaskCompletionSource callback) - { - MessageType = messageType; - Message = message; - Title = title; - Options = options; - Callback = callback; - } + public UiMessageEventArgs(UiMessageType messageType, string message, string title, UiMessageOptions options, TaskCompletionSource callback) + { + MessageType = messageType; + Message = message; + Title = title; + Options = options; + Callback = callback; + } - public UiMessageType MessageType { get; set; } + public UiMessageType MessageType { get; set; } - public string Message { get; } + public string Message { get; } - public string Title { get; } + public string Title { get; } - public UiMessageOptions Options { get; } + public UiMessageOptions Options { get; } - public TaskCompletionSource Callback { get; } - } + public TaskCompletionSource Callback { get; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageOptions.cs index 9da4bcad60b..5cb8e56eeef 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageOptions.cs @@ -1,53 +1,52 @@ -namespace Volo.Abp.AspNetCore.Components.Messages +namespace Volo.Abp.AspNetCore.Components.Messages; + +/// +/// Options to override message dialog appearance. +/// +public class UiMessageOptions { /// - /// Options to override message dialog appearance. - /// - public class UiMessageOptions - { - /// - /// If true, the message dialogue will be centered on the screen. - /// - public bool CenterMessage { get; set; } - - /// - /// If true, the message dialogue will show the large icon for the current message type. - /// - public bool ShowMessageIcon { get; set; } - - /// - /// Overrides the build-in message icon. - /// - public object MessageIcon { get; set; } - - /// - /// Custom text for the Ok button. - /// - public string OkButtonText { get; set; } - - /// - /// Custom icon for the Ok button. - /// - public object OkButtonIcon { get; set; } - - /// - /// Custom text for the Confirmation button. - /// - public string ConfirmButtonText { get; set; } - - /// - /// Custom icon for the Confirmation button. - /// - public object ConfirmButtonIcon { get; set; } - - /// - /// Custom text for the Cancel button. - /// - public string CancelButtonText { get; set; } - - /// - /// Custom icon for the Cancel button. - /// - public object CancelButtonIcon { get; set; } - } + /// If true, the message dialogue will be centered on the screen. + /// + public bool CenterMessage { get; set; } + + /// + /// If true, the message dialogue will show the large icon for the current message type. + /// + public bool ShowMessageIcon { get; set; } + + /// + /// Overrides the build-in message icon. + /// + public object MessageIcon { get; set; } + + /// + /// Custom text for the Ok button. + /// + public string OkButtonText { get; set; } + + /// + /// Custom icon for the Ok button. + /// + public object OkButtonIcon { get; set; } + + /// + /// Custom text for the Confirmation button. + /// + public string ConfirmButtonText { get; set; } + + /// + /// Custom icon for the Confirmation button. + /// + public object ConfirmButtonIcon { get; set; } + + /// + /// Custom text for the Cancel button. + /// + public string CancelButtonText { get; set; } + + /// + /// Custom icon for the Cancel button. + /// + public object CancelButtonIcon { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageType.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageType.cs index 677297055e6..0f8264ecd1e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Messages/UiMessageType.cs @@ -1,14 +1,13 @@ -namespace Volo.Abp.AspNetCore.Components.Messages +namespace Volo.Abp.AspNetCore.Components.Messages; + +/// +/// Defines the possible ui message types with predefined actions. +/// +public enum UiMessageType { - /// - /// Defines the possible ui message types with predefined actions. - /// - public enum UiMessageType - { - Info, - Success, - Warning, - Error, - Confirmation, - } + Info, + Success, + Warning, + Error, + Confirmation, } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/IUiNotificationService.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/IUiNotificationService.cs index dfbde9b1eb9..394fdec2a78 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/IUiNotificationService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/IUiNotificationService.cs @@ -1,16 +1,15 @@ using System; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Notifications +namespace Volo.Abp.AspNetCore.Components.Notifications; + +public interface IUiNotificationService { - public interface IUiNotificationService - { - Task Info(string message, string title = null, Action options = null); - - Task Success(string message, string title = null, Action options = null); - - Task Warn(string message, string title = null, Action options = null); - - Task Error(string message, string title = null, Action options = null); - } + Task Info(string message, string title = null, Action options = null); + + Task Success(string message, string title = null, Action options = null); + + Task Warn(string message, string title = null, Action options = null); + + Task Error(string message, string title = null, Action options = null); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/NullUiNotificationService.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/NullUiNotificationService.cs index ed8217348e5..6c475863253 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/NullUiNotificationService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/NullUiNotificationService.cs @@ -2,27 +2,26 @@ using System.Threading.Tasks; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Notifications +namespace Volo.Abp.AspNetCore.Components.Notifications; + +public class NullUiNotificationService : IUiNotificationService, ITransientDependency { - public class NullUiNotificationService : IUiNotificationService, ITransientDependency + public Task Info(string message, string title = null, Action options = null) { - public Task Info(string message, string title = null, Action options = null) - { - return Task.CompletedTask; - } + return Task.CompletedTask; + } - public Task Success(string message, string title = null, Action options = null) - { - return Task.CompletedTask; - } + public Task Success(string message, string title = null, Action options = null) + { + return Task.CompletedTask; + } - public Task Warn(string message, string title = null, Action options = null) - { - return Task.CompletedTask; - } - public Task Error(string message, string title = null, Action options = null) - { - return Task.CompletedTask; - } + public Task Warn(string message, string title = null, Action options = null) + { + return Task.CompletedTask; + } + public Task Error(string message, string title = null, Action options = null) + { + return Task.CompletedTask; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationEventArgs.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationEventArgs.cs index 30d497d2ab0..554450d0257 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationEventArgs.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationEventArgs.cs @@ -1,23 +1,22 @@ using System; -namespace Volo.Abp.AspNetCore.Components.Notifications +namespace Volo.Abp.AspNetCore.Components.Notifications; + +public class UiNotificationEventArgs : EventArgs { - public class UiNotificationEventArgs : EventArgs + public UiNotificationEventArgs(UiNotificationType notificationType, string message, string title, UiNotificationOptions options) { - public UiNotificationEventArgs(UiNotificationType notificationType, string message, string title, UiNotificationOptions options) - { - NotificationType = notificationType; - Message = message; - Title = title; - Options = options; - } + NotificationType = notificationType; + Message = message; + Title = title; + Options = options; + } - public UiNotificationType NotificationType { get; set; } + public UiNotificationType NotificationType { get; set; } - public string Message { get; } + public string Message { get; } - public string Title { get; } + public string Title { get; } - public UiNotificationOptions Options { get; } - } + public UiNotificationOptions Options { get; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationOptions.cs index eb1c5d7102d..c3f6a74fa54 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationOptions.cs @@ -1,20 +1,19 @@ using Volo.Abp.Localization; -namespace Volo.Abp.AspNetCore.Components.Notifications +namespace Volo.Abp.AspNetCore.Components.Notifications; + +/// +/// Options to override notification appearance. +/// +public class UiNotificationOptions { /// - /// Options to override notification appearance. + /// Custom text for the Ok button. /// - public class UiNotificationOptions - { - /// - /// Custom text for the Ok button. - /// - public ILocalizableString OkButtonText { get; set; } + public ILocalizableString OkButtonText { get; set; } - /// - /// Custom icon for the Ok button. - /// - public object OkButtonIcon { get; set; } - } + /// + /// Custom icon for the Ok button. + /// + public object OkButtonIcon { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationType.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationType.cs index 3547d451e96..bd314455581 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Notifications/UiNotificationType.cs @@ -1,10 +1,9 @@ -namespace Volo.Abp.AspNetCore.Components.Notifications +namespace Volo.Abp.AspNetCore.Components.Notifications; + +public enum UiNotificationType { - public enum UiNotificationType - { - Info, - Success, - Warning, - Error, - } + Info, + Success, + Warning, + Error, } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/IUiPageProgressService.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/IUiPageProgressService.cs index fa9781e2d90..156c7637224 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/IUiPageProgressService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/IUiPageProgressService.cs @@ -1,21 +1,20 @@ using System; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Components.Progression +namespace Volo.Abp.AspNetCore.Components.Progression; + +public interface IUiPageProgressService { - public interface IUiPageProgressService - { - /// - /// An event raised after the notification is received. - /// - public event EventHandler ProgressChanged; + /// + /// An event raised after the notification is received. + /// + public event EventHandler ProgressChanged; - /// - /// Sets the progress percentage. - /// - /// Value of the progress from 0 to 100, or null for indeterminate progress. - /// Additional options. - /// Awaitable task. - Task Go(int? percentage, Action options = null); - } + /// + /// Sets the progress percentage. + /// + /// Value of the progress from 0 to 100, or null for indeterminate progress. + /// Additional options. + /// Awaitable task. + Task Go(int? percentage, Action options = null); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/NullUiPageProgressService.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/NullUiPageProgressService.cs index 5c375e2b40a..2277122418b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/NullUiPageProgressService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/NullUiPageProgressService.cs @@ -2,15 +2,14 @@ using System.Threading.Tasks; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Components.Progression +namespace Volo.Abp.AspNetCore.Components.Progression; + +public class NullUiPageProgressService : IUiPageProgressService, ISingletonDependency { - public class NullUiPageProgressService : IUiPageProgressService, ISingletonDependency - { - public event EventHandler ProgressChanged; + public event EventHandler ProgressChanged; - public Task Go(int? percentage, Action options = null) - { - return Task.CompletedTask; - } + public Task Go(int? percentage, Action options = null) + { + return Task.CompletedTask; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressEventArgs.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressEventArgs.cs index 74af5cb971e..adb4b73a646 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressEventArgs.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressEventArgs.cs @@ -1,17 +1,16 @@ using System; -namespace Volo.Abp.AspNetCore.Components.Progression +namespace Volo.Abp.AspNetCore.Components.Progression; + +public class UiPageProgressEventArgs : EventArgs { - public class UiPageProgressEventArgs : EventArgs + public UiPageProgressEventArgs(int? percentage, UiPageProgressOptions options) { - public UiPageProgressEventArgs(int? percentage, UiPageProgressOptions options) - { - Percentage = percentage; - Options = options; - } + Percentage = percentage; + Options = options; + } - public int? Percentage { get; } + public int? Percentage { get; } - public UiPageProgressOptions Options { get; } - } + public UiPageProgressOptions Options { get; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressOptions.cs index 0ce243552d2..d747e60d030 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressOptions.cs @@ -1,13 +1,12 @@ -namespace Volo.Abp.AspNetCore.Components.Progression +namespace Volo.Abp.AspNetCore.Components.Progression; + +/// +/// Options to override page progress appearance. +/// +public class UiPageProgressOptions { /// - /// Options to override page progress appearance. + /// Type or color, of the page progress. /// - public class UiPageProgressOptions - { - /// - /// Type or color, of the page progress. - /// - public UiPageProgressType Type { get; set; } - } + public UiPageProgressType Type { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressType.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressType.cs index db1d00932d2..fe9c02b98ea 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Progression/UiPageProgressType.cs @@ -1,11 +1,10 @@ -namespace Volo.Abp.AspNetCore.Components.Progression +namespace Volo.Abp.AspNetCore.Components.Progression; + +public enum UiPageProgressType { - public enum UiPageProgressType - { - Default, - Info, - Success, - Warning, - Error, - } + Default, + Info, + Success, + Warning, + Error, } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Microsoft/AspNetCore/Builder/AbpAspNetCoreMultiTenancyApplicationBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Microsoft/AspNetCore/Builder/AbpAspNetCoreMultiTenancyApplicationBuilderExtensions.cs index afc05f9233c..ceb872e5c3e 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Microsoft/AspNetCore/Builder/AbpAspNetCoreMultiTenancyApplicationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Microsoft/AspNetCore/Builder/AbpAspNetCoreMultiTenancyApplicationBuilderExtensions.cs @@ -1,13 +1,12 @@ using Volo.Abp.AspNetCore.MultiTenancy; -namespace Microsoft.AspNetCore.Builder +namespace Microsoft.AspNetCore.Builder; + +public static class AbpAspNetCoreMultiTenancyApplicationBuilderExtensions { - public static class AbpAspNetCoreMultiTenancyApplicationBuilderExtensions + public static IApplicationBuilder UseMultiTenancy(this IApplicationBuilder app) { - public static IApplicationBuilder UseMultiTenancy(this IApplicationBuilder app) - { - return app - .UseMiddleware(); - } + return app + .UseMiddleware(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs index 1d0268556f9..ad36cf0f11f 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs @@ -2,24 +2,23 @@ using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +[DependsOn( + typeof(AbpMultiTenancyModule), + typeof(AbpAspNetCoreModule) + )] +public class AbpAspNetCoreMultiTenancyModule : AbpModule { - [DependsOn( - typeof(AbpMultiTenancyModule), - typeof(AbpAspNetCoreModule) - )] - public class AbpAspNetCoreMultiTenancyModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(options => { - Configure(options => - { - options.TenantResolvers.Add(new QueryStringTenantResolveContributor()); - options.TenantResolvers.Add(new FormTenantResolveContributor()); - options.TenantResolvers.Add(new RouteTenantResolveContributor()); - options.TenantResolvers.Add(new HeaderTenantResolveContributor()); - options.TenantResolvers.Add(new CookieTenantResolveContributor()); - }); - } + options.TenantResolvers.Add(new QueryStringTenantResolveContributor()); + options.TenantResolvers.Add(new FormTenantResolveContributor()); + options.TenantResolvers.Add(new RouteTenantResolveContributor()); + options.TenantResolvers.Add(new HeaderTenantResolveContributor()); + options.TenantResolvers.Add(new CookieTenantResolveContributor()); + }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyOptions.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyOptions.cs index b2ecf708c52..4f89ef7b97a 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyOptions.cs @@ -5,35 +5,34 @@ using Microsoft.AspNetCore.Http; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +public class AbpAspNetCoreMultiTenancyOptions { - public class AbpAspNetCoreMultiTenancyOptions - { - /// - /// Default: . - /// - public string TenantKey { get; set; } + /// + /// Default: . + /// + public string TenantKey { get; set; } - public Func MultiTenancyMiddlewareErrorPageBuilder { get; set; } + public Func MultiTenancyMiddlewareErrorPageBuilder { get; set; } - public AbpAspNetCoreMultiTenancyOptions() + public AbpAspNetCoreMultiTenancyOptions() + { + TenantKey = TenantResolverConsts.DefaultTenantKey; + MultiTenancyMiddlewareErrorPageBuilder = async (context, exception) => { - TenantKey = TenantResolverConsts.DefaultTenantKey; - MultiTenancyMiddlewareErrorPageBuilder = async (context, exception)=> - { - context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;; - context.Response.ContentType = "text/html"; + context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; ; + context.Response.ContentType = "text/html"; - var message = exception.Message; - var details = exception is BusinessException businessException ? businessException.Details : string.Empty; + var message = exception.Message; + var details = exception is BusinessException businessException ? businessException.Details : string.Empty; - await context.Response.WriteAsync($"\r\n"); - await context.Response.WriteAsync($"

{message}

{details}
\r\n"); - await context.Response.WriteAsync("\r\n"); + await context.Response.WriteAsync($"\r\n"); + await context.Response.WriteAsync($"

{message}

{details}
\r\n"); + await context.Response.WriteAsync("\r\n"); // Note the 500 spaces are to work around an IE 'feature' await context.Response.WriteAsync(new string(' ', 500)); - }; - } + }; } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs index 2c2b2de0e90..d4a91f3b129 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyCookieHelper.cs @@ -1,33 +1,32 @@ using System; using Microsoft.AspNetCore.Http; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +public static class AbpMultiTenancyCookieHelper { - public static class AbpMultiTenancyCookieHelper + public static void SetTenantCookie( + HttpContext context, + Guid? tenantId, + string tenantKey) { - public static void SetTenantCookie( - HttpContext context, - Guid? tenantId, - string tenantKey) + if (tenantId != null) + { + context.Response.Cookies.Append( + tenantKey, + tenantId.ToString(), + new CookieOptions + { + Path = "/", + HttpOnly = false, + IsEssential = true, + Expires = DateTimeOffset.Now.AddYears(10) + } + ); + } + else { - if (tenantId != null) - { - context.Response.Cookies.Append( - tenantKey, - tenantId.ToString(), - new CookieOptions - { - Path = "/", - HttpOnly = false, - IsEssential = true, - Expires = DateTimeOffset.Now.AddYears(10) - } - ); - } - else - { - context.Response.Cookies.Delete(tenantKey); - } + context.Response.Cookies.Delete(tenantKey); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs index dd7ca5685e9..1eabd3ebfbf 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs @@ -2,17 +2,16 @@ using Microsoft.AspNetCore.Http; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +public class CookieTenantResolveContributor : HttpTenantResolveContributorBase { - public class CookieTenantResolveContributor : HttpTenantResolveContributorBase - { - public const string ContributorName = "Cookie"; + public const string ContributorName = "Cookie"; - public override string Name => ContributorName; + public override string Name => ContributorName; - protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) - { - return Task.FromResult(httpContext.Request.Cookies[context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey]); - } + protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) + { + return Task.FromResult(httpContext.Request.Cookies[context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey]); } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs index 255e0ac89b3..78f92ac20e5 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs @@ -4,38 +4,37 @@ using Volo.Abp.MultiTenancy; using Volo.Abp.Text.Formatting; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +//TODO: Create a better domain format. We can accept regex for example. + +public class DomainTenantResolveContributor : HttpTenantResolveContributorBase { - //TODO: Create a better domain format. We can accept regex for example. + public const string ContributorName = "Domain"; - public class DomainTenantResolveContributor : HttpTenantResolveContributorBase - { - public const string ContributorName = "Domain"; + public override string Name => ContributorName; - public override string Name => ContributorName; + private static readonly string[] ProtocolPrefixes = { "http://", "https://" }; - private static readonly string[] ProtocolPrefixes = { "http://", "https://" }; + private readonly string _domainFormat; - private readonly string _domainFormat; + public DomainTenantResolveContributor(string domainFormat) + { + _domainFormat = domainFormat.RemovePreFix(ProtocolPrefixes); + } - public DomainTenantResolveContributor(string domainFormat) + protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) + { + if (!httpContext.Request.Host.HasValue) { - _domainFormat = domainFormat.RemovePreFix(ProtocolPrefixes); + return Task.FromResult(null); } - protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) - { - if (!httpContext.Request.Host.HasValue) - { - return Task.FromResult(null); - } - - var hostName = httpContext.Request.Host.Value.RemovePreFix(ProtocolPrefixes); - var extractResult = FormattedStringValueExtracter.Extract(hostName, _domainFormat, ignoreCase: true); + var hostName = httpContext.Request.Host.Value.RemovePreFix(ProtocolPrefixes); + var extractResult = FormattedStringValueExtracter.Extract(hostName, _domainFormat, ignoreCase: true); - context.Handled = true; + context.Handled = true; - return Task.FromResult(extractResult.IsMatch ? extractResult.Matches[0].Value : null); - } + return Task.FromResult(extractResult.IsMatch ? extractResult.Matches[0].Value : null); } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/FormTenantResolveContributor.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/FormTenantResolveContributor.cs index 77c12bef7bc..67ef0a4c2c1 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/FormTenantResolveContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/FormTenantResolveContributor.cs @@ -3,23 +3,22 @@ using Microsoft.AspNetCore.Http; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +public class FormTenantResolveContributor : HttpTenantResolveContributorBase { - public class FormTenantResolveContributor : HttpTenantResolveContributorBase - { - public const string ContributorName = "Form"; + public const string ContributorName = "Form"; - public override string Name => ContributorName; + public override string Name => ContributorName; - protected override async Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) + protected override async Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) + { + if (!httpContext.Request.HasFormContentType) { - if (!httpContext.Request.HasFormContentType) - { - return null; - } - - var form = await httpContext.Request.ReadFormAsync(); - return form[context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey]; + return null; } + + var form = await httpContext.Request.ReadFormAsync(); + return form[context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey]; } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs index a6a52290bef..a0bec0d6061 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs @@ -6,43 +6,42 @@ using Microsoft.Extensions.Logging; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +public class HeaderTenantResolveContributor : HttpTenantResolveContributorBase { - public class HeaderTenantResolveContributor : HttpTenantResolveContributorBase - { - public const string ContributorName = "Header"; + public const string ContributorName = "Header"; - public override string Name => ContributorName; + public override string Name => ContributorName; - protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) + protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) + { + if (httpContext.Request.Headers.IsNullOrEmpty()) { - if (httpContext.Request.Headers.IsNullOrEmpty()) - { - return Task.FromResult((string)null); - } - - var tenantIdKey = context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey; - - var tenantIdHeader = httpContext.Request.Headers[tenantIdKey]; - if (tenantIdHeader == string.Empty || tenantIdHeader.Count < 1) - { - return Task.FromResult((string)null); - } + return Task.FromResult((string)null); + } - if (tenantIdHeader.Count > 1) - { - Log(context, $"HTTP request includes more than one {tenantIdKey} header value. First one will be used. All of them: {tenantIdHeader.JoinAsString(", ")}"); - } + var tenantIdKey = context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey; - return Task.FromResult(tenantIdHeader.First()); + var tenantIdHeader = httpContext.Request.Headers[tenantIdKey]; + if (tenantIdHeader == string.Empty || tenantIdHeader.Count < 1) + { + return Task.FromResult((string)null); } - protected virtual void Log(ITenantResolveContext context, string text) + if (tenantIdHeader.Count > 1) { - context - .ServiceProvider - .GetRequiredService>() - .LogWarning(text); + Log(context, $"HTTP request includes more than one {tenantIdKey} header value. First one will be used. All of them: {tenantIdHeader.JoinAsString(", ")}"); } + + return Task.FromResult(tenantIdHeader.First()); + } + + protected virtual void Log(ITenantResolveContext context, string text) + { + context + .ServiceProvider + .GetRequiredService>() + .LogWarning(text); } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs index 593d9a70244..1197e16baa2 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs @@ -2,32 +2,29 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +[Dependency(ReplaceServices = true)] +public class HttpContextTenantResolveResultAccessor : ITenantResolveResultAccessor, ITransientDependency { - [Dependency(ReplaceServices = true)] - public class HttpContextTenantResolveResultAccessor : ITenantResolveResultAccessor, ITransientDependency - { - public const string HttpContextItemName = "__AbpTenantResolveResult"; + public const string HttpContextItemName = "__AbpTenantResolveResult"; - public TenantResolveResult Result - { - get => _httpContextAccessor.HttpContext?.Items[HttpContextItemName] as TenantResolveResult; - set + public TenantResolveResult Result { + get => _httpContextAccessor.HttpContext?.Items[HttpContextItemName] as TenantResolveResult; + set { + if (_httpContextAccessor.HttpContext == null) { - if (_httpContextAccessor.HttpContext == null) - { - return; - } - - _httpContextAccessor.HttpContext.Items[HttpContextItemName] = value; + return; } + + _httpContextAccessor.HttpContext.Items[HttpContextItemName] = value; } + } - private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IHttpContextAccessor _httpContextAccessor; - public HttpContextTenantResolveResultAccessor(IHttpContextAccessor httpContextAccessor) - { - _httpContextAccessor = httpContextAccessor; - } + public HttpContextTenantResolveResultAccessor(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributorBase.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributorBase.cs index 3b454b5ef91..b0900c899f9 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributorBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributorBase.cs @@ -6,39 +6,38 @@ using Microsoft.Extensions.Logging; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +public abstract class HttpTenantResolveContributorBase : TenantResolveContributorBase { - public abstract class HttpTenantResolveContributorBase : TenantResolveContributorBase + public override async Task ResolveAsync(ITenantResolveContext context) { - public override async Task ResolveAsync(ITenantResolveContext context) + var httpContext = context.GetHttpContext(); + if (httpContext == null) { - var httpContext = context.GetHttpContext(); - if (httpContext == null) - { - return; - } - - try - { - await ResolveFromHttpContextAsync(context, httpContext); - } - catch (Exception e) - { - context.ServiceProvider - .GetRequiredService>() - .LogWarning(e.ToString()); - } + return; } - protected virtual async Task ResolveFromHttpContextAsync(ITenantResolveContext context, HttpContext httpContext) + try { - var tenantIdOrName = await GetTenantIdOrNameFromHttpContextOrNullAsync(context, httpContext); - if (!tenantIdOrName.IsNullOrEmpty()) - { - context.TenantIdOrName = tenantIdOrName; - } + await ResolveFromHttpContextAsync(context, httpContext); } + catch (Exception e) + { + context.ServiceProvider + .GetRequiredService>() + .LogWarning(e.ToString()); + } + } - protected abstract Task GetTenantIdOrNameFromHttpContextOrNullAsync([NotNull] ITenantResolveContext context, [NotNull] HttpContext httpContext); + protected virtual async Task ResolveFromHttpContextAsync(ITenantResolveContext context, HttpContext httpContext) + { + var tenantIdOrName = await GetTenantIdOrNameFromHttpContextOrNullAsync(context, httpContext); + if (!tenantIdOrName.IsNullOrEmpty()) + { + context.TenantIdOrName = tenantIdOrName; + } } + + protected abstract Task GetTenantIdOrNameFromHttpContextOrNullAsync([NotNull] ITenantResolveContext context, [NotNull] HttpContext httpContext); } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs index f3d21a804b9..9cd89272f4f 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs @@ -11,112 +11,111 @@ using Volo.Abp.MultiTenancy; using Volo.Abp.Settings; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +public class MultiTenancyMiddleware : IMiddleware, ITransientDependency { - public class MultiTenancyMiddleware : IMiddleware, ITransientDependency + private readonly ITenantConfigurationProvider _tenantConfigurationProvider; + private readonly ICurrentTenant _currentTenant; + private readonly AbpAspNetCoreMultiTenancyOptions _options; + private readonly ITenantResolveResultAccessor _tenantResolveResultAccessor; + + public MultiTenancyMiddleware( + ITenantConfigurationProvider tenantConfigurationProvider, + ICurrentTenant currentTenant, + IOptions options, + ITenantResolveResultAccessor tenantResolveResultAccessor) { - private readonly ITenantConfigurationProvider _tenantConfigurationProvider; - private readonly ICurrentTenant _currentTenant; - private readonly AbpAspNetCoreMultiTenancyOptions _options; - private readonly ITenantResolveResultAccessor _tenantResolveResultAccessor; + _tenantConfigurationProvider = tenantConfigurationProvider; + _currentTenant = currentTenant; + _tenantResolveResultAccessor = tenantResolveResultAccessor; + _options = options.Value; + } - public MultiTenancyMiddleware( - ITenantConfigurationProvider tenantConfigurationProvider, - ICurrentTenant currentTenant, - IOptions options, - ITenantResolveResultAccessor tenantResolveResultAccessor) + public async Task InvokeAsync(HttpContext context, RequestDelegate next) + { + TenantConfiguration tenant; + try { - _tenantConfigurationProvider = tenantConfigurationProvider; - _currentTenant = currentTenant; - _tenantResolveResultAccessor = tenantResolveResultAccessor; - _options = options.Value; + tenant = await _tenantConfigurationProvider.GetAsync(saveResolveResult: true); } - - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + catch (Exception e) { - TenantConfiguration tenant; - try - { - tenant = await _tenantConfigurationProvider.GetAsync(saveResolveResult: true); - } - catch (Exception e) - { - await _options.MultiTenancyMiddlewareErrorPageBuilder(context, e); - return; - } + await _options.MultiTenancyMiddlewareErrorPageBuilder(context, e); + return; + } - if (tenant?.Id != _currentTenant.Id) + if (tenant?.Id != _currentTenant.Id) + { + using (_currentTenant.Change(tenant?.Id, tenant?.Name)) { - using (_currentTenant.Change(tenant?.Id, tenant?.Name)) + if (_tenantResolveResultAccessor.Result != null && + _tenantResolveResultAccessor.Result.AppliedResolvers.Contains(QueryStringTenantResolveContributor.ContributorName)) { - if (_tenantResolveResultAccessor.Result != null && - _tenantResolveResultAccessor.Result.AppliedResolvers.Contains(QueryStringTenantResolveContributor.ContributorName)) - { - AbpMultiTenancyCookieHelper.SetTenantCookie(context, _currentTenant.Id, _options.TenantKey); - } - - var requestCulture = await TryGetRequestCultureAsync(context); - if (requestCulture != null) - { - CultureInfo.CurrentCulture = requestCulture.Culture; - CultureInfo.CurrentUICulture = requestCulture.UICulture; - AbpRequestCultureCookieHelper.SetCultureCookie( - context, - requestCulture - ); - context.Items[AbpRequestLocalizationMiddleware.HttpContextItemName] = true; - } + AbpMultiTenancyCookieHelper.SetTenantCookie(context, _currentTenant.Id, _options.TenantKey); + } - await next(context); + var requestCulture = await TryGetRequestCultureAsync(context); + if (requestCulture != null) + { + CultureInfo.CurrentCulture = requestCulture.Culture; + CultureInfo.CurrentUICulture = requestCulture.UICulture; + AbpRequestCultureCookieHelper.SetCultureCookie( + context, + requestCulture + ); + context.Items[AbpRequestLocalizationMiddleware.HttpContextItemName] = true; } - } - else - { + await next(context); } } - - private async Task TryGetRequestCultureAsync(HttpContext httpContext) + else { - var requestCultureFeature = httpContext.Features.Get(); + await next(context); + } + } - /* If requestCultureFeature == null, that means the RequestLocalizationMiddleware was not used - * and we don't want to set the culture. */ - if (requestCultureFeature == null) - { - return null; - } + private async Task TryGetRequestCultureAsync(HttpContext httpContext) + { + var requestCultureFeature = httpContext.Features.Get(); - /* If requestCultureFeature.Provider is not null, that means RequestLocalizationMiddleware - * already picked a language, so we don't need to set the default. */ - if (requestCultureFeature.Provider != null) - { - return null; - } + /* If requestCultureFeature == null, that means the RequestLocalizationMiddleware was not used + * and we don't want to set the culture. */ + if (requestCultureFeature == null) + { + return null; + } - var settingProvider = httpContext.RequestServices.GetRequiredService(); - var defaultLanguage = await settingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage); - if (defaultLanguage.IsNullOrWhiteSpace()) - { - return null; - } + /* If requestCultureFeature.Provider is not null, that means RequestLocalizationMiddleware + * already picked a language, so we don't need to set the default. */ + if (requestCultureFeature.Provider != null) + { + return null; + } - string culture; - string uiCulture; + var settingProvider = httpContext.RequestServices.GetRequiredService(); + var defaultLanguage = await settingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage); + if (defaultLanguage.IsNullOrWhiteSpace()) + { + return null; + } - if (defaultLanguage.Contains(';')) - { - var splitted = defaultLanguage.Split(';'); - culture = splitted[0]; - uiCulture = splitted[1]; - } - else - { - culture = defaultLanguage; - uiCulture = defaultLanguage; - } + string culture; + string uiCulture; - return new RequestCulture(culture, uiCulture); + if (defaultLanguage.Contains(';')) + { + var splitted = defaultLanguage.Split(';'); + culture = splitted[0]; + uiCulture = splitted[1]; } + else + { + culture = defaultLanguage; + uiCulture = defaultLanguage; + } + + return new RequestCulture(culture, uiCulture); } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs index 2edcac0eafe..f4f2cf8cb6e 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs @@ -3,33 +3,32 @@ using Microsoft.AspNetCore.Http; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +public class QueryStringTenantResolveContributor : HttpTenantResolveContributorBase { - public class QueryStringTenantResolveContributor : HttpTenantResolveContributorBase - { - public const string ContributorName = "QueryString"; + public const string ContributorName = "QueryString"; - public override string Name => ContributorName; + public override string Name => ContributorName; - protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) + protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) + { + if (httpContext.Request.QueryString.HasValue) { - if (httpContext.Request.QueryString.HasValue) + var tenantKey = context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey; + if (httpContext.Request.Query.ContainsKey(tenantKey)) { - var tenantKey = context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey; - if (httpContext.Request.Query.ContainsKey(tenantKey)) + var tenantValue = httpContext.Request.Query[tenantKey].ToString(); + if (tenantValue.IsNullOrWhiteSpace()) { - var tenantValue = httpContext.Request.Query[tenantKey].ToString(); - if (tenantValue.IsNullOrWhiteSpace()) - { - context.Handled = true; - return Task.FromResult(null); - } - - return Task.FromResult(tenantValue); + context.Handled = true; + return Task.FromResult(null); } - } - return Task.FromResult(null); + return Task.FromResult(tenantValue); + } } + + return Task.FromResult(null); } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs index 7ac3943c840..06e7972aa15 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs @@ -4,18 +4,17 @@ using Microsoft.AspNetCore.Routing; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +public class RouteTenantResolveContributor : HttpTenantResolveContributorBase { - public class RouteTenantResolveContributor : HttpTenantResolveContributorBase - { - public const string ContributorName = "Route"; + public const string ContributorName = "Route"; - public override string Name => ContributorName; + public override string Name => ContributorName; - protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) - { - var tenantId = httpContext.GetRouteValue(context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey); - return Task.FromResult(tenantId != null ? Convert.ToString(tenantId) : null); - } + protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) + { + var tenantId = httpContext.GetRouteValue(context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey); + return Task.FromResult(tenantId != null ? Convert.ToString(tenantId) : null); } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/TenantResolveContextExtensions.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/TenantResolveContextExtensions.cs index 701833bc70a..a4a8669304d 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/TenantResolveContextExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/TenantResolveContextExtensions.cs @@ -2,13 +2,12 @@ using Microsoft.Extensions.Options; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.AspNetCore.MultiTenancy +namespace Volo.Abp.AspNetCore.MultiTenancy; + +public static class TenantResolveContextExtensions { - public static class TenantResolveContextExtensions + public static AbpAspNetCoreMultiTenancyOptions GetAbpAspNetCoreMultiTenancyOptions(this ITenantResolveContext context) { - public static AbpAspNetCoreMultiTenancyOptions GetAbpAspNetCoreMultiTenancyOptions(this ITenantResolveContext context) - { - return context.ServiceProvider.GetRequiredService>().Value; - } + return context.ServiceProvider.GetRequiredService>().Value; } } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyOptionsExtensions.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyOptionsExtensions.cs index aa6f0fdb0e0..8ec02c027a7 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyOptionsExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyOptionsExtensions.cs @@ -1,16 +1,15 @@ using System.Collections.Generic; using Volo.Abp.AspNetCore.MultiTenancy; -namespace Volo.Abp.MultiTenancy +namespace Volo.Abp.MultiTenancy; + +public static class AbpMultiTenancyOptionsExtensions { - public static class AbpMultiTenancyOptionsExtensions + public static void AddDomainTenantResolver(this AbpTenantResolveOptions options, string domainFormat) { - public static void AddDomainTenantResolver(this AbpTenantResolveOptions options, string domainFormat) - { - options.TenantResolvers.InsertAfter( - r => r is CurrentUserTenantResolveContributor, - new DomainTenantResolveContributor(domainFormat) - ); - } + options.TenantResolvers.InsertAfter( + r => r is CurrentUserTenantResolveContributor, + new DomainTenantResolveContributor(domainFormat) + ); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpApplicationConfigurationClientProxy.Generated.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpApplicationConfigurationClientProxy.Generated.cs index 9d1c472bc79..198cfce7113 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpApplicationConfigurationClientProxy.Generated.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpApplicationConfigurationClientProxy.Generated.cs @@ -9,15 +9,14 @@ using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; // ReSharper disable once CheckNamespace -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(IAbpApplicationConfigurationAppService), typeof(AbpApplicationConfigurationClientProxy))] +public partial class AbpApplicationConfigurationClientProxy : ClientProxyBase, IAbpApplicationConfigurationAppService { - [Dependency(ReplaceServices = true)] - [ExposeServices(typeof(IAbpApplicationConfigurationAppService), typeof(AbpApplicationConfigurationClientProxy))] - public partial class AbpApplicationConfigurationClientProxy : ClientProxyBase, IAbpApplicationConfigurationAppService + public virtual async Task GetAsync() { - public virtual async Task GetAsync() - { - return await RequestAsync(nameof(GetAsync)); - } + return await RequestAsync(nameof(GetAsync)); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpApplicationConfigurationClientProxy.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpApplicationConfigurationClientProxy.cs index 41c1031556e..62b582b01b1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpApplicationConfigurationClientProxy.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpApplicationConfigurationClientProxy.cs @@ -3,11 +3,10 @@ using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies; + +[RemoteService(false)] +[DisableConventionalRegistration] +public partial class AbpApplicationConfigurationClientProxy { - [RemoteService(false)] - [DisableConventionalRegistration] - public partial class AbpApplicationConfigurationClientProxy - { - } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpTenantClientProxy.Generated.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpTenantClientProxy.Generated.cs index 8984abfc4c4..291a6e95d12 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpTenantClientProxy.Generated.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpTenantClientProxy.Generated.cs @@ -9,26 +9,25 @@ using Volo.Abp.AspNetCore.Mvc.MultiTenancy; // ReSharper disable once CheckNamespace -namespace Pages.Abp.MultiTenancy.ClientProxies +namespace Pages.Abp.MultiTenancy.ClientProxies; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(IAbpTenantAppService), typeof(AbpTenantClientProxy))] +public partial class AbpTenantClientProxy : ClientProxyBase, IAbpTenantAppService { - [Dependency(ReplaceServices = true)] - [ExposeServices(typeof(IAbpTenantAppService), typeof(AbpTenantClientProxy))] - public partial class AbpTenantClientProxy : ClientProxyBase, IAbpTenantAppService + public virtual async Task FindTenantByNameAsync(string name) { - public virtual async Task FindTenantByNameAsync(string name) + return await RequestAsync(nameof(FindTenantByNameAsync), new ClientProxyRequestTypeValue { - return await RequestAsync(nameof(FindTenantByNameAsync), new ClientProxyRequestTypeValue - { - { typeof(string), name } - }); - } + { typeof(string), name } + }); + } - public virtual async Task FindTenantByIdAsync(Guid id) + public virtual async Task FindTenantByIdAsync(Guid id) + { + return await RequestAsync(nameof(FindTenantByIdAsync), new ClientProxyRequestTypeValue { - return await RequestAsync(nameof(FindTenantByIdAsync), new ClientProxyRequestTypeValue - { - { typeof(Guid), id } - }); - } + { typeof(Guid), id } + }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpTenantClientProxy.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpTenantClientProxy.cs index e73b05b573e..8ca24d13179 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpTenantClientProxy.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/ClientProxies/AbpTenantClientProxy.cs @@ -4,11 +4,11 @@ using Volo.Abp; using Volo.Abp.DependencyInjection; -namespace Pages.Abp.MultiTenancy.ClientProxies +namespace Pages.Abp.MultiTenancy.ClientProxies; + +[RemoteService(false)] +[DisableConventionalRegistration] +public partial class AbpTenantClientProxy { - [RemoteService(false)] - [DisableConventionalRegistration] - public partial class AbpTenantClientProxy - { - } } + diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientCommonModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientCommonModule.cs index e48a63c86c8..d3734e7c663 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientCommonModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientCommonModule.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Pages.Abp.MultiTenancy.ClientProxies; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies; using Volo.Abp.Authorization; @@ -9,37 +9,36 @@ using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +[DependsOn( + typeof(AbpHttpClientModule), + typeof(AbpAspNetCoreMvcContractsModule), + typeof(AbpCachingModule), + typeof(AbpLocalizationModule), + typeof(AbpAuthorizationModule), + typeof(AbpFeaturesModule), + typeof(AbpVirtualFileSystemModule) +)] +public class AbpAspNetCoreMvcClientCommonModule : AbpModule { - [DependsOn( - typeof(AbpHttpClientModule), - typeof(AbpAspNetCoreMvcContractsModule), - typeof(AbpCachingModule), - typeof(AbpLocalizationModule), - typeof(AbpAuthorizationModule), - typeof(AbpFeaturesModule), - typeof(AbpVirtualFileSystemModule) - )] - public class AbpAspNetCoreMvcClientCommonModule : AbpModule + public const string RemoteServiceName = "AbpMvcClient"; + + public override void ConfigureServices(ServiceConfigurationContext context) { - public const string RemoteServiceName = "AbpMvcClient"; + context.Services.AddStaticHttpClientProxies(typeof(AbpAspNetCoreMvcContractsModule).Assembly, RemoteServiceName); - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(options => { - context.Services.AddStaticHttpClientProxies(typeof(AbpAspNetCoreMvcContractsModule).Assembly, RemoteServiceName); + options.FileSets.AddEmbedded(); + }); - Configure(options => - { - options.FileSets.AddEmbedded(); - }); - - Configure(options => - { - options.GlobalContributors.Add(); - }); + Configure(options => + { + options.GlobalContributors.Add(); + }); - context.Services.AddTransient(); - context.Services.AddTransient(); - } + context.Services.AddTransient(); + context.Services.AddTransient(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs index 80e6c4e054b..f173082fa3f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/ICachedApplicationConfigurationClient.cs @@ -1,12 +1,11 @@ using System.Threading.Tasks; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public interface ICachedApplicationConfigurationClient : IAsyncInitialize { - public interface ICachedApplicationConfigurationClient : IAsyncInitialize - { - Task GetAsync(); + Task GetAsync(); - ApplicationConfigurationDto Get(); - } + ApplicationConfigurationDto Get(); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs index f769f512a5f..d3969e7888e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs @@ -2,21 +2,20 @@ using System.Threading.Tasks; using Volo.Abp.Features; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public class RemoteFeatureChecker : FeatureCheckerBase { - public class RemoteFeatureChecker : FeatureCheckerBase - { - protected ICachedApplicationConfigurationClient ConfigurationClient { get; } + protected ICachedApplicationConfigurationClient ConfigurationClient { get; } - public RemoteFeatureChecker(ICachedApplicationConfigurationClient configurationClient) - { - ConfigurationClient = configurationClient; - } + public RemoteFeatureChecker(ICachedApplicationConfigurationClient configurationClient) + { + ConfigurationClient = configurationClient; + } - public override async Task GetOrNullAsync(string name) - { - var configuration = await ConfigurationClient.GetAsync(); - return configuration.Features.Values.GetOrDefault(name); - } + public override async Task GetOrNullAsync(string name) + { + var configuration = await ConfigurationClient.GetAsync(); + return configuration.Features.Values.GetOrDefault(name); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs index 02c97c05989..cb6b76ad744 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs @@ -3,21 +3,20 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public class RemoteLanguageProvider : ILanguageProvider, ITransientDependency { - public class RemoteLanguageProvider : ILanguageProvider, ITransientDependency - { - protected ICachedApplicationConfigurationClient ConfigurationClient { get; } + protected ICachedApplicationConfigurationClient ConfigurationClient { get; } - public RemoteLanguageProvider(ICachedApplicationConfigurationClient configurationClient) - { - ConfigurationClient = configurationClient; - } + public RemoteLanguageProvider(ICachedApplicationConfigurationClient configurationClient) + { + ConfigurationClient = configurationClient; + } - public async Task> GetLanguagesAsync() - { - var configuration = await ConfigurationClient.GetAsync(); - return configuration.Localization.Languages; - } + public async Task> GetLanguagesAsync() + { + var configuration = await ConfigurationClient.GetAsync(); + return configuration.Localization.Languages; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs index f8502fce78d..c01fc6a1af6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteLocalizationContributor.cs @@ -5,67 +5,66 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Localization; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public class RemoteLocalizationContributor : ILocalizationResourceContributor { - public class RemoteLocalizationContributor : ILocalizationResourceContributor + private LocalizationResource _resource; + private ICachedApplicationConfigurationClient _applicationConfigurationClient; + private ILogger _logger; + + public void Initialize(LocalizationResourceInitializationContext context) { - private LocalizationResource _resource; - private ICachedApplicationConfigurationClient _applicationConfigurationClient; - private ILogger _logger; + _resource = context.Resource; + _applicationConfigurationClient = context.ServiceProvider.GetRequiredService(); + _logger = context.ServiceProvider.GetService>() + ?? NullLogger.Instance; + } - public void Initialize(LocalizationResourceInitializationContext context) + public LocalizedString GetOrNull(string cultureName, string name) + { + var resource = GetResourceOrNull(); + if (resource == null) { - _resource = context.Resource; - _applicationConfigurationClient = context.ServiceProvider.GetRequiredService(); - _logger = context.ServiceProvider.GetService>() - ?? NullLogger.Instance; + return null; } - public LocalizedString GetOrNull(string cultureName, string name) + var value = resource.GetOrDefault(name); + if (value == null) { - var resource = GetResourceOrNull(); - if (resource == null) - { - return null; - } - - var value = resource.GetOrDefault(name); - if (value == null) - { - return null; - } - - return new LocalizedString(name, value); + return null; } - public void Fill(string cultureName, Dictionary dictionary) - { - var resource = GetResourceOrNull(); - if (resource == null) - { - return; - } + return new LocalizedString(name, value); + } - foreach (var keyValue in resource) - { - dictionary[keyValue.Key] = new LocalizedString(keyValue.Key, keyValue.Value); - } + public void Fill(string cultureName, Dictionary dictionary) + { + var resource = GetResourceOrNull(); + if (resource == null) + { + return; } - private Dictionary GetResourceOrNull() + foreach (var keyValue in resource) { - var applicationConfigurationDto = _applicationConfigurationClient.Get(); + dictionary[keyValue.Key] = new LocalizedString(keyValue.Key, keyValue.Value); + } + } - var resource = applicationConfigurationDto - .Localization.Values - .GetOrDefault(_resource.ResourceName); + private Dictionary GetResourceOrNull() + { + var applicationConfigurationDto = _applicationConfigurationClient.Get(); - if (resource == null) - { - _logger.LogWarning($"Could not find the localization resource {_resource.ResourceName} on the remote server!"); - } + var resource = applicationConfigurationDto + .Localization.Values + .GetOrDefault(_resource.ResourceName); - return resource; + if (resource == null) + { + _logger.LogWarning($"Could not find the localization resource {_resource.ResourceName} on the remote server!"); } + + return resource; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs index 5ce1ea9edcb..3274c5010cb 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemotePermissionChecker.cs @@ -3,48 +3,47 @@ using Volo.Abp.Authorization.Permissions; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public class RemotePermissionChecker : IPermissionChecker, ITransientDependency { - public class RemotePermissionChecker : IPermissionChecker, ITransientDependency + protected ICachedApplicationConfigurationClient ConfigurationClient { get; } + + public RemotePermissionChecker(ICachedApplicationConfigurationClient configurationClient) { - protected ICachedApplicationConfigurationClient ConfigurationClient { get; } + ConfigurationClient = configurationClient; + } - public RemotePermissionChecker(ICachedApplicationConfigurationClient configurationClient) - { - ConfigurationClient = configurationClient; - } + public async Task IsGrantedAsync(string name) + { + var configuration = await ConfigurationClient.GetAsync(); - public async Task IsGrantedAsync(string name) - { - var configuration = await ConfigurationClient.GetAsync(); + return configuration.Auth.GrantedPolicies.ContainsKey(name); + } - return configuration.Auth.GrantedPolicies.ContainsKey(name); - } + public async Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name) + { + /* This provider always works for the current principal. */ + return await IsGrantedAsync(name); + } - public async Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name) + public async Task IsGrantedAsync(string[] names) + { + var result = new MultiplePermissionGrantResult(); + var configuration = await ConfigurationClient.GetAsync(); + foreach (var name in names) { - /* This provider always works for the current principal. */ - return await IsGrantedAsync(name); + result.Result.Add(name, configuration.Auth.GrantedPolicies.ContainsKey(name) ? + PermissionGrantResult.Granted : + PermissionGrantResult.Undefined); } - public async Task IsGrantedAsync(string[] names) - { - var result = new MultiplePermissionGrantResult(); - var configuration = await ConfigurationClient.GetAsync(); - foreach (var name in names) - { - result.Result.Add(name, configuration.Auth.GrantedPolicies.ContainsKey(name) ? - PermissionGrantResult.Granted : - PermissionGrantResult.Undefined); - } - - return result; - } + return result; + } - public async Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string[] names) - { - /* This provider always works for the current principal. */ - return await IsGrantedAsync(names); - } + public async Task IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string[] names) + { + /* This provider always works for the current principal. */ + return await IsGrantedAsync(names); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs index 89db44b43d3..2599df1ef6e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteSettingProvider.cs @@ -4,36 +4,35 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Settings; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public class RemoteSettingProvider : ISettingProvider, ITransientDependency { - public class RemoteSettingProvider : ISettingProvider, ITransientDependency - { - protected ICachedApplicationConfigurationClient ConfigurationClient { get; } + protected ICachedApplicationConfigurationClient ConfigurationClient { get; } - public RemoteSettingProvider(ICachedApplicationConfigurationClient configurationClient) - { - ConfigurationClient = configurationClient; - } + public RemoteSettingProvider(ICachedApplicationConfigurationClient configurationClient) + { + ConfigurationClient = configurationClient; + } - public async Task GetOrNullAsync(string name) - { - var configuration = await ConfigurationClient.GetAsync(); - return configuration.Setting.Values.GetOrDefault(name); - } + public async Task GetOrNullAsync(string name) + { + var configuration = await ConfigurationClient.GetAsync(); + return configuration.Setting.Values.GetOrDefault(name); + } - public async Task> GetAllAsync(string[] names) - { - var configuration = await ConfigurationClient.GetAsync(); - return names.Select(x => new SettingValue(x, configuration.Setting.Values.GetOrDefault(x))).ToList(); - } + public async Task> GetAllAsync(string[] names) + { + var configuration = await ConfigurationClient.GetAsync(); + return names.Select(x => new SettingValue(x, configuration.Setting.Values.GetOrDefault(x))).ToList(); + } - public async Task> GetAllAsync() - { - var configuration = await ConfigurationClient.GetAsync(); - return configuration - .Setting.Values - .Select(s => new SettingValue(s.Key, s.Value)) - .ToList(); - } + public async Task> GetAllAsync() + { + var configuration = await ConfigurationClient.GetAsync(); + return configuration + .Setting.Values + .Select(s => new SettingValue(s.Key, s.Value)) + .ToList(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs index 48e24611674..a7dc58f82a3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/AbpAspNetCoreMvcClientModule.cs @@ -1,13 +1,12 @@ using Volo.Abp.EventBus; using Volo.Abp.Modularity; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +[DependsOn( + typeof(AbpAspNetCoreMvcClientCommonModule), + typeof(AbpEventBusModule) + )] +public class AbpAspNetCoreMvcClientModule : AbpModule { - [DependsOn( - typeof(AbpAspNetCoreMvcClientCommonModule), - typeof(AbpEventBusModule) - )] - public class AbpAspNetCoreMvcClientModule : AbpModule - { - } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs index e7a78e1d15d..fba7a3fdfe6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClient.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.AspNetCore.Http; using System.Threading.Tasks; using Microsoft.Extensions.Caching.Distributed; @@ -9,81 +9,80 @@ using Volo.Abp.Threading; using Volo.Abp.Users; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +[ExposeServices( + typeof(MvcCachedApplicationConfigurationClient), + typeof(ICachedApplicationConfigurationClient), + typeof(IAsyncInitialize) + )] +public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency { - [ExposeServices( - typeof(MvcCachedApplicationConfigurationClient), - typeof(ICachedApplicationConfigurationClient), - typeof(IAsyncInitialize) - )] - public class MvcCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency + protected IHttpContextAccessor HttpContextAccessor { get; } + protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; } + protected ICurrentUser CurrentUser { get; } + protected IDistributedCache Cache { get; } + + public MvcCachedApplicationConfigurationClient( + IDistributedCache cache, + AbpApplicationConfigurationClientProxy applicationConfigurationAppService, + ICurrentUser currentUser, + IHttpContextAccessor httpContextAccessor) { - protected IHttpContextAccessor HttpContextAccessor { get; } - protected AbpApplicationConfigurationClientProxy ApplicationConfigurationAppService { get; } - protected ICurrentUser CurrentUser { get; } - protected IDistributedCache Cache { get; } + ApplicationConfigurationAppService = applicationConfigurationAppService; + CurrentUser = currentUser; + HttpContextAccessor = httpContextAccessor; + Cache = cache; + } - public MvcCachedApplicationConfigurationClient( - IDistributedCache cache, - AbpApplicationConfigurationClientProxy applicationConfigurationAppService, - ICurrentUser currentUser, - IHttpContextAccessor httpContextAccessor) - { - ApplicationConfigurationAppService = applicationConfigurationAppService; - CurrentUser = currentUser; - HttpContextAccessor = httpContextAccessor; - Cache = cache; - } + public async Task InitializeAsync() + { + await GetAsync(); + } - public async Task InitializeAsync() + public async Task GetAsync() + { + var cacheKey = CreateCacheKey(); + var httpContext = HttpContextAccessor?.HttpContext; + + if (httpContext != null && httpContext.Items[cacheKey] is ApplicationConfigurationDto configuration) { - await GetAsync(); + return configuration; } - public async Task GetAsync() - { - var cacheKey = CreateCacheKey(); - var httpContext = HttpContextAccessor?.HttpContext; - if (httpContext != null && httpContext.Items[cacheKey] is ApplicationConfigurationDto configuration) + configuration = await Cache.GetOrAddAsync( + cacheKey, + async () => await ApplicationConfigurationAppService.GetAsync(), + () => new DistributedCacheEntryOptions { - return configuration; + AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300) //TODO: Should be configurable. } + ); + if (httpContext != null) + { + httpContext.Items[cacheKey] = configuration; + } - configuration = await Cache.GetOrAddAsync( - cacheKey, - async () => await ApplicationConfigurationAppService.GetAsync(), - () => new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300) //TODO: Should be configurable. - } - ); + return configuration; + } - if (httpContext != null) - { - httpContext.Items[cacheKey] = configuration; - } + public ApplicationConfigurationDto Get() + { + var cacheKey = CreateCacheKey(); + var httpContext = HttpContextAccessor?.HttpContext; + if (httpContext != null && httpContext.Items[cacheKey] is ApplicationConfigurationDto configuration) + { return configuration; } - public ApplicationConfigurationDto Get() - { - var cacheKey = CreateCacheKey(); - var httpContext = HttpContextAccessor?.HttpContext; - - if (httpContext != null && httpContext.Items[cacheKey] is ApplicationConfigurationDto configuration) - { - return configuration; - } - - return AsyncHelper.RunSync(GetAsync); - } + return AsyncHelper.RunSync(GetAsync); + } - protected virtual string CreateCacheKey() - { - return MvcCachedApplicationConfigurationClientHelper.CreateCacheKey(CurrentUser); - } + protected virtual string CreateCacheKey() + { + return MvcCachedApplicationConfigurationClientHelper.CreateCacheKey(CurrentUser); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs index ae013c4343e..740a79c8848 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs @@ -1,14 +1,13 @@ using System.Globalization; using Volo.Abp.Users; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +internal static class MvcCachedApplicationConfigurationClientHelper { - internal static class MvcCachedApplicationConfigurationClientHelper + public static string CreateCacheKey(ICurrentUser currentUser) { - public static string CreateCacheKey(ICurrentUser currentUser) - { - var userKey = currentUser.Id?.ToString("N") ?? "Anonymous"; - return $"ApplicationConfiguration_{userKey}_{CultureInfo.CurrentUICulture.Name}"; - } + var userKey = currentUser.Id?.ToString("N") ?? "Anonymous"; + return $"ApplicationConfiguration_{userKey}_{CultureInfo.CurrentUICulture.Name}"; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCurrentApplicationConfigurationCacheResetEventHandler.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCurrentApplicationConfigurationCacheResetEventHandler.cs index e8f5b201da0..8bd39717794 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCurrentApplicationConfigurationCacheResetEventHandler.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCurrentApplicationConfigurationCacheResetEventHandler.cs @@ -5,30 +5,29 @@ using Volo.Abp.EventBus; using Volo.Abp.Users; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public class MvcCurrentApplicationConfigurationCacheResetEventHandler : + ILocalEventHandler, + ITransientDependency { - public class MvcCurrentApplicationConfigurationCacheResetEventHandler : - ILocalEventHandler, - ITransientDependency - { - protected ICurrentUser CurrentUser { get; } - protected IDistributedCache Cache { get; } + protected ICurrentUser CurrentUser { get; } + protected IDistributedCache Cache { get; } - public MvcCurrentApplicationConfigurationCacheResetEventHandler(ICurrentUser currentUser, - IDistributedCache cache) - { - CurrentUser = currentUser; - Cache = cache; - } + public MvcCurrentApplicationConfigurationCacheResetEventHandler(ICurrentUser currentUser, + IDistributedCache cache) + { + CurrentUser = currentUser; + Cache = cache; + } - public virtual async Task HandleEventAsync(CurrentApplicationConfigurationCacheResetEventData eventData) - { - await Cache.RemoveAsync(CreateCacheKey()); - } + public virtual async Task HandleEventAsync(CurrentApplicationConfigurationCacheResetEventData eventData) + { + await Cache.RemoveAsync(CreateCacheKey()); + } - protected virtual string CreateCacheKey() - { - return MvcCachedApplicationConfigurationClientHelper.CreateCacheKey(CurrentUser); - } + protected virtual string CreateCacheKey() + { + return MvcCachedApplicationConfigurationClientHelper.CreateCacheKey(CurrentUser); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs index f4744ca587d..dd4411255e9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs @@ -9,154 +9,153 @@ using Volo.Abp.MultiTenancy; using Volo.Abp.Threading; -namespace Volo.Abp.AspNetCore.Mvc.Client +namespace Volo.Abp.AspNetCore.Mvc.Client; + +public class MvcRemoteTenantStore : ITenantStore, ITransientDependency { - public class MvcRemoteTenantStore : ITenantStore, ITransientDependency + protected AbpTenantClientProxy TenantAppService { get; } + protected IHttpContextAccessor HttpContextAccessor { get; } + protected IDistributedCache Cache { get; } + + public MvcRemoteTenantStore( + AbpTenantClientProxy tenantAppService, + IHttpContextAccessor httpContextAccessor, + IDistributedCache cache) { - protected AbpTenantClientProxy TenantAppService { get; } - protected IHttpContextAccessor HttpContextAccessor { get; } - protected IDistributedCache Cache { get; } - - public MvcRemoteTenantStore( - AbpTenantClientProxy tenantAppService, - IHttpContextAccessor httpContextAccessor, - IDistributedCache cache) - { - TenantAppService = tenantAppService; - HttpContextAccessor = httpContextAccessor; - Cache = cache; - } + TenantAppService = tenantAppService; + HttpContextAccessor = httpContextAccessor; + Cache = cache; + } - public async Task FindAsync(string name) + public async Task FindAsync(string name) + { + var cacheKey = CreateCacheKey(name); + var httpContext = HttpContextAccessor?.HttpContext; + + if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration) { - var cacheKey = CreateCacheKey(name); - var httpContext = HttpContextAccessor?.HttpContext; + return tenantConfiguration; + } - if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration) + tenantConfiguration = await Cache.GetOrAddAsync( + cacheKey, + async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(name)), + () => new DistributedCacheEntryOptions { - return tenantConfiguration; - } - - tenantConfiguration = await Cache.GetOrAddAsync( - cacheKey, - async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(name)), - () => new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = - TimeSpan.FromMinutes(5) //TODO: Should be configurable. + AbsoluteExpirationRelativeToNow = + TimeSpan.FromMinutes(5) //TODO: Should be configurable. } - ); - - if (httpContext != null) - { - httpContext.Items[cacheKey] = tenantConfiguration; - } + ); - return tenantConfiguration; - } - - public async Task FindAsync(Guid id) + if (httpContext != null) { - var cacheKey = CreateCacheKey(id); - var httpContext = HttpContextAccessor?.HttpContext; + httpContext.Items[cacheKey] = tenantConfiguration; + } - if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration) - { - return tenantConfiguration; - } - - tenantConfiguration = await Cache.GetOrAddAsync( - cacheKey, - async () => CreateTenantConfiguration(await TenantAppService.FindTenantByIdAsync(id)), - () => new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = - TimeSpan.FromMinutes(5) //TODO: Should be configurable. - } - ); + return tenantConfiguration; + } - if (httpContext != null) - { - httpContext.Items[cacheKey] = tenantConfiguration; - } + public async Task FindAsync(Guid id) + { + var cacheKey = CreateCacheKey(id); + var httpContext = HttpContextAccessor?.HttpContext; + if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration) + { return tenantConfiguration; } - public TenantConfiguration Find(string name) - { - var cacheKey = CreateCacheKey(name); - var httpContext = HttpContextAccessor?.HttpContext; - - if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration) + tenantConfiguration = await Cache.GetOrAddAsync( + cacheKey, + async () => CreateTenantConfiguration(await TenantAppService.FindTenantByIdAsync(id)), + () => new DistributedCacheEntryOptions { - return tenantConfiguration; - } - - tenantConfiguration = Cache.GetOrAdd( - cacheKey, - () => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(name))), - () => new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = - TimeSpan.FromMinutes(5) //TODO: Should be configurable. + AbsoluteExpirationRelativeToNow = + TimeSpan.FromMinutes(5) //TODO: Should be configurable. } - ); - - if (httpContext != null) - { - httpContext.Items[cacheKey] = tenantConfiguration; - } + ); - return tenantConfiguration; + if (httpContext != null) + { + httpContext.Items[cacheKey] = tenantConfiguration; } - public TenantConfiguration Find(Guid id) + return tenantConfiguration; + } + + public TenantConfiguration Find(string name) + { + var cacheKey = CreateCacheKey(name); + var httpContext = HttpContextAccessor?.HttpContext; + + if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration) { - var cacheKey = CreateCacheKey(id); - var httpContext = HttpContextAccessor?.HttpContext; + return tenantConfiguration; + } - if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration) + tenantConfiguration = Cache.GetOrAdd( + cacheKey, + () => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await TenantAppService.FindTenantByNameAsync(name))), + () => new DistributedCacheEntryOptions { - return tenantConfiguration; - } - - tenantConfiguration = Cache.GetOrAdd( - cacheKey, - () => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await TenantAppService.FindTenantByIdAsync(id))), - () => new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = - TimeSpan.FromMinutes(5) //TODO: Should be configurable. + AbsoluteExpirationRelativeToNow = + TimeSpan.FromMinutes(5) //TODO: Should be configurable. } - ); + ); - if (httpContext != null) - { - httpContext.Items[cacheKey] = tenantConfiguration; - } + if (httpContext != null) + { + httpContext.Items[cacheKey] = tenantConfiguration; + } + + return tenantConfiguration; + } + public TenantConfiguration Find(Guid id) + { + var cacheKey = CreateCacheKey(id); + var httpContext = HttpContextAccessor?.HttpContext; + + if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration) + { return tenantConfiguration; } - protected virtual TenantConfiguration CreateTenantConfiguration(FindTenantResultDto tenantResultDto) - { - if (!tenantResultDto.Success || tenantResultDto.TenantId == null) + tenantConfiguration = Cache.GetOrAdd( + cacheKey, + () => AsyncHelper.RunSync(async () => CreateTenantConfiguration(await TenantAppService.FindTenantByIdAsync(id))), + () => new DistributedCacheEntryOptions { - return null; - } - - return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name); - } + AbsoluteExpirationRelativeToNow = + TimeSpan.FromMinutes(5) //TODO: Should be configurable. + } + ); - protected virtual string CreateCacheKey(string tenantName) + if (httpContext != null) { - return $"RemoteTenantStore_Name_{tenantName}"; + httpContext.Items[cacheKey] = tenantConfiguration; } - protected virtual string CreateCacheKey(Guid tenantId) + return tenantConfiguration; + } + + protected virtual TenantConfiguration CreateTenantConfiguration(FindTenantResultDto tenantResultDto) + { + if (!tenantResultDto.Success || tenantResultDto.TenantId == null) { - return $"RemoteTenantStore_Id_{tenantId:N}"; + return null; } + + return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name); + } + + protected virtual string CreateCacheKey(string tenantName) + { + return $"RemoteTenantStore_Name_{tenantName}"; + } + + protected virtual string CreateCacheKey(Guid tenantId) + { + return $"RemoteTenantStore_Id_{tenantId:N}"; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcContractsModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcContractsModule.cs index 3bf299437cd..278fe6eb219 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcContractsModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcContractsModule.cs @@ -1,13 +1,12 @@ using Volo.Abp.Application; using Volo.Abp.Modularity; -namespace Volo.Abp.AspNetCore.Mvc +namespace Volo.Abp.AspNetCore.Mvc; + +[DependsOn( + typeof(AbpDddApplicationContractsModule) + )] +public class AbpAspNetCoreMvcContractsModule : AbpModule { - [DependsOn( - typeof(AbpDddApplicationContractsModule) - )] - public class AbpAspNetCoreMvcContractsModule : AbpModule - { - } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationAuthConfigurationDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationAuthConfigurationDto.cs index 39b3ca394b5..be5a022b013 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationAuthConfigurationDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationAuthConfigurationDto.cs @@ -1,19 +1,18 @@ using System; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +[Serializable] +public class ApplicationAuthConfigurationDto { - [Serializable] - public class ApplicationAuthConfigurationDto - { - public Dictionary Policies { get; set; } + public Dictionary Policies { get; set; } - public Dictionary GrantedPolicies { get; set; } + public Dictionary GrantedPolicies { get; set; } - public ApplicationAuthConfigurationDto() - { - Policies = new Dictionary(); - GrantedPolicies = new Dictionary(); - } + public ApplicationAuthConfigurationDto() + { + Policies = new Dictionary(); + GrantedPolicies = new Dictionary(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs index 6a4aa49a1ba..9b6a66992fe 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs @@ -2,29 +2,28 @@ using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; using Volo.Abp.AspNetCore.Mvc.MultiTenancy; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +[Serializable] +public class ApplicationConfigurationDto { - [Serializable] - public class ApplicationConfigurationDto - { - public ApplicationLocalizationConfigurationDto Localization { get; set; } + public ApplicationLocalizationConfigurationDto Localization { get; set; } - public ApplicationAuthConfigurationDto Auth { get; set; } + public ApplicationAuthConfigurationDto Auth { get; set; } - public ApplicationSettingConfigurationDto Setting { get; set; } + public ApplicationSettingConfigurationDto Setting { get; set; } - public CurrentUserDto CurrentUser { get; set; } + public CurrentUserDto CurrentUser { get; set; } - public ApplicationFeatureConfigurationDto Features { get; set; } + public ApplicationFeatureConfigurationDto Features { get; set; } - public MultiTenancyInfoDto MultiTenancy { get; set; } + public MultiTenancyInfoDto MultiTenancy { get; set; } - public CurrentTenantDto CurrentTenant { get; set; } + public CurrentTenantDto CurrentTenant { get; set; } - public TimingDto Timing { get; set; } + public TimingDto Timing { get; set; } - public ClockDto Clock { get; set; } + public ClockDto Clock { get; set; } - public ObjectExtensionsDto ObjectExtensions { get; set; } - } + public ObjectExtensionsDto ObjectExtensions { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationFeatureConfigurationDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationFeatureConfigurationDto.cs index 4972d2242d7..9215a466169 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationFeatureConfigurationDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationFeatureConfigurationDto.cs @@ -1,16 +1,15 @@ using System; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +[Serializable] +public class ApplicationFeatureConfigurationDto { - [Serializable] - public class ApplicationFeatureConfigurationDto - { - public Dictionary Values { get; set; } + public Dictionary Values { get; set; } - public ApplicationFeatureConfigurationDto() - { - Values = new Dictionary(); - } + public ApplicationFeatureConfigurationDto() + { + Values = new Dictionary(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs index 5f53694177a..0b229235fac 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs @@ -2,28 +2,27 @@ using System.Collections.Generic; using Volo.Abp.Localization; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +[Serializable] +public class ApplicationLocalizationConfigurationDto { - [Serializable] - public class ApplicationLocalizationConfigurationDto - { - //TODO: Rename to Texts? - public Dictionary> Values { get; set; } + //TODO: Rename to Texts? + public Dictionary> Values { get; set; } - public List Languages { get; set; } + public List Languages { get; set; } - public CurrentCultureDto CurrentCulture { get; set; } + public CurrentCultureDto CurrentCulture { get; set; } - public string DefaultResourceName { get; set; } + public string DefaultResourceName { get; set; } - public Dictionary> LanguagesMap { get; set; } + public Dictionary> LanguagesMap { get; set; } - public Dictionary> LanguageFilesMap { get; set; } + public Dictionary> LanguageFilesMap { get; set; } - public ApplicationLocalizationConfigurationDto() - { - Values = new Dictionary>(); - Languages = new List(); - } + public ApplicationLocalizationConfigurationDto() + { + Values = new Dictionary>(); + Languages = new List(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationSettingConfigurationDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationSettingConfigurationDto.cs index 40cbd89fd1a..a1fbba2bbf5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationSettingConfigurationDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationSettingConfigurationDto.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +[Serializable] +public class ApplicationSettingConfigurationDto { - [Serializable] - public class ApplicationSettingConfigurationDto - { - public Dictionary Values { get; set; } - } -} \ No newline at end of file + public Dictionary Values { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ClockDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ClockDto.cs index 2cff97f8142..5112ac80edb 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ClockDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ClockDto.cs @@ -1,7 +1,6 @@ -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +public class ClockDto { - public class ClockDto - { - public string Kind { get; set; } - } + public string Kind { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentApplicationConfigurationCacheResetEventData.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentApplicationConfigurationCacheResetEventData.cs index e84e96d9dd4..a50cb7b1367 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentApplicationConfigurationCacheResetEventData.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentApplicationConfigurationCacheResetEventData.cs @@ -1,10 +1,9 @@ -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +/// +/// This event is used to invalidate current user's cached configuration. +/// +public class CurrentApplicationConfigurationCacheResetEventData { - /// - /// This event is used to invalidate current user's cached configuration. - /// - public class CurrentApplicationConfigurationCacheResetEventData - { - } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs index b225fac8f03..8f1896e31fa 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs @@ -1,23 +1,22 @@ -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +public class CurrentCultureDto { - public class CurrentCultureDto - { - public string DisplayName { get; set; } + public string DisplayName { get; set; } - public string EnglishName { get; set; } + public string EnglishName { get; set; } - public string ThreeLetterIsoLanguageName { get; set; } + public string ThreeLetterIsoLanguageName { get; set; } - public string TwoLetterIsoLanguageName { get; set; } + public string TwoLetterIsoLanguageName { get; set; } - public bool IsRightToLeft { get; set; } + public bool IsRightToLeft { get; set; } - public string CultureName { get; set; } + public string CultureName { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public string NativeName { get; set; } + public string NativeName { get; set; } - public DateTimeFormatDto DateTimeFormat { get; set; } - } -} \ No newline at end of file + public DateTimeFormatDto DateTimeFormat { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentUserDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentUserDto.cs index b1b97c4b915..534ca68d80c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentUserDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentUserDto.cs @@ -1,34 +1,33 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +[Serializable] +public class CurrentUserDto { - [Serializable] - public class CurrentUserDto - { - public bool IsAuthenticated { get; set; } + public bool IsAuthenticated { get; set; } - public Guid? Id { get; set; } + public Guid? Id { get; set; } - public Guid? TenantId { get; set; } + public Guid? TenantId { get; set; } - public Guid? ImpersonatorUserId { get; set; } + public Guid? ImpersonatorUserId { get; set; } - public Guid? ImpersonatorTenantId { get; set; } + public Guid? ImpersonatorTenantId { get; set; } - public string UserName { get; set; } + public string UserName { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public string SurName { get; set; } + public string SurName { get; set; } - public string Email { get; set; } + public string Email { get; set; } - public bool EmailVerified { get; set; } + public bool EmailVerified { get; set; } - public string PhoneNumber { get; set; } + public string PhoneNumber { get; set; } - public bool PhoneNumberVerified { get; set; } + public bool PhoneNumberVerified { get; set; } - public string[] Roles { get; set; } - } + public string[] Roles { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/DateTimeFormatDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/DateTimeFormatDto.cs index 259dff1da65..5f5ad14a5a5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/DateTimeFormatDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/DateTimeFormatDto.cs @@ -1,19 +1,18 @@ -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +public class DateTimeFormatDto { - public class DateTimeFormatDto - { - public string CalendarAlgorithmType { get; set; } + public string CalendarAlgorithmType { get; set; } - public string DateTimeFormatLong { get; set; } + public string DateTimeFormatLong { get; set; } - public string ShortDatePattern { get; set; } + public string ShortDatePattern { get; set; } - public string FullDateTimePattern { get; set; } + public string FullDateTimePattern { get; set; } - public string DateSeparator { get; set; } + public string DateSeparator { get; set; } - public string ShortTimePattern { get; set; } + public string ShortTimePattern { get; set; } - public string LongTimePattern { get; set; } - } -} \ No newline at end of file + public string LongTimePattern { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/IAbpApplicationConfigurationAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/IAbpApplicationConfigurationAppService.cs index 4c521b9efc8..9c8fd3d414d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/IAbpApplicationConfigurationAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/IAbpApplicationConfigurationAppService.cs @@ -1,10 +1,9 @@ using System.Threading.Tasks; using Volo.Abp.Application.Services; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +public interface IAbpApplicationConfigurationAppService : IApplicationService { - public interface IAbpApplicationConfigurationAppService : IApplicationService - { - Task GetAsync(); - } -} \ No newline at end of file + Task GetAsync(); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs index d15870e7c19..742da779f61 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/EntityExtensionDto.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class EntityExtensionDto { - [Serializable] - public class EntityExtensionDto - { - public Dictionary Properties { get; set; } + public Dictionary Properties { get; set; } - public Dictionary Configuration { get; set; } - } -} \ No newline at end of file + public Dictionary Configuration { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumDto.cs index 4f2dc526eb0..24e9ec9a2f9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumDto.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionEnumDto { - [Serializable] - public class ExtensionEnumDto - { - public List Fields { get; set; } + public List Fields { get; set; } - public string LocalizationResource { get; set; } - } -} \ No newline at end of file + public string LocalizationResource { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumFieldDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumFieldDto.cs index ddc7c349d41..13728d8409f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumFieldDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionEnumFieldDto.cs @@ -1,12 +1,11 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionEnumFieldDto { - [Serializable] - public class ExtensionEnumFieldDto - { - public string Name { get; set; } + public string Name { get; set; } - public object Value { get; set; } - } -} \ No newline at end of file + public object Value { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiCreateDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiCreateDto.cs index a2a588a358f..9179ce7e2e6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiCreateDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiCreateDto.cs @@ -1,13 +1,12 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionPropertyApiCreateDto { - [Serializable] - public class ExtensionPropertyApiCreateDto - { - /// - /// Default: true. - /// - public bool IsAvailable { get; set; } = true; - } -} \ No newline at end of file + /// + /// Default: true. + /// + public bool IsAvailable { get; set; } = true; +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiDto.cs index a9b4ec5b244..920e66141ae 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiDto.cs @@ -1,23 +1,22 @@ using JetBrains.Annotations; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +public class ExtensionPropertyApiDto { - public class ExtensionPropertyApiDto - { - [NotNull] - public ExtensionPropertyApiGetDto OnGet { get; set; } + [NotNull] + public ExtensionPropertyApiGetDto OnGet { get; set; } - [NotNull] - public ExtensionPropertyApiCreateDto OnCreate { get; set; } + [NotNull] + public ExtensionPropertyApiCreateDto OnCreate { get; set; } - [NotNull] - public ExtensionPropertyApiUpdateDto OnUpdate { get; set; } + [NotNull] + public ExtensionPropertyApiUpdateDto OnUpdate { get; set; } - public ExtensionPropertyApiDto() - { - OnGet = new ExtensionPropertyApiGetDto(); - OnCreate = new ExtensionPropertyApiCreateDto(); - OnUpdate = new ExtensionPropertyApiUpdateDto(); - } + public ExtensionPropertyApiDto() + { + OnGet = new ExtensionPropertyApiGetDto(); + OnCreate = new ExtensionPropertyApiCreateDto(); + OnUpdate = new ExtensionPropertyApiUpdateDto(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiGetDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiGetDto.cs index e50a45d15a3..2a9f71295c7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiGetDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiGetDto.cs @@ -1,13 +1,12 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionPropertyApiGetDto { - [Serializable] - public class ExtensionPropertyApiGetDto - { - /// - /// Default: true. - /// - public bool IsAvailable { get; set; } = true; - } -} \ No newline at end of file + /// + /// Default: true. + /// + public bool IsAvailable { get; set; } = true; +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiUpdateDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiUpdateDto.cs index a517b258da8..d234fe37b0e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiUpdateDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyApiUpdateDto.cs @@ -1,13 +1,12 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionPropertyApiUpdateDto { - [Serializable] - public class ExtensionPropertyApiUpdateDto - { - /// - /// Default: true. - /// - public bool IsAvailable { get; set; } = true; - } -} \ No newline at end of file + /// + /// Default: true. + /// + public bool IsAvailable { get; set; } = true; +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyAttributeDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyAttributeDto.cs index 12941a3b893..492756168db 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyAttributeDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyAttributeDto.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionPropertyAttributeDto { - [Serializable] - public class ExtensionPropertyAttributeDto - { - public string TypeSimple { get; set; } + public string TypeSimple { get; set; } - public Dictionary Config { get; set; } - } -} \ No newline at end of file + public Dictionary Config { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyDto.cs index b1ba6f7ea90..a1fb628e1ab 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyDto.cs @@ -2,26 +2,25 @@ using System.Collections.Generic; using JetBrains.Annotations; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionPropertyDto { - [Serializable] - public class ExtensionPropertyDto - { - public string Type { get; set; } + public string Type { get; set; } + + public string TypeSimple { get; set; } + + [CanBeNull] + public LocalizableStringDto DisplayName { get; set; } - public string TypeSimple { get; set; } + public ExtensionPropertyApiDto Api { get; set; } - [CanBeNull] - public LocalizableStringDto DisplayName { get; set; } + public ExtensionPropertyUiDto Ui { get; set; } - public ExtensionPropertyApiDto Api { get; set; } - - public ExtensionPropertyUiDto Ui { get; set; } + public List Attributes { get; set; } - public List Attributes { get; set; } + public Dictionary Configuration { get; set; } - public Dictionary Configuration { get; set; } - - public object DefaultValue { get; set; } - } -} \ No newline at end of file + public object DefaultValue { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiDto.cs index caa5d67957b..cd43df5446c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiDto.cs @@ -1,13 +1,12 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionPropertyUiDto { - [Serializable] - public class ExtensionPropertyUiDto - { - public ExtensionPropertyUiTableDto OnTable { get; set; } - public ExtensionPropertyUiFormDto OnCreateForm { get; set; } - public ExtensionPropertyUiFormDto OnEditForm { get; set; } - public ExtensionPropertyUiLookupDto Lookup { get; set; } - } -} \ No newline at end of file + public ExtensionPropertyUiTableDto OnTable { get; set; } + public ExtensionPropertyUiFormDto OnCreateForm { get; set; } + public ExtensionPropertyUiFormDto OnEditForm { get; set; } + public ExtensionPropertyUiLookupDto Lookup { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiFormDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiFormDto.cs index c4f6f5211c5..2eb506c13db 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiFormDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiFormDto.cs @@ -1,10 +1,9 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionPropertyUiFormDto { - [Serializable] - public class ExtensionPropertyUiFormDto - { - public bool IsVisible { get; set; } - } -} \ No newline at end of file + public bool IsVisible { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiLookupDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiLookupDto.cs index 035178df1ea..b9bc94399c4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiLookupDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiLookupDto.cs @@ -1,14 +1,13 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionPropertyUiLookupDto { - [Serializable] - public class ExtensionPropertyUiLookupDto - { - public string Url { get; set; } - public string ResultListPropertyName { get; set; } - public string DisplayPropertyName { get; set; } - public string ValuePropertyName { get; set; } - public string FilterParamName { get; set; } - } -} \ No newline at end of file + public string Url { get; set; } + public string ResultListPropertyName { get; set; } + public string DisplayPropertyName { get; set; } + public string ValuePropertyName { get; set; } + public string FilterParamName { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiTableDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiTableDto.cs index 4c9e4a7ce0c..cba33fb2f84 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiTableDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ExtensionPropertyUiTableDto.cs @@ -1,10 +1,9 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ExtensionPropertyUiTableDto { - [Serializable] - public class ExtensionPropertyUiTableDto - { - public bool IsVisible { get; set; } - } -} \ No newline at end of file + public bool IsVisible { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/LocalizableStringDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/LocalizableStringDto.cs index b80352d791a..8127a90bd7d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/LocalizableStringDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/LocalizableStringDto.cs @@ -1,21 +1,20 @@ using System; using JetBrains.Annotations; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class LocalizableStringDto { - [Serializable] - public class LocalizableStringDto - { - [NotNull] - public string Name { get; private set; } + [NotNull] + public string Name { get; private set; } - [CanBeNull] - public string Resource { get; set; } + [CanBeNull] + public string Resource { get; set; } - public LocalizableStringDto([NotNull] string name, string resource = null) - { - Name = Check.NotNullOrEmpty(name, nameof(name)); - Resource = resource; - } + public LocalizableStringDto([NotNull] string name, string resource = null) + { + Name = Check.NotNullOrEmpty(name, nameof(name)); + Resource = resource; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ModuleExtensionDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ModuleExtensionDto.cs index e077596f595..aadd08cd286 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ModuleExtensionDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ModuleExtensionDto.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ModuleExtensionDto { - [Serializable] - public class ModuleExtensionDto - { - public Dictionary Entities { get; set; } + public Dictionary Entities { get; set; } - public Dictionary Configuration { get; set; } - } -} \ No newline at end of file + public Dictionary Configuration { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs index 0338bbd4dc7..f63935847ba 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/ObjectExtensionsDto.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending; + +[Serializable] +public class ObjectExtensionsDto { - [Serializable] - public class ObjectExtensionsDto - { - public Dictionary Modules { get; set; } - - public Dictionary Enums { get; set; } - } -} \ No newline at end of file + public Dictionary Modules { get; set; } + + public Dictionary Enums { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/TimingDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/TimingDto.cs index bd95bfba0d5..ca03407ee5f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/TimingDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/TimingDto.cs @@ -1,24 +1,23 @@ -namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations +namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; + +public class TimingDto { - public class TimingDto - { - public TimeZone TimeZone { get; set; } - } + public TimeZone TimeZone { get; set; } +} - public class TimeZone - { - public IanaTimeZone Iana { get; set; } +public class TimeZone +{ + public IanaTimeZone Iana { get; set; } - public WindowsTimeZone Windows { get; set; } - } + public WindowsTimeZone Windows { get; set; } +} - public class WindowsTimeZone - { - public string TimeZoneId { get; set; } - } +public class WindowsTimeZone +{ + public string TimeZoneId { get; set; } +} - public class IanaTimeZone - { - public string TimeZoneName { get; set; } - } +public class IanaTimeZone +{ + public string TimeZoneName { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/CurrentTenantDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/CurrentTenantDto.cs index 06b24f12351..b8b361e7c8d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/CurrentTenantDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/CurrentTenantDto.cs @@ -2,14 +2,13 @@ using System.Collections.Generic; using System.Text; -namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy +namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy; + +public class CurrentTenantDto { - public class CurrentTenantDto - { - public Guid? Id { get; set; } + public Guid? Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public bool IsAvailable { get; set; } - } + public bool IsAvailable { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs index 6f834b18ea8..64bcc775548 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs @@ -1,16 +1,15 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy +namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy; + +[Serializable] +public class FindTenantResultDto { - [Serializable] - public class FindTenantResultDto - { - public bool Success { get; set; } + public bool Success { get; set; } - public Guid? TenantId { get; set; } + public Guid? TenantId { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public bool IsActive { get; set; } - } + public bool IsActive { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/IAbpTenantAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/IAbpTenantAppService.cs index eb02e84ceb7..feb4fc4af75 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/IAbpTenantAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/IAbpTenantAppService.cs @@ -2,12 +2,11 @@ using System.Threading.Tasks; using Volo.Abp.Application.Services; -namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy +namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy; + +public interface IAbpTenantAppService : IApplicationService { - public interface IAbpTenantAppService : IApplicationService - { - Task FindTenantByNameAsync(string name); + Task FindTenantByNameAsync(string name); - Task FindTenantByIdAsync(Guid id); - } -} \ No newline at end of file + Task FindTenantByIdAsync(Guid id); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/MultiTenancyInfoDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/MultiTenancyInfoDto.cs index 165a0e5c21e..c08e4ab60d2 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/MultiTenancyInfoDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/MultiTenancyInfoDto.cs @@ -2,10 +2,9 @@ using System.Collections.Generic; using System.Text; -namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy +namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy; + +public class MultiTenancyInfoDto { - public class MultiTenancyInfoDto - { - public bool IsEnabled { get; set; } - } + public bool IsEnabled { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/AbpAspNetCoreMvcUiBootstrapModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/AbpAspNetCoreMvcUiBootstrapModule.cs index 889ffdc96e9..fe06c4e0844 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/AbpAspNetCoreMvcUiBootstrapModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/AbpAspNetCoreMvcUiBootstrapModule.cs @@ -1,17 +1,16 @@ using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; + +[DependsOn(typeof(AbpAspNetCoreMvcUiModule))] +public class AbpAspNetCoreMvcUiBootstrapModule : AbpModule { - [DependsOn(typeof(AbpAspNetCoreMvcUiModule))] - public class AbpAspNetCoreMvcUiBootstrapModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(options => { - Configure(options => - { - options.FileSets.AddEmbedded("Volo.Abp.AspNetCore.Mvc.UI.Bootstrap"); - }); - } + options.FileSets.AddEmbedded("Volo.Abp.AspNetCore.Mvc.UI.Bootstrap"); + }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Microsoft/AspNetCore/Razor/TagHelpers/AbpTagHelperAttributeListExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Microsoft/AspNetCore/Razor/TagHelpers/AbpTagHelperAttributeListExtensions.cs index ae6684a6a66..81aefb7382a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Microsoft/AspNetCore/Razor/TagHelpers/AbpTagHelperAttributeListExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Microsoft/AspNetCore/Razor/TagHelpers/AbpTagHelperAttributeListExtensions.cs @@ -4,54 +4,54 @@ using Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers //TODO: Move to AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers namespace +; + +public static class AbpTagHelperAttributeListExtensions { - public static class AbpTagHelperAttributeListExtensions + public static void AddClass(this TagHelperAttributeList attributes, string className) { - public static void AddClass(this TagHelperAttributeList attributes, string className) + if (string.IsNullOrWhiteSpace(className)) { - if (string.IsNullOrWhiteSpace(className)) - { - return; - } - - var classAttribute = attributes["class"]; - if (classAttribute == null) - { - attributes.Add("class", className); - } - else - { - var existingClasses = classAttribute.Value.ToString().Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); - existingClasses.AddIfNotContains(className); - attributes.SetAttribute("class", string.Join(" ", existingClasses)); - } + return; } - public static void RemoveClass(this TagHelperAttributeList attributes, string className) + var classAttribute = attributes["class"]; + if (classAttribute == null) { - if (string.IsNullOrWhiteSpace(className)) - { - return; - } - - var classAttribute = attributes["class"]; - if (classAttribute == null) - { - return; - } + attributes.Add("class", className); + } + else + { + var existingClasses = classAttribute.Value.ToString().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); + existingClasses.AddIfNotContains(className); + attributes.SetAttribute("class", string.Join(" ", existingClasses)); + } + } - var classList = classAttribute.Value.ToString().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); - classList.RemoveAll(c => c == className); + public static void RemoveClass(this TagHelperAttributeList attributes, string className) + { + if (string.IsNullOrWhiteSpace(className)) + { + return; + } - attributes.SetAttribute("class", classList.JoinAsString(" ")); + var classAttribute = attributes["class"]; + if (classAttribute == null) + { + return; } - public static void AddIfNotContains(this TagHelperAttributeList attributes, string name, object value) + var classList = classAttribute.Value.ToString().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); + classList.RemoveAll(c => c == className); + + attributes.SetAttribute("class", classList.JoinAsString(" ")); + } + + public static void AddIfNotContains(this TagHelperAttributeList attributes, string name, object value) + { + if (!attributes.ContainsName(name)) { - if (!attributes.ContainsName(name)) - { - attributes.Add(name, value); - } + attributes.Add(name, value); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelper.cs index 1188d680566..5b9c1430f2f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelper.cs @@ -6,44 +6,43 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Threading; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers; + +public abstract class AbpTagHelper : TagHelper, ITransientDependency { - public abstract class AbpTagHelper : TagHelper, ITransientDependency + +} + +public abstract class AbpTagHelper : AbpTagHelper + where TTagHelper : AbpTagHelper + where TService : class, IAbpTagHelperService +{ + protected TService Service { get; } + + public override int Order => Service.Order; + + [HtmlAttributeNotBound] + [ViewContext] + public ViewContext ViewContext { get; set; } + + protected AbpTagHelper(TService service) + { + Service = service; + Service.As>().TagHelper = (TTagHelper)this; + } + + public override void Init(TagHelperContext context) { + Service.Init(context); + } + public override void Process(TagHelperContext context, TagHelperOutput output) + { + Service.Process(context, output); } - public abstract class AbpTagHelper : AbpTagHelper - where TTagHelper : AbpTagHelper - where TService : class, IAbpTagHelperService + public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { - protected TService Service { get; } - - public override int Order => Service.Order; - - [HtmlAttributeNotBound] - [ViewContext] - public ViewContext ViewContext { get; set; } - - protected AbpTagHelper(TService service) - { - Service = service; - Service.As>().TagHelper = (TTagHelper)this; - } - - public override void Init(TagHelperContext context) - { - Service.Init(context); - } - - public override void Process(TagHelperContext context, TagHelperOutput output) - { - Service.Process(context, output); - } - - public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - return Service.ProcessAsync(context, output); - } + return Service.ProcessAsync(context, output); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperLocalizer.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperLocalizer.cs index 700a5f4ee99..c4314134be4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperLocalizer.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperLocalizer.cs @@ -6,45 +6,44 @@ using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc.Localization; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers; + +public class AbpTagHelperLocalizer : IAbpTagHelperLocalizer { - public class AbpTagHelperLocalizer : IAbpTagHelperLocalizer - { - private readonly IStringLocalizerFactory _stringLocalizerFactory; - private readonly AbpMvcDataAnnotationsLocalizationOptions _options; + private readonly IStringLocalizerFactory _stringLocalizerFactory; + private readonly AbpMvcDataAnnotationsLocalizationOptions _options; - public AbpTagHelperLocalizer(IOptions options, IStringLocalizerFactory stringLocalizerFactory) - { - _stringLocalizerFactory = stringLocalizerFactory; - _options = options.Value; - } + public AbpTagHelperLocalizer(IOptions options, IStringLocalizerFactory stringLocalizerFactory) + { + _stringLocalizerFactory = stringLocalizerFactory; + _options = options.Value; + } - public string GetLocalizedText(string text, ModelExplorer explorer) - { - var localizer = GetLocalizerOrNull(explorer); - return localizer == null - ? text - : localizer[text].Value; - } + public string GetLocalizedText(string text, ModelExplorer explorer) + { + var localizer = GetLocalizerOrNull(explorer); + return localizer == null + ? text + : localizer[text].Value; + } - public IStringLocalizer GetLocalizerOrNull(ModelExplorer explorer) - { - return GetLocalizerOrNull(explorer.Container.ModelType.Assembly); - } + public IStringLocalizer GetLocalizerOrNull(ModelExplorer explorer) + { + return GetLocalizerOrNull(explorer.Container.ModelType.Assembly); + } - public IStringLocalizer GetLocalizerOrNull(Assembly assembly) - { - var resourceType = GetResourceType(assembly); - return resourceType == null - ? _stringLocalizerFactory.CreateDefaultOrNull() - : _stringLocalizerFactory.Create(resourceType); - } + public IStringLocalizer GetLocalizerOrNull(Assembly assembly) + { + var resourceType = GetResourceType(assembly); + return resourceType == null + ? _stringLocalizerFactory.CreateDefaultOrNull() + : _stringLocalizerFactory.Create(resourceType); + } - private Type GetResourceType(Assembly assembly) - { - return _options - .AssemblyResources - .GetOrDefault(assembly); - } + private Type GetResourceType(Assembly assembly) + { + return _options + .AssemblyResources + .GetOrDefault(assembly); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs index b53b2b4d56c..b9c3aa92e62 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs @@ -1,46 +1,45 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers; + +//TODO: Refactor this class, extract bootstrap functionality! +public abstract class AbpTagHelperService : IAbpTagHelperService + where TTagHelper : TagHelper { - //TODO: Refactor this class, extract bootstrap functionality! - public abstract class AbpTagHelperService : IAbpTagHelperService - where TTagHelper : TagHelper + protected const string FormGroupContents = "FormGroupContents"; + protected const string TabItems = "TabItems"; + protected const string AccordionItems = "AccordionItems"; + protected const string BreadcrumbItemsContent = "BreadcrumbItemsContent"; + protected const string CarouselItemsContent = "CarouselItemsContent"; + protected const string TabItemsDataTogglePlaceHolder = "{_data_toggle_Placeholder_}"; + protected const string TabItemNamePlaceHolder = "{_Tab_Tag_Name_Placeholder_}"; + protected const string AbpFormContentPlaceHolder = "{_AbpFormContentPlaceHolder_}"; + protected const string AbpTabItemActivePlaceholder = "{_Tab_Active_Placeholder_}"; + protected const string AbpTabDropdownItemsActivePlaceholder = "{_Tab_DropDown_Items_Placeholder_}"; + protected const string AbpTabItemShowActivePlaceholder = "{_Tab_Show_Active_Placeholder_}"; + protected const string AbpBreadcrumbItemActivePlaceholder = "{_Breadcrumb_Active_Placeholder_}"; + protected const string AbpCarouselItemActivePlaceholder = "{_CarouselItem_Active_Placeholder_}"; + protected const string AbpTabItemSelectedPlaceholder = "{_Tab_Selected_Placeholder_}"; + protected const string AbpAccordionParentIdPlaceholder = "{_Parent_Accordion_Id_}"; + + public TTagHelper TagHelper { get; internal set; } + + public virtual int Order { get; } + + public virtual void Init(TagHelperContext context) + { + + } + + public virtual void Process(TagHelperContext context, TagHelperOutput output) + { + + } + + public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { - protected const string FormGroupContents = "FormGroupContents"; - protected const string TabItems = "TabItems"; - protected const string AccordionItems = "AccordionItems"; - protected const string BreadcrumbItemsContent = "BreadcrumbItemsContent"; - protected const string CarouselItemsContent = "CarouselItemsContent"; - protected const string TabItemsDataTogglePlaceHolder = "{_data_toggle_Placeholder_}"; - protected const string TabItemNamePlaceHolder = "{_Tab_Tag_Name_Placeholder_}"; - protected const string AbpFormContentPlaceHolder = "{_AbpFormContentPlaceHolder_}"; - protected const string AbpTabItemActivePlaceholder = "{_Tab_Active_Placeholder_}"; - protected const string AbpTabDropdownItemsActivePlaceholder = "{_Tab_DropDown_Items_Placeholder_}"; - protected const string AbpTabItemShowActivePlaceholder = "{_Tab_Show_Active_Placeholder_}"; - protected const string AbpBreadcrumbItemActivePlaceholder = "{_Breadcrumb_Active_Placeholder_}"; - protected const string AbpCarouselItemActivePlaceholder = "{_CarouselItem_Active_Placeholder_}"; - protected const string AbpTabItemSelectedPlaceholder = "{_Tab_Selected_Placeholder_}"; - protected const string AbpAccordionParentIdPlaceholder = "{_Parent_Accordion_Id_}"; - - public TTagHelper TagHelper { get; internal set; } - - public virtual int Order { get; } - - public virtual void Init(TagHelperContext context) - { - - } - - public virtual void Process(TagHelperContext context, TagHelperOutput output) - { - - } - - public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - Process(context, output); - return Task.CompletedTask; - } + Process(context, output); + return Task.CompletedTask; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertHeaderTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertHeaderTagHelper.cs index b32acb7b1b2..d86ef557fa8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertHeaderTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertHeaderTagHelper.cs @@ -1,19 +1,18 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert; + +[HtmlTargetElement("h1", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] +[HtmlTargetElement("h2", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] +[HtmlTargetElement("h3", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] +[HtmlTargetElement("h4", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] +[HtmlTargetElement("h5", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] +[HtmlTargetElement("h6", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] +public class AbpAlertHeaderTagHelper : AbpTagHelper { - [HtmlTargetElement("h1", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] - [HtmlTargetElement("h2", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] - [HtmlTargetElement("h3", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] - [HtmlTargetElement("h4", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] - [HtmlTargetElement("h5", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] - [HtmlTargetElement("h6", ParentTag = "abp-alert", TagStructure = TagStructure.NormalOrSelfClosing)] - public class AbpAlertHeaderTagHelper : AbpTagHelper + public AbpAlertHeaderTagHelper(AbpAlertHeaderTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpAlertHeaderTagHelper(AbpAlertHeaderTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertHeaderTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertHeaderTagHelperService.cs index 1e3b9e7c2ac..46d3bbf5ef8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertHeaderTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertHeaderTagHelperService.cs @@ -1,13 +1,12 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert; + +public class AbpAlertHeaderTagHelperService : AbpTagHelperService { - public class AbpAlertHeaderTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass("alert-heading"); - } + output.Attributes.AddClass("alert-heading"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertLinkTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertLinkTagHelper.cs index 17e9a335b90..af659ac401b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertLinkTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertLinkTagHelper.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert; + +[HtmlTargetElement("a", Attributes = "abp-alert-link", TagStructure = TagStructure.NormalOrSelfClosing)] +public class AbpAlertLinkTagHelper : AbpTagHelper { - [HtmlTargetElement("a", Attributes = "abp-alert-link", TagStructure = TagStructure.NormalOrSelfClosing)] - public class AbpAlertLinkTagHelper : AbpTagHelper + public AbpAlertLinkTagHelper(AbpAlertLinkTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpAlertLinkTagHelper(AbpAlertLinkTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertLinkTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertLinkTagHelperService.cs index 79372688c30..40746eac6cd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertLinkTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertLinkTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert; + +public class AbpAlertLinkTagHelperService : AbpTagHelperService { - public class AbpAlertLinkTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass("alert-link"); - output.Attributes.RemoveAll("abp-alert-link"); - } + output.Attributes.AddClass("alert-link"); + output.Attributes.RemoveAll("abp-alert-link"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertTagHelper.cs index f4d0c33ced3..19728a99b31 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertTagHelper.cs @@ -1,17 +1,16 @@ using Volo.Abp.AspNetCore.Mvc.UI.Alerts; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert; + +public class AbpAlertTagHelper : AbpTagHelper { - public class AbpAlertTagHelper : AbpTagHelper - { - public AlertType AlertType { get; set; } = AlertType.Default; + public AlertType AlertType { get; set; } = AlertType.Default; - public bool? Dismissible { get; set; } + public bool? Dismissible { get; set; } - public AbpAlertTagHelper(AbpAlertTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpAlertTagHelper(AbpAlertTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertTagHelperService.cs index a8d23429780..6d465f4bb4f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Alert/AbpAlertTagHelperService.cs @@ -3,48 +3,47 @@ using Volo.Abp.AspNetCore.Mvc.UI.Alerts; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert; + +public class AbpAlertTagHelperService : AbpTagHelperService { - public class AbpAlertTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.TagMode = TagMode.StartTagAndEndTag; + output.TagName = "div"; + output.TagMode = TagMode.StartTagAndEndTag; + + AddClasses(context, output); + AddDismissButtonIfDismissible(context, output); + } + + protected virtual void AddClasses(TagHelperContext context, TagHelperOutput output) + { + output.Attributes.Add("role", "alert"); + output.Attributes.AddClass("alert"); - AddClasses(context, output); - AddDismissButtonIfDismissible(context, output); + if (TagHelper.AlertType != AlertType.Default) + { + output.Attributes.AddClass("alert-" + TagHelper.AlertType.ToString().ToLowerInvariant()); } - protected virtual void AddClasses(TagHelperContext context, TagHelperOutput output) + if (TagHelper.Dismissible ?? false) { - output.Attributes.Add("role", "alert"); - output.Attributes.AddClass("alert"); - - if (TagHelper.AlertType != AlertType.Default) - { - output.Attributes.AddClass("alert-" + TagHelper.AlertType.ToString().ToLowerInvariant()); - } - - if (TagHelper.Dismissible ?? false) - { - output.Attributes.AddClass("alert-dismissible"); - output.Attributes.AddClass("fade"); - output.Attributes.AddClass("show"); - } + output.Attributes.AddClass("alert-dismissible"); + output.Attributes.AddClass("fade"); + output.Attributes.AddClass("show"); } + } - protected virtual void AddDismissButtonIfDismissible(TagHelperContext context, TagHelperOutput output) + protected virtual void AddDismissButtonIfDismissible(TagHelperContext context, TagHelperOutput output) + { + if (!TagHelper.Dismissible ?? true) { - if (!TagHelper.Dismissible ?? true) - { - return; - } + return; + } - var buttonAsHtml = - ""; + var buttonAsHtml = + ""; - output.PostContent.SetHtmlContent(buttonAsHtml); - } + output.PostContent.SetHtmlContent(buttonAsHtml); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeTagHelper.cs index bfb83f73637..82da24d088e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeTagHelper.cs @@ -1,24 +1,22 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Badge -{ +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Badge; - [HtmlTargetElement("a", Attributes = "abp-badge")] - [HtmlTargetElement("span", Attributes = "abp-badge")] - [HtmlTargetElement("a", Attributes = "abp-badge-pill")] - [HtmlTargetElement("span", Attributes = "abp-badge-pill")] - public class AbpBadgeTagHelper : AbpTagHelper - { - [HtmlAttributeName("abp-badge")] - public AbpBadgeType BadgeType { get; set; } = AbpBadgeType._; +[HtmlTargetElement("a", Attributes = "abp-badge")] +[HtmlTargetElement("span", Attributes = "abp-badge")] +[HtmlTargetElement("a", Attributes = "abp-badge-pill")] +[HtmlTargetElement("span", Attributes = "abp-badge-pill")] +public class AbpBadgeTagHelper : AbpTagHelper +{ + [HtmlAttributeName("abp-badge")] + public AbpBadgeType BadgeType { get; set; } = AbpBadgeType._; - [HtmlAttributeName("abp-badge-pill")] - public AbpBadgeType BadgePillType { get; set; } = AbpBadgeType._; + [HtmlAttributeName("abp-badge-pill")] + public AbpBadgeType BadgePillType { get; set; } = AbpBadgeType._; - public AbpBadgeTagHelper(AbpBadgeTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpBadgeTagHelper(AbpBadgeTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeTagHelperService.cs index 14aeefeb25b..384b7383ecc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeTagHelperService.cs @@ -1,39 +1,38 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Badge +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Badge; + +public class AbpBadgeTagHelperService : AbpTagHelperService { - public class AbpBadgeTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - SetBadgeClass(context, output); - SetBadgeStyle(context, output); - } - - protected virtual void SetBadgeStyle(TagHelperContext context, TagHelperOutput output) - { - var badgeType = GetBadgeType(context, output); + SetBadgeClass(context, output); + SetBadgeStyle(context, output); + } - if (badgeType != AbpBadgeType.Default && badgeType != AbpBadgeType._) - { - output.Attributes.AddClass("bg-" + badgeType.ToString().ToLowerInvariant()); - } - } + protected virtual void SetBadgeStyle(TagHelperContext context, TagHelperOutput output) + { + var badgeType = GetBadgeType(context, output); - protected virtual void SetBadgeClass(TagHelperContext context, TagHelperOutput output) + if (badgeType != AbpBadgeType.Default && badgeType != AbpBadgeType._) { - output.Attributes.AddClass("badge"); - - if (TagHelper.BadgePillType != AbpBadgeType._) - { - output.Attributes.AddClass("rounded-pill"); - } + output.Attributes.AddClass("bg-" + badgeType.ToString().ToLowerInvariant()); } + } + + protected virtual void SetBadgeClass(TagHelperContext context, TagHelperOutput output) + { + output.Attributes.AddClass("badge"); - protected virtual AbpBadgeType GetBadgeType(TagHelperContext context, TagHelperOutput output) + if (TagHelper.BadgePillType != AbpBadgeType._) { - return TagHelper.BadgeType != AbpBadgeType._ ? TagHelper.BadgeType : TagHelper.BadgePillType; + output.Attributes.AddClass("rounded-pill"); } } + + protected virtual AbpBadgeType GetBadgeType(TagHelperContext context, TagHelperOutput output) + { + return TagHelper.BadgeType != AbpBadgeType._ ? TagHelper.BadgeType : TagHelper.BadgePillType; + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeType.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeType.cs index ffc78d377ad..77dafac397c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Badge/AbpBadgeType.cs @@ -1,16 +1,15 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Badge +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Badge; + +public enum AbpBadgeType { - public enum AbpBadgeType - { - _, - Default, - Primary, - Secondary, - Success, - Danger, - Warning, - Info, - Light, - Dark - } -} \ No newline at end of file + _, + Default, + Primary, + Secondary, + Success, + Danger, + Warning, + Info, + Light, + Dark +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteFooterTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteFooterTagHelper.cs index d4619390efd..ac3a6342c53 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteFooterTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteFooterTagHelper.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote; + +[HtmlTargetElement("footer", ParentTag = "blockquote")] +public class AbpBlockquoteFooterTagHelper : AbpTagHelper { - [HtmlTargetElement("footer", ParentTag = "blockquote")] - public class AbpBlockquoteFooterTagHelper : AbpTagHelper + public AbpBlockquoteFooterTagHelper(AbpBlockquoteFooterTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpBlockquoteFooterTagHelper(AbpBlockquoteFooterTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteFooterTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteFooterTagHelperService.cs index 6280f5de993..55d9d0673e8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteFooterTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteFooterTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote; + +public class AbpBlockquoteFooterTagHelperService : AbpTagHelperService { - public class AbpBlockquoteFooterTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass("blockquote-footer"); - } - + output.Attributes.AddClass("blockquote-footer"); } -} \ No newline at end of file + +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteParagraphTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteParagraphTagHelper.cs index 0e915f2a361..8734cc52e8c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteParagraphTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteParagraphTagHelper.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote; + +[HtmlTargetElement("p", ParentTag = "blockquote")] +public class AbpBlockquoteParagraphTagHelper : AbpTagHelper { - [HtmlTargetElement("p", ParentTag = "blockquote")] - public class AbpBlockquoteParagraphTagHelper : AbpTagHelper + public AbpBlockquoteParagraphTagHelper(AbpBlockquoteParagraphTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpBlockquoteParagraphTagHelper(AbpBlockquoteParagraphTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteParagraphTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteParagraphTagHelperService.cs index d3ce37cbc5a..513cee78337 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteParagraphTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteParagraphTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote; + +public class AbpBlockquoteParagraphTagHelperService : AbpTagHelperService { - public class AbpBlockquoteParagraphTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass("mb-0"); - } - + output.Attributes.AddClass("mb-0"); } -} \ No newline at end of file + +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteTagHelper.cs index 74e2a10e2d8..72835b53e07 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteTagHelper.cs @@ -1,11 +1,10 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote; + +public class AbpBlockquoteTagHelper : AbpTagHelper { - public class AbpBlockquoteTagHelper : AbpTagHelper + public AbpBlockquoteTagHelper(AbpBlockquoteTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpBlockquoteTagHelper(AbpBlockquoteTagHelperService tagHelperService) - : base(tagHelperService) - { - - } + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteTagHelperService.cs index 6c26747d11c..53fa7b0b5de 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Blockquote/AbpBlockquoteTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Blockquote; + +public class AbpBlockquoteTagHelperService : AbpTagHelperService { - public class AbpBlockquoteTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass("blockquote"); - output.TagName = "blockquote"; - } + output.Attributes.AddClass("blockquote"); + output.TagName = "blockquote"; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderTagHelper.cs index bc7a6f98291..f701ca4c2d6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderTagHelper.cs @@ -1,16 +1,15 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border; + +[HtmlTargetElement(Attributes = "abp-border")] +public class AbpBorderTagHelper : AbpTagHelper { - [HtmlTargetElement(Attributes = "abp-border")] - public class AbpBorderTagHelper : AbpTagHelper - { - public AbpBorderType AbpBorder { get; set; } = AbpBorderType.Default; + public AbpBorderType AbpBorder { get; set; } = AbpBorderType.Default; - public AbpBorderTagHelper(AbpBorderTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpBorderTagHelper(AbpBorderTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderTagHelperService.cs index 3bf4bc16d45..f8446a493dc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderTagHelperService.cs @@ -1,91 +1,90 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border; + +public class AbpBorderTagHelperService : AbpTagHelperService { - public class AbpBorderTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - var borderAttributeAsString = TagHelper.AbpBorder.ToString().ToLowerInvariant(); + var borderAttributeAsString = TagHelper.AbpBorder.ToString().ToLowerInvariant(); - var borderClass = "border" + GetBorderDirection(context, output, borderAttributeAsString) + GetExtensionIfBorderIsSubtractive(context, output, borderAttributeAsString); + var borderClass = "border" + GetBorderDirection(context, output, borderAttributeAsString) + GetExtensionIfBorderIsSubtractive(context, output, borderAttributeAsString); - output.Attributes.AddClass(borderClass); + output.Attributes.AddClass(borderClass); - SetBorderType(context, output, borderAttributeAsString); - } + SetBorderType(context, output, borderAttributeAsString); + } - protected virtual string GetBorderDirection(TagHelperContext context, TagHelperOutput output, string borderAttributeAsString) + protected virtual string GetBorderDirection(TagHelperContext context, TagHelperOutput output, string borderAttributeAsString) + { + if (borderAttributeAsString.Contains("top")) { - if (borderAttributeAsString.Contains("top")) - { - return "-top"; - } - if (borderAttributeAsString.Contains("right")) - { - return "-right"; - } - if (borderAttributeAsString.Contains("left")) - { - return "-left"; - } - if (borderAttributeAsString.Contains("bottom")) - { - return "-bottom"; - } - - return ""; + return "-top"; } - - protected virtual string GetExtensionIfBorderIsSubtractive(TagHelperContext context, TagHelperOutput output, string borderAttributeAsString) + if (borderAttributeAsString.Contains("right")) + { + return "-right"; + } + if (borderAttributeAsString.Contains("left")) { - if (borderAttributeAsString.Contains("_0")) - { - return "-0"; - } + return "-left"; + } + if (borderAttributeAsString.Contains("bottom")) + { + return "-bottom"; + } + + return ""; + } - return ""; + protected virtual string GetExtensionIfBorderIsSubtractive(TagHelperContext context, TagHelperOutput output, string borderAttributeAsString) + { + if (borderAttributeAsString.Contains("_0")) + { + return "-0"; } - protected virtual void SetBorderType(TagHelperContext context, TagHelperOutput output, string borderAttributeAsString) + return ""; + } + + protected virtual void SetBorderType(TagHelperContext context, TagHelperOutput output, string borderAttributeAsString) + { + if (borderAttributeAsString.Contains("primary")) + { + output.Attributes.AddClass("border-primary"); + } + if (borderAttributeAsString.Contains("secondary")) + { + output.Attributes.AddClass("border-secondary"); + } + if (borderAttributeAsString.Contains("success")) + { + output.Attributes.AddClass("border-success"); + } + if (borderAttributeAsString.Contains("danger")) + { + output.Attributes.AddClass("border-danger"); + } + if (borderAttributeAsString.Contains("warning")) + { + output.Attributes.AddClass("border-warning"); + } + if (borderAttributeAsString.Contains("info")) + { + output.Attributes.AddClass("border-info"); + } + if (borderAttributeAsString.Contains("light")) + { + output.Attributes.AddClass("border-light"); + } + if (borderAttributeAsString.Contains("dark")) + { + output.Attributes.AddClass("border-dark"); + } + if (borderAttributeAsString.Contains("white")) { - if (borderAttributeAsString.Contains("primary")) - { - output.Attributes.AddClass("border-primary"); - } - if (borderAttributeAsString.Contains("secondary")) - { - output.Attributes.AddClass("border-secondary"); - } - if (borderAttributeAsString.Contains("success")) - { - output.Attributes.AddClass("border-success"); - } - if (borderAttributeAsString.Contains("danger")) - { - output.Attributes.AddClass("border-danger"); - } - if (borderAttributeAsString.Contains("warning")) - { - output.Attributes.AddClass("border-warning"); - } - if (borderAttributeAsString.Contains("info")) - { - output.Attributes.AddClass("border-info"); - } - if (borderAttributeAsString.Contains("light")) - { - output.Attributes.AddClass("border-light"); - } - if (borderAttributeAsString.Contains("dark")) - { - output.Attributes.AddClass("border-dark"); - } - if (borderAttributeAsString.Contains("white")) - { - output.Attributes.AddClass("border-white"); - } + output.Attributes.AddClass("border-white"); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderType.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderType.cs index 14b1684876a..c59780971be 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpBorderType.cs @@ -1,106 +1,105 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border; + +public enum AbpBorderType { - public enum AbpBorderType - { - Default, - _0, - Primary, - Secondary, - Success, - Danger, - Warning, - Info, - Light, - Dark, - White, - Primary_0, - Secondary_0, - Success_0, - Danger_0, - Warning_0, - Info_0, - Light_0, - Dark_0, - White_0, - Top, - Top_0, - Top_Primary, - Top_Secondary, - Top_Success, - Top_Danger, - Top_Warning, - Top_Info, - Top_Light, - Top_Dark, - Top_White, - Top_Primary_0, - Top_Secondary_0, - Top_Success_0, - Top_Danger_0, - Top_Warning_0, - Top_Info_0, - Top_Light_0, - Top_Dark_0, - Top_White_0, - Right, - Right_0, - Right_Primary, - Right_Secondary, - Right_Success, - Right_Danger, - Right_Warning, - Right_Info, - Right_Light, - Right_Dark, - Right_White, - Right_Primary_0, - Right_Secondary_0, - Right_Success_0, - Right_Danger_0, - Right_Warning_0, - Right_Info_0, - Right_Light_0, - Right_Dark_0, - Right_White_0, - Left, - Left_0, - Left_Primary, - Left_Secondary, - Left_Success, - Left_Danger, - Left_Warning, - Left_Info, - Left_Light, - Left_Dark, - Left_White, - Left_Primary_0, - Left_Secondary_0, - Left_Success_0, - Left_Danger_0, - Left_Warning_0, - Left_Info_0, - Left_Light_0, - Left_Dark_0, - Left_White_0, - Bottom, - Bottom_0, - Bottom_Primary, - Bottom_Secondary, - Bottom_Success, - Bottom_Danger, - Bottom_Warning, - Bottom_Info, - Bottom_Light, - Bottom_Dark, - Bottom_White, - Bottom_Primary_0, - Bottom_Secondary_0, - Bottom_Success_0, - Bottom_Danger_0, - Bottom_Warning_0, - Bottom_Info_0, - Bottom_Light_0, - Bottom_Dark_0, - Bottom_White_0, - } -} \ No newline at end of file + Default, + _0, + Primary, + Secondary, + Success, + Danger, + Warning, + Info, + Light, + Dark, + White, + Primary_0, + Secondary_0, + Success_0, + Danger_0, + Warning_0, + Info_0, + Light_0, + Dark_0, + White_0, + Top, + Top_0, + Top_Primary, + Top_Secondary, + Top_Success, + Top_Danger, + Top_Warning, + Top_Info, + Top_Light, + Top_Dark, + Top_White, + Top_Primary_0, + Top_Secondary_0, + Top_Success_0, + Top_Danger_0, + Top_Warning_0, + Top_Info_0, + Top_Light_0, + Top_Dark_0, + Top_White_0, + Right, + Right_0, + Right_Primary, + Right_Secondary, + Right_Success, + Right_Danger, + Right_Warning, + Right_Info, + Right_Light, + Right_Dark, + Right_White, + Right_Primary_0, + Right_Secondary_0, + Right_Success_0, + Right_Danger_0, + Right_Warning_0, + Right_Info_0, + Right_Light_0, + Right_Dark_0, + Right_White_0, + Left, + Left_0, + Left_Primary, + Left_Secondary, + Left_Success, + Left_Danger, + Left_Warning, + Left_Info, + Left_Light, + Left_Dark, + Left_White, + Left_Primary_0, + Left_Secondary_0, + Left_Success_0, + Left_Danger_0, + Left_Warning_0, + Left_Info_0, + Left_Light_0, + Left_Dark_0, + Left_White_0, + Bottom, + Bottom_0, + Bottom_Primary, + Bottom_Secondary, + Bottom_Success, + Bottom_Danger, + Bottom_Warning, + Bottom_Info, + Bottom_Light, + Bottom_Dark, + Bottom_White, + Bottom_Primary_0, + Bottom_Secondary_0, + Bottom_Success_0, + Bottom_Danger_0, + Bottom_Warning_0, + Bottom_Info_0, + Bottom_Light_0, + Bottom_Dark_0, + Bottom_White_0, +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedTagHelper.cs index f8c3489cc97..6dc0ecd305a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedTagHelper.cs @@ -1,16 +1,15 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border; + +[HtmlTargetElement(Attributes = "abp-rounded")] +public class AbpRoundedTagHelper : AbpTagHelper { - [HtmlTargetElement(Attributes = "abp-rounded")] - public class AbpRoundedTagHelper : AbpTagHelper - { - public AbpRoundedType AbpRounded { get; set; } = AbpRoundedType.Default; + public AbpRoundedType AbpRounded { get; set; } = AbpRoundedType.Default; - public AbpRoundedTagHelper(AbpRoundedTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpRoundedTagHelper(AbpRoundedTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedTagHelperService.cs index 89436785ba3..798380e4119 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedTagHelperService.cs @@ -1,20 +1,19 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border; + +public class AbpRoundedTagHelperService : AbpTagHelperService { - public class AbpRoundedTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - var roundedClass = "rounded"; - - if (TagHelper.AbpRounded != AbpRoundedType.Default) - { - roundedClass += "-" + TagHelper.AbpRounded.ToString().ToLowerInvariant().Replace("_",""); - } + var roundedClass = "rounded"; - output.Attributes.AddClass(roundedClass); + if (TagHelper.AbpRounded != AbpRoundedType.Default) + { + roundedClass += "-" + TagHelper.AbpRounded.ToString().ToLowerInvariant().Replace("_", ""); } + + output.Attributes.AddClass(roundedClass); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedType.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedType.cs index 1910ffc7143..ab4620f0f55 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Border/AbpRoundedType.cs @@ -1,12 +1,11 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border; + +public enum AbpRoundedType { - public enum AbpRoundedType - { - Default, - _0, - Top, - Right, - Left, - Bottom - } -} \ No newline at end of file + Default, + _0, + Top, + Right, + Left, + Bottom +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelper.cs index e27781479f2..71ce3406fa5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelper.cs @@ -1,17 +1,16 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb; + +public class AbpBreadcrumbItemTagHelper : AbpTagHelper { - public class AbpBreadcrumbItemTagHelper : AbpTagHelper - { - public string Href { get; set; } + public string Href { get; set; } - public string Title { get; set; } + public string Title { get; set; } - public bool Active { get; set; } + public bool Active { get; set; } - public AbpBreadcrumbItemTagHelper(AbpBreadcrumbItemTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpBreadcrumbItemTagHelper(AbpBreadcrumbItemTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs index 3fa8a274725..9935b90903c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs @@ -5,49 +5,48 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb; + +public class AbpBreadcrumbItemTagHelperService : AbpTagHelperService { - public class AbpBreadcrumbItemTagHelperService : AbpTagHelperService - { - private readonly HtmlEncoder _encoder; + private readonly HtmlEncoder _encoder; - public AbpBreadcrumbItemTagHelperService(HtmlEncoder encoder) - { - _encoder = encoder; - } + public AbpBreadcrumbItemTagHelperService(HtmlEncoder encoder) + { + _encoder = encoder; + } - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "li"; - output.TagMode = TagMode.StartTagAndEndTag; - output.Attributes.AddClass("breadcrumb-item"); - output.Attributes.AddClass(AbpBreadcrumbItemActivePlaceholder); + public override void Process(TagHelperContext context, TagHelperOutput output) + { + output.TagName = "li"; + output.TagMode = TagMode.StartTagAndEndTag; + output.Attributes.AddClass("breadcrumb-item"); + output.Attributes.AddClass(AbpBreadcrumbItemActivePlaceholder); - var list = context.GetValue>(BreadcrumbItemsContent); + var list = context.GetValue>(BreadcrumbItemsContent); - output.Content.SetHtmlContent(GetInnerHtml(context, output)); + output.Content.SetHtmlContent(GetInnerHtml(context, output)); - list.Add(new BreadcrumbItem - { - Html = output.Render(_encoder), - Active = TagHelper.Active - }); + list.Add(new BreadcrumbItem + { + Html = output.Render(_encoder), + Active = TagHelper.Active + }); - output.SuppressOutput(); - } + output.SuppressOutput(); + } - protected virtual string GetInnerHtml(TagHelperContext context, TagHelperOutput output) + protected virtual string GetInnerHtml(TagHelperContext context, TagHelperOutput output) + { + if (string.IsNullOrWhiteSpace(TagHelper.Href)) { - if (string.IsNullOrWhiteSpace(TagHelper.Href)) - { - output.Attributes.Add("aria-current", "page"); - return _encoder.Encode(TagHelper.Title); - } - - var link = new TagBuilder("a"); - link.Attributes.Add("href", TagHelper.Href); - link.InnerHtml.AppendHtml(TagHelper.Title); - return link.ToHtmlString(); + output.Attributes.Add("aria-current", "page"); + return _encoder.Encode(TagHelper.Title); } + + var link = new TagBuilder("a"); + link.Attributes.Add("href", TagHelper.Href); + link.InnerHtml.AppendHtml(TagHelper.Title); + return link.ToHtmlString(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelper.cs index a207d46a49e..cdb9f29741e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelper.cs @@ -1,11 +1,10 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb; + +public class AbpBreadcrumbTagHelper : AbpTagHelper { - public class AbpBreadcrumbTagHelper : AbpTagHelper + public AbpBreadcrumbTagHelper(AbpBreadcrumbTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpBreadcrumbTagHelper(AbpBreadcrumbTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs index 4b433ac4957..a23dc6c294c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs @@ -4,66 +4,65 @@ using System.Linq; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb; + +public class AbpBreadcrumbTagHelperService : AbpTagHelperService { - public class AbpBreadcrumbTagHelperService : AbpTagHelperService + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { - public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "nav"; - output.Attributes.Add("aria-label", "breadcrumb"); - - var list = InitilizeFormGroupContentsContext(context, output); + output.TagName = "nav"; + output.Attributes.Add("aria-label", "breadcrumb"); - await output.GetChildContentAsync(); + var list = InitilizeFormGroupContentsContext(context, output); - var listTagBuilder = GetOlTagBuilder(); + await output.GetChildContentAsync(); - SetInnerList(context, output, list, listTagBuilder); + var listTagBuilder = GetOlTagBuilder(); - output.Content.SetHtmlContent(listTagBuilder); - } - - protected virtual TagBuilder GetOlTagBuilder() - { - var builder = new TagBuilder("ol"); - builder.AddCssClass("breadcrumb"); - return builder; - } + SetInnerList(context, output, list, listTagBuilder); - protected virtual void SetInnerList(TagHelperContext context, TagHelperOutput output, List list, TagBuilder listTagBuilder) - { - SetLastOneActiveIfThereIsNotAny(context, output, list); + output.Content.SetHtmlContent(listTagBuilder); + } - foreach (var breadcrumbItem in list) - { - var htmlPart = SetActiveClassIfActiveAndGetHtml(breadcrumbItem); + protected virtual TagBuilder GetOlTagBuilder() + { + var builder = new TagBuilder("ol"); + builder.AddCssClass("breadcrumb"); + return builder; + } - listTagBuilder.InnerHtml.AppendHtml(htmlPart); - } - } + protected virtual void SetInnerList(TagHelperContext context, TagHelperOutput output, List list, TagBuilder listTagBuilder) + { + SetLastOneActiveIfThereIsNotAny(context, output, list); - protected virtual List InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output) + foreach (var breadcrumbItem in list) { - var items = new List(); - context.Items[BreadcrumbItemsContent] = items; - return items; - } + var htmlPart = SetActiveClassIfActiveAndGetHtml(breadcrumbItem); - protected virtual void SetLastOneActiveIfThereIsNotAny(TagHelperContext context, TagHelperOutput output, List list) - { - if (list.Count > 0 && !list.Any(bc => bc.Active)) - { - list.Last().Active = true; - } + listTagBuilder.InnerHtml.AppendHtml(htmlPart); } + } - protected virtual string SetActiveClassIfActiveAndGetHtml(BreadcrumbItem item) + protected virtual List InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output) + { + var items = new List(); + context.Items[BreadcrumbItemsContent] = items; + return items; + } + + protected virtual void SetLastOneActiveIfThereIsNotAny(TagHelperContext context, TagHelperOutput output, List list) + { + if (list.Count > 0 && !list.Any(bc => bc.Active)) { - return item.Active ? - item.Html.Replace(AbpBreadcrumbItemActivePlaceholder, " active") : - item.Html.Replace(AbpBreadcrumbItemActivePlaceholder, ""); + list.Last().Active = true; } + } + protected virtual string SetActiveClassIfActiveAndGetHtml(BreadcrumbItem item) + { + return item.Active ? + item.Html.Replace(AbpBreadcrumbItemActivePlaceholder, " active") : + item.Html.Replace(AbpBreadcrumbItemActivePlaceholder, ""); } + } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/BreadcrumbItem.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/BreadcrumbItem.cs index 7f69abdfcac..37a194b9067 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/BreadcrumbItem.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/BreadcrumbItem.cs @@ -1,9 +1,8 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb; + +public class BreadcrumbItem { - public class BreadcrumbItem - { - public string Html { get; set; } + public string Html { get; set; } - public bool Active { get; set; } - } + public bool Active { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupDirection.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupDirection.cs index 53f3c3b6f9c..9b4e42805dc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupDirection.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupDirection.cs @@ -3,11 +3,10 @@ using System.Linq; using System.Threading.Tasks; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public enum AbpButtonGroupDirection { - public enum AbpButtonGroupDirection - { - Horizontal, - Vertical - } + Horizontal, + Vertical } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupSize.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupSize.cs index 42635dd232a..d54cdcea8c5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupSize.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupSize.cs @@ -1,10 +1,9 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public enum AbpButtonGroupSize { - public enum AbpButtonGroupSize - { - Default, - Small, - Medium, - Large - } + Default, + Small, + Medium, + Large } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupTagHelper.cs index b1958fc8af1..cc48c96bf92 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupTagHelper.cs @@ -1,15 +1,14 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public class AbpButtonGroupTagHelper : AbpTagHelper { - public class AbpButtonGroupTagHelper : AbpTagHelper - { - public AbpButtonGroupDirection Direction { get; set; } = AbpButtonGroupDirection.Horizontal; + public AbpButtonGroupDirection Direction { get; set; } = AbpButtonGroupDirection.Horizontal; - public AbpButtonGroupSize Size { get; set; } = AbpButtonGroupSize.Default; + public AbpButtonGroupSize Size { get; set; } = AbpButtonGroupSize.Default; - public AbpButtonGroupTagHelper(AbpButtonGroupTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpButtonGroupTagHelper(AbpButtonGroupTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupTagHelperService.cs index 3250fe68770..fb646e9941c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonGroupTagHelperService.cs @@ -2,56 +2,55 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public class AbpButtonGroupTagHelperService : AbpTagHelperService { - public class AbpButtonGroupTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - AddButtonGroupClass(context, output); - AddSizeClass(context, output); - AddAttributes(context, output); + AddButtonGroupClass(context, output); + AddSizeClass(context, output); + AddAttributes(context, output); - output.TagName = "div"; - } + output.TagName = "div"; + } - protected virtual void AddSizeClass(TagHelperContext context, TagHelperOutput output) + protected virtual void AddSizeClass(TagHelperContext context, TagHelperOutput output) + { + switch (TagHelper.Size) { - switch (TagHelper.Size) - { - case AbpButtonGroupSize.Default: - break; - case AbpButtonGroupSize.Small: - output.Attributes.AddClass("btn-group-sm"); - break; - case AbpButtonGroupSize.Medium: - output.Attributes.AddClass("btn-group-md"); - break; - case AbpButtonGroupSize.Large: - output.Attributes.AddClass("btn-group-lg"); - break; - } + case AbpButtonGroupSize.Default: + break; + case AbpButtonGroupSize.Small: + output.Attributes.AddClass("btn-group-sm"); + break; + case AbpButtonGroupSize.Medium: + output.Attributes.AddClass("btn-group-md"); + break; + case AbpButtonGroupSize.Large: + output.Attributes.AddClass("btn-group-lg"); + break; } + } - protected virtual void AddButtonGroupClass(TagHelperContext context, TagHelperOutput output) + protected virtual void AddButtonGroupClass(TagHelperContext context, TagHelperOutput output) + { + switch (TagHelper.Direction) { - switch (TagHelper.Direction) - { - case AbpButtonGroupDirection.Horizontal: - output.Attributes.AddClass("btn-group"); - break; - case AbpButtonGroupDirection.Vertical: - output.Attributes.AddClass("btn-group-vertical"); - break; - default: - output.Attributes.AddClass("btn-group"); - break; - } + case AbpButtonGroupDirection.Horizontal: + output.Attributes.AddClass("btn-group"); + break; + case AbpButtonGroupDirection.Vertical: + output.Attributes.AddClass("btn-group-vertical"); + break; + default: + output.Attributes.AddClass("btn-group"); + break; } + } - protected virtual void AddAttributes(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.Add("role", "group"); - } + protected virtual void AddAttributes(TagHelperContext context, TagHelperOutput output) + { + output.Attributes.Add("role", "group"); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSize.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSize.cs index b3aae45f6d0..96f7b27d1e7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSize.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSize.cs @@ -1,20 +1,19 @@ using System; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public enum AbpButtonSize { - public enum AbpButtonSize - { - Default, - Small, - Medium, - Large, - [Obsolete("https://getbootstrap.com/docs/5.0/components/buttons/#block-buttons")] - Block, - [Obsolete("https://getbootstrap.com/docs/5.0/components/buttons/#block-buttons")] - Block_Small, - [Obsolete("https://getbootstrap.com/docs/5.0/components/buttons/#block-buttons")] - Block_Medium, - [Obsolete("https://getbootstrap.com/docs/5.0/components/buttons/#block-buttons")] - Block_Large, - } + Default, + Small, + Medium, + Large, + [Obsolete("https://getbootstrap.com/docs/5.0/components/buttons/#block-buttons")] + Block, + [Obsolete("https://getbootstrap.com/docs/5.0/components/buttons/#block-buttons")] + Block_Small, + [Obsolete("https://getbootstrap.com/docs/5.0/components/buttons/#block-buttons")] + Block_Medium, + [Obsolete("https://getbootstrap.com/docs/5.0/components/buttons/#block-buttons")] + Block_Large, } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSizeExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSizeExtensions.cs index 5927d06e438..bdd0de72f23 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSizeExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonSizeExtensions.cs @@ -1,26 +1,25 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public static class AbpButtonSizeExtensions { - public static class AbpButtonSizeExtensions + public static string ToClassName(this AbpButtonSize size) { - public static string ToClassName(this AbpButtonSize size) + switch (size) { - switch (size) - { - case AbpButtonSize.Small: - case AbpButtonSize.Block_Small: - return "btn-sm"; - case AbpButtonSize.Medium: - case AbpButtonSize.Block_Medium: - return "btn-md"; - case AbpButtonSize.Large: - case AbpButtonSize.Block_Large: - return "btn-lg"; - case AbpButtonSize.Block: - case AbpButtonSize.Default: - return ""; - default: - throw new AbpException($"Unknown {nameof(AbpButtonSize)}: {size}"); - } + case AbpButtonSize.Small: + case AbpButtonSize.Block_Small: + return "btn-sm"; + case AbpButtonSize.Medium: + case AbpButtonSize.Block_Medium: + return "btn-md"; + case AbpButtonSize.Large: + case AbpButtonSize.Block_Large: + return "btn-lg"; + case AbpButtonSize.Block: + case AbpButtonSize.Default: + return ""; + default: + throw new AbpException($"Unknown {nameof(AbpButtonSize)}: {size}"); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs index f7ffa84c39b..624d7502744 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs @@ -1,31 +1,30 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +[HtmlTargetElement("abp-button", TagStructure = TagStructure.NormalOrSelfClosing)] +public class AbpButtonTagHelper : AbpTagHelper, IButtonTagHelperBase { - [HtmlTargetElement("abp-button", TagStructure = TagStructure.NormalOrSelfClosing)] - public class AbpButtonTagHelper : AbpTagHelper, IButtonTagHelperBase - { - public AbpButtonType ButtonType { get; set; } = AbpButtonType.Default; + public AbpButtonType ButtonType { get; set; } = AbpButtonType.Default; - public AbpButtonSize Size { get; set; } = AbpButtonSize.Default; + public AbpButtonSize Size { get; set; } = AbpButtonSize.Default; - public string BusyText { get; set; } + public string BusyText { get; set; } - public string Text { get; set; } + public string Text { get; set; } - public string Icon { get; set; } + public string Icon { get; set; } - public bool? Disabled { get; set; } + public bool? Disabled { get; set; } - public FontIconType IconType { get; set; } = FontIconType.FontAwesome; + public FontIconType IconType { get; set; } = FontIconType.FontAwesome; - public bool BusyTextIsHtml { get; set; } + public bool BusyTextIsHtml { get; set; } - public AbpButtonTagHelper(AbpButtonTagHelperService service) - : base(service) - { + public AbpButtonTagHelper(AbpButtonTagHelperService service) + : base(service) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperService.cs index fb74d5c1da1..e5576332b3e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperService.cs @@ -3,58 +3,57 @@ using Microsoft.Extensions.Localization; using System; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public class AbpButtonTagHelperService : AbpButtonTagHelperServiceBase { - public class AbpButtonTagHelperService : AbpButtonTagHelperServiceBase + protected const string DataBusyTextAttributeName = "data-busy-text"; + protected const string DataBusyTextIsHtmlAttributeName = "data-busy-text-is-html"; + + protected IStringLocalizer L { get; } + + public AbpButtonTagHelperService(IStringLocalizer localizer) { - protected const string DataBusyTextAttributeName = "data-busy-text"; - protected const string DataBusyTextIsHtmlAttributeName = "data-busy-text-is-html"; + L = localizer; + } - protected IStringLocalizer L { get; } + public override void Process(TagHelperContext context, TagHelperOutput output) + { + base.Process(context, output); + output.TagName = "button"; + AddType(context, output); + AddBusyText(context, output); + AddBusyTextIsHtml(context, output); + } - public AbpButtonTagHelperService(IStringLocalizer localizer) + protected virtual void AddType(TagHelperContext context, TagHelperOutput output) + { + if (output.Attributes.ContainsName("type")) { - L = localizer; + return; } - public override void Process(TagHelperContext context, TagHelperOutput output) - { - base.Process(context, output); - output.TagName = "button"; - AddType(context, output); - AddBusyText(context, output); - AddBusyTextIsHtml(context, output); - } + output.Attributes.Add("type", "button"); + } - protected virtual void AddType(TagHelperContext context, TagHelperOutput output) + protected virtual void AddBusyText(TagHelperContext context, TagHelperOutput output) + { + var busyText = TagHelper.BusyText ?? L["ProcessingWithThreeDot"]; + if (busyText.IsNullOrWhiteSpace()) { - if (output.Attributes.ContainsName("type")) - { - return; - } - - output.Attributes.Add("type", "button"); + return; } - protected virtual void AddBusyText(TagHelperContext context, TagHelperOutput output) - { - var busyText = TagHelper.BusyText ?? L["ProcessingWithThreeDot"]; - if (busyText.IsNullOrWhiteSpace()) - { - return; - } - - output.Attributes.SetAttribute(DataBusyTextAttributeName, busyText); - } + output.Attributes.SetAttribute(DataBusyTextAttributeName, busyText); + } - protected virtual void AddBusyTextIsHtml(TagHelperContext context, TagHelperOutput output) + protected virtual void AddBusyTextIsHtml(TagHelperContext context, TagHelperOutput output) + { + if (!TagHelper.BusyTextIsHtml) { - if (!TagHelper.BusyTextIsHtml) - { - return; - } - - output.Attributes.SetAttribute(DataBusyTextIsHtmlAttributeName, TagHelper.BusyTextIsHtml.ToString().ToLower()); + return; } + + output.Attributes.SetAttribute(DataBusyTextIsHtmlAttributeName, TagHelper.BusyTextIsHtml.ToString().ToLower()); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs index cb795bdc6c5..17422327c8d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs @@ -3,82 +3,81 @@ using System; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public abstract class AbpButtonTagHelperServiceBase : AbpTagHelperService + where TTagHelper : TagHelper, IButtonTagHelperBase { - public abstract class AbpButtonTagHelperServiceBase : AbpTagHelperService - where TTagHelper : TagHelper, IButtonTagHelperBase + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - NormalizeTagMode(context, output); - AddClasses(context, output); - AddIcon(context, output); - AddText(context, output); - AddDisabled(context, output); - } + NormalizeTagMode(context, output); + AddClasses(context, output); + AddIcon(context, output); + AddText(context, output); + AddDisabled(context, output); + } + + protected virtual void NormalizeTagMode(TagHelperContext context, TagHelperOutput output) + { + output.TagMode = TagMode.StartTagAndEndTag; + } + + protected virtual void AddClasses(TagHelperContext context, TagHelperOutput output) + { + output.Attributes.AddClass("btn"); - protected virtual void NormalizeTagMode(TagHelperContext context, TagHelperOutput output) + if (TagHelper.ButtonType != AbpButtonType.Default) { - output.TagMode = TagMode.StartTagAndEndTag; + output.Attributes.AddClass("btn-" + TagHelper.ButtonType.ToString().ToLowerInvariant().Replace("_", "-")); } - protected virtual void AddClasses(TagHelperContext context, TagHelperOutput output) + if (TagHelper.Size != AbpButtonSize.Default) { - output.Attributes.AddClass("btn"); - - if (TagHelper.ButtonType != AbpButtonType.Default) - { - output.Attributes.AddClass("btn-" + TagHelper.ButtonType.ToString().ToLowerInvariant().Replace("_","-")); - } - - if (TagHelper.Size != AbpButtonSize.Default) - { - output.Attributes.AddClass(TagHelper.Size.ToClassName()); - } + output.Attributes.AddClass(TagHelper.Size.ToClassName()); } + } - protected virtual void AddIcon(TagHelperContext context, TagHelperOutput output) + protected virtual void AddIcon(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.Icon.IsNullOrWhiteSpace()) { - if (TagHelper.Icon.IsNullOrWhiteSpace()) - { - return; - } - - var icon = new TagBuilder("i"); - icon.AddCssClass(GetIconClass(context, output)); - output.Content.AppendHtml(icon); - output.Content.Append(" "); + return; } - protected virtual string GetIconClass(TagHelperContext context, TagHelperOutput output) + var icon = new TagBuilder("i"); + icon.AddCssClass(GetIconClass(context, output)); + output.Content.AppendHtml(icon); + output.Content.Append(" "); + } + + protected virtual string GetIconClass(TagHelperContext context, TagHelperOutput output) + { + switch (TagHelper.IconType) { - switch (TagHelper.IconType) - { - case FontIconType.FontAwesome: - return "fa fa-" + TagHelper.Icon; - default: - return TagHelper.Icon; - } + case FontIconType.FontAwesome: + return "fa fa-" + TagHelper.Icon; + default: + return TagHelper.Icon; } + } - protected virtual void AddText(TagHelperContext context, TagHelperOutput output) + protected virtual void AddText(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.Text.IsNullOrWhiteSpace()) { - if (TagHelper.Text.IsNullOrWhiteSpace()) - { - return; - } - - var span = new TagBuilder("span"); - span.InnerHtml.AppendHtml(TagHelper.Text); - output.Content.AppendHtml(span); + return; } - protected virtual void AddDisabled(TagHelperContext context, TagHelperOutput output) + var span = new TagBuilder("span"); + span.InnerHtml.AppendHtml(TagHelper.Text); + output.Content.AppendHtml(span); + } + + protected virtual void AddDisabled(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.Disabled ?? false) { - if (TagHelper.Disabled ?? false) - { - output.Attributes.Add("disabled", "disabled"); - } + output.Attributes.Add("disabled", "disabled"); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonToolbarTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonToolbarTagHelper.cs index 7c716b88f89..afbd6bb53a0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonToolbarTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonToolbarTagHelper.cs @@ -1,11 +1,10 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public class AbpButtonToolbarTagHelper : AbpTagHelper { - public class AbpButtonToolbarTagHelper : AbpTagHelper + public AbpButtonToolbarTagHelper(AbpButtonToolbarTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpButtonToolbarTagHelper(AbpButtonToolbarTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonToolbarTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonToolbarTagHelperService.cs index 1581cc8bd3a..60336216146 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonToolbarTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonToolbarTagHelperService.cs @@ -1,15 +1,14 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public class AbpButtonToolbarTagHelperService : AbpTagHelperService { - public class AbpButtonToolbarTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.Attributes.AddClass("btn-toolbar"); - output.Attributes.Add("role","toolbar"); - } + output.TagName = "div"; + output.Attributes.AddClass("btn-toolbar"); + output.Attributes.Add("role", "toolbar"); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonType.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonType.cs index a6ced457e00..0e9990e6835 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonType.cs @@ -1,24 +1,23 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public enum AbpButtonType { - public enum AbpButtonType - { - Default, - Primary, - Secondary, - Success, - Danger, - Warning, - Info, - Light, - Dark, - Outline_Primary, - Outline_Secondary, - Outline_Success, - Outline_Danger, - Outline_Warning, - Outline_Info, - Outline_Light, - Outline_Dark, - Link - } -} \ No newline at end of file + Default, + Primary, + Secondary, + Success, + Danger, + Warning, + Info, + Light, + Dark, + Outline_Primary, + Outline_Secondary, + Outline_Success, + Outline_Danger, + Outline_Warning, + Outline_Info, + Outline_Light, + Outline_Dark, + Link +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelper.cs index 9a553a1be5f..bf3b4d8bac9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelper.cs @@ -1,28 +1,27 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +[HtmlTargetElement("a", Attributes = "abp-button", TagStructure = TagStructure.NormalOrSelfClosing)] +[HtmlTargetElement("input", Attributes = "abp-button", TagStructure = TagStructure.WithoutEndTag)] +public class AbpLinkButtonTagHelper : AbpTagHelper, IButtonTagHelperBase { - [HtmlTargetElement("a", Attributes = "abp-button", TagStructure = TagStructure.NormalOrSelfClosing)] - [HtmlTargetElement("input", Attributes = "abp-button", TagStructure = TagStructure.WithoutEndTag)] - public class AbpLinkButtonTagHelper : AbpTagHelper, IButtonTagHelperBase - { - [HtmlAttributeName("abp-button")] - public AbpButtonType ButtonType { get; set; } + [HtmlAttributeName("abp-button")] + public AbpButtonType ButtonType { get; set; } - public AbpButtonSize Size { get; set; } = AbpButtonSize.Default; + public AbpButtonSize Size { get; set; } = AbpButtonSize.Default; - public string Text { get; set; } + public string Text { get; set; } - public string Icon { get; set; } + public string Icon { get; set; } - public bool? Disabled { get; set; } + public bool? Disabled { get; set; } - public FontIconType IconType { get; } = FontIconType.FontAwesome; + public FontIconType IconType { get; } = FontIconType.FontAwesome; - public AbpLinkButtonTagHelper(AbpLinkButtonTagHelperService service) - : base(service) - { + public AbpLinkButtonTagHelper(AbpLinkButtonTagHelperService service) + : base(service) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelperService.cs index f92e2d51374..44dc9962842 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelperService.cs @@ -1,32 +1,31 @@ using System; using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public class AbpLinkButtonTagHelperService : AbpButtonTagHelperServiceBase { - public class AbpLinkButtonTagHelperService : AbpButtonTagHelperServiceBase + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - base.Process(context, output); - AddType(context, output); - AddRole(context, output); - } + base.Process(context, output); + AddType(context, output); + AddRole(context, output); + } - protected virtual void AddType(TagHelperContext context, TagHelperOutput output) + protected virtual void AddType(TagHelperContext context, TagHelperOutput output) + { + if (!output.Attributes.ContainsName("type") && + output.TagName.Equals("input", StringComparison.InvariantCultureIgnoreCase)) { - if (!output.Attributes.ContainsName("type") && - output.TagName.Equals("input", StringComparison.InvariantCultureIgnoreCase)) - { - output.Attributes.Add("type", "button"); - } + output.Attributes.Add("type", "button"); } + } - protected virtual void AddRole(TagHelperContext context, TagHelperOutput output) + protected virtual void AddRole(TagHelperContext context, TagHelperOutput output) + { + if (!output.Attributes.ContainsName("role")) { - if (!output.Attributes.ContainsName("role")) - { - output.Attributes.Add("role", "button"); - } + output.Attributes.Add("role", "button"); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/IButtonTagHelperBase.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/IButtonTagHelperBase.cs index ee88c4d2944..8ba73b2ab9c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/IButtonTagHelperBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/IButtonTagHelperBase.cs @@ -1,17 +1,16 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; + +public interface IButtonTagHelperBase { - public interface IButtonTagHelperBase - { - AbpButtonType ButtonType { get; } + AbpButtonType ButtonType { get; } - AbpButtonSize Size { get; } + AbpButtonSize Size { get; } - string Text { get; } + string Text { get; } - string Icon { get; } + string Icon { get; } - bool? Disabled { get; } + bool? Disabled { get; } - FontIconType IconType { get; } - } -} \ No newline at end of file + FontIconType IconType { get; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundTagHelper.cs index 5e95e8bf87b..9b4697c44af 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundTagHelper.cs @@ -1,19 +1,18 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +[HtmlTargetElement("abp-card", Attributes = "background")] +[HtmlTargetElement("abp-card-header", Attributes = "background")] +[HtmlTargetElement("abp-card-body", Attributes = "background")] +[HtmlTargetElement("abp-card-footer", Attributes = "background")] +public class AbpCardBackgroundTagHelper : AbpTagHelper { - [HtmlTargetElement("abp-card", Attributes = "background")] - [HtmlTargetElement("abp-card-header", Attributes = "background")] - [HtmlTargetElement("abp-card-body", Attributes = "background")] - [HtmlTargetElement("abp-card-footer", Attributes = "background")] - public class AbpCardBackgroundTagHelper : AbpTagHelper - { - public AbpCardBackgroundType Background { get; set; } = AbpCardBackgroundType.Default; + public AbpCardBackgroundType Background { get; set; } = AbpCardBackgroundType.Default; - public AbpCardBackgroundTagHelper(AbpCardBackgroundTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpCardBackgroundTagHelper(AbpCardBackgroundTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundTagHelperService.cs index 248d737648a..af8e0bbf510 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundTagHelperService.cs @@ -1,23 +1,22 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardBackgroundTagHelperService : AbpTagHelperService { - public class AbpCardBackgroundTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - SetBackground(context, output); - } + SetBackground(context, output); + } - protected virtual void SetBackground(TagHelperContext context, TagHelperOutput output) + protected virtual void SetBackground(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.Background == AbpCardBackgroundType.Default) { - if (TagHelper.Background == AbpCardBackgroundType.Default) - { - return; - } - - output.Attributes.AddClass("bg-" + TagHelper.Background.ToString().ToLowerInvariant()); + return; } + + output.Attributes.AddClass("bg-" + TagHelper.Background.ToString().ToLowerInvariant()); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundType.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundType.cs index 2eb9732ce83..da7aca4eec6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBackgroundType.cs @@ -1,15 +1,14 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public enum AbpCardBackgroundType { - public enum AbpCardBackgroundType - { - Default, - Primary, - Secondary, - Success, - Danger, - Warning, - Info, - Light, - Dark, - } + Default, + Primary, + Secondary, + Success, + Danger, + Warning, + Info, + Light, + Dark, } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelper.cs index b28b126cf2f..34a14e6f33e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelper.cs @@ -1,15 +1,14 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardBodyTagHelper : AbpTagHelper { - public class AbpCardBodyTagHelper : AbpTagHelper - { - public string Title { get; set; } + public string Title { get; set; } - public string Subtitle { get; set; } + public string Subtitle { get; set; } - public AbpCardBodyTagHelper(AbpCardBodyTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpCardBodyTagHelper(AbpCardBodyTagHelperService tagHelperService) + : base(tagHelperService) + { - } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs index 5707775a3a9..172fa778b6f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs @@ -3,39 +3,38 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardBodyTagHelperService : AbpTagHelperService { - public class AbpCardBodyTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.Attributes.AddClass("card-body"); + output.TagName = "div"; + output.Attributes.AddClass("card-body"); - ProcessTitle(output); - ProcessSubtitle(output); - } + ProcessTitle(output); + ProcessSubtitle(output); + } - protected virtual void ProcessTitle(TagHelperOutput output) + protected virtual void ProcessTitle(TagHelperOutput output) + { + if (!TagHelper.Title.IsNullOrWhiteSpace()) { - if (!TagHelper.Title.IsNullOrWhiteSpace()) - { - var cardTitle = new TagBuilder(AbpCardTitleTagHelper.DefaultHeading.ToHtmlTag()); - cardTitle.AddCssClass("card-title"); - cardTitle.InnerHtml.AppendHtml(TagHelper.Title); - output.PreContent.AppendHtml(cardTitle); - } + var cardTitle = new TagBuilder(AbpCardTitleTagHelper.DefaultHeading.ToHtmlTag()); + cardTitle.AddCssClass("card-title"); + cardTitle.InnerHtml.AppendHtml(TagHelper.Title); + output.PreContent.AppendHtml(cardTitle); } + } - protected virtual void ProcessSubtitle(TagHelperOutput output) + protected virtual void ProcessSubtitle(TagHelperOutput output) + { + if (!TagHelper.Subtitle.IsNullOrWhiteSpace()) { - if (!TagHelper.Subtitle.IsNullOrWhiteSpace()) - { - var cardSubtitle = new TagBuilder(AbpCardSubtitleTagHelper.DefaultHeading.ToHtmlTag()); - cardSubtitle.AddCssClass("card-subtitle text-muted mb-2"); - cardSubtitle.InnerHtml.AppendHtml(TagHelper.Subtitle); - output.PreContent.AppendHtml(cardSubtitle); - } + var cardSubtitle = new TagBuilder(AbpCardSubtitleTagHelper.DefaultHeading.ToHtmlTag()); + cardSubtitle.AddCssClass("card-subtitle text-muted mb-2"); + cardSubtitle.InnerHtml.AppendHtml(TagHelper.Subtitle); + output.PreContent.AppendHtml(cardSubtitle); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBorderColorType.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBorderColorType.cs index 0f5ccc33630..8da13ccbb87 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBorderColorType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBorderColorType.cs @@ -1,15 +1,14 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public enum AbpCardBorderColorType { - public enum AbpCardBorderColorType - { - Default, - Primary, - Secondary, - Success, - Danger, - Warning, - Info, - Light, - Dark, - } + Default, + Primary, + Secondary, + Success, + Danger, + Warning, + Info, + Light, + Dark, } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardFooterTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardFooterTagHelper.cs index 44b85885765..087c02320e1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardFooterTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardFooterTagHelper.cs @@ -1,11 +1,10 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardFooterTagHelper : AbpTagHelper { - public class AbpCardFooterTagHelper : AbpTagHelper + public AbpCardFooterTagHelper(AbpCardFooterTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpCardFooterTagHelper(AbpCardFooterTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardFooterTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardFooterTagHelperService.cs index 2a127a495bd..abf4e710206 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardFooterTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardFooterTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardFooterTagHelperService : AbpTagHelperService { - public class AbpCardFooterTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass("card-footer"); - output.TagName = "div"; - } + output.Attributes.AddClass("card-footer"); + output.TagName = "div"; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardHeaderTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardHeaderTagHelper.cs index 0584d40ced5..54d61cf61de 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardHeaderTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardHeaderTagHelper.cs @@ -1,10 +1,9 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardHeaderTagHelper : AbpTagHelper { - public class AbpCardHeaderTagHelper : AbpTagHelper + public AbpCardHeaderTagHelper(AbpCardHeaderTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpCardHeaderTagHelper(AbpCardHeaderTagHelperService tagHelperService) - : base(tagHelperService) - { - } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardHeaderTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardHeaderTagHelperService.cs index 2f68196607f..96e8f91a83c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardHeaderTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardHeaderTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardHeaderTagHelperService : AbpTagHelperService { - public class AbpCardHeaderTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.Attributes.AddClass("card-header"); - } + output.TagName = "div"; + output.Attributes.AddClass("card-header"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImagePosition.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImagePosition.cs index b3396a513b2..f101e44313c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImagePosition.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImagePosition.cs @@ -1,9 +1,8 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public enum AbpCardImagePosition { - public enum AbpCardImagePosition - { - None, - Top, - Bottom - } -} \ No newline at end of file + None, + Top, + Bottom +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImagePositionExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImagePositionExtensions.cs index 7a3f74449c6..5ab36766515 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImagePositionExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImagePositionExtensions.cs @@ -1,20 +1,19 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public static class AbpCardImagePositionExtensions { - public static class AbpCardImagePositionExtensions + public static string ToClassName(this AbpCardImagePosition position) { - public static string ToClassName(this AbpCardImagePosition position) + switch (position) { - switch (position) - { - case AbpCardImagePosition.None: - return "card-img"; - case AbpCardImagePosition.Top: - return "card-img-top"; - case AbpCardImagePosition.Bottom: - return "card-img-bottom"; - default: - throw new AbpException("Unknown AbpCardImagePosition: " + position); - } + case AbpCardImagePosition.None: + return "card-img"; + case AbpCardImagePosition.Top: + return "card-img-top"; + case AbpCardImagePosition.Bottom: + return "card-img-bottom"; + default: + throw new AbpException("Unknown AbpCardImagePosition: " + position); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImageTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImageTagHelper.cs index 4a173968d02..0610cfa150c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImageTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImageTagHelper.cs @@ -1,18 +1,17 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +[HtmlTargetElement("img", Attributes = "abp-card-image", TagStructure = TagStructure.WithoutEndTag)] +[HtmlTargetElement("abp-image", Attributes = "abp-card-image", TagStructure = TagStructure.WithoutEndTag)] +public class AbpCardImageTagHelper : AbpTagHelper { - [HtmlTargetElement("img", Attributes = "abp-card-image", TagStructure = TagStructure.WithoutEndTag)] - [HtmlTargetElement("abp-image", Attributes = "abp-card-image", TagStructure = TagStructure.WithoutEndTag)] - public class AbpCardImageTagHelper : AbpTagHelper - { - [HtmlAttributeName("abp-card-image")] - public AbpCardImagePosition Position { get; set; } = AbpCardImagePosition.Top; + [HtmlAttributeName("abp-card-image")] + public AbpCardImagePosition Position { get; set; } = AbpCardImagePosition.Top; - public AbpCardImageTagHelper(AbpCardImageTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpCardImageTagHelper(AbpCardImageTagHelperService tagHelperService) + : base(tagHelperService) + { - } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImageTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImageTagHelperService.cs index 65cb8ff2bcd..4d91cd30c9c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImageTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardImageTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardImageTagHelperService : AbpTagHelperService { - public class AbpCardImageTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass(TagHelper.Position.ToClassName()); - output.Attributes.RemoveAll("abp-card-image"); - } + output.Attributes.AddClass(TagHelper.Position.ToClassName()); + output.Attributes.RemoveAll("abp-card-image"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardLinkTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardLinkTagHelper.cs index 8f7f29bbb51..9626dd2bd4b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardLinkTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardLinkTagHelper.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +[HtmlTargetElement("a", Attributes = "abp-card-link")] +public class AbpCardLinkTagHelper : AbpTagHelper { - [HtmlTargetElement("a", Attributes = "abp-card-link")] - public class AbpCardLinkTagHelper : AbpTagHelper + public AbpCardLinkTagHelper(AbpCardLinkTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpCardLinkTagHelper(AbpCardLinkTagHelperService tagHelperService) - : base(tagHelperService) - { - - } + } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardLinkTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardLinkTagHelperService.cs index 5cdba7cdbac..d4dc7754793 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardLinkTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardLinkTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardLinkTagHelperService : AbpTagHelperService { - public class AbpCardLinkTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass("card-link"); - output.Attributes.RemoveAll("abp-card-link"); - } + output.Attributes.AddClass("card-link"); + output.Attributes.RemoveAll("abp-card-link"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardSubtitleTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardSubtitleTagHelper.cs index cc6ef506dde..e740af26647 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardSubtitleTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardSubtitleTagHelper.cs @@ -1,15 +1,14 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardSubtitleTagHelper : AbpTagHelper { - public class AbpCardSubtitleTagHelper : AbpTagHelper - { - public static HtmlHeadingType DefaultHeading { get; set; } = HtmlHeadingType.H6; + public static HtmlHeadingType DefaultHeading { get; set; } = HtmlHeadingType.H6; - public HtmlHeadingType Heading { get; set; } = DefaultHeading; + public HtmlHeadingType Heading { get; set; } = DefaultHeading; - public AbpCardSubtitleTagHelper(AbpCardSubtitleTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpCardSubtitleTagHelper(AbpCardSubtitleTagHelperService tagHelperService) + : base(tagHelperService) + { - } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardSubtitleTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardSubtitleTagHelperService.cs index 8f9084d3bf3..5710c810008 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardSubtitleTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardSubtitleTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardSubtitleTagHelperService : AbpTagHelperService { - public class AbpCardSubtitleTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = TagHelper.Heading.ToHtmlTag(); - output.Attributes.AddClass("card-subtitle"); - } + output.TagName = TagHelper.Heading.ToHtmlTag(); + output.Attributes.AddClass("card-subtitle"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTagHelper.cs index c186e8857c0..5b568e16a6b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTagHelper.cs @@ -1,12 +1,11 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardTagHelper : AbpTagHelper { - public class AbpCardTagHelper : AbpTagHelper - { - public AbpCardBorderColorType Border { get; set; } = AbpCardBorderColorType.Default; + public AbpCardBorderColorType Border { get; set; } = AbpCardBorderColorType.Default; - public AbpCardTagHelper(AbpCardTagHelperService tagHelperService) - : base(tagHelperService) - { - } + public AbpCardTagHelper(AbpCardTagHelperService tagHelperService) + : base(tagHelperService) + { } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTagHelperService.cs index 29a462797d3..61691549044 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTagHelperService.cs @@ -1,25 +1,24 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardTagHelperService : AbpTagHelperService { - public class AbpCardTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.Attributes.AddClass("card"); + output.TagName = "div"; + output.Attributes.AddClass("card"); - SetBorder(context, output); - } - protected virtual void SetBorder(TagHelperContext context, TagHelperOutput output) + SetBorder(context, output); + } + protected virtual void SetBorder(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.Border == AbpCardBorderColorType.Default) { - if (TagHelper.Border == AbpCardBorderColorType.Default) - { - return; - } - - output.Attributes.AddClass("border-" + TagHelper.Border.ToString().ToLowerInvariant()); + return; } + + output.Attributes.AddClass("border-" + TagHelper.Border.ToString().ToLowerInvariant()); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorTagHelper.cs index f9787b1f182..45ddf9725ae 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorTagHelper.cs @@ -1,19 +1,18 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +[HtmlTargetElement("abp-card", Attributes = "text-color")] +[HtmlTargetElement("abp-card-header", Attributes = "text-color")] +[HtmlTargetElement("abp-card-body", Attributes = "text-color")] +[HtmlTargetElement("abp-card-footer", Attributes = "text-color")] +public class AbpCardTextColorTagHelper : AbpTagHelper { - [HtmlTargetElement("abp-card", Attributes = "text-color")] - [HtmlTargetElement("abp-card-header", Attributes = "text-color")] - [HtmlTargetElement("abp-card-body", Attributes = "text-color")] - [HtmlTargetElement("abp-card-footer", Attributes = "text-color")] - public class AbpCardTextColorTagHelper : AbpTagHelper - { - public AbpCardTextColorType TextColor { get; set; } = AbpCardTextColorType.Default; + public AbpCardTextColorType TextColor { get; set; } = AbpCardTextColorType.Default; - public AbpCardTextColorTagHelper(AbpCardTextColorTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpCardTextColorTagHelper(AbpCardTextColorTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorTagHelperService.cs index 36484a33f83..04be1fa5bb4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorTagHelperService.cs @@ -1,23 +1,22 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardTextColorTagHelperService : AbpTagHelperService { - public class AbpCardTextColorTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - SetTextColor(context, output); - } + SetTextColor(context, output); + } - protected virtual void SetTextColor(TagHelperContext context, TagHelperOutput output) + protected virtual void SetTextColor(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.TextColor == AbpCardTextColorType.Default) { - if (TagHelper.TextColor == AbpCardTextColorType.Default) - { - return; - } - - output.Attributes.AddClass("text-" + TagHelper.TextColor.ToString().ToLowerInvariant()); + return; } + + output.Attributes.AddClass("text-" + TagHelper.TextColor.ToString().ToLowerInvariant()); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorType.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorType.cs index eb415945b08..45df26f7617 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextColorType.cs @@ -1,16 +1,15 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public enum AbpCardTextColorType { - public enum AbpCardTextColorType - { - Default, - White, - Primary, - Secondary, - Success, - Danger, - Warning, - Info, - Light, - Dark - } + Default, + White, + Primary, + Secondary, + Success, + Danger, + Warning, + Info, + Light, + Dark } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextTagHelper.cs index 00e2468dfe2..6cb434b17aa 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextTagHelper.cs @@ -1,10 +1,9 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardTextTagHelper : AbpTagHelper { - public class AbpCardTextTagHelper : AbpTagHelper + public AbpCardTextTagHelper(AbpCardTextTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpCardTextTagHelper(AbpCardTextTagHelperService tagHelperService) - : base(tagHelperService) - { - } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextTagHelperService.cs index ba2d619126f..41195ef9666 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTextTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardTextTagHelperService : AbpTagHelperService { - public class AbpCardTextTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "p"; - output.Attributes.AddClass("card-text"); - } + output.TagName = "p"; + output.Attributes.AddClass("card-text"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTitleTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTitleTagHelper.cs index 410a64d76d8..ba3b6a41e18 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTitleTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTitleTagHelper.cs @@ -1,14 +1,13 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardTitleTagHelper : AbpTagHelper { - public class AbpCardTitleTagHelper : AbpTagHelper - { - public static HtmlHeadingType DefaultHeading { get; set; } = HtmlHeadingType.H5; + public static HtmlHeadingType DefaultHeading { get; set; } = HtmlHeadingType.H5; - public HtmlHeadingType Heading { get; set; } = DefaultHeading; + public HtmlHeadingType Heading { get; set; } = DefaultHeading; - public AbpCardTitleTagHelper(AbpCardTitleTagHelperService tagHelperService) - : base(tagHelperService) - { - } + public AbpCardTitleTagHelper(AbpCardTitleTagHelperService tagHelperService) + : base(tagHelperService) + { } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTitleTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTitleTagHelperService.cs index 9ad27a49a02..2977fc42e99 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTitleTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardTitleTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; + +public class AbpCardTitleTagHelperService : AbpTagHelperService { - public class AbpCardTitleTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = TagHelper.Heading.ToHtmlTag(); - output.Attributes.AddClass("card-title"); - } + output.TagName = TagHelper.Heading.ToHtmlTag(); + output.Attributes.AddClass("card-title"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelper.cs index e8e983b34ae..65a47b73c4f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelper.cs @@ -1,21 +1,20 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel; + +public class AbpCarouselItemTagHelper : AbpTagHelper { - public class AbpCarouselItemTagHelper : AbpTagHelper - { - public bool? Active { get; set; } + public bool? Active { get; set; } - public string Src { get; set; } + public string Src { get; set; } - public string Alt { get; set; } + public string Alt { get; set; } - public string CaptionTitle { get; set; } + public string CaptionTitle { get; set; } - public string Caption { get; set; } + public string Caption { get; set; } - public AbpCarouselItemTagHelper(AbpCarouselItemTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpCarouselItemTagHelper(AbpCarouselItemTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs index 1af2b759a47..a8a3030e95e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs @@ -5,79 +5,78 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel; + +public class AbpCarouselItemTagHelperService : AbpTagHelperService { - public class AbpCarouselItemTagHelperService : AbpTagHelperService - { - private readonly HtmlEncoder _encoder; + private readonly HtmlEncoder _encoder; - public AbpCarouselItemTagHelperService(HtmlEncoder encoder) - { - _encoder = encoder; - } + public AbpCarouselItemTagHelperService(HtmlEncoder encoder) + { + _encoder = encoder; + } - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.Attributes.AddClass("carousel-item"); - output.Attributes.AddClass(AbpCarouselItemActivePlaceholder); + public override void Process(TagHelperContext context, TagHelperOutput output) + { + output.TagName = "div"; + output.Attributes.AddClass("carousel-item"); + output.Attributes.AddClass(AbpCarouselItemActivePlaceholder); - SetInnerImgTag(context, output); - SetActive(context, output); - AddCaption(context, output); + SetInnerImgTag(context, output); + SetActive(context, output); + AddCaption(context, output); - AddToContext(context, output); + AddToContext(context, output); - output.SuppressOutput(); - } + output.SuppressOutput(); + } - private void AddToContext(TagHelperContext context, TagHelperOutput output) - { - var getOutputAsHtml = output.Render(_encoder); + private void AddToContext(TagHelperContext context, TagHelperOutput output) + { + var getOutputAsHtml = output.Render(_encoder); - var itemList = context.GetValue>(CarouselItemsContent); + var itemList = context.GetValue>(CarouselItemsContent); - itemList.Add(new CarouselItem(getOutputAsHtml, TagHelper.Active ?? false)); - } + itemList.Add(new CarouselItem(getOutputAsHtml, TagHelper.Active ?? false)); + } - protected virtual void SetInnerImgTag(TagHelperContext context, TagHelperOutput output) - { - var img = new TagBuilder("img"); - img.AddCssClass("d-block w-100"); - img.Attributes.Add("src", TagHelper.Src); - img.Attributes.Add("alt", TagHelper.Alt); + protected virtual void SetInnerImgTag(TagHelperContext context, TagHelperOutput output) + { + var img = new TagBuilder("img"); + img.AddCssClass("d-block w-100"); + img.Attributes.Add("src", TagHelper.Src); + img.Attributes.Add("alt", TagHelper.Alt); - output.Content.SetHtmlContent(img); - } + output.Content.SetHtmlContent(img); + } - protected virtual void SetActive(TagHelperContext context, TagHelperOutput output) + protected virtual void SetActive(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.Active ?? false) { - if (TagHelper.Active??false) - { - output.Attributes.AddClass("active"); - } + output.Attributes.AddClass("active"); } + } - protected virtual void AddCaption(TagHelperContext context, TagHelperOutput output) + protected virtual void AddCaption(TagHelperContext context, TagHelperOutput output) + { + if (string.IsNullOrWhiteSpace(TagHelper.Caption) && string.IsNullOrWhiteSpace(TagHelper.CaptionTitle)) { - if (string.IsNullOrWhiteSpace(TagHelper.Caption) && string.IsNullOrWhiteSpace(TagHelper.CaptionTitle)) - { - return; - } - - var title = new TagBuilder("h5"); - title.InnerHtml.AppendHtml(TagHelper.CaptionTitle); + return; + } - var caption = new TagBuilder("p"); - caption.InnerHtml.AppendHtml(TagHelper.Caption); + var title = new TagBuilder("h5"); + title.InnerHtml.AppendHtml(TagHelper.CaptionTitle); - var wrapper = new TagBuilder("div"); - wrapper.AddCssClass("carousel-caption d-none d-md-block"); - wrapper.InnerHtml.AppendHtml(title); - wrapper.InnerHtml.AppendHtml(caption); + var caption = new TagBuilder("p"); + caption.InnerHtml.AppendHtml(TagHelper.Caption); - output.PostContent.SetHtmlContent(wrapper); - } + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("carousel-caption d-none d-md-block"); + wrapper.InnerHtml.AppendHtml(title); + wrapper.InnerHtml.AppendHtml(caption); + output.PostContent.SetHtmlContent(wrapper); } + } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelper.cs index becb13ca47e..e9931241c28 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelper.cs @@ -1,19 +1,18 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel; + +public class AbpCarouselTagHelper : AbpTagHelper { - public class AbpCarouselTagHelper : AbpTagHelper - { - public string Id { get; set; } + public string Id { get; set; } - public bool? Crossfade { get; set; } + public bool? Crossfade { get; set; } - public bool? Controls { get; set; } + public bool? Controls { get; set; } - public bool? Indicators { get; set; } + public bool? Indicators { get; set; } - public AbpCarouselTagHelper(AbpCarouselTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpCarouselTagHelper(AbpCarouselTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs index bb3c38f12bc..9264737b7b1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs @@ -8,174 +8,173 @@ using System.Threading.Tasks; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel; + +public class AbpCarouselTagHelperService : AbpTagHelperService { - public class AbpCarouselTagHelperService : AbpTagHelperService + protected IStringLocalizer L { get; } + + public AbpCarouselTagHelperService(IStringLocalizer localizer) { - protected IStringLocalizer L { get; } + L = localizer; + } - public AbpCarouselTagHelperService(IStringLocalizer localizer) - { - L = localizer; - } + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + output.TagName = "div"; - public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; + SetRandomIdIfNotProvided(); + AddBasicAttributes(context, output); - SetRandomIdIfNotProvided(); - AddBasicAttributes(context, output); + var itemList = InitilizeCarouselItemsContentsContext(context, output); - var itemList = InitilizeCarouselItemsContentsContext(context, output); + await output.GetChildContentAsync(); - await output.GetChildContentAsync(); + SetOneItemAsActive(context, output, itemList); + SetItems(context, output, itemList); + SetControls(context, output, itemList); + SetIndicators(context, output, itemList); + } - SetOneItemAsActive(context, output, itemList); - SetItems(context, output, itemList); - SetControls(context, output, itemList); - SetIndicators(context, output, itemList); - } + protected virtual List InitilizeCarouselItemsContentsContext(TagHelperContext context, TagHelperOutput output) + { + var items = new List(); + context.Items[CarouselItemsContent] = items; + return items; + } - protected virtual List InitilizeCarouselItemsContentsContext(TagHelperContext context, TagHelperOutput output) - { - var items = new List(); - context.Items[CarouselItemsContent] = items; - return items; - } + protected virtual void SetItems(TagHelperContext context, TagHelperOutput output, List itemList) + { + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("carousel-inner"); - protected virtual void SetItems(TagHelperContext context, TagHelperOutput output, List itemList) + foreach (var carouselItem in itemList) { - var wrapper = new TagBuilder("div"); - wrapper.AddCssClass("carousel-inner"); + SetActiveIfActive(carouselItem); - foreach (var carouselItem in itemList) - { - SetActiveIfActive(carouselItem); + wrapper.InnerHtml.AppendHtml(carouselItem.Html); + } - wrapper.InnerHtml.AppendHtml(carouselItem.Html); - } + output.Content.SetHtmlContent(wrapper); + } - output.Content.SetHtmlContent(wrapper); + protected virtual void SetControls(TagHelperContext context, TagHelperOutput output, List itemList) + { + if (!TagHelper.Controls ?? false) + { + return; } - protected virtual void SetControls(TagHelperContext context, TagHelperOutput output, List itemList) - { - if (!TagHelper.Controls ?? false) - { - return; - } + // create 'previous' item + var prevIcon = new TagBuilder("span"); + prevIcon.AddCssClass("carousel-control-prev-icon"); + prevIcon.Attributes.Add("aria-hidden", "true"); + + var prevText = new TagBuilder("span"); + prevText.AddCssClass("visually-hidden"); + prevText.InnerHtml.Append(L["Previous"].Value); + + var prevAnchor = new TagBuilder("a"); + prevAnchor.AddCssClass("carousel-control-prev"); + prevAnchor.Attributes.Add("href", "#" + TagHelper.Id); + prevAnchor.Attributes.Add("role", "button"); + prevAnchor.Attributes.Add("data-bs-slide", "prev"); + + prevAnchor.InnerHtml.AppendHtml(prevIcon); + prevAnchor.InnerHtml.AppendHtml(prevText); + + // create 'next' item + var nextIcon = new TagBuilder("span"); + nextIcon.AddCssClass("carousel-control-next-icon"); + nextIcon.Attributes.Add("aria-hidden", "true"); + + var nextText = new TagBuilder("span"); + nextText.AddCssClass("visually-hidden"); + nextText.InnerHtml.Append(L["Next"].Value); + + var nextAnchor = new TagBuilder("a"); + nextAnchor.AddCssClass("carousel-control-next"); + nextAnchor.Attributes.Add("href", "#" + TagHelper.Id); + nextAnchor.Attributes.Add("role", "button"); + nextAnchor.Attributes.Add("data-bs-slide", "next"); + + nextAnchor.InnerHtml.AppendHtml(nextIcon); + nextAnchor.InnerHtml.AppendHtml(nextText); + + // append post content + output.PostContent.AppendHtml(prevAnchor); + output.PostContent.AppendHtml(nextAnchor); + } - // create 'previous' item - var prevIcon = new TagBuilder("span"); - prevIcon.AddCssClass("carousel-control-prev-icon"); - prevIcon.Attributes.Add("aria-hidden", "true"); - - var prevText = new TagBuilder("span"); - prevText.AddCssClass("visually-hidden"); - prevText.InnerHtml.Append(L["Previous"].Value); - - var prevAnchor = new TagBuilder("a"); - prevAnchor.AddCssClass("carousel-control-prev"); - prevAnchor.Attributes.Add("href", "#" + TagHelper.Id); - prevAnchor.Attributes.Add("role", "button"); - prevAnchor.Attributes.Add("data-bs-slide", "prev"); - - prevAnchor.InnerHtml.AppendHtml(prevIcon); - prevAnchor.InnerHtml.AppendHtml(prevText); - - // create 'next' item - var nextIcon = new TagBuilder("span"); - nextIcon.AddCssClass("carousel-control-next-icon"); - nextIcon.Attributes.Add("aria-hidden", "true"); - - var nextText = new TagBuilder("span"); - nextText.AddCssClass("visually-hidden"); - nextText.InnerHtml.Append(L["Next"].Value); - - var nextAnchor = new TagBuilder("a"); - nextAnchor.AddCssClass("carousel-control-next"); - nextAnchor.Attributes.Add("href", "#" + TagHelper.Id); - nextAnchor.Attributes.Add("role", "button"); - nextAnchor.Attributes.Add("data-bs-slide", "next"); - - nextAnchor.InnerHtml.AppendHtml(nextIcon); - nextAnchor.InnerHtml.AppendHtml(nextText); - - // append post content - output.PostContent.AppendHtml(prevAnchor); - output.PostContent.AppendHtml(nextAnchor); + protected virtual void SetIndicators(TagHelperContext context, TagHelperOutput output, List itemList) + { + if (!TagHelper.Indicators ?? false) + { + return; } - protected virtual void SetIndicators(TagHelperContext context, TagHelperOutput output, List itemList) - { - if (!TagHelper.Indicators ?? false) - { - return; - } + var list = new TagBuilder("ol"); + list.AddCssClass("carousel-indicators"); - var list = new TagBuilder("ol"); - list.AddCssClass("carousel-indicators"); + for (var i = 0; i < itemList.Count; i++) + { + var listItem = new TagBuilder("li"); + listItem.Attributes.Add("data-bs-target", "#" + TagHelper.Id); + listItem.Attributes.Add("data-bs-slide-to", i.ToString()); - for (var i = 0; i < itemList.Count; i++) + if (itemList[i].Active) { - var listItem = new TagBuilder("li"); - listItem.Attributes.Add("data-bs-target", "#" + TagHelper.Id); - listItem.Attributes.Add("data-bs-slide-to", i.ToString()); - - if (itemList[i].Active) - { - listItem.AddCssClass("active"); - } - - list.InnerHtml.AppendHtml(listItem); + listItem.AddCssClass("active"); } - output.PreContent.SetHtmlContent(list); + list.InnerHtml.AppendHtml(listItem); } - protected virtual void SetOneItemAsActive(TagHelperContext context, TagHelperOutput output, List itemList) - { - if (!itemList.Any(it => it.Active) && itemList.Count > 0) - { - itemList.FirstOrDefault().Active = true; - } - } + output.PreContent.SetHtmlContent(list); + } - protected virtual void AddBasicAttributes(TagHelperContext context, TagHelperOutput output) + protected virtual void SetOneItemAsActive(TagHelperContext context, TagHelperOutput output, List itemList) + { + if (!itemList.Any(it => it.Active) && itemList.Count > 0) { - output.Attributes.Add("data-bs-ride", "carousel"); - output.Attributes.Add("id", TagHelper.Id); - AddBasicClasses(context, output); + itemList.FirstOrDefault().Active = true; } + } - protected virtual void AddBasicClasses(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass("carousel"); - output.Attributes.AddClass("slide"); - SetFadeAnimation(context, output); - } + protected virtual void AddBasicAttributes(TagHelperContext context, TagHelperOutput output) + { + output.Attributes.Add("data-bs-ride", "carousel"); + output.Attributes.Add("id", TagHelper.Id); + AddBasicClasses(context, output); + } - protected virtual void SetFadeAnimation(TagHelperContext context, TagHelperOutput output) - { - if (TagHelper.Crossfade ?? false) - { - output.Attributes.AddClass("carousel-fade"); - } - } + protected virtual void AddBasicClasses(TagHelperContext context, TagHelperOutput output) + { + output.Attributes.AddClass("carousel"); + output.Attributes.AddClass("slide"); + SetFadeAnimation(context, output); + } - protected virtual void SetRandomIdIfNotProvided() + protected virtual void SetFadeAnimation(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.Crossfade ?? false) { - if (string.IsNullOrWhiteSpace(TagHelper.Id)) - { - TagHelper.Id = "C" + Guid.NewGuid().ToString("N"); - } + output.Attributes.AddClass("carousel-fade"); } + } - protected virtual void SetActiveIfActive(CarouselItem item) + protected virtual void SetRandomIdIfNotProvided() + { + if (string.IsNullOrWhiteSpace(TagHelper.Id)) { - item.Html = item.Html.Replace(AbpCarouselItemActivePlaceholder, item.Active ? "active" : ""); + TagHelper.Id = "C" + Guid.NewGuid().ToString("N"); } + } + protected virtual void SetActiveIfActive(CarouselItem item) + { + item.Html = item.Html.Replace(AbpCarouselItemActivePlaceholder, item.Active ? "active" : ""); } + } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/CarouselItem.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/CarouselItem.cs index da901f39b0f..2942a62541a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/CarouselItem.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/CarouselItem.cs @@ -1,15 +1,14 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel; + +public class CarouselItem { - public class CarouselItem + public CarouselItem(string html, bool active) { - public CarouselItem(string html, bool active) - { - Html = html; - Active = active; - } + Html = html; + Active = active; + } - public string Html { get; set; } + public string Html { get; set; } - public bool Active { get; set; } - } + public bool Active { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelper.cs index d1ec7e41b45..8742631e9a7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelper.cs @@ -1,17 +1,16 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse; + +public class AbpAccordionItemTagHelper : AbpTagHelper { - public class AbpAccordionItemTagHelper : AbpTagHelper - { - public string Id { get; set; } + public string Id { get; set; } - public string Title { get; set; } + public string Title { get; set; } - public bool? Active { get; set; } + public bool? Active { get; set; } - public AbpAccordionItemTagHelper(AbpAccordionItemTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpAccordionItemTagHelper(AbpAccordionItemTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs index 3ea2824b62e..7f3f7e9c17e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs @@ -5,81 +5,80 @@ using System.Threading.Tasks; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse; + +public class AbpAccordionItemTagHelperService : AbpTagHelperService { - public class AbpAccordionItemTagHelperService : AbpTagHelperService + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { - public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - SetRandomIdIfNotProvided(); + SetRandomIdIfNotProvided(); - var childContent = await output.GetChildContentAsync(); + var childContent = await output.GetChildContentAsync(); - var html = GetAccordionHeaderItem(context, output) + GetAccordionContentItem(context, output, childContent); + var html = GetAccordionHeaderItem(context, output) + GetAccordionContentItem(context, output, childContent); - var tabHeaderItems = context.GetValue>(AccordionItems); - tabHeaderItems.Add(html); + var tabHeaderItems = context.GetValue>(AccordionItems); + tabHeaderItems.Add(html); - output.SuppressOutput(); - } + output.SuppressOutput(); + } - protected virtual string GetAccordionHeaderItem(TagHelperContext context, TagHelperOutput output) - { - var button = new TagBuilder("button"); - button.AddCssClass("btn btn-link"); - button.Attributes.Add("type", "button"); - button.Attributes.Add("data-bs-toggle", "collapse"); - button.Attributes.Add("data-bs-target", "#" + GetContentId()); - button.Attributes.Add("aria-expanded", "true"); - button.Attributes.Add("aria-controls", GetContentId()); - button.InnerHtml.AppendHtml(TagHelper.Title); - - var h5 = new TagBuilder("h5"); - h5.AddCssClass("mb-0"); - h5.InnerHtml.AppendHtml(button); - - var header = new TagBuilder("div"); - header.AddCssClass("card-header"); - header.Attributes.Add("id", GetHeadingId()); - header.InnerHtml.AppendHtml(h5); - - return header.ToHtmlString(); - } + protected virtual string GetAccordionHeaderItem(TagHelperContext context, TagHelperOutput output) + { + var button = new TagBuilder("button"); + button.AddCssClass("btn btn-link"); + button.Attributes.Add("type", "button"); + button.Attributes.Add("data-bs-toggle", "collapse"); + button.Attributes.Add("data-bs-target", "#" + GetContentId()); + button.Attributes.Add("aria-expanded", "true"); + button.Attributes.Add("aria-controls", GetContentId()); + button.InnerHtml.AppendHtml(TagHelper.Title); + + var h5 = new TagBuilder("h5"); + h5.AddCssClass("mb-0"); + h5.InnerHtml.AppendHtml(button); + + var header = new TagBuilder("div"); + header.AddCssClass("card-header"); + header.Attributes.Add("id", GetHeadingId()); + header.InnerHtml.AppendHtml(h5); + + return header.ToHtmlString(); + } - protected virtual string GetAccordionContentItem(TagHelperContext context, TagHelperOutput output, TagHelperContent content) - { - var show = (TagHelper.Active ?? false) ? " show" : ""; + protected virtual string GetAccordionContentItem(TagHelperContext context, TagHelperOutput output, TagHelperContent content) + { + var show = (TagHelper.Active ?? false) ? " show" : ""; - var cardBody = new TagBuilder("div"); - cardBody.AddCssClass("card-body"); - cardBody.InnerHtml.AppendHtml(content); + var cardBody = new TagBuilder("div"); + cardBody.AddCssClass("card-body"); + cardBody.InnerHtml.AppendHtml(content); - var wrapper = new TagBuilder("div"); - wrapper.AddCssClass("collapse" + show); - wrapper.Attributes.Add("id", GetContentId()); - wrapper.Attributes.Add("aria-labelledby", GetHeadingId()); - wrapper.Attributes.Add("data-bs-parent", "#" + AbpAccordionParentIdPlaceholder); - wrapper.InnerHtml.AppendHtml(cardBody); + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("collapse" + show); + wrapper.Attributes.Add("id", GetContentId()); + wrapper.Attributes.Add("aria-labelledby", GetHeadingId()); + wrapper.Attributes.Add("data-bs-parent", "#" + AbpAccordionParentIdPlaceholder); + wrapper.InnerHtml.AppendHtml(cardBody); - return wrapper.ToHtmlString(); - } + return wrapper.ToHtmlString(); + } - protected virtual string GetHeadingId() - { - return "heading" + TagHelper.Id; ; - } + protected virtual string GetHeadingId() + { + return "heading" + TagHelper.Id; ; + } - protected virtual string GetContentId() - { - return "content" + TagHelper.Id; ; - } + protected virtual string GetContentId() + { + return "content" + TagHelper.Id; ; + } - protected virtual void SetRandomIdIfNotProvided() + protected virtual void SetRandomIdIfNotProvided() + { + if (string.IsNullOrWhiteSpace(TagHelper.Id)) { - if (string.IsNullOrWhiteSpace(TagHelper.Id)) - { - TagHelper.Id = "A" + Guid.NewGuid().ToString("N"); - } + TagHelper.Id = "A" + Guid.NewGuid().ToString("N"); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelper.cs index c297a7c6307..49cca3199f2 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelper.cs @@ -1,13 +1,12 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse; + +public class AbpAccordionTagHelper : AbpTagHelper { - public class AbpAccordionTagHelper : AbpTagHelper - { - public string Id { get; set; } + public string Id { get; set; } - public AbpAccordionTagHelper(AbpAccordionTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpAccordionTagHelper(AbpAccordionTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs index d55bb04d219..c33b25022b4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs @@ -6,60 +6,59 @@ using System.Threading.Tasks; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse; + +public class AbpAccordionTagHelperService : AbpTagHelperService { - public class AbpAccordionTagHelperService : AbpTagHelperService - { - protected IHtmlGenerator HtmlGenerator { get; } + protected IHtmlGenerator HtmlGenerator { get; } - public AbpAccordionTagHelperService(IHtmlGenerator htmlGenerator) - { - HtmlGenerator = htmlGenerator; - } + public AbpAccordionTagHelperService(IHtmlGenerator htmlGenerator) + { + HtmlGenerator = htmlGenerator; + } - public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - SetRandomIdIfNotProvided(); + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + SetRandomIdIfNotProvided(); - output.TagName = "div"; - output.TagMode = TagMode.StartTagAndEndTag; - output.Attributes.AddClass("accordion"); - output.Attributes.Add("id",TagHelper.Id); + output.TagName = "div"; + output.TagMode = TagMode.StartTagAndEndTag; + output.Attributes.AddClass("accordion"); + output.Attributes.Add("id", TagHelper.Id); - var items = InitilizeFormGroupContentsContext(context, output); + var items = InitilizeFormGroupContentsContext(context, output); - await output.GetChildContentAsync(); + await output.GetChildContentAsync(); - SetContent(context, output, items); - } + SetContent(context, output, items); + } - protected virtual void SetContent(TagHelperContext context, TagHelperOutput output, List items) + protected virtual void SetContent(TagHelperContext context, TagHelperOutput output, List items) + { + foreach (var item in items) { - foreach (var item in items) - { - var content = item.Replace(AbpAccordionParentIdPlaceholder, HtmlGenerator.Encode(TagHelper.Id)); + var content = item.Replace(AbpAccordionParentIdPlaceholder, HtmlGenerator.Encode(TagHelper.Id)); - var wrapper = new TagBuilder("div"); - wrapper.AddCssClass("card"); - wrapper.InnerHtml.AppendHtml(content); + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("card"); + wrapper.InnerHtml.AppendHtml(content); - output.Content.AppendHtml(wrapper); - } + output.Content.AppendHtml(wrapper); } + } - protected virtual List InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output) - { - var items = new List(); - context.Items[AccordionItems] = items; - return items; - } + protected virtual List InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output) + { + var items = new List(); + context.Items[AccordionItems] = items; + return items; + } - protected virtual void SetRandomIdIfNotProvided() + protected virtual void SetRandomIdIfNotProvided() + { + if (string.IsNullOrWhiteSpace(TagHelper.Id)) { - if (string.IsNullOrWhiteSpace(TagHelper.Id)) - { - TagHelper.Id = "A" + Guid.NewGuid().ToString("N"); - } + TagHelper.Id = "A" + Guid.NewGuid().ToString("N"); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelper.cs index a50907addb2..cd6d5d43edc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelper.cs @@ -1,17 +1,16 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse; + +public class AbpCollapseBodyTagHelper : AbpTagHelper { - public class AbpCollapseBodyTagHelper : AbpTagHelper - { - public string Id { get; set; } + public string Id { get; set; } - public bool? Multi { get; set; } + public bool? Multi { get; set; } - public bool? Show { get; set; } + public bool? Show { get; set; } - public AbpCollapseBodyTagHelper(AbpCollapseBodyTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpCollapseBodyTagHelper(AbpCollapseBodyTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelperService.cs index 843efae0f4c..85685ccf808 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelperService.cs @@ -2,29 +2,28 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse; + +public class AbpCollapseBodyTagHelperService : AbpTagHelperService { - public class AbpCollapseBodyTagHelperService : AbpTagHelperService + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { - public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.Attributes.AddClass("collapse"); - output.Attributes.Add("id", TagHelper.Id); + output.TagName = "div"; + output.Attributes.AddClass("collapse"); + output.Attributes.Add("id", TagHelper.Id); - if (TagHelper.Show ?? false) - { - output.Attributes.AddClass("show"); - } + if (TagHelper.Show ?? false) + { + output.Attributes.AddClass("show"); + } - if (TagHelper.Multi ?? false) - { - output.Attributes.AddClass("multi-collapse"); - } + if (TagHelper.Multi ?? false) + { + output.Attributes.AddClass("multi-collapse"); + } - var childContent = await output.GetChildContentAsync(); + var childContent = await output.GetChildContentAsync(); - output.Content.SetHtmlContent(childContent); - } + output.Content.SetHtmlContent(childContent); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseButtonTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseButtonTagHelper.cs index 6b8fc8c30ba..c1219b3bbb3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseButtonTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseButtonTagHelper.cs @@ -1,20 +1,18 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse; + +[HtmlTargetElement("abp-button", Attributes = "abp-collapse-id")] +[HtmlTargetElement("a", Attributes = "abp-collapse-id")] +public class AbpCollapseButtonTagHelper : AbpTagHelper { + [HtmlAttributeName("abp-collapse-id")] + public string BodyId { get; set; } - [HtmlTargetElement("abp-button", Attributes = "abp-collapse-id")] - [HtmlTargetElement("a", Attributes = "abp-collapse-id")] - public class AbpCollapseButtonTagHelper : AbpTagHelper + public AbpCollapseButtonTagHelper(AbpCollapseButtonTagHelperService tagHelperService) + : base(tagHelperService) { - [HtmlAttributeName("abp-collapse-id")] - public string BodyId { get; set; } - - public AbpCollapseButtonTagHelper(AbpCollapseButtonTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseButtonTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseButtonTagHelperService.cs index fcc4ff413ef..49b356379a3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseButtonTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseButtonTagHelperService.cs @@ -2,54 +2,53 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse; + +public class AbpCollapseButtonTagHelperService : AbpTagHelperService { - public class AbpCollapseButtonTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - AddCommonAttributes(context, output); + AddCommonAttributes(context, output); - if (output.TagName == "abp-button" || output.TagName == "button") - { - AddButtonAttributes(context,output); - } - else if (output.TagName == "a") - { - AddLinkAttributes(context, output); - } + if (output.TagName == "abp-button" || output.TagName == "button") + { + AddButtonAttributes(context, output); } - - protected virtual void AddCommonAttributes(TagHelperContext context, TagHelperOutput output) + else if (output.TagName == "a") { - output.Attributes.Add("data-bs-toggle", "collapse"); - output.Attributes.Add("aria-expanded", "false"); - output.Attributes.Add("aria-controls", TagHelper.BodyId); + AddLinkAttributes(context, output); } + } - protected virtual void AddButtonAttributes(TagHelperContext context, TagHelperOutput output) - { - if (TagHelper.BodyId.Trim().Split(' ').Length > 1) - { - output.Attributes.Add("data-bs-target", ".multi-collapse"); - return; - } + protected virtual void AddCommonAttributes(TagHelperContext context, TagHelperOutput output) + { + output.Attributes.Add("data-bs-toggle", "collapse"); + output.Attributes.Add("aria-expanded", "false"); + output.Attributes.Add("aria-controls", TagHelper.BodyId); + } - output.Attributes.Add("data-bs-target", "#" + TagHelper.BodyId); + protected virtual void AddButtonAttributes(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.BodyId.Trim().Split(' ').Length > 1) + { + output.Attributes.Add("data-bs-target", ".multi-collapse"); + return; } - protected virtual void AddLinkAttributes(TagHelperContext context, TagHelperOutput output) - { - if (TagHelper.BodyId.Trim().Split(' ').Length > 1) - { - output.Attributes.Add("href", ".multi-collapse"); - return; - } + output.Attributes.Add("data-bs-target", "#" + TagHelper.BodyId); + } - output.Attributes.Add("href", "#" + TagHelper.BodyId); + protected virtual void AddLinkAttributes(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.BodyId.Trim().Split(' ').Length > 1) + { + output.Attributes.Add("href", ".multi-collapse"); + return; } + output.Attributes.Add("href", "#" + TagHelper.BodyId); } + } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelper.cs index de20c8743cb..ac87900307d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelper.cs @@ -1,29 +1,28 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownButtonTagHelper : AbpTagHelper { - public class AbpDropdownButtonTagHelper : AbpTagHelper - { - public string Text { get; set; } + public string Text { get; set; } - public AbpButtonSize Size { get; set; } = AbpButtonSize.Default; + public AbpButtonSize Size { get; set; } = AbpButtonSize.Default; - public DropdownStyle DropdownStyle { get; set; } = DropdownStyle.Single; + public DropdownStyle DropdownStyle { get; set; } = DropdownStyle.Single; - public AbpButtonType ButtonType { get; set; } = AbpButtonType.Default; + public AbpButtonType ButtonType { get; set; } = AbpButtonType.Default; - public string Icon { get; set; } + public string Icon { get; set; } - public FontIconType IconType { get; set; } = FontIconType.FontAwesome; + public FontIconType IconType { get; set; } = FontIconType.FontAwesome; - public bool? Link { get; set; } + public bool? Link { get; set; } - public bool? NavLink { get; set; } + public bool? NavLink { get; set; } - public AbpDropdownButtonTagHelper(AbpDropdownButtonTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpDropdownButtonTagHelper(AbpDropdownButtonTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs index faa8fe7d752..8a5f5df409d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs @@ -8,138 +8,137 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown -{ - public class AbpDropdownButtonTagHelperService : AbpTagHelperService - { +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; - private readonly HtmlEncoder _htmlEncoder; - private readonly IServiceProvider _serviceProvider; +public class AbpDropdownButtonTagHelperService : AbpTagHelperService +{ - public AbpDropdownButtonTagHelperService( - HtmlEncoder htmlEncoder, - IServiceProvider serviceProvider) - { - _htmlEncoder = htmlEncoder; - _serviceProvider = serviceProvider; - } + private readonly HtmlEncoder _htmlEncoder; + private readonly IServiceProvider _serviceProvider; - public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - var content = await output.GetChildContentAsync(); + public AbpDropdownButtonTagHelperService( + HtmlEncoder htmlEncoder, + IServiceProvider serviceProvider) + { + _htmlEncoder = htmlEncoder; + _serviceProvider = serviceProvider; + } - var buttonsAsHtml = await GetButtonsAsHtmlAsync(context, output, content); + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + var content = await output.GetChildContentAsync(); - output.PreElement.SetHtmlContent(buttonsAsHtml); + var buttonsAsHtml = await GetButtonsAsHtmlAsync(context, output, content); - output.TagName = "div"; - output.TagMode = TagMode.StartTagAndEndTag; - output.Content.SetContent(""); - output.Attributes.Clear(); - } + output.PreElement.SetHtmlContent(buttonsAsHtml); - protected virtual async Task GetButtonsAsHtmlAsync(TagHelperContext context, TagHelperOutput output, - TagHelperContent content) - { - var buttonBuilder = new StringBuilder(""); + output.TagName = "div"; + output.TagMode = TagMode.StartTagAndEndTag; + output.Content.SetContent(""); + output.Attributes.Clear(); + } - var mainButton = await GetMainButtonAsync(context, output, content); + protected virtual async Task GetButtonsAsHtmlAsync(TagHelperContext context, TagHelperOutput output, + TagHelperContent content) + { + var buttonBuilder = new StringBuilder(""); - buttonBuilder.AppendLine(mainButton); + var mainButton = await GetMainButtonAsync(context, output, content); - if (TagHelper.DropdownStyle == DropdownStyle.Split) - { - var splitButton = await GetSplitButtonAsync(context, output); + buttonBuilder.AppendLine(mainButton); - buttonBuilder.AppendLine(splitButton); - } + if (TagHelper.DropdownStyle == DropdownStyle.Split) + { + var splitButton = await GetSplitButtonAsync(context, output); - return buttonBuilder.ToString(); + buttonBuilder.AppendLine(splitButton); } - protected virtual async Task GetMainButtonAsync(TagHelperContext context, TagHelperOutput output, TagHelperContent content) - { - var abpButtonTagHelper = _serviceProvider.GetRequiredService(); - - abpButtonTagHelper.Icon = TagHelper.Icon; - abpButtonTagHelper.Text = TagHelper.Text; - abpButtonTagHelper.IconType = TagHelper.IconType; - abpButtonTagHelper.Size = TagHelper.Size; - abpButtonTagHelper.ButtonType = TagHelper.ButtonType; - var attributes = GetAttributesForMainButton(context, output); + return buttonBuilder.ToString(); + } - var buttonTag = await abpButtonTagHelper.ProcessAndGetOutputAsync(attributes, context, "button", TagMode.StartTagAndEndTag); + protected virtual async Task GetMainButtonAsync(TagHelperContext context, TagHelperOutput output, TagHelperContent content) + { + var abpButtonTagHelper = _serviceProvider.GetRequiredService(); - buttonTag.PreContent.SetHtmlContent(content); + abpButtonTagHelper.Icon = TagHelper.Icon; + abpButtonTagHelper.Text = TagHelper.Text; + abpButtonTagHelper.IconType = TagHelper.IconType; + abpButtonTagHelper.Size = TagHelper.Size; + abpButtonTagHelper.ButtonType = TagHelper.ButtonType; + var attributes = GetAttributesForMainButton(context, output); - if ((TagHelper.NavLink ?? false) || (TagHelper.Link ?? false)) - { - var linkTag = ConvertButtonToLink(buttonTag); - return linkTag.Render(_htmlEncoder); - } + var buttonTag = await abpButtonTagHelper.ProcessAndGetOutputAsync(attributes, context, "button", TagMode.StartTagAndEndTag); - return buttonTag.Render(_htmlEncoder); - } + buttonTag.PreContent.SetHtmlContent(content); - protected virtual async Task GetSplitButtonAsync(TagHelperContext context, TagHelperOutput output) + if ((TagHelper.NavLink ?? false) || (TagHelper.Link ?? false)) { - var abpButtonTagHelper = _serviceProvider.GetRequiredService(); + var linkTag = ConvertButtonToLink(buttonTag); + return linkTag.Render(_htmlEncoder); + } - abpButtonTagHelper.Size = TagHelper.Size; - abpButtonTagHelper.ButtonType = TagHelper.ButtonType; - var attributes = GetAttributesForSplitButton(context, output); + return buttonTag.Render(_htmlEncoder); + } - return await abpButtonTagHelper.RenderAsync(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag); - } + protected virtual async Task GetSplitButtonAsync(TagHelperContext context, TagHelperOutput output) + { + var abpButtonTagHelper = _serviceProvider.GetRequiredService(); - protected virtual TagHelperAttributeList GetAttributesForMainButton(TagHelperContext context, TagHelperOutput output) - { + abpButtonTagHelper.Size = TagHelper.Size; + abpButtonTagHelper.ButtonType = TagHelper.ButtonType; + var attributes = GetAttributesForSplitButton(context, output); - var attributes = new TagHelperAttributeList(); + return await abpButtonTagHelper.RenderAsync(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag); + } - foreach (var tagHelperAttribute in output.Attributes) - { - attributes.Add(tagHelperAttribute); - } + protected virtual TagHelperAttributeList GetAttributesForMainButton(TagHelperContext context, TagHelperOutput output) + { - if (TagHelper.DropdownStyle != DropdownStyle.Split) - { - attributes.AddClass("dropdown-toggle"); - attributes.Add("data-bs-toggle", "dropdown"); - attributes.Add("aria-haspopup", "true"); - attributes.Add("aria-expanded", "false"); - } + var attributes = new TagHelperAttributeList(); - return attributes; + foreach (var tagHelperAttribute in output.Attributes) + { + attributes.Add(tagHelperAttribute); } - protected virtual TagHelperAttributeList GetAttributesForSplitButton(TagHelperContext context, TagHelperOutput output) + if (TagHelper.DropdownStyle != DropdownStyle.Split) { - var attributes = new TagHelperAttributeList + attributes.AddClass("dropdown-toggle"); + attributes.Add("data-bs-toggle", "dropdown"); + attributes.Add("aria-haspopup", "true"); + attributes.Add("aria-expanded", "false"); + } + + return attributes; + } + + protected virtual TagHelperAttributeList GetAttributesForSplitButton(TagHelperContext context, TagHelperOutput output) + { + var attributes = new TagHelperAttributeList { {"data-bs-toggle", "dropdown"}, {"aria-haspopup", "true"}, {"aria-expanded", "false"}, }; - attributes.AddClass("dropdown-toggle"); - attributes.AddClass("dropdown-toggle-split"); + attributes.AddClass("dropdown-toggle"); + attributes.AddClass("dropdown-toggle-split"); - return attributes; - } + return attributes; + } - protected virtual TagHelperOutput ConvertButtonToLink(TagHelperOutput buttonTag) - { - buttonTag.TagName = "a"; - buttonTag.Attributes.RemoveAll("type"); - buttonTag.Attributes.Add("roles", "button"); - buttonTag.Attributes.Add("href", "#"); + protected virtual TagHelperOutput ConvertButtonToLink(TagHelperOutput buttonTag) + { + buttonTag.TagName = "a"; + buttonTag.Attributes.RemoveAll("type"); + buttonTag.Attributes.Add("roles", "button"); + buttonTag.Attributes.Add("href", "#"); - if (TagHelper.NavLink??false) - { - buttonTag.Attributes.AddClass("nav-link"); - } - return buttonTag; + if (TagHelper.NavLink ?? false) + { + buttonTag.Attributes.AddClass("nav-link"); } + return buttonTag; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownDividerTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownDividerTagHelper.cs index 691d7c23a56..f87abb78f7b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownDividerTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownDividerTagHelper.cs @@ -1,11 +1,10 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownDividerTagHelper : AbpTagHelper { - public class AbpDropdownDividerTagHelper : AbpTagHelper + public AbpDropdownDividerTagHelper(AbpDropdownDividerTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpDropdownDividerTagHelper(AbpDropdownDividerTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownDividerTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownDividerTagHelperService.cs index 4e420f538b8..7ff04e4f1dc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownDividerTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownDividerTagHelperService.cs @@ -1,15 +1,14 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownDividerTagHelperService : AbpTagHelperService { - public class AbpDropdownDividerTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.Attributes.AddClass("dropdown-divider"); - output.TagMode = TagMode.StartTagAndEndTag; - } + output.TagName = "div"; + output.Attributes.AddClass("dropdown-divider"); + output.TagMode = TagMode.StartTagAndEndTag; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownHeaderTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownHeaderTagHelper.cs index cc2a910a07a..da0ee56f40d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownHeaderTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownHeaderTagHelper.cs @@ -1,11 +1,10 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownHeaderTagHelper : AbpTagHelper { - public class AbpDropdownHeaderTagHelper : AbpTagHelper + public AbpDropdownHeaderTagHelper(AbpDropdownHeaderTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpDropdownHeaderTagHelper(AbpDropdownHeaderTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownHeaderTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownHeaderTagHelperService.cs index 73157f45cc2..aed611f6e0a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownHeaderTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownHeaderTagHelperService.cs @@ -1,15 +1,14 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownHeaderTagHelperService : AbpTagHelperService { - public class AbpDropdownHeaderTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "h6"; - output.Attributes.AddClass("dropdown-header"); - output.TagMode = TagMode.StartTagAndEndTag; - } + output.TagName = "h6"; + output.Attributes.AddClass("dropdown-header"); + output.TagMode = TagMode.StartTagAndEndTag; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTagHelper.cs index c017986271f..a2a84038638 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTagHelper.cs @@ -1,15 +1,14 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownItemTagHelper : AbpTagHelper { - public class AbpDropdownItemTagHelper : AbpTagHelper - { - public bool? Active { get; set; } + public bool? Active { get; set; } - public bool? Disabled { get; set; } + public bool? Disabled { get; set; } - public AbpDropdownItemTagHelper(AbpDropdownItemTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpDropdownItemTagHelper(AbpDropdownItemTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTagHelperService.cs index 5f74b7a3033..29815c5a4e1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTagHelperService.cs @@ -1,34 +1,33 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownItemTagHelperService : AbpTagHelperService { - public class AbpDropdownItemTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "a"; - output.Attributes.AddClass("dropdown-item"); - output.TagMode = TagMode.StartTagAndEndTag; + output.TagName = "a"; + output.Attributes.AddClass("dropdown-item"); + output.TagMode = TagMode.StartTagAndEndTag; - SetActiveClassIfActive(context,output); - SetDisabledClassIfDisabled(context,output); - } + SetActiveClassIfActive(context, output); + SetDisabledClassIfDisabled(context, output); + } - protected virtual void SetActiveClassIfActive(TagHelperContext context, TagHelperOutput output) + protected virtual void SetActiveClassIfActive(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.Active ?? false) { - if (TagHelper.Active??false) - { - output.Attributes.AddClass("active"); - } + output.Attributes.AddClass("active"); } + } - protected virtual void SetDisabledClassIfDisabled(TagHelperContext context, TagHelperOutput output) + protected virtual void SetDisabledClassIfDisabled(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.Disabled ?? false) { - if (TagHelper.Disabled??false) - { - output.Attributes.AddClass("disabled"); - } + output.Attributes.AddClass("disabled"); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTextTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTextTagHelper.cs index 4c5e82fac7e..b231aa63ef6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTextTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTextTagHelper.cs @@ -1,11 +1,10 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownItemTextTagHelper : AbpTagHelper { - public class AbpDropdownItemTextTagHelper : AbpTagHelper + public AbpDropdownItemTextTagHelper(AbpDropdownItemTextTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpDropdownItemTextTagHelper(AbpDropdownItemTextTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTextTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTextTagHelperService.cs index 8cd84eade61..51b8af6250e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTextTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownItemTextTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownItemTextTagHelperService : AbpTagHelperService { - public class AbpDropdownItemTextTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass("dropdown-item-text"); - output.TagName = "span"; - } + output.Attributes.AddClass("dropdown-item-text"); + output.TagName = "span"; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownMenuTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownMenuTagHelper.cs index 04523033bcb..1744d1922f6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownMenuTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownMenuTagHelper.cs @@ -1,13 +1,12 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownMenuTagHelper : AbpTagHelper { - public class AbpDropdownMenuTagHelper : AbpTagHelper - { - public DropdownAlign Align { get; set; } = DropdownAlign.Start; + public DropdownAlign Align { get; set; } = DropdownAlign.Start; - public AbpDropdownMenuTagHelper(AbpDropdownMenuTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpDropdownMenuTagHelper(AbpDropdownMenuTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownMenuTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownMenuTagHelperService.cs index 80c4d31c873..1a9a1b6c55c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownMenuTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownMenuTagHelperService.cs @@ -1,29 +1,28 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownMenuTagHelperService : AbpTagHelperService { - public class AbpDropdownMenuTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.Attributes.AddClass("dropdown-menu"); - output.TagMode = TagMode.StartTagAndEndTag; + output.TagName = "div"; + output.Attributes.AddClass("dropdown-menu"); + output.TagMode = TagMode.StartTagAndEndTag; - SetAlign(context, output); - } + SetAlign(context, output); + } - protected virtual void SetAlign(TagHelperContext context, TagHelperOutput output) + protected virtual void SetAlign(TagHelperContext context, TagHelperOutput output) + { + switch (TagHelper.Align) { - switch (TagHelper.Align) - { - case DropdownAlign.End: - output.Attributes.AddClass("dropdown-menu-end"); - return; - case DropdownAlign.Start: - return; - } + case DropdownAlign.End: + output.Attributes.AddClass("dropdown-menu-end"); + return; + case DropdownAlign.Start: + return; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownTagHelper.cs index 5daad8a9b7a..2cd06cff740 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownTagHelper.cs @@ -1,13 +1,12 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownTagHelper : AbpTagHelper { - public class AbpDropdownTagHelper : AbpTagHelper - { - public DropdownDirection Direction { get; set; } = DropdownDirection.Down; + public DropdownDirection Direction { get; set; } = DropdownDirection.Down; - public AbpDropdownTagHelper(AbpDropdownTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpDropdownTagHelper(AbpDropdownTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownTagHelperService.cs index 8f37fca5ee0..581239a4b6c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownTagHelperService.cs @@ -1,37 +1,36 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public class AbpDropdownTagHelperService : AbpTagHelperService { - public class AbpDropdownTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.Attributes.AddClass("dropdown"); - output.Attributes.AddClass("btn-group"); + output.TagName = "div"; + output.Attributes.AddClass("dropdown"); + output.Attributes.AddClass("btn-group"); - SetDirection(context, output); + SetDirection(context, output); - output.TagMode = TagMode.StartTagAndEndTag; - } + output.TagMode = TagMode.StartTagAndEndTag; + } - protected virtual void SetDirection(TagHelperContext context, TagHelperOutput output) + protected virtual void SetDirection(TagHelperContext context, TagHelperOutput output) + { + switch (TagHelper.Direction) { - switch (TagHelper.Direction) - { - case DropdownDirection.Down: - return; - case DropdownDirection.Up: - output.Attributes.AddClass("dropup"); - return; - case DropdownDirection.Right: - output.Attributes.AddClass("dropright"); - return; - case DropdownDirection.Left: - output.Attributes.AddClass("dropleft"); - return; - } + case DropdownDirection.Down: + return; + case DropdownDirection.Up: + output.Attributes.AddClass("dropup"); + return; + case DropdownDirection.Right: + output.Attributes.AddClass("dropright"); + return; + case DropdownDirection.Left: + output.Attributes.AddClass("dropleft"); + return; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownAlign.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownAlign.cs index a15cf821ea4..331a0c3e5f0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownAlign.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownAlign.cs @@ -1,8 +1,7 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public enum DropdownAlign { - public enum DropdownAlign - { - Start, - End - } -} \ No newline at end of file + Start, + End +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownDirection.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownDirection.cs index f7c90ae58c6..e67025e6140 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownDirection.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownDirection.cs @@ -1,10 +1,9 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public enum DropdownDirection { - public enum DropdownDirection - { - Down, - Up, - Right, - Left - } -} \ No newline at end of file + Down, + Up, + Right, + Left +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownStyle.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownStyle.cs index 67d02ace229..6ea9256748a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownStyle.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/DropdownStyle.cs @@ -1,8 +1,7 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown; + +public enum DropdownStyle { - public enum DropdownStyle - { - Single, - Split - } -} \ No newline at end of file + Single, + Split +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/ModelExplorerExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/ModelExplorerExtensions.cs index b6bedac11bf..eced70b75e1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/ModelExplorerExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/ModelExplorerExtensions.cs @@ -3,18 +3,17 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; + +public static class ModelExplorerExtensions { - public static class ModelExplorerExtensions + public static T GetAttribute(this ModelExplorer property) where T : Attribute { - public static T GetAttribute(this ModelExplorer property) where T : Attribute - { - return property?.Metadata?.ContainerType?.GetTypeInfo()?.GetProperty(property.Metadata.PropertyName)?.GetCustomAttribute(); - } + return property?.Metadata?.ContainerType?.GetTypeInfo()?.GetProperty(property.Metadata.PropertyName)?.GetCustomAttribute(); + } - public static int GetDisplayOrder(this ModelExplorer explorer) - { - return GetAttribute(explorer)?.Number ?? DisplayOrder.Default; - } + public static int GetDisplayOrder(this ModelExplorer explorer) + { + return GetAttribute(explorer)?.Number ?? DisplayOrder.Default; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperAttributeExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperAttributeExtensions.cs index ef581529a6b..09d0513fbd3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperAttributeExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperAttributeExtensions.cs @@ -1,25 +1,24 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using System.Collections.Generic; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; + +public static class TagHelperAttributeExtensions { - public static class TagHelperAttributeExtensions + public static string ToHtmlAttributeAsString(this TagHelperAttribute attribute) { - public static string ToHtmlAttributeAsString(this TagHelperAttribute attribute) - { - return attribute.Name + "=\"" + attribute.Value + "\""; - } - - public static string ToHtmlAttributesAsString(this List attributes) - { - var attributesAsString = ""; + return attribute.Name + "=\"" + attribute.Value + "\""; + } - foreach (var attribute in attributes) - { - attributesAsString += attribute.ToHtmlAttributeAsString() + " "; - } + public static string ToHtmlAttributesAsString(this List attributes) + { + var attributesAsString = ""; - return attributesAsString; + foreach (var attribute in attributes) + { + attributesAsString += attribute.ToHtmlAttributeAsString() + " "; } + + return attributesAsString; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperContextExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperContextExtensions.cs index c2b3e411925..47ab8827e75 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperContextExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperContextExtensions.cs @@ -3,18 +3,17 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; + +public static class TagHelperContextExtensions { - public static class TagHelperContextExtensions + public static T GetValue(this TagHelperContext context, string key) { - public static T GetValue(this TagHelperContext context, string key) + if (!context.Items.ContainsKey(key)) { - if (!context.Items.ContainsKey(key)) - { - return default(T); - } - - return (T)context.Items[key]; + return default(T); } + + return (T)context.Items[key]; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs index 761b72ec99d..227c8240027 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs @@ -3,43 +3,42 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using System.Text.Encodings.Web; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; + +public static class TagHelperExtensions { - public static class TagHelperExtensions + public static async Task ProcessAndGetOutputAsync( + this TagHelper tagHelper, + TagHelperAttributeList attributeList, + TagHelperContext context, + string tagName = "div", + TagMode tagMode = TagMode.SelfClosing) { - public static async Task ProcessAndGetOutputAsync( - this TagHelper tagHelper, - TagHelperAttributeList attributeList, - TagHelperContext context, - string tagName = "div", - TagMode tagMode = TagMode.SelfClosing) - { - var innerOutput = new TagHelperOutput( - tagName, - attributeList, - (useCachedResult, encoder) => Task.Run(() => new DefaultTagHelperContent())) - { - TagMode = tagMode - }; - - var innerContext = new TagHelperContext( - attributeList, - context.Items, - Guid.NewGuid().ToString() - ); - - tagHelper.Init(context); - - await tagHelper.ProcessAsync(innerContext, innerOutput); - - return innerOutput; - } - - public static async Task RenderAsync(this TagHelper tagHelper, TagHelperAttributeList attributeList, TagHelperContext context, HtmlEncoder htmlEncoder, string tagName = "div", TagMode tagMode = TagMode.SelfClosing) + var innerOutput = new TagHelperOutput( + tagName, + attributeList, + (useCachedResult, encoder) => Task.Run(() => new DefaultTagHelperContent())) { - var innerOutput = await tagHelper.ProcessAndGetOutputAsync(attributeList, context, tagName, tagMode); + TagMode = tagMode + }; + + var innerContext = new TagHelperContext( + attributeList, + context.Items, + Guid.NewGuid().ToString() + ); + + tagHelper.Init(context); + + await tagHelper.ProcessAsync(innerContext, innerOutput); + + return innerOutput; + } + + public static async Task RenderAsync(this TagHelper tagHelper, TagHelperAttributeList attributeList, TagHelperContext context, HtmlEncoder htmlEncoder, string tagName = "div", TagMode tagMode = TagMode.SelfClosing) + { + var innerOutput = await tagHelper.ProcessAndGetOutputAsync(attributeList, context, tagName, tagMode); - return innerOutput.Render(htmlEncoder); - } + return innerOutput.Render(htmlEncoder); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperOutputExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperOutputExtensions.cs index 0cc9bae6e2b..40ca23a8f1d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperOutputExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperOutputExtensions.cs @@ -2,17 +2,16 @@ using System.IO; using System.Text.Encodings.Web; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; + +public static class TagHelperOutputExtensions { - public static class TagHelperOutputExtensions + public static string Render(this TagHelperOutput output, HtmlEncoder htmlEncoder) { - public static string Render(this TagHelperOutput output, HtmlEncoder htmlEncoder) + using (var writer = new StringWriter()) { - using (var writer = new StringWriter()) - { - output.WriteTo(writer, htmlEncoder); - return writer.ToString(); - } + output.WriteTo(writer, htmlEncoder); + return writer.ToString(); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureCaptionTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureCaptionTagHelper.cs index 9bac7ca93a4..ea35a52fa4e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureCaptionTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureCaptionTagHelper.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure; + +[HtmlTargetElement("abp-figcaption")] +public class AbpFigureCaptionTagHelper : AbpTagHelper { - [HtmlTargetElement("abp-figcaption")] - public class AbpFigureCaptionTagHelper : AbpTagHelper + public AbpFigureCaptionTagHelper(AbpFigureCaptionTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpFigureCaptionTagHelper(AbpFigureCaptionTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureCaptionTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureCaptionTagHelperService.cs index f14a4a18fd1..e2df91691bf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureCaptionTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureCaptionTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure; + +public class AbpFigureCaptionTagHelperService : AbpTagHelperService { - public class AbpFigureCaptionTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "figcaption"; - output.Attributes.AddClass("figure-caption"); - } + output.TagName = "figcaption"; + output.Attributes.AddClass("figure-caption"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureImageTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureImageTagHelper.cs index 4b395508adc..7229a406562 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureImageTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureImageTagHelper.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure; + +[HtmlTargetElement("abp-image", ParentTag = "abp-figure")] +public class AbpFigureImageTagHelper : AbpTagHelper { - [HtmlTargetElement("abp-image", ParentTag = "abp-figure")] - public class AbpFigureImageTagHelper : AbpTagHelper + public AbpFigureImageTagHelper(AbpFigureImageTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpFigureImageTagHelper(AbpFigureImageTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureImageTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureImageTagHelperService.cs index 51237fe2975..f79eb9b9e1c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureImageTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureImageTagHelperService.cs @@ -1,13 +1,12 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure; + +public class AbpFigureImageTagHelperService : AbpTagHelperService { - public class AbpFigureImageTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.AddClass("figure-img"); - } + output.Attributes.AddClass("figure-img"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureTagHelper.cs index 88b99b61386..1b9b8116e77 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureTagHelper.cs @@ -1,11 +1,10 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure; + +public class AbpFigureTagHelper : AbpTagHelper { - public class AbpFigureTagHelper : AbpTagHelper + public AbpFigureTagHelper(AbpFigureTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpFigureTagHelper(AbpFigureTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureTagHelperService.cs index 7fe094f94ef..6c75c299b50 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Figure/AbpFigureTagHelperService.cs @@ -1,14 +1,13 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Figure; + +public class AbpFigureTagHelperService : AbpTagHelperService { - public class AbpFigureTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "figure"; - output.Attributes.AddClass("figure"); - } + output.TagName = "figure"; + output.Attributes.AddClass("figure"); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/FontIconType.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/FontIconType.cs index 81debc06b09..ebc23d68ff4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/FontIconType.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/FontIconType.cs @@ -1,8 +1,7 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers; + +public enum FontIconType { - public enum FontIconType - { - FontAwesome, - Other - } -} \ No newline at end of file + FontAwesome, + Other +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelper.cs index d7107931513..da4a567b5d9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelper.cs @@ -4,63 +4,62 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; + +[HtmlTargetElement("abp-dynamic-form", TagStructure = TagStructure.NormalOrSelfClosing)] +public class AbpDynamicFormTagHelper : AbpTagHelper { - [HtmlTargetElement("abp-dynamic-form", TagStructure = TagStructure.NormalOrSelfClosing)] - public class AbpDynamicFormTagHelper : AbpTagHelper - { - [HtmlAttributeName("abp-model")] - public ModelExpression Model { get; set; } + [HtmlAttributeName("abp-model")] + public ModelExpression Model { get; set; } - public bool? SubmitButton { get; set; } + public bool? SubmitButton { get; set; } - public bool? RequiredSymbols { get; set; } = true; + public bool? RequiredSymbols { get; set; } = true; -#region MvcFormTagHelperAttiributes + #region MvcFormTagHelperAttiributes - private const string ActionAttributeName = "asp-action"; - private const string AreaAttributeName = "asp-area"; - private const string PageAttributeName = "asp-page"; - private const string PageHandlerAttributeName = "asp-page-handler"; - private const string FragmentAttributeName = "asp-fragment"; - private const string ControllerAttributeName = "asp-controller"; - private const string RouteAttributeName = "asp-route"; - private const string RouteValuesDictionaryName = "asp-all-route-data"; - private const string RouteValuesPrefix = "asp-route-"; + private const string ActionAttributeName = "asp-action"; + private const string AreaAttributeName = "asp-area"; + private const string PageAttributeName = "asp-page"; + private const string PageHandlerAttributeName = "asp-page-handler"; + private const string FragmentAttributeName = "asp-fragment"; + private const string ControllerAttributeName = "asp-controller"; + private const string RouteAttributeName = "asp-route"; + private const string RouteValuesDictionaryName = "asp-all-route-data"; + private const string RouteValuesPrefix = "asp-route-"; - [HtmlAttributeName(ActionAttributeName)] - public string Action { get; set; } + [HtmlAttributeName(ActionAttributeName)] + public string Action { get; set; } - [HtmlAttributeName(ControllerAttributeName)] - public string Controller { get; set; } + [HtmlAttributeName(ControllerAttributeName)] + public string Controller { get; set; } - [HtmlAttributeName(AreaAttributeName)] - public string Area { get; set; } + [HtmlAttributeName(AreaAttributeName)] + public string Area { get; set; } - [HtmlAttributeName(PageAttributeName)] - public string Page { get; set; } + [HtmlAttributeName(PageAttributeName)] + public string Page { get; set; } - [HtmlAttributeName(PageHandlerAttributeName)] - public string PageHandler { get; set; } + [HtmlAttributeName(PageHandlerAttributeName)] + public string PageHandler { get; set; } - [HtmlAttributeName(FragmentAttributeName)] - public string Fragment { get; set; } + [HtmlAttributeName(FragmentAttributeName)] + public string Fragment { get; set; } - [HtmlAttributeName(RouteAttributeName)] - public string Route { get; set; } + [HtmlAttributeName(RouteAttributeName)] + public string Route { get; set; } - [EditorBrowsable(EditorBrowsableState.Never)] - public string Method { get; set; } + [EditorBrowsable(EditorBrowsableState.Never)] + public string Method { get; set; } - [HtmlAttributeName(RouteValuesDictionaryName, DictionaryAttributePrefix = RouteValuesPrefix)] - public IDictionary RouteValues { get; set; } + [HtmlAttributeName(RouteValuesDictionaryName, DictionaryAttributePrefix = RouteValuesPrefix)] + public IDictionary RouteValues { get; set; } -#endregion + #endregion - public AbpDynamicFormTagHelper(AbpDynamicFormTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpDynamicFormTagHelper(AbpDynamicFormTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs index 410a3d1454e..38f55ca04e6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs @@ -15,298 +15,297 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; + +public class AbpDynamicFormTagHelperService : AbpTagHelperService { - public class AbpDynamicFormTagHelperService : AbpTagHelperService + private readonly HtmlEncoder _htmlEncoder; + private readonly IHtmlGenerator _htmlGenerator; + private readonly IServiceProvider _serviceProvider; + private readonly IStringLocalizer _localizer; + + public AbpDynamicFormTagHelperService( + HtmlEncoder htmlEncoder, + IHtmlGenerator htmlGenerator, + IServiceProvider serviceProvider, + IStringLocalizer localizer) { - private readonly HtmlEncoder _htmlEncoder; - private readonly IHtmlGenerator _htmlGenerator; - private readonly IServiceProvider _serviceProvider; - private readonly IStringLocalizer _localizer; - - public AbpDynamicFormTagHelperService( - HtmlEncoder htmlEncoder, - IHtmlGenerator htmlGenerator, - IServiceProvider serviceProvider, - IStringLocalizer localizer) - { - _htmlEncoder = htmlEncoder; - _htmlGenerator = htmlGenerator; - _serviceProvider = serviceProvider; - _localizer = localizer; - } + _htmlEncoder = htmlEncoder; + _htmlGenerator = htmlGenerator; + _serviceProvider = serviceProvider; + _localizer = localizer; + } - public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) - { - var list = InitilizeFormGroupContentsContext(context, output); + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + var list = InitilizeFormGroupContentsContext(context, output); - NormalizeTagMode(context, output); + NormalizeTagMode(context, output); - var childContent = await output.GetChildContentAsync(); + var childContent = await output.GetChildContentAsync(); - await ConvertToMvcForm(context, output); + await ConvertToMvcForm(context, output); - await ProcessFieldsAsync(context, output); + await ProcessFieldsAsync(context, output); - RemoveFormGroupItemsNotInModel(context, output, list); + RemoveFormGroupItemsNotInModel(context, output, list); - SetContent(context, output, list, childContent); + SetContent(context, output, list, childContent); - SetFormAttributes(context, output); + SetFormAttributes(context, output); - await SetSubmitButton(context, output); - } + await SetSubmitButton(context, output); + } - protected virtual async Task ConvertToMvcForm(TagHelperContext context, TagHelperOutput output) + protected virtual async Task ConvertToMvcForm(TagHelperContext context, TagHelperOutput output) + { + var formTagHelper = new FormTagHelper(_htmlGenerator) { - var formTagHelper = new FormTagHelper(_htmlGenerator) - { - Action = TagHelper.Action, - Controller = TagHelper.Controller, - Area = TagHelper.Area, - Page = TagHelper.Page, - PageHandler = TagHelper.PageHandler, - Antiforgery = true, - Fragment = TagHelper.Fragment, - Route = TagHelper.Route, - Method = TagHelper.Method, - RouteValues = TagHelper.RouteValues, - ViewContext = TagHelper.ViewContext - }; - - var formTagOutput = await formTagHelper.ProcessAndGetOutputAsync(output.Attributes, context, "form", TagMode.StartTagAndEndTag); - - await formTagOutput.GetChildContentAsync(); - - output.PostContent.AppendHtml(formTagOutput.PostContent); - output.PreContent.AppendHtml(formTagOutput.PreContent); - } + Action = TagHelper.Action, + Controller = TagHelper.Controller, + Area = TagHelper.Area, + Page = TagHelper.Page, + PageHandler = TagHelper.PageHandler, + Antiforgery = true, + Fragment = TagHelper.Fragment, + Route = TagHelper.Route, + Method = TagHelper.Method, + RouteValues = TagHelper.RouteValues, + ViewContext = TagHelper.ViewContext + }; + + var formTagOutput = await formTagHelper.ProcessAndGetOutputAsync(output.Attributes, context, "form", TagMode.StartTagAndEndTag); + + await formTagOutput.GetChildContentAsync(); + + output.PostContent.AppendHtml(formTagOutput.PostContent); + output.PreContent.AppendHtml(formTagOutput.PreContent); + } + + protected virtual void NormalizeTagMode(TagHelperContext context, TagHelperOutput output) + { + output.TagMode = TagMode.StartTagAndEndTag; + output.TagName = "form"; + } + + protected virtual void SetFormAttributes(TagHelperContext context, TagHelperOutput output) + { + output.Attributes.AddIfNotContains("method", "post"); + } + + protected virtual void SetContent(TagHelperContext context, TagHelperOutput output, List items, TagHelperContent childContent) + { + var contentBuilder = new StringBuilder(""); - protected virtual void NormalizeTagMode(TagHelperContext context, TagHelperOutput output) + foreach (var item in items.OrderBy(o => o.Order)) { - output.TagMode = TagMode.StartTagAndEndTag; - output.TagName = "form"; + contentBuilder.AppendLine(item.HtmlContent); } - protected virtual void SetFormAttributes(TagHelperContext context, TagHelperOutput output) + var content = childContent.GetContent(); + if (content.Contains(AbpFormContentPlaceHolder)) { - output.Attributes.AddIfNotContains("method", "post"); + content = content.Replace(AbpFormContentPlaceHolder, contentBuilder.ToString()); } - - protected virtual void SetContent(TagHelperContext context, TagHelperOutput output, List items, TagHelperContent childContent) + else { - var contentBuilder = new StringBuilder(""); - - foreach (var item in items.OrderBy(o => o.Order)) - { - contentBuilder.AppendLine(item.HtmlContent); - } + content = contentBuilder + content; + } - var content = childContent.GetContent(); - if (content.Contains(AbpFormContentPlaceHolder)) - { - content = content.Replace(AbpFormContentPlaceHolder, contentBuilder.ToString()); - } - else - { - content = contentBuilder + content; - } + output.Content.SetHtmlContent(content); + } - output.Content.SetHtmlContent(content); + protected virtual async Task SetSubmitButton(TagHelperContext context, TagHelperOutput output) + { + if (!TagHelper.SubmitButton ?? true) + { + return; } - protected virtual async Task SetSubmitButton(TagHelperContext context, TagHelperOutput output) - { - if (!TagHelper.SubmitButton ?? true) - { - return; - } + var buttonHtml = await ProcessSubmitButtonAndGetContentAsync(context, output); - var buttonHtml = await ProcessSubmitButtonAndGetContentAsync(context, output); + output.PostContent.AppendHtml(buttonHtml); + } - output.PostContent.AppendHtml(buttonHtml); - } + protected virtual List InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output) + { + var items = new List(); + context.Items[FormGroupContents] = items; + return items; + } - protected virtual List InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output) - { - var items = new List(); - context.Items[FormGroupContents] = items; - return items; - } + protected virtual async Task ProcessFieldsAsync(TagHelperContext context, TagHelperOutput output) + { + var models = GetModels(context, output); - protected virtual async Task ProcessFieldsAsync(TagHelperContext context, TagHelperOutput output) + foreach (var model in models) { - var models = GetModels(context, output); - - foreach (var model in models) + if (IsSelectGroup(context, model)) { - if (IsSelectGroup(context, model)) - { - await ProcessSelectGroupAsync(context, output, model); - } - else - { - await ProcessInputGroupAsync(context, output, model); - } + await ProcessSelectGroupAsync(context, output, model); + } + else + { + await ProcessInputGroupAsync(context, output, model); } } + } - protected virtual void RemoveFormGroupItemsNotInModel(TagHelperContext context, TagHelperOutput output, List items) - { - var models = GetModels(context, output); + protected virtual void RemoveFormGroupItemsNotInModel(TagHelperContext context, TagHelperOutput output, List items) + { + var models = GetModels(context, output); - items.RemoveAll(x => models.All(m => !m.Name.Equals(x.PropertyName, StringComparison.InvariantCultureIgnoreCase))); - } + items.RemoveAll(x => models.All(m => !m.Name.Equals(x.PropertyName, StringComparison.InvariantCultureIgnoreCase))); + } - protected virtual async Task ProcessSelectGroupAsync(TagHelperContext context, TagHelperOutput output, ModelExpression model) - { - var abpSelectTagHelper = GetSelectGroupTagHelper(context, output, model); + protected virtual async Task ProcessSelectGroupAsync(TagHelperContext context, TagHelperOutput output, ModelExpression model) + { + var abpSelectTagHelper = GetSelectGroupTagHelper(context, output, model); - await abpSelectTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag); - } + await abpSelectTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag); + } - protected virtual AbpTagHelper GetSelectGroupTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model) - { - return IsRadioGroup(model.ModelExplorer) ? - GetAbpRadioInputTagHelper(model) : - GetSelectTagHelper(model); - } + protected virtual AbpTagHelper GetSelectGroupTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model) + { + return IsRadioGroup(model.ModelExplorer) ? + GetAbpRadioInputTagHelper(model) : + GetSelectTagHelper(model); + } - protected virtual AbpTagHelper GetSelectTagHelper(ModelExpression model) - { - var abpSelectTagHelper = _serviceProvider.GetRequiredService(); - abpSelectTagHelper.AspFor = model; - abpSelectTagHelper.AspItems = null; - abpSelectTagHelper.ViewContext = TagHelper.ViewContext; - return abpSelectTagHelper; - } + protected virtual AbpTagHelper GetSelectTagHelper(ModelExpression model) + { + var abpSelectTagHelper = _serviceProvider.GetRequiredService(); + abpSelectTagHelper.AspFor = model; + abpSelectTagHelper.AspItems = null; + abpSelectTagHelper.ViewContext = TagHelper.ViewContext; + return abpSelectTagHelper; + } - protected virtual AbpTagHelper GetAbpRadioInputTagHelper(ModelExpression model) - { - var radioButtonAttribute = model.ModelExplorer.GetAttribute(); - var abpRadioInputTagHelper = _serviceProvider.GetRequiredService(); - abpRadioInputTagHelper.AspFor = model; - abpRadioInputTagHelper.AspItems = null; - abpRadioInputTagHelper.Inline = radioButtonAttribute.Inline; - abpRadioInputTagHelper.Disabled = radioButtonAttribute.Disabled; - abpRadioInputTagHelper.ViewContext = TagHelper.ViewContext; - return abpRadioInputTagHelper; - } + protected virtual AbpTagHelper GetAbpRadioInputTagHelper(ModelExpression model) + { + var radioButtonAttribute = model.ModelExplorer.GetAttribute(); + var abpRadioInputTagHelper = _serviceProvider.GetRequiredService(); + abpRadioInputTagHelper.AspFor = model; + abpRadioInputTagHelper.AspItems = null; + abpRadioInputTagHelper.Inline = radioButtonAttribute.Inline; + abpRadioInputTagHelper.Disabled = radioButtonAttribute.Disabled; + abpRadioInputTagHelper.ViewContext = TagHelper.ViewContext; + return abpRadioInputTagHelper; + } - protected virtual async Task ProcessSubmitButtonAndGetContentAsync(TagHelperContext context, TagHelperOutput output) - { - var abpButtonTagHelper = _serviceProvider.GetRequiredService(); - var attributes = new TagHelperAttributeList { new TagHelperAttribute("type", "submit") }; - abpButtonTagHelper.Text = _localizer["Submit"]; - abpButtonTagHelper.ButtonType = AbpButtonType.Primary; + protected virtual async Task ProcessSubmitButtonAndGetContentAsync(TagHelperContext context, TagHelperOutput output) + { + var abpButtonTagHelper = _serviceProvider.GetRequiredService(); + var attributes = new TagHelperAttributeList { new TagHelperAttribute("type", "submit") }; + abpButtonTagHelper.Text = _localizer["Submit"]; + abpButtonTagHelper.ButtonType = AbpButtonType.Primary; - return await abpButtonTagHelper.RenderAsync(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag); - } + return await abpButtonTagHelper.RenderAsync(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag); + } - protected virtual async Task ProcessInputGroupAsync(TagHelperContext context, TagHelperOutput output, ModelExpression model) - { - var abpInputTagHelper = _serviceProvider.GetRequiredService(); - abpInputTagHelper.AspFor = model; - abpInputTagHelper.ViewContext = TagHelper.ViewContext; - abpInputTagHelper.DisplayRequiredSymbol = TagHelper.RequiredSymbols ?? true; + protected virtual async Task ProcessInputGroupAsync(TagHelperContext context, TagHelperOutput output, ModelExpression model) + { + var abpInputTagHelper = _serviceProvider.GetRequiredService(); + abpInputTagHelper.AspFor = model; + abpInputTagHelper.ViewContext = TagHelper.ViewContext; + abpInputTagHelper.DisplayRequiredSymbol = TagHelper.RequiredSymbols ?? true; - await abpInputTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag); - } + await abpInputTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag); + } - protected virtual List GetModels(TagHelperContext context, TagHelperOutput output) + protected virtual List GetModels(TagHelperContext context, TagHelperOutput output) + { + return TagHelper.Model.ModelExplorer.Properties.Aggregate(new List(), ExploreModelsRecursively); + } + + protected virtual List ExploreModelsRecursively(List list, ModelExplorer model) + { + if (model.GetAttribute() != null) { - return TagHelper.Model.ModelExplorer.Properties.Aggregate(new List(), ExploreModelsRecursively); + return list; } - protected virtual List ExploreModelsRecursively(List list, ModelExplorer model) + if (IsCsharpClassOrPrimitive(model.ModelType) || IsListOfCsharpClassOrPrimitive(model.ModelType)) { - if (model.GetAttribute() != null) - { - return list; - } - - if (IsCsharpClassOrPrimitive(model.ModelType) || IsListOfCsharpClassOrPrimitive(model.ModelType)) - { - list.Add(ModelExplorerToModelExpressionConverter(model)); - - return list; - } - - if (IsListOfSelectItem(model.ModelType)) - { - return list; - } + list.Add(ModelExplorerToModelExpressionConverter(model)); - return model.Properties.Aggregate(list, ExploreModelsRecursively); + return list; } - protected virtual ModelExpression ModelExplorerToModelExpressionConverter(ModelExplorer explorer) + if (IsListOfSelectItem(model.ModelType)) { - var temp = explorer; - var propertyName = explorer.Metadata.PropertyName; - - while (temp?.Container?.Metadata?.PropertyName != null) - { - temp = temp.Container; - propertyName = temp.Metadata.PropertyName + "." + propertyName; - } - - return new ModelExpression(propertyName, explorer); + return list; } - protected virtual bool IsListOfCsharpClassOrPrimitive(Type type) - { - var genericType = type.GenericTypeArguments.FirstOrDefault(); + return model.Properties.Aggregate(list, ExploreModelsRecursively); + } - if (genericType == null || !IsCsharpClassOrPrimitive(genericType)) - { - return false; - } + protected virtual ModelExpression ModelExplorerToModelExpressionConverter(ModelExplorer explorer) + { + var temp = explorer; + var propertyName = explorer.Metadata.PropertyName; - return type.ToString().StartsWith("System.Collections.Generic.IEnumerable`") || type.ToString().StartsWith("System.Collections.Generic.List`"); + while (temp?.Container?.Metadata?.PropertyName != null) + { + temp = temp.Container; + propertyName = temp.Metadata.PropertyName + "." + propertyName; } - protected virtual bool IsCsharpClassOrPrimitive(Type type) - { - if (type == null) - { - return false; - } + return new ModelExpression(propertyName, explorer); + } - return type.IsPrimitive || - type.IsValueType || - type == typeof(string) || - type == typeof(Guid) || - type == typeof(DateTime) || - type == typeof(ValueType) || - type == typeof(TimeSpan) || - type == typeof(DateTimeOffset) || - type.IsEnum; - } + protected virtual bool IsListOfCsharpClassOrPrimitive(Type type) + { + var genericType = type.GenericTypeArguments.FirstOrDefault(); - protected virtual bool IsListOfSelectItem(Type type) + if (genericType == null || !IsCsharpClassOrPrimitive(genericType)) { - return type == typeof(List) || type == typeof(IEnumerable); + return false; } - protected virtual bool IsSelectGroup(TagHelperContext context, ModelExpression model) - { - return IsEnum(model.ModelExplorer) || AreSelectItemsProvided(model.ModelExplorer); - } + return type.ToString().StartsWith("System.Collections.Generic.IEnumerable`") || type.ToString().StartsWith("System.Collections.Generic.List`"); + } - protected virtual bool IsEnum(ModelExplorer explorer) + protected virtual bool IsCsharpClassOrPrimitive(Type type) + { + if (type == null) { - return explorer.Metadata.IsEnum; + return false; } - protected virtual bool AreSelectItemsProvided(ModelExplorer explorer) - { - return explorer.GetAttribute() != null; - } + return type.IsPrimitive || + type.IsValueType || + type == typeof(string) || + type == typeof(Guid) || + type == typeof(DateTime) || + type == typeof(ValueType) || + type == typeof(TimeSpan) || + type == typeof(DateTimeOffset) || + type.IsEnum; + } - protected virtual bool IsRadioGroup(ModelExplorer explorer) - { - return explorer.GetAttribute() != null; - } + protected virtual bool IsListOfSelectItem(Type type) + { + return type == typeof(List) || type == typeof(IEnumerable); + } + + protected virtual bool IsSelectGroup(TagHelperContext context, ModelExpression model) + { + return IsEnum(model.ModelExplorer) || AreSelectItemsProvided(model.ModelExplorer); + } + + protected virtual bool IsEnum(ModelExplorer explorer) + { + return explorer.Metadata.IsEnum; + } + + protected virtual bool AreSelectItemsProvided(ModelExplorer explorer) + { + return explorer.GetAttribute() != null; + } + + protected virtual bool IsRadioGroup(ModelExplorer explorer) + { + return explorer.GetAttribute() != null; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormContentTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormContentTagHelper.cs index 9606cc1b77d..af0ff4e2d3d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormContentTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormContentTagHelper.cs @@ -1,15 +1,14 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.DependencyInjection; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; + +[HtmlTargetElement("abp-form-content", TagStructure = TagStructure.WithoutEndTag)] +public class AbpFormContentTagHelper : AbpTagHelper, ITransientDependency { - [HtmlTargetElement("abp-form-content", TagStructure = TagStructure.WithoutEndTag)] - public class AbpFormContentTagHelper : AbpTagHelper, ITransientDependency + public AbpFormContentTagHelper(AbpFormContentTagHelperService tagHelperService) + : base(tagHelperService) { - public AbpFormContentTagHelper(AbpFormContentTagHelperService tagHelperService) - : base(tagHelperService) - { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormContentTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormContentTagHelperService.cs index 9cb06d5364a..d973c31fb22 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormContentTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormContentTagHelperService.cs @@ -1,15 +1,14 @@ using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; + +public class AbpFormContentTagHelperService : AbpTagHelperService { - public class AbpFormContentTagHelperService : AbpTagHelperService + public override void Process(TagHelperContext context, TagHelperOutput output) { - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.Attributes.Clear(); - output.TagName = "div"; - output.TagMode = TagMode.StartTagAndEndTag; - output.Content.SetContent(AbpFormContentPlaceHolder); - } + output.Attributes.Clear(); + output.TagName = "div"; + output.TagMode = TagMode.StartTagAndEndTag; + output.Content.SetContent(AbpFormContentPlaceHolder); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormControlSize.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormControlSize.cs index 79070b559e1..94acbca97ee 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormControlSize.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpFormControlSize.cs @@ -1,10 +1,9 @@ -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; + +public enum AbpFormControlSize { - public enum AbpFormControlSize - { - Default, - Small, - Medium, - Large - } + Default, + Small, + Medium, + Large } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpIdNameTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpIdNameTagHelper.cs index 7bc1c674a70..d24e247abe3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpIdNameTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpIdNameTagHelper.cs @@ -7,43 +7,42 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Options; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; + +[HtmlTargetElement(Attributes = "abp-id-name")] +public class AbpIdNameTagHelper : AbpTagHelper { - [HtmlTargetElement(Attributes = "abp-id-name")] - public class AbpIdNameTagHelper : AbpTagHelper - { - /// - /// Make sure this TagHelper is executed first. - /// - public override int Order => -1000 - 1; + /// + /// Make sure this TagHelper is executed first. + /// + public override int Order => -1000 - 1; - [HtmlAttributeName("abp-id-name")] - public ModelExpression IdNameFor { get; set; } + [HtmlAttributeName("abp-id-name")] + public ModelExpression IdNameFor { get; set; } - private readonly MvcViewOptions _mvcViewOptions; + private readonly MvcViewOptions _mvcViewOptions; - public AbpIdNameTagHelper(IOptions mvcViewOptions) - { - _mvcViewOptions = mvcViewOptions.Value; - } + public AbpIdNameTagHelper(IOptions mvcViewOptions) + { + _mvcViewOptions = mvcViewOptions.Value; + } - public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + if (IdNameFor != null) { - if (IdNameFor != null) + if (!context.AllAttributes.Any(x => x.Name.Equals("id", StringComparison.OrdinalIgnoreCase))) { - if (!context.AllAttributes.Any(x => x.Name.Equals("id", StringComparison.OrdinalIgnoreCase))) - { - var id = TagBuilder.CreateSanitizedId(IdNameFor.Name, _mvcViewOptions.HtmlHelperOptions.IdAttributeDotReplacement); - output.Attributes.Add("id", id); - } - - if (!context.AllAttributes.Any(x => x.Name.Equals("name", StringComparison.OrdinalIgnoreCase))) - { - output.Attributes.Add("name", IdNameFor.Name); - } + var id = TagBuilder.CreateSanitizedId(IdNameFor.Name, _mvcViewOptions.HtmlHelperOptions.IdAttributeDotReplacement); + output.Attributes.Add("id", id); } - return Task.CompletedTask; + if (!context.AllAttributes.Any(x => x.Name.Equals("name", StringComparison.OrdinalIgnoreCase))) + { + output.Attributes.Add("name", IdNameFor.Name); + } } + + return Task.CompletedTask; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs index fdab58203a3..5778e476920 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs @@ -2,48 +2,47 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; + +public class AbpInputTagHelper : AbpTagHelper { - public class AbpInputTagHelper : AbpTagHelper - { - public ModelExpression AspFor { get; set; } + public ModelExpression AspFor { get; set; } - public string Label { get; set; } + public string Label { get; set; } - [HtmlAttributeName("info")] - public string InfoText { get; set; } + [HtmlAttributeName("info")] + public string InfoText { get; set; } - [HtmlAttributeName("disabled")] - public bool IsDisabled { get; set; } = false; + [HtmlAttributeName("disabled")] + public bool IsDisabled { get; set; } = false; - [HtmlAttributeName("readonly")] - public bool? IsReadonly { get; set; } = false; + [HtmlAttributeName("readonly")] + public bool? IsReadonly { get; set; } = false; - public bool AutoFocus { get; set; } + public bool AutoFocus { get; set; } - [HtmlAttributeName("type")] - public string InputTypeName { get; set; } + [HtmlAttributeName("type")] + public string InputTypeName { get; set; } - public AbpFormControlSize Size { get; set; } = AbpFormControlSize.Default; + public AbpFormControlSize Size { get; set; } = AbpFormControlSize.Default; - [HtmlAttributeName("required-symbol")] - public bool DisplayRequiredSymbol { get; set; } = true; + [HtmlAttributeName("required-symbol")] + public bool DisplayRequiredSymbol { get; set; } = true; - [HtmlAttributeName("asp-format")] - public string Format { get; set; } + [HtmlAttributeName("asp-format")] + public string Format { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public string Value { get; set; } + public string Value { get; set; } - public bool SuppressLabel { get; set; } + public bool SuppressLabel { get; set; } - public CheckBoxHiddenInputRenderMode? CheckBoxHiddenInputRenderMode { get; set; } + public CheckBoxHiddenInputRenderMode? CheckBoxHiddenInputRenderMode { get; set; } - public AbpInputTagHelper(AbpInputTagHelperService tagHelperService) - : base(tagHelperService) - { + public AbpInputTagHelper(AbpInputTagHelperService tagHelperService) + : base(tagHelperService) + { - } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs index 1ef29c799b6..3bc99436ca0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs @@ -11,462 +11,461 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; + +public class AbpInputTagHelperService : AbpTagHelperService { - public class AbpInputTagHelperService : AbpTagHelperService + private readonly IHtmlGenerator _generator; + private readonly HtmlEncoder _encoder; + private readonly IAbpTagHelperLocalizer _tagHelperLocalizer; + + public AbpInputTagHelperService(IHtmlGenerator generator, HtmlEncoder encoder, IAbpTagHelperLocalizer tagHelperLocalizer) { - private readonly IHtmlGenerator _generator; - private readonly HtmlEncoder _encoder; - private readonly IAbpTagHelperLocalizer _tagHelperLocalizer; + _generator = generator; + _encoder = encoder; + _tagHelperLocalizer = tagHelperLocalizer; + } - public AbpInputTagHelperService(IHtmlGenerator generator, HtmlEncoder encoder, IAbpTagHelperLocalizer tagHelperLocalizer) - { - _generator = generator; - _encoder = encoder; - _tagHelperLocalizer = tagHelperLocalizer; - } + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + var (innerHtml, isCheckBox) = await GetFormInputGroupAsHtmlAsync(context, output); - public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + if (isCheckBox && TagHelper.CheckBoxHiddenInputRenderMode.HasValue) { - var (innerHtml, isCheckBox) = await GetFormInputGroupAsHtmlAsync(context, output); - - if (isCheckBox && TagHelper.CheckBoxHiddenInputRenderMode.HasValue) - { - TagHelper.ViewContext.CheckBoxHiddenInputRenderMode = TagHelper.CheckBoxHiddenInputRenderMode.Value; - } + TagHelper.ViewContext.CheckBoxHiddenInputRenderMode = TagHelper.CheckBoxHiddenInputRenderMode.Value; + } - var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder(); + var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder(); - AddGroupToFormGroupContents( - context, - TagHelper.AspFor.Name, - SurroundInnerHtmlAndGet(context, output, innerHtml, isCheckBox), - order, - out var suppress - ); + AddGroupToFormGroupContents( + context, + TagHelper.AspFor.Name, + SurroundInnerHtmlAndGet(context, output, innerHtml, isCheckBox), + order, + out var suppress + ); - if (suppress) - { - output.SuppressOutput(); - } - else + if (suppress) + { + output.SuppressOutput(); + } + else + { + output.TagMode = TagMode.StartTagAndEndTag; + output.TagName = "div"; + LeaveOnlyGroupAttributes(context, output); + output.Attributes.AddClass(isCheckBox ? "mb-2" : "mb-3"); + if (isCheckBox) { - output.TagMode = TagMode.StartTagAndEndTag; - output.TagName = "div"; - LeaveOnlyGroupAttributes(context, output); - output.Attributes.AddClass(isCheckBox ? "mb-2" : "mb-3"); - if (isCheckBox) - { - output.Attributes.AddClass("form-check"); - } - output.Content.AppendHtml(innerHtml); + output.Attributes.AddClass("form-check"); } + output.Content.AppendHtml(innerHtml); } + } - protected virtual async Task<(string, bool)> GetFormInputGroupAsHtmlAsync(TagHelperContext context, TagHelperOutput output) - { - var (inputTag, isCheckBox) = await GetInputTagHelperOutputAsync(context, output); + protected virtual async Task<(string, bool)> GetFormInputGroupAsHtmlAsync(TagHelperContext context, TagHelperOutput output) + { + var (inputTag, isCheckBox) = await GetInputTagHelperOutputAsync(context, output); - var inputHtml = inputTag.Render(_encoder); - var label = await GetLabelAsHtmlAsync(context, output, inputTag, isCheckBox); - var info = GetInfoAsHtml(context, output, inputTag, isCheckBox); - var validation = isCheckBox ? "" : await GetValidationAsHtmlAsync(context, output, inputTag); + var inputHtml = inputTag.Render(_encoder); + var label = await GetLabelAsHtmlAsync(context, output, inputTag, isCheckBox); + var info = GetInfoAsHtml(context, output, inputTag, isCheckBox); + var validation = isCheckBox ? "" : await GetValidationAsHtmlAsync(context, output, inputTag); - return (GetContent(context, output, label, inputHtml, validation, info, isCheckBox), isCheckBox); - } + return (GetContent(context, output, label, inputHtml, validation, info, isCheckBox), isCheckBox); + } - protected virtual async Task GetValidationAsHtmlAsync(TagHelperContext context, TagHelperOutput output, TagHelperOutput inputTag) + protected virtual async Task GetValidationAsHtmlAsync(TagHelperContext context, TagHelperOutput output, TagHelperOutput inputTag) + { + if (IsOutputHidden(inputTag)) { - if (IsOutputHidden(inputTag)) - { - return ""; - } + return ""; + } - var validationMessageTagHelper = new ValidationMessageTagHelper(_generator) - { - For = TagHelper.AspFor, - ViewContext = TagHelper.ViewContext - }; + var validationMessageTagHelper = new ValidationMessageTagHelper(_generator) + { + For = TagHelper.AspFor, + ViewContext = TagHelper.ViewContext + }; - var attributeList = new TagHelperAttributeList { { "class", "text-danger" } }; + var attributeList = new TagHelperAttributeList { { "class", "text-danger" } }; - return await validationMessageTagHelper.RenderAsync(attributeList, context, _encoder, "span", TagMode.StartTagAndEndTag); - } + return await validationMessageTagHelper.RenderAsync(attributeList, context, _encoder, "span", TagMode.StartTagAndEndTag); + } - protected virtual string GetContent(TagHelperContext context, TagHelperOutput output, string label, string inputHtml, string validation, string infoHtml, bool isCheckbox) - { - var innerContent = isCheckbox ? - inputHtml + label : - label + inputHtml; + protected virtual string GetContent(TagHelperContext context, TagHelperOutput output, string label, string inputHtml, string validation, string infoHtml, bool isCheckbox) + { + var innerContent = isCheckbox ? + inputHtml + label : + label + inputHtml; - return innerContent + infoHtml + validation; - } + return innerContent + infoHtml + validation; + } - protected virtual string SurroundInnerHtmlAndGet(TagHelperContext context, TagHelperOutput output, string innerHtml, bool isCheckbox) - { - return "
" + - Environment.NewLine + innerHtml + Environment.NewLine + - "
"; - } + protected virtual string SurroundInnerHtmlAndGet(TagHelperContext context, TagHelperOutput output, string innerHtml, bool isCheckbox) + { + return "
" + + Environment.NewLine + innerHtml + Environment.NewLine + + "
"; + } - protected virtual TagHelper GetInputTagHelper(TagHelperContext context, TagHelperOutput output) + protected virtual TagHelper GetInputTagHelper(TagHelperContext context, TagHelperOutput output) + { + if (TagHelper.AspFor.ModelExplorer.GetAttribute