Browse Source

Merge branch 'dev' into feat/checkers-structs

pull/12602/head
John Nyingi 4 years ago
committed by GitHub
parent
commit
ba3afada33
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      README.md
  2. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
  3. 33
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  4. 6
      docs/en/Microservice-Architecture.md
  5. 11
      docs/en/Migration-Guides/Abp-5_3.md
  6. 1
      docs/en/Migration-Guides/Index.md
  7. 2
      docs/en/Modules/OpenIddict.md
  8. 14
      docs/en/Road-Map.md
  9. 18
      docs/en/Samples/Index.md
  10. 2
      docs/en/Samples/Microservice-Demo.md
  11. 98
      docs/en/Startup-Templates/Application.md
  12. 23
      docs/en/Themes/LeptonXLite/blazor.md
  13. 13
      docs/en/Themes/LeptonXLite/mvc.md
  14. 8
      docs/en/Tutorials/Todo/Index.md
  15. 24
      docs/en/UI/AspNetCore/JavaScript-API/GlobalFeatures.md
  16. 1
      docs/en/UI/AspNetCore/JavaScript-API/Index.md
  17. 23
      docs/en/docs-nav.json
  18. 2
      docs/zh-Hans/Distributed-Event-Bus.md
  19. 1
      docs/zh-Hans/Domain-Services.md
  20. 4
      docs/zh-Hans/Entities.md
  21. 2
      docs/zh-Hans/Module-Development-Basics.md
  22. 570
      docs/zh-Hans/Text-Templating-Razor.md
  23. 527
      docs/zh-Hans/Text-Templating-Scriban.md
  24. 444
      docs/zh-Hans/Text-Templating.md
  25. BIN
      docs/zh-Hans/images/abp-book.png
  26. BIN
      docs/zh-Hans/images/abp-select2-multiple.png
  27. BIN
      docs/zh-Hans/images/abp-select2-single.png
  28. BIN
      docs/zh-Hans/images/account-module-forgot-password.png
  29. BIN
      docs/zh-Hans/images/account-module-login.png
  30. BIN
      docs/zh-Hans/images/account-module-manage-account.png
  31. BIN
      docs/zh-Hans/images/account-module-register.png
  32. BIN
      docs/zh-Hans/images/add-new-propert-to-user-database-extra-properties.png
  33. BIN
      docs/zh-Hans/images/add-new-propert-to-user-database-field.png
  34. BIN
      docs/zh-Hans/images/add-new-property-enum.png
  35. BIN
      docs/zh-Hans/images/add-new-property-to-user-form-validation-error-custom.png
  36. BIN
      docs/zh-Hans/images/add-new-property-to-user-form-validation-error.png
  37. BIN
      docs/zh-Hans/images/add-new-property-to-user-form.png
  38. BIN
      docs/zh-Hans/images/add-new-property-to-user-table.png
  39. BIN
      docs/zh-Hans/images/angular-module-dev-app-project.png
  40. BIN
      docs/zh-Hans/images/angular-module-folder-structure.png
  41. BIN
      docs/zh-Hans/images/blazor-generic-exception-message.png
  42. BIN
      docs/zh-Hans/images/blazor-user-friendly-exception.png
  43. BIN
      docs/zh-Hans/images/bookstore-visual-studio-solution-v3.png
  44. BIN
      docs/zh-Hans/images/cmskit-module-blog-post-edit.png
  45. BIN
      docs/zh-Hans/images/cmskit-module-blog-posts-page.png
  46. BIN
      docs/zh-Hans/images/cmskit-module-blogs-edit.png
  47. BIN
      docs/zh-Hans/images/cmskit-module-blogs-feature-action.png
  48. BIN
      docs/zh-Hans/images/cmskit-module-blogs-page.png
  49. BIN
      docs/zh-Hans/images/cmskit-module-comment-page.png
  50. BIN
      docs/zh-Hans/images/cmskit-module-comments-detail.png
  51. BIN
      docs/zh-Hans/images/cmskit-module-features-dialog-2.png
  52. BIN
      docs/zh-Hans/images/cmskit-module-features-dialog.png
  53. BIN
      docs/zh-Hans/images/cmskit-module-features-scroll-index.png
  54. BIN
      docs/zh-Hans/images/cmskit-module-global-resources-page.png
  55. BIN
      docs/zh-Hans/images/cmskit-module-menus-page.png
  56. BIN
      docs/zh-Hans/images/cmskit-module-menus-public.png
  57. BIN
      docs/zh-Hans/images/cmskit-module-pages-edit.png
  58. BIN
      docs/zh-Hans/images/cmskit-module-pages-page.png
  59. BIN
      docs/zh-Hans/images/cmskit-module-ratings.png
  60. BIN
      docs/zh-Hans/images/cmskit-module-reactions.png
  61. BIN
      docs/zh-Hans/images/cmskit-module-tag-edit.png
  62. BIN
      docs/zh-Hans/images/cmskit-module-tags-page.png
  63. BIN
      docs/zh-Hans/images/data-table-colum-extension-blazor-component-render-solution.png
  64. BIN
      docs/zh-Hans/images/data-table-colum-extension-blazor-component-render.png
  65. BIN
      docs/zh-Hans/images/docs-create-project-v4.4.0.png
  66. BIN
      docs/zh-Hans/images/docs-module_solution-explorer.png
  67. BIN
      docs/zh-Hans/images/extension-navigation-property-form.png
  68. BIN
      docs/zh-Hans/images/extension-navigation-property-table.png
  69. BIN
      docs/zh-Hans/images/features-modal.png
  70. BIN
      docs/zh-Hans/images/features-module-opening.png
  71. BIN
      docs/zh-Hans/images/generated-static-client-proxies.png
  72. BIN
      docs/zh-Hans/images/hello-template-razor.png
  73. BIN
      docs/zh-Hans/images/identity-module-menu.png
  74. BIN
      docs/zh-Hans/images/identity-module-permissions.png
  75. BIN
      docs/zh-Hans/images/identity-module-roles.png
  76. BIN
      docs/zh-Hans/images/identity-module-users.png
  77. BIN
      docs/zh-Hans/images/implementing-domain-driven-design-book.png
  78. BIN
      docs/zh-Hans/images/module-tenant-management-actions.png
  79. BIN
      docs/zh-Hans/images/module-tenant-management-new-tenant.png
  80. BIN
      docs/zh-Hans/images/module-tenant-management-page.png
  81. BIN
      docs/zh-Hans/images/multiple-file-template-razor.png
  82. BIN
      docs/zh-Hans/images/optimistic-concurrency.png
  83. BIN
      docs/zh-Hans/images/page-header-toolbar-blazor.png
  84. BIN
      docs/zh-Hans/images/page-toolbar-button-blazor.png
  85. BIN
      docs/zh-Hans/images/page-toolbar-button.png
  86. BIN
      docs/zh-Hans/images/page-toolbar-custom-component-blazor.png
  87. BIN
      docs/zh-Hans/images/page-toolbar-custom-component.png
  88. BIN
      docs/zh-Hans/images/permissions-module-dialog.png
  89. BIN
      docs/zh-Hans/images/permissions-module-open-dialog.png
  90. BIN
      docs/zh-Hans/images/replace-email-layout-razor.png
  91. BIN
      docs/zh-Hans/images/static-js-proxy-example.png
  92. BIN
      docs/zh-Hans/images/table-column-extension-example-blazor.png
  93. BIN
      docs/zh-Hans/images/table-column-extension-example.png
  94. BIN
      docs/zh-Hans/images/upgrade-diff-empty-folders.png
  95. BIN
      docs/zh-Hans/images/user-action-blazor-extension-click-me.png
  96. BIN
      docs/zh-Hans/images/user-action-extension-click-me.png
  97. BIN
      docs/zh-Hans/images/user-action-extension-on-blazor-project.png
  98. BIN
      docs/zh-Hans/images/user-action-extension-on-solution.png
  99. BIN
      docs/zh-Hans/images/winmerge-comparison-result.png
  100. BIN
      docs/zh-Hans/images/winmerge-file-diff.png

4
README.md

@ -7,7 +7,9 @@
[![MyGet (nightly builds)](https://img.shields.io/myget/abp-nightly/vpre/Volo.Abp.svg?style=flat-square)](https://docs.abp.io/en/abp/latest/Nightly-Builds) [![MyGet (nightly builds)](https://img.shields.io/myget/abp-nightly/vpre/Volo.Abp.svg?style=flat-square)](https://docs.abp.io/en/abp/latest/Nightly-Builds)
[![NuGet Download](https://img.shields.io/nuget/dt/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core) [![NuGet Download](https://img.shields.io/nuget/dt/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core)
ABP Framework is a complete **infrastructure** based on the **ASP.NET Core** to create **modern web applications** and **APIs** by following the software development **best practices** and the **latest technologies**. [![ABP Discord server](https://img.shields.io/discord/951497912645476422?label=Discord)](https://discord.gg/abp)
ABP Framework is a complete **infrastructure** based on the **ASP.NET Core** to create **modern web applications** and **APIs** by following the software development **best practices** and the **latest technologies**. Check out https://abp.io
## Getting Started ## Getting Started

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

@ -26,6 +26,8 @@
"Volo.AbpIo.Domain:030009": "User not found!", "Volo.AbpIo.Domain:030009": "User not found!",
"Volo.AbpIo.Domain:030010": "To purchase the trial license, you first need to activate your trial license!", "Volo.AbpIo.Domain:030010": "To purchase the trial license, you first need to activate your trial license!",
"Volo.AbpIo.Domain:030011": "You cannot delete a trial license when it is purchased!", "Volo.AbpIo.Domain:030011": "You cannot delete a trial license when it is purchased!",
"Volo.AbpIo.Domain:070000": "The organization name can only contain latin letters, numbers, dots and hyphens!",
"Volo.AbpIo.Domain:070001": "The company name can only contain latin letters, numbers, dots, space and hyphens!",
"WantToLearn?": "Want to learn?", "WantToLearn?": "Want to learn?",
"ReadyToGetStarted?": "Ready to get started?", "ReadyToGetStarted?": "Ready to get started?",
"JoinOurCommunity": "Join our community", "JoinOurCommunity": "Join our community",

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

@ -379,8 +379,6 @@
"TaxNoValidationMessage": "TAX/VAT No is too long!", "TaxNoValidationMessage": "TAX/VAT No is too long!",
"NotesValidationMessage": "Notes field is too long!", "NotesValidationMessage": "Notes field is too long!",
"CheckYourBillingInfo": "You can create your invoice only once! Check your billing information before creating your invoice.", "CheckYourBillingInfo": "You can create your invoice only once! Check your billing information before creating your invoice.",
"Volo.AbpIo.Commercial:030000": "You already used your trial period.",
"Volo.AbpIo.Commercial:030001": "This organization name already exists.",
"StartYourFreeTrial": "Start your free trial", "StartYourFreeTrial": "Start your free trial",
"TrialLicenseModelInvalidErrorMessage": "One of the following fields is invalid: Country Name, Company Size, Industry or Purpose Of Usage.", "TrialLicenseModelInvalidErrorMessage": "One of the following fields is invalid: Country Name, Company Size, Industry or Purpose Of Usage.",
"Trial": "Trial", "Trial": "Trial",
@ -488,10 +486,8 @@
"BackOfficeApplicationExplanation": "The actual web application of your system, with multiple UI framework options. You can create any kind of business application.", "BackOfficeApplicationExplanation": "The actual web application of your system, with multiple UI framework options. You can create any kind of business application.",
"LandingWebsite": "Landing Website", "LandingWebsite": "Landing Website",
"LandingWebsiteExplanation": "A generic landing/public website that can be used for several purposes, like introducing your company, selling your products, etc.", "LandingWebsiteExplanation": "A generic landing/public website that can be used for several purposes, like introducing your company, selling your products, etc.",
"ABPFrameworkEBook": "E-Book: Mastering ABP Framework", "ABPFrameworkEBook": "Mastering ABP Framework e-book",
"MasteringAbpFrameworkEBookDescription": "Included within your ABP Commercial license", "MasteringAbpFrameworkEBookDescription": "Included within your ABP Commercial license",
"Volo.AbpIo.Domain:070000": "The organization name can only contain latin letters, numbers, dots and hyphens!",
"Volo.AbpIo.Domain:070001": "The company name can only contain latin letters, numbers, dots, space and hyphens!",
"FullName": "Full Name", "FullName": "Full Name",
"LicenseTypeNotCorrect": "The license type is not correct!", "LicenseTypeNotCorrect": "The license type is not correct!",
"Trainings": "Trainings", "Trainings": "Trainings",
@ -508,6 +504,31 @@
"OnboardingTrainingFaqExplanation": "Yes, we have ABP Training Services to help you get your ABP project started fast. You will learn about ABP from an ABP core team member and you will get the skills to begin your ABP project. In the onboarding training, we will explain how to set up your development environment, install the required tools, create a fully functional CRUD page. The training will be live and the Zoom application will be used, and we are open to using other online meeting platforms. The language of the training will be English. You can also ask your questions about ABP during the sessions. A convenient time and date will be planned for both parties. To get more information, contact us at <a href=\"mailto:info@abp.io\">info@abp.io</a>.", "OnboardingTrainingFaqExplanation": "Yes, we have ABP Training Services to help you get your ABP project started fast. You will learn about ABP from an ABP core team member and you will get the skills to begin your ABP project. In the onboarding training, we will explain how to set up your development environment, install the required tools, create a fully functional CRUD page. The training will be live and the Zoom application will be used, and we are open to using other online meeting platforms. The language of the training will be English. You can also ask your questions about ABP during the sessions. A convenient time and date will be planned for both parties. To get more information, contact us at <a href=\"mailto:info@abp.io\">info@abp.io</a>.",
"AddBasket": "Add to Basket", "AddBasket": "Add to Basket",
"SendTrainingRequest": "Send Training Request", "SendTrainingRequest": "Send Training Request",
"OnlyEnglishVersionOfThisDocumentIsTheRecentAndValid": "* The English version of this document is the most up-to-date and the English version will prevail in any dispute." "OnlyEnglishVersionOfThisDocumentIsTheRecentAndValid": "* The English version of this document is the most up-to-date and the English version will prevail in any dispute.",
"Pricing_Page_Title": "Plans & Pricing",
"Pricing_Page_Description": "Choose the features and functionality your business needs today. Buy an ABP Commercial license and create unlimited projects.",
"Pricing_Page_HurryUp": "Hurry Up!",
"Pricing_Page_BuyLicense": "Buy a license at <strong>2021 prices</strong> until January 16!",
"Pricing_Page_ValidForExistingCustomers": "Also valid for existing customers and license renewals.",
"Pricing_Page_Hint1": "The license price includes a certain number of developer seats. If you have more developers, you can always purchase additional seats.",
"Pricing_Page_Hint2": "You can purchase more developer licenses now or in the future. Licenses are seat based, so you can transfer a seat from a developer to another.",
"Pricing_Page_Hint3": "You can develop unlimited count of different products with your license.",
"Pricing_Page_Hint4": "ABP Suite is a tool to assist your development to improve your productivity. It supports generating CRUD pages and creating new projects.",
"Pricing_Page_Hint5": "You can use all the pre-built modules in your applications.",
"Pricing_Page_Hint6": "You can use all the pre-built themes in your applications.",
"Pricing_Page_Hint7": "A startup template is a Visual Studio solution to make you jump-start to your project. All fundamental modules are added and pre-configured for you.",
"Pricing_Page_Hint8": "Mastering ABP Framework e-book explains how to implement .NET solutions with best practices. It is sold on Amazon.com and you can download the book for free within your license.",
"Pricing_Page_Hint9": "You can download the source-code of any module. You may want to add the source code to your solution to make radical changes or just keep it for yourself for security reasons.",
"Pricing_Page_Hint10": "Licenses are for lifetime. That means you can continue to develop your application forever. Accessing to the latest version and getting support are granted within the license period (1 year unless you renew it).",
"Pricing_Page_Hint11": "No restrictions on deployment! You can deploy to as many servers as you want, including the cloud services or on-premises.",
"Pricing_Page_Hint12": "You can update the modules, themes and tools to the latest version within your active license period. After your license expires, you need to renew it, to continue to get updates for bug fixes, new features and enhancements.",
"Pricing_Page_Hint13": "You can get the premium support for one year (you can renew your license to extend it).",
"Pricing_Page_Hint14": "Team and Business licenses have incident/question count limit. If you buy additional developer licenses, your incident limit increases by {0} (for the Team License) or {1} (for the Business License) per developer.",
"Pricing_Page_Hint15": "Only Enterprise License includes private support. You can send e-mail directly to the ABP Team or ask questions on support.abp.io with private ticket option. The private tickets are not visible to the public.",
"Pricing_Page_Hint16": "You can download the source-code of all ABP themes. You may want to add the source code to your solution to make radical changes or just keep it for yourself for security reasons.",
"Pricing_Page_Testimonial_1": "ABP Commercial allowed SC Ventures to deliver a bank-grade multi-tenant silo-database SaaS platform in 9 months to support the accounts receivable / accounts payable supply chain financing of significant value invoices from multiple integrated anchors. The modularity of ABP made it possible for the team to deliver in record time, pass all VAPT, and deploy the containerized micro-services stack via full CI/CD and pipelines into production.",
"Pricing_Page_Testimonial_2": "We are seeing the value of using ABP Commercial to reduce the overhead of custom development projects. And the team is able to unify the code pattern in different project streams. We see more potential in the framework for us to build new features faster than before. We trust we will be constantly seeing the value of leveraging ABP Commercial.",
"Pricing_Page_Testimonial_3": "We love ABP. We don't have to write everything from scratch. We start from out-of-the-box features and just focus on what we really need to write. Also, ABP is well-architected and the code is high quality with fewer bugs. If we would have to write everything we needed on our own, we might have to spend years. Once more things we like is that the new version, or issue fixing, or improvement come out very soon every other week. We don't wait too long.",
"Pricing_Page_Testimonial_4": "ABP Commercial is a fantastic product would recommend. Commercial products to market for our customers in a single configurable platform. The jump start that the framework and tooling provide any team is worth every cent. ABP Commercial was the best fit for our needs."
} }
} }

6
docs/en/Microservice-Architecture.md

@ -23,8 +23,8 @@ One common advise to start a new solution is **always to start with a monolith**
However, developing such a well-modular application can be a problem since it is **hard to keep modules isolated** from each other as you would do it for microservices (see [Stefan Tilkov's article](https://martinfowler.com/articles/dont-start-monolith.html) about that). Microservice architecture naturally forces you to develop well isolated services, but in a modular monolithic application it's easy to tight couple modules to each other and design **weak module boundaries** and API contracts. However, developing such a well-modular application can be a problem since it is **hard to keep modules isolated** from each other as you would do it for microservices (see [Stefan Tilkov's article](https://martinfowler.com/articles/dont-start-monolith.html) about that). Microservice architecture naturally forces you to develop well isolated services, but in a modular monolithic application it's easy to tight couple modules to each other and design **weak module boundaries** and API contracts.
ABP can help you in that point by offerring a **microservice-compatible, strict module architecture** where your module is splitted into multiple layers/projects and developed in its own VS solution completely isolated and independent from other modules. Such a developed module is a natural microservice yet it can be easily plugged-in a monolithic application. See the [module development best practice guide](Best-Practices/Index.md) that offers a **microservice-first module design**. All [standard ABP modules](https://github.com/abpframework/abp/tree/master/modules) are developed based on this guide. So, you can use these modules by embedding into your monolithic solution or deploy them separately and use via remote APIs. They can share a single database or can have their own database based on your simple configuration. ABP can help you in that point by offering a **microservice-compatible, strict module architecture** where your module is split into multiple layers/projects and developed in its own VS solution completely isolated and independent from other modules. Such a developed module is a natural microservice yet it can be easily plugged-in a monolithic application. See the [module development best practice guide](Best-Practices/Index.md) that offers a **microservice-first module design**. All [standard ABP modules](https://github.com/abpframework/abp/tree/master/modules) are developed based on this guide. So, you can use these modules by embedding into your monolithic solution or deploy them separately and use via remote APIs. They can share a single database or can have their own database based on your simple configuration.
## Microservice Demo Solution ## Microservice Demo Solution: eShopOnAbp
The [sample microservice solution](Samples/Microservice-Demo.md) demonstrates a complete microservice solution based on the ABP framework. The [eShopOnAbp project](https://github.com/abpframework/eShopOnAbp) demonstrates a complete microservice solution based on the ABP framework.

11
docs/en/Migration-Guides/Abp-5_3.md

@ -0,0 +1,11 @@
# ABP Version 5.3 Migration Guide
This document is a guide for upgrading ABP v5.2 solutions to ABP v5.3. There is a change in this version that may effect your applications, please read it carefully and apply the necessary changes to your application.
## AutoMapper Upgraded to v11.0.1
AutoMapper library upgraded to **v11.0.1** in this version. So, you need to change your project's target SDK that use the **AutoMapper** library (typically your `*.Application` project). You can change it from `netstandard2.0` to `netstandard2.1` or `net6` if needed. Please see [#12189](https://github.com/abpframework/abp/pull/12189) for more info.
## See Also
* [Official blog post for the 5.3 release](https://blog.abp.io/abp/ABP.IO-Platform-5.3-RC-Has-Been-Published)

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

@ -2,6 +2,7 @@
The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../Upgrading.md). The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../Upgrading.md).
- [5.2 to 5.3](Abp-5_3.md)
- [5.1 to 5.2](Abp-5_2.md) - [5.1 to 5.2](Abp-5_2.md)
- [4.x to 5.0](Abp-5_0.md) - [4.x to 5.0](Abp-5_0.md)
- [4.2 to 4.3](Abp-4_3.md) - [4.2 to 4.3](Abp-4_3.md)

2
docs/en/Modules/OpenIddict.md

@ -81,7 +81,7 @@ PreConfigure<OpenIddictServerBuilder>(builder =>
}); });
``` ```
#### AbpOpenIddictOptions #### AbpOpenIddictAspNetCoreOptions
`UpdateAbpClaimTypes(default: true)`: Updates AbpClaimTypes to be compatible with identity server claims. `UpdateAbpClaimTypes(default: true)`: Updates AbpClaimTypes to be compatible with identity server claims.
`AddDevelopmentEncryptionAndSigningCertificate(default: true)`: Registers (and generates if necessary) a user-specific development encryption/development signing certificate. `AddDevelopmentEncryptionAndSigningCertificate(default: true)`: Registers (and generates if necessary) a user-specific development encryption/development signing certificate.

14
docs/en/Road-Map.md

@ -4,15 +4,18 @@ This document provides a road map, release schedule and planned features for the
## Next Versions ## Next Versions
### v5.3 ### v5.4
In [5.3 milestone](https://github.com/abpframework/abp/milestone/65), we will be mostly working on the following topics: In [5.4 milestone](https://github.com/abpframework/abp/milestone/67), we will be mostly working on the following topics:
* Providing an OpenIddict integration to replace current IdentityServer4 integration.
* Maturing and documenting the [eShopOnAbp](https://github.com/abpframework/eShopOnAbp) project, writing a free e-book that explains the solution. * Maturing and documenting the [eShopOnAbp](https://github.com/abpframework/eShopOnAbp) project, writing a free e-book that explains the solution.
* Working on the [LeptonX](https://blog.abp.io/abp/LeptonX-Theme-for-ABP-Framework-Alpha-Release) theme and making it as the default theme for the ABP Framework UI options. * Working on the [LeptonX](https://blog.abp.io/abp/LeptonX-Theme-for-ABP-Framework-Alpha-Release) theme and making it as the default theme for the ABP Framework UI options.
* Working on more examples and guides. * Improvements on the existing features and providing more guides.
The planned release date for v5.3 is **May, 2022**. The planned release date for v5.4 is **July, 2022**.
> After the version 5.4, we will be working for 6.0 which will be released in the end of 2022 based on .NET 7.0.
## Backlog Items ## Backlog Items
@ -20,8 +23,8 @@ The *Next Versions* section above shows the main focus of the planned versions.
Here, a list of major items in the backlog we are considering to work on in the next versions. Here, a list of major items in the backlog we are considering to work on in the next versions.
* [#7221](https://github.com/abpframework/abp/issues/7221) / Alternative to IdentityServer4
* [#2183](https://github.com/abpframework/abp/issues/2183) / Dapr integration * [#2183](https://github.com/abpframework/abp/issues/2183) / Dapr integration
* [#6655](https://github.com/abpframework/abp/pull/6655) / Use Typescript for the MVC UI
* [#236](https://github.com/abpframework/abp/issues/236) / Resource based authorization system * [#236](https://github.com/abpframework/abp/issues/236) / Resource based authorization system
* [#2882](https://github.com/abpframework/abp/issues/2882) / Providing a gRPC integration infrastructure (while it is [already possible](https://github.com/abpframework/abp-samples/tree/master/GrpcDemo) to create or consume gRPC endpoints for your application, we plan to create endpoints for the [standard application modules](https://docs.abp.io/en/abp/latest/Modules/Index)) * [#2882](https://github.com/abpframework/abp/issues/2882) / Providing a gRPC integration infrastructure (while it is [already possible](https://github.com/abpframework/abp-samples/tree/master/GrpcDemo) to create or consume gRPC endpoints for your application, we plan to create endpoints for the [standard application modules](https://docs.abp.io/en/abp/latest/Modules/Index))
* [#1754](https://github.com/abpframework/abp/issues/1754) / Multi-lingual entities * [#1754](https://github.com/abpframework/abp/issues/1754) / Multi-lingual entities
@ -31,7 +34,6 @@ Here, a list of major items in the backlog we are considering to work on in the
* [#4223](https://github.com/abpframework/abp/issues/4223) / WebHook system * [#4223](https://github.com/abpframework/abp/issues/4223) / WebHook system
* [#162](https://github.com/abpframework/abp/issues/162) / Azure ElasticDB Integration for multitenancy * [#162](https://github.com/abpframework/abp/issues/162) / Azure ElasticDB Integration for multitenancy
* [#2296](https://github.com/abpframework/abp/issues/2296) / Feature toggling infrastructure * [#2296](https://github.com/abpframework/abp/issues/2296) / Feature toggling infrastructure
* [#6655](https://github.com/abpframework/abp/pull/6655) / Use Typescript for the MVC UI
You can always check the milestone planning and the prioritized backlog issues on [the GitHub repository](https://github.com/abpframework/abp/milestones) for a detailed road map. The backlog items are subject to change. We are adding new items and changing priorities based on the community feedbacks and goals of the project. You can always check the milestone planning and the prioritized backlog issues on [the GitHub repository](https://github.com/abpframework/abp/milestones) for a detailed road map. The backlog items are subject to change. We are adding new items and changing priorities based on the community feedbacks and goals of the project.

18
docs/en/Samples/Index.md

@ -2,15 +2,19 @@
Here, a list of official samples built with the ABP Framework. Most of these samples are located under the [abpframework/abp-samples](https://github.com/abpframework/abp-samples) GitHub repository. Here, a list of official samples built with the ABP Framework. Most of these samples are located under the [abpframework/abp-samples](https://github.com/abpframework/abp-samples) GitHub repository.
### Microservice Demo ## eShopOnAbp
A complete solution to demonstrate how to build systems based on the microservice architecture. Reference microservice solution built with the ABP Framework and .NET.
* [The complete documentation for this sample](Microservice-Demo.md) * [Source code](https://github.com/abpframework/eShopOnAbp)
* [Source code](https://github.com/abpframework/abp-samples/tree/master/MicroserviceDemo)
* [Microservice architecture document](../Microservice-Architecture.md)
### Book Store ## EventHub
This is a reference application built with the ABP Framework. It implements the Domain Driven Design with multiple application layers.
* [Source code](https://github.com/abpframework/eventhub)
## Book Store
A simple CRUD application to show basic principles of developing an application with the ABP Framework. The same sample was implemented with different technologies: A simple CRUD application to show basic principles of developing an application with the ABP Framework. The same sample was implemented with different technologies:
@ -28,7 +32,7 @@ A simple CRUD application to show basic principles of developing an application
While there is no Razor Pages & MongoDB combination, you can check both documents to understand it since DB & UI selection don't effect each other. While there is no Razor Pages & MongoDB combination, you can check both documents to understand it since DB & UI selection don't effect each other.
### Other Samples ## Other Samples
* **Event Organizer**: A sample application to create events (meetups) and allow others to register the events. Developed using EF Core and Blazor UI. * **Event Organizer**: A sample application to create events (meetups) and allow others to register the events. Developed using EF Core and Blazor UI.
* [Source code](https://github.com/abpframework/abp-samples/tree/master/EventOrganizer) * [Source code](https://github.com/abpframework/abp-samples/tree/master/EventOrganizer)

2
docs/en/Samples/Microservice-Demo.md

@ -1,5 +1,7 @@
# Microservice Demo Solution # Microservice Demo Solution
> This solution is no longer maintained. See [the eShopOnAbp project](https://github.com/abpframework/eShopOnAbp) for the replacement solution.
*"Microservices are a software development technique—a variant of the **service-oriented architecture** (SOA) architectural style that structures an application as a collection of **loosely coupled services**. In a microservices architecture, services are **fine-grained** and the protocols are **lightweight**. The benefit of decomposing an application into different smaller services is that it improves **modularity**. This makes the application easier to understand, develop, test, and become more resilient to architecture erosion. It **parallelizes development** by enabling small autonomous teams to **develop, deploy and scale** their respective services independently. It also allows the architecture of an individual service to emerge through **continuous refactoring**. Microservices-based architectures enable **continuous delivery and deployment**."* *"Microservices are a software development technique—a variant of the **service-oriented architecture** (SOA) architectural style that structures an application as a collection of **loosely coupled services**. In a microservices architecture, services are **fine-grained** and the protocols are **lightweight**. The benefit of decomposing an application into different smaller services is that it improves **modularity**. This makes the application easier to understand, develop, test, and become more resilient to architecture erosion. It **parallelizes development** by enabling small autonomous teams to **develop, deploy and scale** their respective services independently. It also allows the architecture of an individual service to emerge through **continuous refactoring**. Microservices-based architectures enable **continuous delivery and deployment**."*
— [Wikipedia](https://en.wikipedia.org/wiki/Microservices) — [Wikipedia](https://en.wikipedia.org/wiki/Microservices)

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

@ -13,7 +13,7 @@ This document explains **the solution structure** and projects in details. If yo
You can use the [ABP CLI](../CLI.md) to create a new project using this startup template. Alternatively, you can directly create & download from the [Get Started](https://abp.io/get-started) page. CLI approach is used here. You can use the [ABP CLI](../CLI.md) to create a new project using this startup template. Alternatively, you can directly create & download from the [Get Started](https://abp.io/get-started) page. CLI approach is used here.
First, install the ABP CLI if you haven't installed before: First, install the ABP CLI if you haven't installed it before:
````bash ````bash
dotnet tool install -g Volo.Abp.Cli dotnet tool install -g Volo.Abp.Cli
@ -25,8 +25,8 @@ Then use the `abp new` command in an empty folder to create a new solution:
abp new Acme.BookStore -t app abp new Acme.BookStore -t app
```` ````
* `Acme.BookStore` is the solution name, like *YourCompany.YourProduct*. You can use single level, two-levels or three-levels naming. * `Acme.BookStore` is the solution name, like *YourCompany.YourProduct*. You can use single-level, two-level or three-level naming.
* This example specified the template name (`-t` or `--template` option). However, `app` is already the default template if you don't specify it. * This example specified the template name (`-t` or `--template` option). However, `app` is already the default template if you didn't specify it.
### Specify the UI Framework ### Specify the UI Framework
@ -36,7 +36,7 @@ This template provides multiple UI frameworks:
* `blazor`: Blazor UI * `blazor`: Blazor UI
* `angular`: Angular UI * `angular`: Angular UI
Use `-u` or `--ui` option to specify the UI framework: Use the `-u` or `--ui` option to specify the UI framework:
````bash ````bash
abp new Acme.BookStore -u angular abp new Acme.BookStore -u angular
@ -61,7 +61,7 @@ This template supports the following mobile application frameworks:
- `react-native`: React Native - `react-native`: React Native
Use `-m` (or `--mobile`) option to specify the mobile application framework: Use the `-m` (or `--mobile`) option to specify the mobile application framework:
````bash ````bash
abp new Acme.BookStore -m react-native abp new Acme.BookStore -m react-native
@ -75,7 +75,7 @@ Based on the options you've specified, you will get a slightly different solutio
### Default Structure ### Default Structure
If you don't specify any additional option, you will have a solution like shown below: If you don't specify any additional options, you will have a solution as shown below:
![bookstore-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-v3.png) ![bookstore-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-v3.png)
@ -93,7 +93,7 @@ This project contains constants, enums and other objects these are actually a pa
A `BookType` enum and a `BookConsts` class (which may have some constant fields for the `Book` entity, like `MaxNameLength`) are good candidates for this project. A `BookType` enum and a `BookConsts` class (which may have some constant fields for the `Book` entity, like `MaxNameLength`) are good candidates for this project.
* This project has no dependency to other projects in the solution. All other projects depend on this directly or indirectly. * This project has no dependency on other projects in the solution. All other projects depend on this one directly or indirectly.
#### .Domain Project #### .Domain Project
@ -105,7 +105,7 @@ A `Book` entity, a `BookManager` domain service and an `IBookRepository` interfa
#### .Application.Contracts Project #### .Application.Contracts Project
This project mainly contains [application service](../Application-Services.md) **interfaces** and [Data Transfer Objects](../Data-Transfer-Objects.md) (DTO) of the application layer. It does exists to separate interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package. This project mainly contains [application service](../Application-Services.md) **interfaces** and [Data Transfer Objects](../Data-Transfer-Objects.md) (DTO) of the application layer. It exists to separate the interface & implementation of the application layer. In this way, the interface project can be shared to the clients as a contract package.
An `IBookAppService` interface and a `BookCreationDto` class are good candidates for this project. An `IBookAppService` interface and a `BookCreationDto` class are good candidates for this project.
@ -130,7 +130,7 @@ This is the integration project for the EF Core. It defines the `DbContext` and
#### .DbMigrator Project #### .DbMigrator Project
This is a console application which simplifies to execute database migrations on development and production environments. When you run this application, it; This is a console application that simplifies the execution of database migrations on development and production environments. When you run this application, it:
* Creates the database if necessary. * Creates the database if necessary.
* Applies the pending database migrations. * Applies the pending database migrations.
@ -140,24 +140,24 @@ This is a console application which simplifies to execute database migrations on
Especially, seeding initial data is important at this point. ABP has a modular data seed infrastructure. See [its documentation](../Data-Seeding.md) for more about the data seeding. Especially, seeding initial data is important at this point. ABP has a modular data seed infrastructure. See [its documentation](../Data-Seeding.md) for more about the data seeding.
While creating database & applying migrations seems only necessary for relational databases, this projects comes even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds initial data which is necessary for the application. While creating database & applying migrations seem only necessary for relational databases, this project comes even if you choose a NoSQL database provider (like MongoDB). In that case, it still seeds the initial data which is necessary for the application.
* Depends on the `.EntityFrameworkCore` project (for EF Core) since it needs to access to the migrations. * Depends on the `.EntityFrameworkCore` project (for EF Core) since it needs to access to the migrations.
* Depends on the `.Application.Contracts` project to be able to access permission definitions, because initial data seeder grants all permissions for the admin role by default. * Depends on the `.Application.Contracts` project to be able to access permission definitions, because the initial data seeder grants all permissions to the admin role by default.
#### .HttpApi Project #### .HttpApi Project
This project is used to define your API Controllers. This project is used to define your API Controllers.
Most of time you don't need to manually define API Controllers since ABP's [Auto API Controllers](../API/Auto-API-Controllers.md) feature creates them automagically based on your application layer. However, in case of you need to write API controllers, this is the best place to do it. Most of the time you don't need to manually define API Controllers since ABP's [Auto API Controllers](../API/Auto-API-Controllers.md) feature creates them automagically based on your application layer. However, in case of you need to write API controllers, this is the best place to do it.
* Depends on the `.Application.Contracts` project to be able to inject the application service interfaces. * Depends on the `.Application.Contracts` project to be able to inject the application service interfaces.
#### .HttpApi.Client Project #### .HttpApi.Client Project
This is a project that defines C# client proxies to use the HTTP APIs of the solution. You can share this library to 3rd-party clients, so they can easily consume your HTTP APIs in their Dotnet applications (For other type of applications, they can still use your APIs, either manually or using a tool in their own platform) This is a project that defines C# client proxies to use the HTTP APIs of the solution. You can share this library to 3rd-party clients, so they can easily consume your HTTP APIs in their Dotnet applications (For other types of applications, they can still use your APIs, either manually or using a tool in their own platform)
Most of time you don't need to manually create C# client proxies, thanks to ABP's [Dynamic C# API Clients](../API/Dynamic-CSharp-API-Clients.md) feature. Most of the time you don't need to manually create C# client proxies, thanks to ABP's [Dynamic C# API Clients](../API/Dynamic-CSharp-API-Clients.md) feature.
`.HttpApi.Client.ConsoleTestApp` project is a console application created to demonstrate the usage of the client proxies. `.HttpApi.Client.ConsoleTestApp` project is a console application created to demonstrate the usage of the client proxies.
@ -169,17 +169,17 @@ Most of time you don't need to manually create C# client proxies, thanks to ABP'
This project contains the User Interface (UI) of the application if you are using ASP.NET Core MVC UI. It contains Razor pages, JavaScript files, CSS files, images and so on... This project contains the User Interface (UI) of the application if you are using ASP.NET Core MVC UI. It contains Razor pages, JavaScript files, CSS files, images and so on...
This project contains the main `appsettings.json` file that contains the connection string and other configuration of the application. This project contains the main `appsettings.json` file that contains the connection string and other configurations of the application.
* Depends on the `.HttpApi` since UI layer needs to use APIs and application service interfaces of the solution. * Depends on the `.HttpApi` project since the UI layer needs to use APIs and the application service interfaces of the solution.
> If you check the source code of the `.Web.csproj` file, you will see the references to the `.Application` and the `.EntityFrameworkCore` projects. > If you check the source code of the `.Web.csproj` file, you will see the references to the `.Application` and the `.EntityFrameworkCore` projects.
> >
> These references are actually not needed while coding your UI layer, because UI layer normally doesn't depend on the EF Core or the Application layer's implementation. This startup templates are ready for the tiered deployment, where API layer is hosted in a separate server than the UI layer. > These references are actually not needed while coding your UI layer, because the UI layer normally doesn't depend on the EF Core or the Application layer's implementation. These startup templates are ready for tiered deployment, where the API layer is hosted on a separate server than the UI layer.
> >
> However, if you don't choose the `--tiered` option, these references will be in the .Web project to be able to host the Web, API and application layers in a single application endpoint. > However, if you don't choose the `--tiered` option, these references will be in the .Web project to be able to host the Web, API and application layers in a single application endpoint.
> >
> This gives you to ability to use domain entities & repositories in your presentation layer. However, this is considered as a bad practice according to the DDD. > This gives you the ability to use domain entities & repositories in your presentation layer. However, this is considered as a bad practice according to DDD.
#### Test Projects #### Test Projects
@ -195,32 +195,32 @@ In addition, `.HttpApi.Client.ConsoleTestApp` is a console application (not an a
Test projects are prepared for integration testing; Test projects are prepared for integration testing;
* It is fully integrated to ABP framework and all services in your application. * It is fully integrated into the ABP framework and all services in your application.
* It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library. * It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library.
* Authorization is disabled, so any application service can be easily used in tests. * Authorization is disabled, so any application service can be easily used in tests.
You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all initialization process). You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all the initialization processes).
#### How to Run? #### How to Run?
Set `.Web` as the startup project and run the application. Default username is `admin` and password is `1q2w3E*`. Set `.Web` as the startup project and run the application. The default username is `admin` and the password is `1q2w3E*`.
See [Getting Started With the ASP.NET Core MVC Template](../Getting-Started-AspNetCore-MVC-Template.md) for more information. See [Getting Started With the ASP.NET Core MVC Template](../Getting-Started-AspNetCore-MVC-Template.md) for more information.
### Tiered Structure ### Tiered Structure
If you have selected the ASP.NET Core UI and specified the `--tiered` option, the solution created will be a tiered solution. The purpose of the tiered structure is to be able to **deploy Web application and HTTP API to different servers**: If you have selected the ASP.NET Core UI and specified the `--tiered` option, the solution created will be a tiered solution. The purpose of the tiered structure is to be able to **deploy Web applications and HTTP API to different servers**:
![bookstore-visual-studio-solution-v3](../images/tiered-solution-servers.png) ![bookstore-visual-studio-solution-v3](../images/tiered-solution-servers.png)
* Browser runs your UI by executing HTML, CSS & JavaScript. * Browser runs your UI by executing HTML, CSS & JavaScript.
* Web servers hosts static UI files (CSS, JavaScript, image... etc.) & dynamic components (e.g. Razor pages). It performs HTTP requests to the API server to execute the business logic of the application. * Web servers host static UI files (CSS, JavaScript, image... etc.) & dynamic components (e.g. Razor pages). It performs HTTP requests to the API server to execute the business logic of the application.
* API Server hosts the HTTP APIs which then use application & domain layers of the application to perform the business logic. * The API Server hosts the HTTP APIs which then use the application & domain layers of the application to perform the business logic.
* Finally, database server hosts your database. * Finally, database server hosts your database.
So, the resulting solution allows a 4-tiered deployment, by comparing to 3-tiered deployment of the default structure explained before. So, the resulting solution allows a 4-tiered deployment, by comparing to 3-tiered deployment of the default structure explained before.
> Unless you actually need to such a 4-tiered deployment, its suggested to go with the default structure which is simpler to develop, deploy and maintain. > Unless you actually need such a 4-tiered deployment, it's suggested to go with the default structure which is simpler to develop, deploy and maintain.
The solution structure is shown below: The solution structure is shown below:
@ -246,17 +246,17 @@ This project is an application that hosts the API of the solution. It has its ow
Just like the default structure, this project contains the User Interface (UI) of the application. It contains razor pages, JavaScript files, style files, images and so on... Just like the default structure, this project contains the User Interface (UI) of the application. It contains razor pages, JavaScript files, style files, images and so on...
This project contains an `appsettings.json` file, but this time it does not have a connection string because it never connects to the database. Instead, it mainly contains endpoint of the remote API server and the authentication server. This project contains an `appsettings.json` file, but this time it does not have a connection string because it never connects to the database. Instead, it mainly contains the endpoint of the remote API server and the authentication server.
#### Pre-requirements #### Pre-requirements
* [Redis](https://redis.io/): The applications use Redis as as distributed cache. So, you need to have Redis installed & running. * [Redis](https://redis.io/): The applications use Redis as a distributed cache. So, you need to have Redis installed & running.
#### How to Run? #### How to Run?
You should run the application with the given order: You should run the application with the given order:
* First, run the `.IdentityServer` since other applications depends on it. * First, run the `.IdentityServer` since other applications depend on it.
* Then run the `.HttpApi.Host` since it is used by the `.Web` application. * Then run the `.HttpApi.Host` since it is used by the `.Web` application.
* Finally, you can run the `.Web` project and login to the application (using `admin` as the username and `1q2w3E*` as the password). * Finally, you can run the `.Web` project and login to the application (using `admin` as the username and `1q2w3E*` as the password).
@ -286,9 +286,9 @@ Angular application module structure:
#### AppModule #### AppModule
`AppModule` is the root module of the application. Some of ABP modules and some essential modules imported to the `AppModule`. `AppModule` is the root module of the application. Some of the ABP modules and some essential modules are imported to `AppModule`.
ABP Config modules also have imported to `AppModule`  for initially requirements of lazy-loadable ABP modules. ABP Config modules have also been imported to `AppModule` for initial requirements of the lazy-loadable ABP modules.
#### AppRoutingModule #### AppRoutingModule
@ -315,22 +315,22 @@ You should add `routes` property in the `data` object to add a link on the menu
``` ```
In the above example; In the above example;
* If the user is not logged in, AuthGuard blocks access and redirects to the login page. * If the user is not logged in, AuthGuard blocks access and redirects to the login page.
* PermissionGuard checks the user's permission with `requiredPolicy` property of the `rotues` object. If the user is not authorized to access the page, the 403 page appears. * PermissionGuard checks the user's permission with the `requiredPolicy` property of the `routes` object. If the user is not authorized to access the page, the 403 page appears.
* `name` property of `routes` is the menu link label. A localization key can be defined . * The `name` property of `routes` is the menu link label. A localization key can be defined.
* `iconClass` property of `routes` object is the menu link icon class. * The `iconClass` property of the `routes` object is the menu link icon class.
* `requiredPolicy` property of `routes` object is the required policy key to access the page. * The `requiredPolicy` property of the `routes` object is the required policy key to access the page.
After the above `routes` definition, if the user is authorized, the dashboard link will appear on the menu. After the above `routes` definition, if the user is authorized, the dashboard link will appear on the menu.
#### Shared Module #### Shared Module
The modules that may be required for all modules have imported to the `SharedModule`. You should import the `SharedModule` to all modules. The modules that may be required for all modules have been imported to the `SharedModule`. You should import `SharedModule` to all modules.
See the [Sharing Modules](https://angular.io/guide/sharing-ngmodules) document. See the [Sharing Modules](https://angular.io/guide/sharing-ngmodules) document.
#### Environments #### Environments
The files under the `src/environments` folder has the essential configuration of the application. The files under the `src/environments` folder have the essential configuration of the application.
#### Home Module #### Home Module
@ -338,11 +338,11 @@ Home module is an example lazy-loadable module that loads on the root address of
#### Styles #### Styles
The required style files added to `styles` array in the `angular.json`. `AppComponent` loads some style files lazily via `LazyLoadService` after the main bundle is loaded to shorten the first rendering time. The required style files are added to the `styles` array in `angular.json`. `AppComponent` loads some style files lazily via `LazyLoadService` after the main bundle is loaded to shorten the first rendering time.
#### Testing #### Testing
You should create your tests in the same folder as the file file you want to test. You should create your tests in the same folder as the file you want to test.
See the [testing document](https://angular.io/guide/testing). See the [testing document](https://angular.io/guide/testing).
@ -356,7 +356,7 @@ See the [testing document](https://angular.io/guide/testing).
### React Native ### React Native
if `-m react-native` option is spesified in new project command, the solution includes the [React Native](https://reactnative.dev/) application in the `react-native` folder. If the `-m react-native` option is specified in the new project command, the solution includes the [React Native](https://reactnative.dev/) application in the `react-native` folder.
The server-side is similar to the solution described above. `*.HttpApi.Host` project serves the API, so the React Native application consumes it. The server-side is similar to the solution described above. `*.HttpApi.Host` project serves the API, so the React Native application consumes it.
@ -366,17 +366,17 @@ React Native application folder structure as like below:
![react-native-folder-structure](../images/react-native-folder-structure.png) ![react-native-folder-structure](../images/react-native-folder-structure.png)
* `App.js` is bootstrap component of the application. * `App.js` is the bootstrap component of the application.
* `Environment.js` file has the essential configuration of the application. `prod` and `dev` configurations defined in this file. * `Environment.js` file has the essential configuration of the application. `prod` and `dev` configurations are defined in this file.
* [Contexts](https://reactjs.org/docs/context.html) are created in the `src/contexts` folder. * [Contexts](https://reactjs.org/docs/context.html) are created in the `src/contexts` folder.
* [Higher order components](https://reactjs.org/docs/higher-order-components.html) are created in the`src/hocs` folder. * [Higher order components](https://reactjs.org/docs/higher-order-components.html) are created in the `src/hocs` folder.
* [Custom hooks](https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook) are created in the`src/hooks`. * [Custom hooks](https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook) are created in `src/hooks`.
* [Axios interceptors](https://github.com/axios/axios#interceptors) are created in the `src/interceptors` folder. * [Axios interceptors](https://github.com/axios/axios#interceptors) are created in the `src/interceptors` folder.
* Utility functions are exported from `src/utils` folder. * Utility functions are exported from `src/utils` folder.
#### Components #### Components
Components that can be used on all screens are created in the `src/components` folder. All components have created as a function that able to use [hooks](https://reactjs.org/docs/hooks-intro.html). Components that can be used on all screens are created in the `src/components` folder. All components have been created as a function that is able to use [hooks](https://reactjs.org/docs/hooks-intro.html).
#### Screens #### Screens
@ -388,13 +388,13 @@ Each screen is used in a navigator in the `src/navigators` folder.
#### Navigation #### Navigation
[React Navigation](https://reactnavigation.org/) is used as a navigation library. Navigators are created in the `src/navigators`. A [drawer](https://reactnavigation.org/docs/drawer-based-navigation/) navigator and several [stack](https://reactnavigation.org/docs/hello-react-navigation/#installing-the-stack-navigator-library) navigators have created in this folder. See the [above diagram](#screens) for navigation structure. [React Navigation](https://reactnavigation.org/) is used as a navigation library. Navigators are created in the `src/navigators`. A [drawer](https://reactnavigation.org/docs/drawer-based-navigation/) navigator and several [stack](https://reactnavigation.org/docs/hello-react-navigation/#installing-the-stack-navigator-library) navigators have been created in this folder. See the [above diagram](#screens) for the navigation structure.
#### State Management #### State Management
[Redux](https://redux.js.org/) is used as state management library. [Redux Toolkit](https://redux-toolkit.js.org/) library is used as a toolset for efficient Redux development. [Redux](https://redux.js.org/) is used as a state management library. [Redux Toolkit](https://redux-toolkit.js.org/) library is used as a toolset for efficient Redux development.
Actions, reducers, sagas, selectors are created in the `src/store` folder. Store folder as like below: Actions, reducers, sagas and selectors are created in the `src/store` folder. Store folder is as below:
![react-native-store-folder](../images/react-native-store-folder.png) ![react-native-store-folder](../images/react-native-store-folder.png)
@ -426,11 +426,11 @@ See the [Testing Overview](https://reactjs.org/docs/testing.html) document.
* [Native Base](https://nativebase.io/) is used as UI components library. * [Native Base](https://nativebase.io/) is used as UI components library.
* [React Navigation](https://reactnavigation.org/) is used as navigation library. * [React Navigation](https://reactnavigation.org/) is used as navigation library.
* [Axios](https://github.com/axios/axios) is used as HTTP client library. * [Axios](https://github.com/axios/axios) is used as an HTTP client library.
* [Redux](https://redux.js.org/) is used as state management library. * [Redux](https://redux.js.org/) is used as state management library.
* [Redux Toolkit](https://redux-toolkit.js.org/) library is used as a toolset for efficient Redux development. * [Redux Toolkit](https://redux-toolkit.js.org/) library is used as a toolset for efficient Redux development.
* [Redux-Saga](https://redux-saga.js.org/) is used to manage asynchronous processes. * [Redux-Saga](https://redux-saga.js.org/) is used to manage asynchronous processes.
* [Redux Persist](https://github.com/rt2zz/redux-persist) is used as state persistance. * [Redux Persist](https://github.com/rt2zz/redux-persist) is used as state persistence.
* [Reselect](https://github.com/reduxjs/reselect) is used to create memoized selectors. * [Reselect](https://github.com/reduxjs/reselect) is used to create memoized selectors.
* [i18n-js](https://github.com/fnando/i18n-js) is used as i18n library. * [i18n-js](https://github.com/fnando/i18n-js) is used as i18n library.
* [expo-font](https://docs.expo.io/versions/latest/sdk/font/) library allows loading fonts easily. * [expo-font](https://docs.expo.io/versions/latest/sdk/font/) library allows loading fonts easily.

23
docs/en/Themes/LeptonXLite/blazor.md

@ -23,12 +23,17 @@ LeptonX Lite has implementation for the ABP Framework Blazor WebAssembly & Blazo
dotnet add package Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme dotnet add package Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme
``` ```
- Remove **Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme** reference from the project since it's not necessary after switching to LeptonX Lite.
- Remove the old theme from the **DependsOn** attribute in your module class and add the **AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeModule** type to the **DependsOn** attribute. - Remove the old theme from the **DependsOn** attribute in your module class and add the **AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeModule** type to the **DependsOn** attribute.
```diff ```diff
[DependsOn( [DependsOn(
// Remove BasicTheme module from DependsOn attribute
- typeof(AbpAspNetCoreComponentsWebAssemblyBasicThemeModule), - typeof(AbpAspNetCoreComponentsWebAssemblyBasicThemeModule),
+ typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeModule)
// Add LeptonX Lite module to DependsOn attribute
+ typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeModule),
)] )]
``` ```
@ -53,19 +58,27 @@ builder.RootComponents.Add<App>("#ApplicationContainer");
dotnet add package Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme dotnet add package Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme
``` ```
- Remove old theme from the **DependsOn** attribute in your module class and add the **AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeModule** type to the **DependsOn** attribute. - Remove **Volo.Abp.AspNetCore.Components.Server.BasicTheme** reference from the project since it's not necessary after switching to LeptonX Lite.
- Remove old theme from the **DependsOn** attribute in your module class and add the **AbpAspNetCoreComponentsServerLeptonXLiteThemeModule** type to the **DependsOn** attribute.
```diff ```diff
[DependsOn( [DependsOn(
// Remove BasicTheme module from DependsOn attribute
- typeof(AbpAspNetCoreComponentsServerBasicThemeModule), - typeof(AbpAspNetCoreComponentsServerBasicThemeModule),
// Add LeptonX Lite module to DependsOn attribute
+ typeof(AbpAspNetCoreComponentsServerLeptonXLiteThemeModule) + typeof(AbpAspNetCoreComponentsServerLeptonXLiteThemeModule)
)] )]
``` ```
- Update AbpBundlingOptions - Replace `BlazorBasicThemeBundles` with `BlazorLeptonXLiteThemeBundles` in `AbpBundlingOptions`:
```diff ```diff
options.StyleBundles.Configure( options.StyleBundles.Configure(
// Remove following line
- BlazorBasicThemeBundles.Styles.Global, - BlazorBasicThemeBundles.Styles.Global,
// Add following line instead
+ BlazorLeptonXLiteThemeBundles.Styles.Global, + BlazorLeptonXLiteThemeBundles.Styles.Global,
bundle => bundle =>
{ {
@ -84,12 +97,16 @@ builder.RootComponents.Add<App>("#ApplicationContainer");
``` ```
- Then replace script & style bundles as following: - Then replace script & style bundles as following:
```diff ```diff
// Remove following line
- <abp-style-bundle name="@BlazorBasicThemeBundles.Styles.Global" /> - <abp-style-bundle name="@BlazorBasicThemeBundles.Styles.Global" />
// Add following line instead
+ <abp-style-bundle name="@BlazorLeptonXLiteThemeBundles.Styles.Global" /> + <abp-style-bundle name="@BlazorLeptonXLiteThemeBundles.Styles.Global" />
``` ```
```diff ```diff
// Remove following line
- <abp-script-bundle name="@BlazorBasicThemeBundles.Scripts.Global" /> - <abp-script-bundle name="@BlazorBasicThemeBundles.Scripts.Global" />
// Add following line instead
+ <abp-script-bundle name="@BlazorLeptonXLiteThemeBundles.Scripts.Global" /> + <abp-script-bundle name="@BlazorLeptonXLiteThemeBundles.Scripts.Global" />
``` ```

13
docs/en/Themes/LeptonXLite/mvc.md

@ -10,25 +10,32 @@ LeptonX Lite has implementation for the ABP Framework Razor Pages. It's a simpli
- Add **Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite** package to your **Web** application. - Add **Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite** package to your **Web** application.
```bash ```bash
abp add-package Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite dotnet add package Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite --prerelease
``` ```
- Remove **Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic** reference from the project since it's not necessary after switching to LeptonX Lite.
- Make sure the old theme is removed and LeptonX is added in your Module class. - Make sure the old theme is removed and LeptonX is added in your Module class.
```diff ```diff
[DependsOn( [DependsOn(
// Remove BasicTheme module from DependsOn attribute
- typeof(AbpAspNetCoreMvcUiBasicThemeModule), - typeof(AbpAspNetCoreMvcUiBasicThemeModule),
+ typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule)
// Add LeptonX Lite module to DependsOn attribute
+ typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule),
)] )]
``` ```
- Update AbpBundlingOptions - Replace `BasicThemeBundles` with `LeptonXLiteThemeBundles` in AbpBundlingOptions
```diff ```diff
Configure<AbpBundlingOptions>(options => Configure<AbpBundlingOptions>(options =>
{ {
options.StyleBundles.Configure( options.StyleBundles.Configure(
// Remove following line
- BasicThemeBundles.Styles.Global, - BasicThemeBundles.Styles.Global,
// Add following line instead
+ LeptonXLiteThemeBundles.Styles.Global + LeptonXLiteThemeBundles.Styles.Global
bundle => bundle =>
{ {

8
docs/en/Tutorials/Todo/Index.md

@ -96,13 +96,7 @@ Ensure that the `TodoApp.HttpApi.Host` project is the startup project, then run
You can explore and test your HTTP API with this UI. If it works, we can run the Angular client application. You can explore and test your HTTP API with this UI. If it works, we can run the Angular client application.
First, run the following command to restore the NPM packages; You can run the application using the following command:
````bash
npm install
````
It will take some time to install all the packages. Then you can run the application using the following command:
````bash ````bash
npm start npm start

24
docs/en/UI/AspNetCore/JavaScript-API/GlobalFeatures.md

@ -0,0 +1,24 @@
# ASP.NET Core MVC / Razor Pages UI: JavaScript Global Features API
`abp.globalFeatures` API allows you to get the enabled features of the [Global Features](../../../Global-Features.md) in the client side.
> This document only explains the JavaScript API. See the [Global Features](../../../Global-Features.md) document to understand the ABP Global Features system.
## Usage
````js
//Gets all enabled global features.
> abp.globalFeatures.enabledFeatures
[ 'Shopping.Payment', 'Ecommerce.Subscription' ]
//Check the global feature is enabled
> abp.globalFeatures.isEnabled('Ecommerce.Subscription')
true
> abp.globalFeatures.isEnabled('My.Subscription')
false
````

1
docs/en/UI/AspNetCore/JavaScript-API/Index.md

@ -10,6 +10,7 @@ ABP provides a set of JavaScript APIs for ASP.NET Core MVC / Razor Pages applica
* [DOM](DOM.md) * [DOM](DOM.md)
* [Events](Events.md) * [Events](Events.md)
* [Features](Features.md) * [Features](Features.md)
* [Global Features](GlobalFeatures.md)
* [Localization](Localization.md) * [Localization](Localization.md)
* [Logging](Logging.md) * [Logging](Logging.md)
* [ResourceLoader](ResourceLoader.md) * [ResourceLoader](ResourceLoader.md)

23
docs/en/docs-nav.json

@ -1320,11 +1320,32 @@
"path": "Samples/Index.md" "path": "Samples/Index.md"
}, },
{ {
"text": "Microservice Demo", "text": "eShopOnAbp",
"path": "https://github.com/abpframework/eShopOnAbp"
},
{
"text": "EventHub",
"path": "https://github.com/abpframework/eventhub"
},
{
"text": "Microservice Demo (legacy)",
"path": "Samples/Microservice-Demo.md" "path": "Samples/Microservice-Demo.md"
} }
] ]
}, },
{
"text": "Books",
"items": [
{
"text": "Mastering ABP Framework",
"path": "https://abp.io/books/mastering-abp-framework"
},
{
"text": "Implementing Domain Driven Design",
"path": "https://abp.io/books/implementing-domain-driven-design"
}
]
},
{ {
"text": "Release Information", "text": "Release Information",
"items": [ "items": [

2
docs/zh-Hans/Distributed-Event-Bus.md

@ -84,7 +84,7 @@ namespace AbpDemo
#### 关于序列化的事件对象 #### 关于序列化的事件对象
事件传输对象**必须是可序列化**的,因为将其传输到流程外时,它们将被序列化/反序列化为JSON或其他格式. 事件传输对象**必须是可序列化**的,因为将其传输到进程外时,它们将被序列化/反序列化为JSON或其他格式.
避免循环引用,多态,私有setter,并提供默认(空)构造函数,如果你有其他的构造函数.(虽然某些序列化器可能会正常工作),就像DTO一样. 避免循环引用,多态,私有setter,并提供默认(空)构造函数,如果你有其他的构造函数.(虽然某些序列化器可能会正常工作),就像DTO一样.

1
docs/zh-Hans/Domain-Services.md

@ -116,7 +116,6 @@ namespace MyProject.Issues
## 应用程序服务与领域服务 ## 应用程序服务与领域服务
虽然应用服务和领域服务都实现了业务规则,但存在根本的逻辑和形式差异;
虽然 [应用服务](Application-Services.md) 和领域服务都实现了业务规则,但存在根本的逻辑和形式差异: 虽然 [应用服务](Application-Services.md) 和领域服务都实现了业务规则,但存在根本的逻辑和形式差异:
* 应用程序服务实现应用程序的 **用例** (典型 Web 应用程序中的用户交互), 而领域服务实现 **核心的、用例独立的领域逻辑**. * 应用程序服务实现应用程序的 **用例** (典型 Web 应用程序中的用户交互), 而领域服务实现 **核心的、用例独立的领域逻辑**.

4
docs/zh-Hans/Entities.md

@ -70,7 +70,7 @@ public class BookAppService : ApplicationService, IBookAppService
} }
```` ````
* `BookAppService` 注入图书实体的默认[仓库](Repositories.md),使用`InsertAsync`方法插入 `Book` 到数据库中. * `BookAppService` 注入图书实体的默认[仓储](Repositories.md),使用`InsertAsync`方法插入 `Book` 到数据库中.
* `GuidGenerator`类型是 `IGuidGenerator`,它是在`ApplicationService`基类中定义的属性. ABP将这样常用属性预注入,所以不需要手动[注入](Dependency-Injection.md). * `GuidGenerator`类型是 `IGuidGenerator`,它是在`ApplicationService`基类中定义的属性. ABP将这样常用属性预注入,所以不需要手动[注入](Dependency-Injection.md).
* 如果你想遵循DDD最佳实践,请参阅下面的*聚合示例*部分. * 如果你想遵循DDD最佳实践,请参阅下面的*聚合示例*部分.
@ -373,7 +373,7 @@ public static class IdentityUserExtensions
* 对于 [Entity Framework Core](Entity-Framework-Core.md),这是两种类型的配置; * 对于 [Entity Framework Core](Entity-Framework-Core.md),这是两种类型的配置;
* 默认它以 `JSON` 字符串形式存储在 `ExtraProperties` 字段中. 序列化到 `JSON` 和反序列化到 `JSON` 由ABP使用EF Core的[值转换](https://docs.microsoft.com/zh-cn/ef/core/modeling/value-conversions)系统自动完成. * 默认它以 `JSON` 字符串形式存储在 `ExtraProperties` 字段中. 序列化到 `JSON` 和反序列化到 `JSON` 由ABP使用EF Core的[值转换](https://docs.microsoft.com/zh-cn/ef/core/modeling/value-conversions)系统自动完成.
* 如果需要,你可以使用 `ObjectExtensionManager` 为所需的额外属性定义一个单独的数据库字段. 那些使用 `ObjectExtensionManager` 配置的属性继续使用单个 `JSON` 字段. 当你使用预构建的[应用模块](Modules/Index.md)并且想要[扩展模块的实体](Customizing-Application-Modules-Extending-Entities.md). 参阅[EF Core迁移文档](Entity-Framework-Core.md)了解如何使用 `ObjectExtensionManager`. * 如果需要,你可以使用 `ObjectExtensionManager` 为所需的额外属性定义一个单独的数据库字段. 未使用 `ObjectExtensionManager` 配置的属性继续使用单个 `JSON` 字段. 当你使用预构建的[应用模块](Modules/Index.md)并且想要[扩展模块的实体](Customizing-Application-Modules-Extending-Entities.md). 参阅[EF Core迁移文档](Entity-Framework-Core.md)了解如何使用 `ObjectExtensionManager`.
* 对于 [MongoDB](MongoDB.md), 它以 **常规字段** 存储, 因为 MongoDB 天生支持这种 [额外](https://mongodb.github.io/mongo-csharp-driver/1.11/serialization/#supporting-extra-elements) 系统. * 对于 [MongoDB](MongoDB.md), 它以 **常规字段** 存储, 因为 MongoDB 天生支持这种 [额外](https://mongodb.github.io/mongo-csharp-driver/1.11/serialization/#supporting-extra-elements) 系统.
### 讨论额外的属性 ### 讨论额外的属性

2
docs/zh-Hans/Module-Development-Basics.md

@ -49,7 +49,7 @@ public class BlogModule : AbpModule
} }
} }
```` ````
有关配置系统的更多信息,请参阅配置(TODO:link)文档. 有关配置系统的更多信息,请参阅[配置](Configuration.md)文档.
##### 配置服务前和后 ##### 配置服务前和后

570
docs/zh-Hans/Text-Templating-Razor.md

@ -0,0 +1,570 @@
# Razor 集成
Razor模板是标准的C#类, 所以你可以使用任何C#的功能, 例如`依赖注入`, 使用`LINQ`, 自定义方法甚至使用`仓储`
## 安装
建议使用[ABP CLI](CLI.md)安装此包.
### 使用ABP CLI
在项目文件夹(.csproj 文件)中打开命令行窗口并输入以下命令:
````bash
abp add-package Volo.Abp.TextTemplating.Razor
````
### 手动安装
如果你想要手动安装:
1. 添加 [Volo.Abp.TextTemplating.Razor](https://www.nuget.org/packages/Volo.Abp.TextTemplating.Razor) NuGet 包到你的项目:
````
Install-Package Volo.Abp.TextTemplating.Razor
````
2.添加 `AbpTextTemplatingRazorModule` 到你的模块的依赖列表:
````csharp
[DependsOn(
//...other dependencies
typeof(AbpTextTemplatingRazorModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
````
## 添加 MetadataReference到CSharpCompilerOptions
你需要将添加`MetadataReference`模板中使用的类型添加到 `CSharpCompilerOptions` 的 `References`.
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpRazorTemplateCSharpCompilerOptions>(options =>
{
options.References.Add(MetadataReference.CreateFromFile(typeof(YourModule).Assembly.Location));
});
}
```
## 添加MetadataReference到模板
你可以添加一些`MetadataReference`到模板
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
services.Configure<AbpCompiledViewProviderOptions>(options =>
{
//Hello is template name.
options.TemplateReferences.Add("Hello", new List<Assembly>()
{
Assembly.Load("Microsoft.Extensions.Logging.Abstractions"),
Assembly.Load("Microsoft.Extensions.Logging")
}
.Select(x => MetadataReference.CreateFromFile(x.Location))
.ToList());
});
}
```
## 定义模板
在渲染模板之前,需要定义它. 创建一个继承自 `TemplateDefinitionProvider` 的类:
````csharp
public class DemoTemplateDefinitionProvider : TemplateDefinitionProvider
{
public override void Define(ITemplateDefinitionContext context)
{
context.Add(
new TemplateDefinition("Hello") //template name: "Hello"
.WithRazorEngine()
.WithVirtualFilePath(
"/Demos/Hello/Hello.cshtml", //template content path
isInlineLocalized: true
)
);
}
}
````
* `context` 对象用于添加新模板或获取依赖模块定义的模板. 使用 `context.Add(...)` 定义新模板.
* `TemplateDefinition` 是代表模板的类,每个模板必须有唯一的名称(在渲染模板时使用).
* `/Demos/Hello/Hello.cshtml` 是模板文件的路径.
* `isInlineLocalized` 声明针对所有语言使用一个模板(`true` 还是针对每种语言使用不同的模板(`false`). 更多内容参阅下面的本地化部分.
* `WithRenderEngine` 方法为模板设置渲染引擎.
### 模板基类
每个 `cshtml` 模板页面都需要继承`RazorTemplatePageBase` 或 `RazorTemplatePageBase<Model>`. 基类提供了一些使用实用的属性可以在模板中使用. 例如: `Localizer`, `ServiceProvider`.
### 模板内容
`WithVirtualFilePath` 表示我们使用[虚拟文件系统](Virtual-File-System.md)存储模板内容. 在项目内创建一个 `Hello.cshtml` 文件,并在属性窗口中将其标记为"**嵌入式资源**":
![hello-template-razor](images/hello-template-razor.png)
示例 `Hello.cshtml` 内容如下所示:
```csharp
namespace HelloModelNamespace
{
public class HelloModel
{
public string Name { get; set; }
}
}
```
[虚拟文件系统](Virtual-File-System.md) 需要在[模块](Module-Development-Basics.md)类的 `ConfigureServices` 方法添加你的文件:
````csharp
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<TextTemplateDemoModule>("TextTemplateDemo");
});
````
* `TextTemplateDemoModule`是模块类.
* `TextTemplateDemo` 是你的项目的根命名空间.
## 渲染模板
`ITemplateRenderer` 服务用于渲染模板内容.
### 示例: 渲染一个简单的模板
````csharp
public class HelloDemo : ITransientDependency
{
private readonly ITemplateRenderer _templateRenderer;
public HelloDemo(ITemplateRenderer templateRenderer)
{
_templateRenderer = templateRenderer;
}
public async Task RunAsync()
{
var result = await _templateRenderer.RenderAsync(
"Hello", //the template name
new HelloModel
{
Name = "John"
}
);
Console.WriteLine(result);
}
}
````
* `HelloDemo` 是一个简单的类,在构造函数注入了 `ITemplateRenderer` 并在 `RunAsync` 方法中使用它.
* `RenderAsync` 有两个基本参数:
* `templateName`: 要渲染的模板名称 (本示例中是 `Hello`).
* `model`: 在模板内部用做 `model` 的对象 (本示例中是 `HelloModel` 对象).
示例会返回以下结果:
````csharp
Hello John :)
````
## 本地化
可以基于当前文化对模板内容进行本地化. 以下部分描述了两种类型的本地化选项.
### 内联本地化
内联本地化使用[本地化系统](Localization.md)本地化模板内的文本.
#### 示例: 重置密码链接
假设你需要向用户发送电子邮件重置密码. 模板内容:
```csharp
namespace ResetMyPasswordModelNamespace
{
public class ResetMyPasswordModel
{
public string Link { get; set; }
public string Name { get; set; }
}
}
```
```csharp
@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase<ResetMyPasswordModelNamespace.ResetMyPasswordModel>
<a title="@Localizer["ResetMyPasswordTitle"]" href="@Model.Link">@Localizer["ResetMyPassword", Model.Name]</a>
```
`Localizer` 函数用于根据当前用户的文化来定位给定的Key,你需要在本地化文件中定义 `ResetMyPassword` 键:
````json
"ResetMyPasswordTitle": "Reset my password",
"ResetMyPassword": "Hi {0}, Click here to reset your password"
````
你还需要在模板定义提供程序类中声明要与此模板一起使用的本地化资源:
````csharp
context.Add(
new TemplateDefinition(
"PasswordReset", //Template name
typeof(DemoResource) //LOCALIZATION RESOURCE
)
.WithRazorEngine()
.WithVirtualFilePath(
"/Demos/PasswordReset/PasswordReset.cshtml", //template content path
isInlineLocalized: true
)
);
````
当你这样渲染模板时:
````csharp
var result = await _templateRenderer.RenderAsync(
"PasswordReset", //the template name
new PasswordResetModel
{
Name = "john",
Link = "https://abp.io/example-link?userId=123&token=ABC"
}
);
````
你可以看到以下本地化结果:
````csharp
<a title="Reset my password" href="https://abp.io/example-link?userId=123&token=ABC">Hi john, Click here to reset your password</a>
````
> 如果你为应用程序定义了 [默认本地化资源](Localization.md), 则无需声明模板定义的资源类型.
### 多个内容本地化
你可能希望为每种语言创建不同的模板文件,而不是使用本地化系统本地化单个模板. 如果模板对于特定的文化(而不是简单的文本本地化)应该是完全不同的,则可能需要使用它.
#### 示例: 欢迎电子邮件模板
假设你要发送电子邮件欢迎用户,但要定义基于用户的文化完全不同的模板.
首先创建一个文件夹,将模板放在里面,像 `en.cshtml`, `tr.cshtml` 每一个你支持的文化:
![multiple-file-template-razor](images/multiple-file-template-razor.png)
然后在模板定义提供程序类中添加模板定义:
````csharp
context.Add(
new TemplateDefinition(
name: "WelcomeEmail",
defaultCultureName: "en"
)
.WithRazorEngine()
.WithVirtualFilePath(
"/Demos/WelcomeEmail/Templates", //template content folder
isInlineLocalized: false
)
);
````
* 设置 **默认文化名称**, 当没有所需的文化模板,回退到缺省文化.
* 指定 **模板文件夹** 而不是单个模板文件.
* 设置 `isInlineLocalized` 为 `false`.
就这些,你可以渲染当前文化的模板:
````csharp
var result = await _templateRenderer.RenderAsync("WelcomeEmail");
````
> 为了简单我们跳过了模型,但是你可以使用前面所述的模型.
### 指定文化
`ITemplateRenderer` 服务如果没有指定则使用当前文化 (`CultureInfo.CurrentUICulture`). 如果你需要你可以使用 `cultureName` 参数指定文化.
````csharp
var result = await _templateRenderer.RenderAsync(
"WelcomeEmail",
cultureName: "en"
);
````
## 布局模板
布局模板用于在其他模板之间创建共享布局. 它类似于ASP.NET Core MVC / Razor Pages中的布局系统.
### 示例: 邮件HTML布局模板
例如,你想为所有电子邮件模板创建一个布局.
首先像之前一样创建一个模板文件:
```csharp
@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
</head>
<body>
@Body
</body>
</html>
```
* 布局模板必须具有 **Body** 部分作为渲染的子内容的占位符.
在模板定义提供程序中注册模板:
````csharp
context.Add(
new TemplateDefinition(
"EmailLayout",
isLayout: true //SET isLayout!
)
.WithRazorEngine()
.WithVirtualFilePath(
"/Demos/EmailLayout/EmailLayout.cshtml",
isInlineLocalized: true
)
);
````
现在你可以将此模板用作任何其他模板的布局:
````csharp
context.Add(
new TemplateDefinition(
name: "WelcomeEmail",
defaultCultureName: "en",
layout: "EmailLayout" //Set the LAYOUT
)
.WithRazorEngine()
.WithVirtualFilePath(
"/Demos/WelcomeEmail/Templates",
isInlineLocalized: false
)
);
````
## 全局上下文
ABP传递 `model`,可用于访问模板内的模型. 如果需要,可以传递更多的全局变量.
示例模板内容:
````csharp
@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase
A global object value: @GlobalContext["myGlobalObject"]
````
模板假定它渲染上下文中的 `myGlobalObject` 对象. 你可以如下所示提供它:
````csharp
var result = await _templateRenderer.RenderAsync(
"GlobalContextUsage",
globalContext: new Dictionary<string, object>
{
{"myGlobalObject", "TEST VALUE"}
}
);
````
渲染的结果将是:
````
A global object value: TEST VALUE
````
## 替换存在的模板
通过替换应用程序中使用的模块定义的模板. 这样你可以根据自己的需求自定义模板,而无需更改模块代码.
### 选项-1: 使用虚拟文件系统
[虚拟文件系统](Virtual-File-System.md)允许你通过将相同文件放入项目中的相同路径来覆盖任何文件.
#### 示例: 替换标准电子邮件布局模板
ABP框架提供了一个[邮件发送系统](Emailing.md), 它在内部使用文本模板来渲染邮件内容. 它在 `/Volo/Abp/Emailing/Templates/Layout.cshtml` 路径定义了一个标准邮件布局模板. 模板的唯一名称是 `Abp.StandardEmailTemplates.Layout` 并且这个字符中`Volo.Abp.Emailing.Templates.StandardEmailTemplates`静态类上定义为常量.
执行以下步骤将替换模板替换成你自定义的;
**1)** 在你的项目中相同的路径添加一个新文件 (`/Volo/Abp/Emailing/Templates/Layout.cshtml`):
![replace-email-layout-razor](images/replace-email-layout-razor.png)
**2)** 准备你的邮件布局模板:
````html
@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>This my header</h1>
@Body
<footer>
This is my footer...
</footer>
</body>
</html>
````
此示例只是向模板添加页眉和页脚并呈现它们之间的内容(请参阅上面的布局模板部分).
**3)** 在`.csproj`文件配置嵌入式资源e
* 添加 [Microsoft.Extensions.FileProviders.Embedded](https://www.nuget.org/packages/Microsoft.Extensions.FileProviders.Embedded) NuGet 包到你的项目.
* 在 `.csproj` 中添加 `<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>` 到 `<PropertyGroup>...</PropertyGroup>` 部分.
* 添加以下代码到你的 `.csproj` 文件:
````xml
<ItemGroup>
<None Remove="Volo\Abp\Emailing\Templates\*.cshtml" />
<EmbeddedResource Include="Volo\Abp\Emailing\Templates\*.cshtml" />
</ItemGroup>
````
这将模板文件做为"嵌入式资源".
**4)** 配置虚拟文件系统
在[模块](Module-Development-Basics.md) `ConfigureServices` 方法配置 `AbpVirtualFileSystemOptions` 将嵌入的文件添加到虚拟文件系统中:
```csharp
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<BookStoreDomainModule>();
});
```
`BookStoreDomainModule` 应该是你的模块名称
> 确保你的模块(支持或间接)[依赖](Module-Development-Basics.md) `AbpEmailingModule`. 因为VFS可以基于依赖顺序覆盖文件.
现在渲染邮件布局模板时会使用你的模板.
### 选项-2: 使用模板定义提供者
你可以创建一个模板定义提供者类来获取邮件布局模板来更改它的虚拟文件路径.
**示例: 使用 `/MyTemplates/EmailLayout.cshtml` 文件而不是标准模板**
```csharp
using Volo.Abp.DependencyInjection;
using Volo.Abp.Emailing.Templates;
using Volo.Abp.TextTemplating;
namespace MyProject
{
public class MyTemplateDefinitionProvider
: TemplateDefinitionProvider, ITransientDependency
{
public override void Define(ITemplateDefinitionContext context)
{
var emailLayoutTemplate = context.GetOrNull(StandardEmailTemplates.Layout);
emailLayoutTemplate
.WithVirtualFilePath(
"/MyTemplates/EmailLayout.cshtml",
isInlineLocalized: true
);
}
}
}
```
你依然应该添加 `/MyTemplates/EmailLayout.cshtml` 到虚拟文件系统. 这种方法允许你在任何文件夹中找到模板,而不是在依赖模块定义的文件夹中.
除了模板内容之外你还可以操作模板定义属性, 例如`DisplayName`, `Layout`或`LocalizationSource`.
## 高级功能
本节介绍文本模板系统的一些内部知识和高级用法.
### 模板内容Provider
`TemplateRenderer` 用于渲染模板,这是大多数情况下所需的模板. 但是你可以使用 `ITemplateContentProvider` 获取原始(未渲染的)模板内容.
> `ITemplateRenderer` 内部使用 `ITemplateContentProvider` 获取原始模板内容.
示例:
````csharp
public class TemplateContentDemo : ITransientDependency
{
private readonly ITemplateContentProvider _templateContentProvider;
public TemplateContentDemo(ITemplateContentProvider templateContentProvider)
{
_templateContentProvider = templateContentProvider;
}
public async Task RunAsync()
{
var result = await _templateContentProvider
.GetContentOrNullAsync("Hello");
Console.WriteLine(result);
}
}
````
结果是原始模板内容:
````
@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase<HelloModelNamespace.HelloModel>
Hello @Model.Name
````
* `GetContentOrNullAsync` 如果没有为请求的模板定义任何内容,则返回 `null`.
* 它可以获取 `cultureName` 参数,如果模板针对不同的文化具有不同的文件,则可以使用该参数(请参见上面的"多内容本地化"部分).
### 模板内容贡献者
`ITemplateContentProvider` 服务使用 `ITemplateContentContributor` 实现来查找模板内容. 有一个预实现的内容贡献者 `VirtualFileTemplateContentContributor`,它从上面描述的虚拟文件系统中获取模板内容.
你可以实现 `ITemplateContentContributor` 从另一个源读取原始模板内容.
示例:
````csharp
public class MyTemplateContentProvider
: ITemplateContentContributor, ITransientDependency
{
public async Task<string> GetOrNullAsync(TemplateContentContributorContext context)
{
var templateName = context.TemplateDefinition.Name;
//TODO: Try to find content from another source
return null;
}
}
````
如果源无法找到内容, 则返回 `null`, `ITemplateContentProvider` 将回退到下一个贡献者.
### Template Definition Manager
`ITemplateDefinitionManager` 服务可用于获取模板定义(由模板定义提供程序创建).
## 另请参阅
* 本文开发和引用的[应用程序示例源码](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo).
* [本地化系统](Localization.md).
* [虚拟文件系统](Virtual-File-System.md).

527
docs/zh-Hans/Text-Templating-Scriban.md

@ -0,0 +1,527 @@
# Scriban 集成
## 安装
建议使用[ABP CLI](CLI.md)安装此包.
### 使用ABP CLI
在项目文件夹(.csproj 文件)中打开命令行窗口并输入以下命令:
````bash
abp add-package Volo.Abp.TextTemplating.Scriban
````
### 手动安装
如果你想要手动安装:
1. 添加 [Volo.Abp.TextTemplating.Scriban](https://www.nuget.org/packages/Volo.Abp.TextTemplating.Scriban) NuGet 包到你的项目:
````
Install-Package Volo.Abp.TextTemplating.Scriban
````
2.添加 `AbpTextTemplatingScribanModule` 到你的模块的依赖列表:
````csharp
[DependsOn(
//...other dependencies
typeof(AbpTextTemplatingScribanModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
````
## 定义模板
在渲染模板之前,需要定义它. 创建一个继承自 `TemplateDefinitionProvider` 的类:
````csharp
public class DemoTemplateDefinitionProvider : TemplateDefinitionProvider
{
public override void Define(ITemplateDefinitionContext context)
{
context.Add(
new TemplateDefinition("Hello") //template name: "Hello"
.WithVirtualFilePath(
"/Demos/Hello/Hello.tpl", //template content path
isInlineLocalized: true
)
.WithScribanEngine()
);
}
}
````
* `context` 对象用于添加新模板或获取依赖模块定义的模板. 使用 `context.Add(...)` 定义新模板.
* `TemplateDefinition` 是代表模板的类,每个模板必须有唯一的名称(在渲染模板时使用).
* `/Demos/Hello/Hello.tpl` 是模板文件的路径.
* `isInlineLocalized` 声明针对所有语言使用一个模板(`true` 还是针对每种语言使用不同的模板(`false`). 更多内容参阅下面的本地化部分.
* `WithScribanEngine` 方法为模板设置渲染引擎.
### 模板内容
`WithVirtualFilePath` 表示我们使用[虚拟文件系统](Virtual-File-System.md)存储模板内容. 在项目内创建一个 `Hello.tpl` 文件,并在属性窗口中将其标记为"**嵌入式资源**":
![hello-template](images/hello-template.png)
示例 `Hello.tpl` 内容如下所示:
````
Hello {%{{{model.name}}}%} :)
````
[虚拟文件系统](Virtual-File-System.md) 需要在[模块](Module-Development-Basics.md)类的 `ConfigureServices` 方法添加你的文件:
````csharp
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<TextTemplateDemoModule>("TextTemplateDemo");
});
````
* `TextTemplateDemoModule`是模块类.
* `TextTemplateDemo` 是你的项目的根命名空间.
## 渲染模板
`ITemplateRenderer` 服务用于渲染模板内容.
### 示例: 渲染一个简单的模板
````csharp
public class HelloDemo : ITransientDependency
{
private readonly ITemplateRenderer _templateRenderer;
public HelloDemo(ITemplateRenderer templateRenderer)
{
_templateRenderer = templateRenderer;
}
public async Task RunAsync()
{
var result = await _templateRenderer.RenderAsync(
"Hello", //the template name
new HelloModel
{
Name = "John"
}
);
Console.WriteLine(result);
}
}
````
* `HelloDemo` 是一个简单的类,在构造函数注入了 `ITemplateRenderer` 并在 `RunAsync` 方法中使用它.
* `RenderAsync` 有两个基本参数:
* `templateName`: 要渲染的模板名称 (本示例中是 `Hello`).
* `model`: 在模板内部用做 `model` 的对象 (本示例中是 `HelloModel` 对象).
示例会返回以下结果:
````csharp
Hello John :)
````
### 匿名模型
虽然建议为模板创建模型类,但在简单情况下使用匿名对象也是可行的:
````csharp
var result = await _templateRenderer.RenderAsync(
"Hello",
new
{
Name = "John"
}
);
````
示例中我们并没有创建模型类,但是创建了一个匿名对象模型.
### PascalCase 与 snake_case
PascalCase 属性名(如 `UserName`) 在模板中使用蛇形命名(如 `user_name`).
## 本地化
可以基于当前文化对模板内容进行本地化. 以下部分描述了两种类型的本地化选项.
### 内联本地化
内联本地化使用[本地化系统](Localization.md)本地化模板内的文本.
#### 示例: 重置密码链接
假设你需要向用户发送电子邮件重置密码. 模板内容:
````
<a title="{%{{{L "ResetMyPasswordTitle"}}}%}" href="{%{{{model.link}}}%}">{%{{{L "ResetMyPassword" model.name}}}%}</a>
````
`L` 函数用于根据当前用户的文化来定位给定的Key,你需要在本地化文件中定义 `ResetMyPassword` 键:
````json
"ResetMyPasswordTitle": "Reset my password",
"ResetMyPassword": "Hi {0}, Click here to reset your password"
````
你还需要在模板定义提供程序类中声明要与此模板一起使用的本地化资源:
````csharp
context.Add(
new TemplateDefinition(
"PasswordReset", //Template name
typeof(DemoResource) //LOCALIZATION RESOURCE
)
.WithScribanEngine()
.WithVirtualFilePath(
"/Demos/PasswordReset/PasswordReset.tpl", //template content path
isInlineLocalized: true
)
);
````
当你这样渲染模板时:
````csharp
var result = await _templateRenderer.RenderAsync(
"PasswordReset", //the template name
new PasswordResetModel
{
Name = "john",
Link = "https://abp.io/example-link?userId=123&token=ABC"
}
);
````
你可以看到以下本地化结果:
````csharp
<a title="Reset my password" href="https://abp.io/example-link?userId=123&token=ABC">Hi john, Click here to reset your password</a>
````
> 如果你为应用程序定义了 [默认本地化资源](Localization.md), 则无需声明模板定义的资源类型.
### 多个内容本地化
你可能希望为每种语言创建不同的模板文件,而不是使用本地化系统本地化单个模板. 如果模板对于特定的文化(而不是简单的文本本地化)应该是完全不同的,则可能需要使用它.
#### 示例: 欢迎电子邮件模板
假设你要发送电子邮件欢迎用户,但要定义基于用户的文化完全不同的模板.
首先创建一个文件夹,将模板放在里面,像 `en.tpl`, `tr.tpl` 每一个你支持的文化:
![multiple-file-template](images/multiple-file-template.png)
然后在模板定义提供程序类中添加模板定义:
````csharp
context.Add(
new TemplateDefinition(
name: "WelcomeEmail",
defaultCultureName: "en"
)
.WithScribanEngine()
.WithVirtualFilePath(
"/Demos/WelcomeEmail/Templates", //template content folder
isInlineLocalized: false
)
);
````
* 设置 **默认文化名称**, 当没有所需的文化模板,回退到缺省文化.
* 指定 **模板文件夹** 而不是单个模板文件.
* 设置 `isInlineLocalized` 为 `false`.
就这些,你可以渲染当前文化的模板:
````csharp
var result = await _templateRenderer.RenderAsync("WelcomeEmail");
````
> 为了简单我们跳过了模型,但是你可以使用前面所述的模型.
### 指定文化
`ITemplateRenderer` 服务如果没有指定则使用当前文化 (`CultureInfo.CurrentUICulture`). 如果你需要你可以使用 `cultureName` 参数指定文化.
````csharp
var result = await _templateRenderer.RenderAsync(
"WelcomeEmail",
cultureName: "en"
);
````
## 布局模板
布局模板用于在其他模板之间创建共享布局. 它类似于ASP.NET Core MVC / Razor Pages中的布局系统.
### 示例: 邮件HTML布局模板
例如,你想为所有电子邮件模板创建一个布局.
首先像之前一样创建一个模板文件:
````xml
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
</head>
<body>
{%{{{content}}}%}
</body>
</html>
````
* 布局模板必须具有 **{%{{{content}}}%}** 部分作为渲染的子内容的占位符.
在模板定义提供程序中注册模板:
````csharp
context.Add(
new TemplateDefinition(
"EmailLayout",
isLayout: true //SET isLayout!
)
.WithScribanEngine()
.WithVirtualFilePath(
"/Demos/EmailLayout/EmailLayout.tpl",
isInlineLocalized: true
)
);
````
现在你可以将此模板用作任何其他模板的布局:
````csharp
context.Add(
new TemplateDefinition(
name: "WelcomeEmail",
defaultCultureName: "en",
layout: "EmailLayout" //Set the LAYOUT
)
.WithScribanEngine()
.WithVirtualFilePath(
"/Demos/WelcomeEmail/Templates",
isInlineLocalized: false
)
);
````
## 全局上下文
ABP传递 `model`,可用于访问模板内的模型. 如果需要,可以传递更多的全局变量.
示例模板内容:
````
A global object value: {%{{{myGlobalObject}}}%}
````
模板假定它渲染上下文中的 `myGlobalObject` 对象. 你可以如下所示提供它:
````csharp
var result = await _templateRenderer.RenderAsync(
"GlobalContextUsage",
globalContext: new Dictionary<string, object>
{
{"myGlobalObject", "TEST VALUE"}
}
);
````
渲染的结果将是:
````
A global object value: TEST VALUE
````
## 替换存在的模板
通过替换应用程序中使用的模块定义的模板. 这样你可以根据自己的需求自定义模板,而无需更改模块代码.
### 选项-1: 使用虚拟文件系统
[虚拟文件系统](Virtual-File-System.md)允许你通过将相同文件放入项目中的相同路径来覆盖任何文件.
#### 示例: 替换标准电子邮件布局模板
ABP框架提供了一个[邮件发送系统](Emailing.md), 它在内部使用文本模板来渲染邮件内容. 它在 `/Volo/Abp/Emailing/Templates/Layout.tp` 路径定义了一个标准邮件布局模板. 模板的唯一名称是 `Abp.StandardEmailTemplates.Layout` 并且这个字符中`Volo.Abp.Emailing.Templates.StandardEmailTemplates`静态类上定义为常量.
执行以下步骤将替换模板替换成你自定义的;
**1)** 在你的项目中相同的路径添加一个新文件 (`/Volo/Abp/Emailing/Templates/Layout.tpl`):
![replace-email-layout](images/replace-email-layout.png)
**2)** 准备你的邮件布局模板:
````html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>This my header</h1>
{%{{{content}}}%}
<footer>
This is my footer...
</footer>
</body>
</html>
````
此示例只是向模板添加页眉和页脚并呈现它们之间的内容(请参阅上面的布局模板部分).
**3)** 在`.csproj`文件配置嵌入式资源e
* 添加 [Microsoft.Extensions.FileProviders.Embedded](https://www.nuget.org/packages/Microsoft.Extensions.FileProviders.Embedded) NuGet 包到你的项目.
* 在 `.csproj` 中添加 `<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>` 到 `<PropertyGroup>...</PropertyGroup>` 部分.
* 添加以下代码到你的 `.csproj` 文件:
````xml
<ItemGroup>
<None Remove="Volo\Abp\Emailing\Templates\*.tpl" />
<EmbeddedResource Include="Volo\Abp\Emailing\Templates\*.tpl" />
</ItemGroup>
````
这将模板文件做为"嵌入式资源".
**4)** 配置虚拟文件系统
在[模块](Module-Development-Basics.md) `ConfigureServices` 方法配置 `AbpVirtualFileSystemOptions` 将嵌入的文件添加到虚拟文件系统中:
```csharp
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<BookStoreDomainModule>();
});
```
`BookStoreDomainModule` 应该是你的模块名称
> 确保你的模块(支持或间接)[依赖](Module-Development-Basics.md) `AbpEmailingModule`. 因为VFS可以基于依赖顺序覆盖文件.
现在渲染邮件布局模板时会使用你的模板.
### 选项-2: 使用模板定义提供者
你可以创建一个模板定义提供者类来获取邮件布局模板来更改它的虚拟文件路径.
**示例: 使用 `/MyTemplates/EmailLayout.tpl` 文件而不是标准模板**
```csharp
using Volo.Abp.DependencyInjection;
using Volo.Abp.Emailing.Templates;
using Volo.Abp.TextTemplating;
namespace MyProject
{
public class MyTemplateDefinitionProvider
: TemplateDefinitionProvider, ITransientDependency
{
public override void Define(ITemplateDefinitionContext context)
{
var emailLayoutTemplate = context.GetOrNull(StandardEmailTemplates.Layout);
emailLayoutTemplate
.WithVirtualFilePath(
"/MyTemplates/EmailLayout.tpl",
isInlineLocalized: true
);
}
}
}
```
你依然应该添加 `/MyTemplates/EmailLayout.tpl` 到虚拟文件系统. 这种方法允许你在任何文件夹中找到模板,而不是在依赖模块定义的文件夹中.
除了模板内容之外你还可以操作模板定义属性, 例如`DisplayName`, `Layout`或`LocalizationSource`.
## 高级功能
本节介绍文本模板系统的一些内部知识和高级用法.
### 模板内容Provider
`TemplateRenderer` 用于渲染模板,这是大多数情况下所需的模板. 但是你可以使用 `ITemplateContentProvider` 获取原始(未渲染的)模板内容.
> `ITemplateRenderer` 内部使用 `ITemplateContentProvider` 获取原始模板内容.
示例:
````csharp
public class TemplateContentDemo : ITransientDependency
{
private readonly ITemplateContentProvider _templateContentProvider;
public TemplateContentDemo(ITemplateContentProvider templateContentProvider)
{
_templateContentProvider = templateContentProvider;
}
public async Task RunAsync()
{
var result = await _templateContentProvider
.GetContentOrNullAsync("Hello");
Console.WriteLine(result);
}
}
````
结果是原始模板内容:
````
Hello {%{{{model.name}}}%} :)
````
* `GetContentOrNullAsync` 如果没有为请求的模板定义任何内容,则返回 `null`.
* 它可以获取 `cultureName` 参数,如果模板针对不同的文化具有不同的文件,则可以使用该参数(请参见上面的"多内容本地化"部分).
### 模板内容贡献者
`ITemplateContentProvider` 服务使用 `ITemplateContentContributor` 实现来查找模板内容. 有一个预实现的内容贡献者 `VirtualFileTemplateContentContributor`,它从上面描述的虚拟文件系统中获取模板内容.
你可以实现 `ITemplateContentContributor` 从另一个源读取原始模板内容.
示例:
````csharp
public class MyTemplateContentProvider
: ITemplateContentContributor, ITransientDependency
{
public async Task<string> GetOrNullAsync(TemplateContentContributorContext context)
{
var templateName = context.TemplateDefinition.Name;
//TODO: Try to find content from another source
return null;
}
}
````
如果源无法找到内容, 则返回 `null`, `ITemplateContentProvider` 将回退到下一个贡献者.
### Template Definition Manager
`ITemplateDefinitionManager` 服务可用于获取模板定义(由模板定义提供程序创建).
## 另请参阅
* 本文开发和引用的[应用程序示例源码](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo).
* [本地化系统](Localization.md).
* [虚拟文件系统](Virtual-File-System.md).

444
docs/zh-Hans/Text-Templating.md

@ -8,450 +8,30 @@ Template + Model =renderer=> Rendered Content
它非常类似于 ASP.NET Core Razor View (或 Page): 它非常类似于 ASP.NET Core Razor View (或 Page):
*RAZOR VIEW (or PAGE) + MODEL ==render==> HTML CONTENT* *RAZOR VIEW (或 PAGE) + MODEL ==render==> HTML CONTENT*
你可以将渲染的输出用于任何目的,例如发送电子邮件或准备一些报告. 你可以将渲染的输出用于任何目的,例如发送电子邮件或准备一些报告.
### 示例 模板渲染引擎非常强大:
Here, a simple template: * 它支持**条件逻辑**, **循环**等等.
* 模板内容**可以本地化**.
```` * 你可以为其他渲染模板定义**布局模板**。
Hello {%{{{model.name}}}%} :)
````
你可以定义一个含有 `Name` 属性的类来渲染这个模板:
````csharp
public class HelloModel
{
public string Name { get; set; }
}
````
如果你使用 `Name` 为 `John` 的 `HelloModel` 渲染模板,输出为:
````
Hello John :)
````
模板渲染引擎非常强大;
* 它基于 [Scriban](https://github.com/lunet-io/scriban) 库, 所以它支持 **条件逻辑**, **循环** 等.
* 模板内容 **可以本地化**.
* 你可以定义 **布局模板** 在渲染其他模板中用做布局.
* 对于高级场景,你可以传递任何对象到模板上下文. * 对于高级场景,你可以传递任何对象到模板上下文.
### 源码 ABP框架提供了两个模板引擎:
这里是本文开发和引用的[示例应用程序源码](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo).
## 安装
推荐使用 [ABP CLI](CLI.md) 安装包.
### 使用 ABP CLI
在项目目录(.csproj file)打开命令行窗口运行以下命令:
````bash
abp add-package Volo.Abp.TextTemplating
````
### 手动安装
如果你想要手动安装;
1. 添加 [Volo.Abp.TextTemplating](https://www.nuget.org/packages/Volo.Abp.TextTemplating) NuGet包到你的项目:
````
Install-Package Volo.Abp.TextTemplating
````
2. 添加 `AbpTextTemplatingModule` 到你的模块依赖列表:
````csharp
[DependsOn(
//...other dependencies
typeof(AbpTextTemplatingModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
````
## 定义模板
在渲染模板之前,需要定义它. 创建一个继承自 `TemplateDefinitionProvider` 的类:
````csharp
public class DemoTemplateDefinitionProvider : TemplateDefinitionProvider
{
public override void Define(ITemplateDefinitionContext context)
{
context.Add(
new TemplateDefinition("Hello") //template name: "Hello"
.WithVirtualFilePath(
"/Demos/Hello/Hello.tpl", //template content path
isInlineLocalized: true
)
);
}
}
````
* `context` 对象用于添加新模板或获取依赖模块定义的模板. 使用 `context.Add(...)` 定义新模板.
* `TemplateDefinition` 是代表模板的类,每个模板必须有唯一的名称(在渲染模板时使用).
* `/Demos/Hello/Hello.tpl` 是模板文件的路径.
* `isInlineLocalized` 声明针对所有语言使用一个模板(`true` 还是针对每种语言使用不同的模板(`false`). 更多内容参阅下面的本地化部分.
### 模板内容
`WithVirtualFilePath` 表示我们使用[虚拟文件系统](Virtual-File-System.md)存储模板内容. 在项目内创建一个 `Hello.tpl` 文件,并在属性窗口中将其标记为"**嵌入式资源**":
![hello-template](images/hello-template.png)
示例 `Hello.tpl` 内容如下所示:
````
Hello {%{{{model.name}}}%} :)
````
[虚拟文件系统](Virtual-File-System.md) 需要在[模块](Module-Development-Basics.md)类的 `ConfigureServices` 方法添加你的文件:
````csharp
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<TextTemplateDemoModule>("TextTemplateDemo");
});
````
* `TextTemplateDemoModule`是模块类.
* `TextTemplateDemo` 是你的项目的根命名空间.
## 渲染模板
`ITemplateRenderer` 服务用于渲染模板内容.
### 示例: 渲染一个简单的模板
````csharp
public class HelloDemo : ITransientDependency
{
private readonly ITemplateRenderer _templateRenderer;
public HelloDemo(ITemplateRenderer templateRenderer)
{
_templateRenderer = templateRenderer;
}
public async Task RunAsync()
{
var result = await _templateRenderer.RenderAsync(
"Hello", //the template name
new HelloModel
{
Name = "John"
}
);
Console.WriteLine(result);
}
}
````
* `HelloDemo` 是一个简单的类,在构造函数注入了 `ITemplateRenderer` 并在 `RunAsync` 方法中使用它.
* `RenderAsync` 有两个基本参数:
* `templateName`: 要渲染的模板名称 (本示例中是 `Hello`).
* `model`: 在模板内部用做 `model` 的对象 (本示例中是 `HelloModel` 对象).
示例会返回以下结果:
````csharp
Hello John :)
````
### 匿名模型
虽然建议为模板创建模型类,但在简单情况下使用匿名对象也是可行的:
````csharp
var result = await _templateRenderer.RenderAsync(
"Hello",
new
{
Name = "John"
}
);
````
示例中我们并没有创建模型类,但是创建了一个匿名对象模型.
### PascalCase 与 snake_case
PascalCase 属性名(如 `UserName`) 在模板中使用蛇形命名(如 `user_name`).
## 本地化
可以基于当前文化对模板内容进行本地化. 以下部分描述了两种类型的本地化选项.
### 内联本地化
内联本地化使用[本地化系统](Localization.md)本地化模板内的文本.
#### 示例: 重置密码链接
假设你需要向用户发送电子邮件重置密码. 模板内容:
````
<a title="{%{{{L "ResetMyPasswordTitle"}}}%}" href="{%{{{model.link}}}%}">{%{{{L "ResetMyPassword" model.name}}}%}</a>
````
`L` 函数用于根据当前用户的文化来定位给定的Key,你需要在本地化文件中定义 `ResetMyPassword` 键:
````json
"ResetMyPasswordTitle": "Reset my password",
"ResetMyPassword": "Hi {0}, Click here to reset your password"
````
你还需要在模板定义提供程序类中声明要与此模板一起使用的本地化资源:
````csharp
context.Add(
new TemplateDefinition(
"PasswordReset", //Template name
typeof(DemoResource) //LOCALIZATION RESOURCE
).WithVirtualFilePath(
"/Demos/PasswordReset/PasswordReset.tpl", //template content path
isInlineLocalized: true
)
);
````
当你这样渲染模板时:
````csharp
var result = await _templateRenderer.RenderAsync(
"PasswordReset", //the template name
new PasswordResetModel
{
Name = "john",
Link = "https://abp.io/example-link?userId=123&token=ABC"
}
);
````
你可以看到以下本地化结果:
````csharp
<a title="Reset my password" href="https://abp.io/example-link?userId=123&token=ABC">Hi john, Click here to reset your password</a>
````
> 如果你为应用程序定义了 [默认本地化资源](Localization.md), 则无需声明模板定义的资源类型.
### 多个内容本地化
你可能希望为每种语言创建不同的模板文件,而不是使用本地化系统本地化单个模板. 如果模板对于特定的文化(而不是简单的文本本地化)应该是完全不同的,则可能需要使用它.
#### 示例: 欢迎电子邮件模板
假设你要发送电子邮件欢迎用户,但要定义基于用户的文化完全不同的模板.
首先创建一个文件夹,将模板放在里面,像 `en.tpl`, `tr.tpl` 每一个你支持的文化:
![multiple-file-template](images/multiple-file-template.png)
然后在模板定义提供程序类中添加模板定义:
````csharp
context.Add(
new TemplateDefinition(
name: "WelcomeEmail",
defaultCultureName: "en"
)
.WithVirtualFilePath(
"/Demos/WelcomeEmail/Templates", //template content folder
isInlineLocalized: false
)
);
````
* 设置 **默认文化名称**, 当没有所需的文化模板,回退到缺省文化.
* 指定 **模板文件夹** 而不是单个模板文件.
* 设置 `isInlineLocalized` 为 `false`.
就这些,你可以渲染当前文化的模板:
````csharp
var result = await _templateRenderer.RenderAsync("WelcomeEmail");
````
> 为了简单我们跳过了模型,但是你可以使用前面所述的模型.
### 指定文化
`ITemplateRenderer` 服务如果没有指定则使用当前文化 (`CultureInfo.CurrentUICulture`). 如果你需要你可以使用 `cultureName` 参数指定文化.
````csharp
var result = await _templateRenderer.RenderAsync(
"WelcomeEmail",
cultureName: "en"
);
````
## 布局模板
布局模板用于在其他模板之间创建共享布局. 它类似于ASP.NET Core MVC / Razor Pages中的布局系统.
### 示例: 邮件HTML布局模板
例如,你想为所有电子邮件模板创建一个布局.
首先像之前一样创建一个模板文件:
````xml
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
</head>
<body>
{%{{{content}}}%}
</body>
</html>
````
* 布局模板必须具有 **{%{{{content}}}%}** 部分作为渲染的子内容的占位符.
在模板定义提供程序中注册模板:
````csharp
context.Add(
new TemplateDefinition(
"EmailLayout",
isLayout: true //SET isLayout!
).WithVirtualFilePath(
"/Demos/EmailLayout/EmailLayout.tpl",
isInlineLocalized: true
)
);
````
现在你可以将此模板用作任何其他模板的布局:
````csharp
context.Add(
new TemplateDefinition(
name: "WelcomeEmail",
defaultCultureName: "en",
layout: "EmailLayout" //Set the LAYOUT
).WithVirtualFilePath(
"/Demos/WelcomeEmail/Templates",
isInlineLocalized: false
)
);
````
## 全局上下文
ABP传递 `model`,可用于访问模板内的模型. 如果需要,可以传递更多的全局变量.
示例模板内容:
````
A global object value: {%{{{myGlobalObject}}}%}
````
模板假定它渲染上下文中的 `myGlobalObject` 对象. 你可以如下所示提供它:
````csharp
var result = await _templateRenderer.RenderAsync(
"GlobalContextUsage",
globalContext: new Dictionary<string, object>
{
{"myGlobalObject", "TEST VALUE"}
}
);
````
渲染的结果将是:
````
A global object value: TEST VALUE
````
## 高级功能
本节介绍文本模板系统的一些内部知识和高级用法.
### 模板内容Provider
`TemplateRenderer` 用于渲染模板,这是大多数情况下所需的模板. 但是你可以使用 `ITemplateContentProvider` 获取原始(未渲染的)模板内容.
> `ITemplateRenderer` 内部使用 `ITemplateContentProvider` 获取原始模板内容.
示例:
````csharp
public class TemplateContentDemo : ITransientDependency
{
private readonly ITemplateContentProvider _templateContentProvider;
public TemplateContentDemo(ITemplateContentProvider templateContentProvider)
{
_templateContentProvider = templateContentProvider;
}
public async Task RunAsync()
{
var result = await _templateContentProvider
.GetContentOrNullAsync("Hello");
Console.WriteLine(result);
}
}
````
结果是原始模板内容:
````
Hello {%{{{model.name}}}%} :)
````
* `GetContentOrNullAsync` 如果没有为请求的模板定义任何内容,则返回 `null`.
* 它可以获取 `cultureName` 参数,如果模板针对不同的文化具有不同的文件,则可以使用该参数(请参见上面的"多内容本地化"部分).
### 模板内容贡献者
`ITemplateContentProvider` 服务使用 `ITemplateContentContributor` 实现来查找模板内容. 有一个预实现的内容贡献者 `VirtualFileTemplateContentContributor`,它从上面描述的虚拟文件系统中获取模板内容.
你可以实现 `ITemplateContentContributor` 从另一个源读取原始模板内容.
示例:
````csharp
public class MyTemplateContentProvider
: ITemplateContentContributor, ITransientDependency
{
public async Task<string> GetOrNullAsync(TemplateContentContributorContext context)
{
var templateName = context.TemplateDefinition.Name;
//TODO: Try to find content from another source
return null;
}
}
```` * **[Razor](Text-Templating-Razor.md)**
* **[Scriban](Text-Templating-Scriban.md)**
如果源无法找到内容, 则返回 `null`, `ITemplateContentProvider` 将回退到下一个贡献者. 你可以在同一个应用应用程序中使用不同的模板引擎, 或者创建一个新的自定义模板引擎.
### Template Definition Manager ## 源码
`ITemplateDefinitionManager` 服务可用于获取模板定义(由模板定义提供程序创建). 查看开发和引用的[应用程序示例源码](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo).
## 另请参阅 ## 另请参阅
* 本文开发和引用的[应用程序示例源码](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo). * 本文开发和引用的[应用程序示例源码](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo).
* [本地化系统](Localization.md). * [本地化系统](Localization.md).
* [虚拟文件系统](Virtual-File-System.md). * [虚拟文件系统](Virtual-File-System.md).

BIN
docs/zh-Hans/images/abp-book.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
docs/zh-Hans/images/abp-select2-multiple.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
docs/zh-Hans/images/abp-select2-single.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
docs/zh-Hans/images/account-module-forgot-password.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/zh-Hans/images/account-module-login.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/zh-Hans/images/account-module-manage-account.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/zh-Hans/images/account-module-register.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/zh-Hans/images/add-new-propert-to-user-database-extra-properties.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
docs/zh-Hans/images/add-new-propert-to-user-database-field.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
docs/zh-Hans/images/add-new-property-enum.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/zh-Hans/images/add-new-property-to-user-form-validation-error-custom.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
docs/zh-Hans/images/add-new-property-to-user-form-validation-error.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
docs/zh-Hans/images/add-new-property-to-user-form.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

BIN
docs/zh-Hans/images/add-new-property-to-user-table.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
docs/zh-Hans/images/angular-module-dev-app-project.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
docs/zh-Hans/images/angular-module-folder-structure.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

BIN
docs/zh-Hans/images/blazor-generic-exception-message.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/zh-Hans/images/blazor-user-friendly-exception.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/zh-Hans/images/bookstore-visual-studio-solution-v3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/zh-Hans/images/cmskit-module-blog-post-edit.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
docs/zh-Hans/images/cmskit-module-blog-posts-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/zh-Hans/images/cmskit-module-blogs-edit.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/zh-Hans/images/cmskit-module-blogs-feature-action.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/zh-Hans/images/cmskit-module-blogs-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/zh-Hans/images/cmskit-module-comment-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/zh-Hans/images/cmskit-module-comments-detail.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
docs/zh-Hans/images/cmskit-module-features-dialog-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/zh-Hans/images/cmskit-module-features-dialog.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/zh-Hans/images/cmskit-module-features-scroll-index.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
docs/zh-Hans/images/cmskit-module-global-resources-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
docs/zh-Hans/images/cmskit-module-menus-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/zh-Hans/images/cmskit-module-menus-public.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/zh-Hans/images/cmskit-module-pages-edit.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

BIN
docs/zh-Hans/images/cmskit-module-pages-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/zh-Hans/images/cmskit-module-ratings.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
docs/zh-Hans/images/cmskit-module-reactions.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
docs/zh-Hans/images/cmskit-module-tag-edit.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
docs/zh-Hans/images/cmskit-module-tags-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
docs/zh-Hans/images/data-table-colum-extension-blazor-component-render-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
docs/zh-Hans/images/data-table-colum-extension-blazor-component-render.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/zh-Hans/images/docs-create-project-v4.4.0.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/zh-Hans/images/docs-module_solution-explorer.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/zh-Hans/images/extension-navigation-property-form.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
docs/zh-Hans/images/extension-navigation-property-table.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
docs/zh-Hans/images/features-modal.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 35 KiB

BIN
docs/zh-Hans/images/features-module-opening.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 24 KiB

BIN
docs/zh-Hans/images/generated-static-client-proxies.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
docs/zh-Hans/images/hello-template-razor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
docs/zh-Hans/images/identity-module-menu.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
docs/zh-Hans/images/identity-module-permissions.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 30 KiB

BIN
docs/zh-Hans/images/identity-module-roles.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/zh-Hans/images/identity-module-users.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/zh-Hans/images/implementing-domain-driven-design-book.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
docs/zh-Hans/images/module-tenant-management-actions.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
docs/zh-Hans/images/module-tenant-management-new-tenant.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 15 KiB

BIN
docs/zh-Hans/images/module-tenant-management-page.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 21 KiB

BIN
docs/zh-Hans/images/multiple-file-template-razor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
docs/zh-Hans/images/optimistic-concurrency.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
docs/zh-Hans/images/page-header-toolbar-blazor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
docs/zh-Hans/images/page-toolbar-button-blazor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/zh-Hans/images/page-toolbar-button.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
docs/zh-Hans/images/page-toolbar-custom-component-blazor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

BIN
docs/zh-Hans/images/page-toolbar-custom-component.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/zh-Hans/images/permissions-module-dialog.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 31 KiB

BIN
docs/zh-Hans/images/permissions-module-open-dialog.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 25 KiB

BIN
docs/zh-Hans/images/replace-email-layout-razor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
docs/zh-Hans/images/static-js-proxy-example.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
docs/zh-Hans/images/table-column-extension-example-blazor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/zh-Hans/images/table-column-extension-example.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/zh-Hans/images/upgrade-diff-empty-folders.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 984 B

BIN
docs/zh-Hans/images/user-action-blazor-extension-click-me.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
docs/zh-Hans/images/user-action-extension-click-me.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
docs/zh-Hans/images/user-action-extension-on-blazor-project.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
docs/zh-Hans/images/user-action-extension-on-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/zh-Hans/images/winmerge-comparison-result.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
docs/zh-Hans/images/winmerge-file-diff.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

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

Loading…
Cancel
Save