Browse Source

Merge branch 'dev' into stsrki/blazorise-0933

pull/8223/head
Halil İbrahim Kalkan 5 years ago
committed by GitHub
parent
commit
5ff485eb72
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      Directory.Build.props
  2. 14
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  3. 14
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json
  4. 12
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json
  5. 10
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  6. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
  7. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json
  8. 2
      configureawait.props
  9. 139
      docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/POST.md
  10. BIN
      docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/abp-suite-separate-tenant-schema.png
  11. BIN
      docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/account-lepton-source.png
  12. BIN
      docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/cms-kit-menu.png
  13. BIN
      docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/cms-kit-selection.png
  14. BIN
      docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/enable-disable-features.png
  15. BIN
      docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/forms-answer.png
  16. BIN
      docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/forms-edit-report.png
  17. BIN
      docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/new-tenant-modal.png
  18. BIN
      docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/tenant-db-migrate.png
  19. 134
      docs/en/Blog-Posts/2021-03-31 v4_3 Preview/POST.md
  20. BIN
      docs/en/Blog-Posts/2021-03-31 v4_3 Preview/email-settings-page.png
  21. 3
      docs/en/Blog-Posts/2021-04-05 CmsKit/POST.md
  22. 7
      docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/POST.md
  23. BIN
      docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/result.jpg
  24. 30
      docs/en/Migration-Guides/Abp-4_3.md
  25. 6
      docs/en/Tutorials/Part-5.md
  26. BIN
      docs/en/Tutorials/images/blazor-edit-book-action-2.png
  27. 10
      docs/en/UI/Angular/Account-Module.md
  28. 4
      docs/en/docs-nav.json
  29. 100
      docs/zh-Hans/Multi-Lingual-Entities.md
  30. 4
      docs/zh-Hans/docs-nav.json
  31. 4
      framework/Volo.Abp.sln
  32. 3
      framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavToolbar.razor.cs
  33. 5
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor
  34. 3
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs
  35. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj
  36. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
  37. 3
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentInputFormatter.cs
  38. 6
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs
  39. 2
      framework/src/Volo.Abp.AspNetCore.Serilog/Volo.Abp.AspNetCore.Serilog.csproj
  40. 54
      framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs
  41. 1
      framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj
  42. 2
      framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs
  43. 4
      framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj
  44. 4
      framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs
  45. 2
      framework/src/Volo.Abp.BlobStoring.Aliyun/Volo.Abp.BlobStoring.Aliyun.csproj
  46. 4
      framework/src/Volo.Abp.BlobStoring.Aws/Volo.Abp.BlobStoring.Aws.csproj
  47. 2
      framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj
  48. 6
      framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
  49. 118
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs
  50. 60
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs
  51. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs
  52. 18
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/NpmPackageProjectBuildPipelineBuilder.cs
  53. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/NugetPackageProjectBuildPipelineBuilder.cs
  54. 14
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContext.cs
  55. 10
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/INpmPackageInfoProvider.cs
  56. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs
  57. 62
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/NpmPackageInfoProvider.cs
  58. 110
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/NpmPackageProjectBuilder.cs
  59. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/NugetPackageInfoProvider.cs
  60. 13
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/NugetPackageProjectBuilder.cs
  61. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SourceCodeTypes.cs
  62. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs
  63. 32
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularSourceCodeAdder.cs
  64. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NuGetPackageInfo.cs
  65. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs
  66. 118
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNpmPackageAdder.cs
  67. 79
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs
  68. 49
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs
  69. 20
      framework/src/Volo.Abp.Core/System/Collections/Generic/AbpDictionaryExtensions.cs
  70. 15
      framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs
  71. 2
      framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
  72. 1
      framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj
  73. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs
  74. 4
      framework/src/Volo.Abp.EventBus.Rebus/Volo.Abp.EventBus.Rebus.csproj
  75. 2
      framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj
  76. 3
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
  77. 2
      framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj
  78. 2
      framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs
  79. 2
      framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj
  80. 2
      framework/src/Volo.Abp.Kafka/Volo.Abp.Kafka.csproj
  81. 2
      framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj
  82. 2
      framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj
  83. 2
      framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj
  84. 4
      framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs
  85. 10
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IHasMultiLingual.cs
  86. 21
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs
  87. 7
      framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs
  88. 0
      framework/src/Volo.Abp.MultiLingualObjects/FodyWeavers.xml
  89. 0
      framework/src/Volo.Abp.MultiLingualObjects/FodyWeavers.xsd
  90. 1
      framework/src/Volo.Abp.MultiLingualObjects/Volo.Abp.MultiLingualObjects.csproj
  91. 4
      framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/AbpMultiLingualObjectsModule.cs
  92. 10
      framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/IMultiLingualObject.cs
  93. 14
      framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/IMultiLingualObjectManager.cs
  94. 7
      framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/IObjectTranslation.cs
  95. 48
      framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager.cs
  96. 6
      framework/src/Volo.Abp.Quartz/Volo.Abp.Quartz.csproj
  97. 2
      framework/src/Volo.Abp.Swashbuckle/Volo.Abp.Swashbuckle.csproj
  98. 2
      framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj
  99. 2
      framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj
  100. 4
      framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj

6
Directory.Build.props

@ -5,13 +5,13 @@
<MicrosoftPackageVersion>5.0.*</MicrosoftPackageVersion>
<!-- Microsoft.NET.Test.Sdk https://www.nuget.org/packages/Microsoft.NET.Test.Sdk -->
<MicrosoftNETTestSdkPackageVersion>16.8.3</MicrosoftNETTestSdkPackageVersion>
<MicrosoftNETTestSdkPackageVersion>16.9.1</MicrosoftNETTestSdkPackageVersion>
<!-- NSubstitute https://www.nuget.org/packages/NSubstitute -->
<NSubstitutePackageVersion>4.2.2</NSubstitutePackageVersion>
<!-- Shouldly https://www.nuget.org/packages/Shouldly -->
<ShouldlyPackageVersion>4.0.1</ShouldlyPackageVersion>
<ShouldlyPackageVersion>4.0.3</ShouldlyPackageVersion>
<!-- xunit https://www.nuget.org/packages/xUnit -->
<xUnitPackageVersion>2.4.1</xUnitPackageVersion>
@ -23,7 +23,7 @@
<xUnitRunnerVisualstudioPackageVersion>2.4.3</xUnitRunnerVisualstudioPackageVersion>
<!-- Mongo2Go https://www.nuget.org/packages/Mongo2Go -->
<Mongo2GoPackageVersion>2.2.14</Mongo2GoPackageVersion>
<Mongo2GoPackageVersion>3.0.0</Mongo2GoPackageVersion>
</PropertyGroup>
</Project>

14
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json

@ -255,14 +255,22 @@
"ProjectDownloads": "Project Downloads",
"ShowProjectDownloadsOfOrganization": "Project Downloads",
"ShowAuditLogsOfOrganization": "Audit Logs",
"Enum:EntityChangeType:0": "Crated",
"Enum:EntityChangeType:0": "Created",
"Enum:EntityChangeType:1": "Updated",
"Enum:EntityChangeType:2": "Deleted",
"TenantId": "Tenant ID",
"ChangeTime": "Change time",
"EntityTypeFullName": "Entity type full name",
"AuditLogsOf{0}Organization": "Audit logs of \"{0}\" organization",
"AuditLogsFor{0}Organization": "Audit logs for \"{0}\" organization",
"Permission:EntityChange": "Entity Change",
"Permission:ProjectDownload": "Project Download"
"Permission:ProjectDownload": "Project Download",
"Permission:PaymentRequest": "Payment Request",
"CreatorEmailAddress": "Creator email address",
"EmailSendDate": "Email send date",
"PaymentRequestsFor{0}Organization": "Payment requests for \"{0}\" organization",
"PaymentDetails": "Payment Details",
"PaymentProduct": "Payment Product",
"ProductName": "Product Name",
"Code": "Code"
}
}

14
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json

@ -204,14 +204,22 @@
"ProjectDownloads": "Proje İndirmeleri",
"ShowProjectDownloadsOfOrganization": "Proje İndirmeleri",
"ShowAuditLogsOfOrganization": "Denetim Günlükleri",
"Enum:EntityChangeType:0": "Crated",
"Enum:EntityChangeType:0": "Oluşturuldu",
"Enum:EntityChangeType:1": "Güncellendi",
"Enum:EntityChangeType:2": "Silindi",
"TenantId": "Kiracı Kimliği",
"ChangeTime": "Değişiklik Zamanı",
"EntityTypeFullName": "Varlık türü tam adı",
"AuditLogsOf{0}Organization": "\"{0}\" kuruluşunun denetim günlükleri",
"AuditLogsFor{0}Organization": "\"{0}\" kuruluşu için denetim günlükleri",
"Permission:EntityChange": "Varlık Değişikliği",
"Permission:ProjectDownload": "Proje Indirme"
"Permission:ProjectDownload": "Proje İndirme",
"Permission:PaymentRequest": "Ödeme isteği",
"CreatorEmailAddress": "Oluşturan kişinin e-posta adresi",
"EmailSendDate": "E-posta gönderme tarihi",
"PaymentRequestsFor{0}Organization": "\"{0}\" kuruluşu için ödeme istekleri",
"PaymentDetails": "Ödeme Detayları",
"PaymentProduct": "Ödeme Ürünü",
"ProductName": "Ürün İsmi",
"Code": "Kod"
}
}

12
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json

@ -245,8 +245,16 @@
"TenantId": "租户ID",
"ChangeTime": "变更时间",
"EntityTypeFullName": "实体类型全名",
"AuditLogsOf{0}Organization": "\"{0}\" 组织的审核日志",
"AuditLogsFor{0}Organization": "\"{0}\" 组织的审核日志",
"Permission:EntityChange": "实体变更",
"Permission:ProjectDownload": "项目下载"
"Permission:ProjectDownload": "项目下载",
"Permission:PaymentRequest": "支付请求",
"CreatorEmailAddress": "创作者的电子邮件地址",
"EmailSendDate": "电子邮件发送日期",
"PaymentRequestsFor{0}Organization": "\"{0}\" 组织的付款请求",
"PaymentDetails": "付款详情",
"PaymentProduct": "付款产品",
"ProductName": "产品名称",
"Code": "代码"
}
}

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

@ -128,13 +128,13 @@
"YourFullName": "Your full name",
"EmailField": "E-mail Address",
"YourEmailAddress": "Your e-mail address",
"HowMayWeHelpYou": "How may we help you",
"HowMayWeHelpYou": "How may we help you?",
"SendMessage": "Send Message",
"Success": "Success",
"WeWillReplyYou.": "Your message is sent! We will reply you in a short time.",
"WeWillReplyYou": "We received your message and will be in touch shortly.",
"GoHome": "Go Home",
"CreateLiveDemo": "Create Live Demo",
"RegisterToTheNewsletter": "Register to the newsletter to get information on happenings about ABP.IO, like new releases.",
"RegisterToTheNewsletter": "Register for the newsletter to receive information regarding ABP.IO, including new releases etc.",
"EnterYourEmailOrLogin": "Enter your e-mail address to create your demo or <a href=\"{0}\">Login</a> using your existing account.",
"ApplicationTemplate": "Application Template",
"ApplicationTemplateExplanation": "Application startup template is used to create a new web application.",
@ -287,6 +287,8 @@
"PrivateTicketEmailSupport": "Private ticket & email support",
"BuyNow": "Buy Now",
"PayViaAmexCard": "How can I pay via my AMEX card?",
"PayViaAmexCardDescription": "The default payment gateway 'Iyzico' may decline some AMEX credit cards due to the security measures. In this case, you can pay through the alternative payment gateway '2Checkout'."
"PayViaAmexCardDescription": "The default payment gateway 'Iyzico' may decline some AMEX credit cards due to the security measures. In this case, you can pay through the alternative payment gateway '2Checkout'.",
"ThankYou": "Thank you",
"InvalidReCaptchaErrorMessage": "There was an error verifying reCAPTCHA. Please try again."
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json

@ -30,6 +30,7 @@
"UserNameNotFound": "{0} kullanıcı adı ile bir kullanıcı yok",
"SuccessfullyAddedToNewsletter": "Bültenimize abone olduğunuz için teşekkürler!",
"MyProfile": "Profilim",
"EmailNotValid": "Lütfen uygun bir e-posta adresi giriniz"
"EmailNotValid": "Lütfen uygun bir e-posta adresi giriniz",
"InvalidReCaptchaErrorMessage": "ReCAPTCHA doğrulanırken hata oluştu, lütfen tekrar deneyin."
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json

@ -131,7 +131,7 @@
"HowMayWeHelpYou": "我们如何帮助你",
"SendMessage": "发送消息",
"Success": "成功",
"WeWillReplyYou.": "你的消息已经发送! 我们会在短时间内给你答复.",
"WeWillReplyYou": "你的消息已经发送! 我们会在短时间内给你答复.",
"GoHome": "回到主页面",
"CreateLiveDemo": "创建在线演示",
"RegisterToTheNewsletter": "注册到时事简报以获取有关ABP.IO的消息,比如新发布的内容.",
@ -287,6 +287,7 @@
"PrivateTicketEmailSupport": "私有票和email支持",
"BuyNow": "现在购买",
"PayViaAmexCard": "我如何通过我的AMEX卡付款?",
"PayViaAmexCardDescription": "由于安全措施,默认付款网关“ Iyzico”可能会拒绝某些AMEX信用卡。 在这种情况下,您可以通过备用付款网关“ 2Checkout”付款。"
"PayViaAmexCardDescription": "由于安全措施,默认付款网关“ Iyzico”可能会拒绝某些AMEX信用卡。 在这种情况下,您可以通过备用付款网关“ 2Checkout”付款。",
"InvalidReCaptchaErrorMessage": "验证reCAPTCHA时出错,请重试。"
}
}

2
configureawait.props

@ -1,7 +1,7 @@
<Project>
<ItemGroup>
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" PrivateAssets="All" />
<PackageReference Include="Fody" Version="6.2.0">
<PackageReference Include="Fody" Version="6.5.0">
<PrivateAssets>All</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>

139
docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/POST.md

@ -0,0 +1,139 @@
# ABP Commercial 4.3 RC Has Been Published
ABP Commercial version 4.3 RC (Release Candidate) has been published alongside ABP Framework 4.3. RC (TODO: link). I will introduce the new features in this blog post. Here, a list of highlights for this release;
* The **microservice starter template** is getting more mature. We've also added a **service template** to add new microservices to the solution.
* New option for the application starter template to have a **separate database schema for tenant databases**.
* New **Forms** module to create surveys
* **Enable/disable modules** per edition/tenant.
* **Lepton theme** and **Account module**'s source codes are available with the Team License.
Here, some other features already covered in the ABP Framework announcement, but worth mentioning here since they are also implemented for the ABP Commercial;
* **Blazor UI server-side** support
* **Email setting** management UI
* **Module extensibility** system is now available for the **Blazor UI** too.
> This post doesn't cover the features and changes done on the ABP Framework side. Please also see the **ABP Framework 4.3. RC blog post** (TODO: link).
## The Migration Guide
**This upgrade requires some manual work documented in [the migration guide](https://docs.abp.io/en/commercial/4.3/migration-guides/v4_3).** Please read the guide carefully. Even if your application doesn't break on upgrade, you should apply the changes to avoid future release problems.
## What's New With The ABP Commercial 4.3
### The Microservice Starter Template
We'd introduced an initial version of the [microservice starter template](https://docs.abp.io/en/commercial/4.3/startup-templates/microservice/index) in the [previous version](https://blog.abp.io/abp/ABP-IO-Platform-v4-2-RC-Has-Been-Released). It is getting more mature with this release. We've made a lot of improvements and changes, including;
* New **"service" template** to add new microservices for the solution. It still requires some manual work to integrate to other services and gateways; however, it makes progress very easy and straightforward.
* Added [Tye](https://github.com/dotnet/tye) configuration to develop and test the solution easier.
* Added [Prometheus](https://prometheus.io/), [Grafana](https://grafana.com/) integrations for monitoring the solution.
* **Automatic database migrations**. Every microservice automatically checks and migrates/seeds its database on startup (concurrency issues are resolved for multiple instances). For multi-tenant systems, tenant databases are also upgraded by the queue.
* For multi-tenant systems, **databases are being created on the fly** for new tenants with separate connection strings.
* Created **separate solution (`.sln`) file** for each microservice, gateway, and application. In this way, you can focus on what you are working on. The main (roof) solution file only includes the executable projects in these solutions.
* All microservices are converted to the standard **layered module structure**, making it easier to align with ABP application development practices.
After this release, **we will be preparing microservice development guides** based on this startup solution.
### Separate Tenant Schema
ABP's multi-tenancy system allows to the creation of dedicated databases for tenants. However, the application startup solution comes with a single database migration path; hence it has a single database schema. As a result, tenant databases have some host-related tables. These tables are not used for tenants, and they are always empty. However, their existence may disturb us as a clean developer.
With this release, the application startup template provides an option to address this problem. So, if you want, you can have a separate migration path for tenant databases. Of course, this has a cost; You will have two DbContexts for migration purposes, bringing additional complexity to your solution. We've done our best to reduce this complexity and added a README file into the migration assembly. If you prefer this approach, please check that README file.
You can specify the new `--separate-tenant-schema` parameter while you are creating a new solution using the [ABP CLI](https://docs.abp.io/en/abp/4.3/CLI):
````bash
abp new Acme.BookStore --separate-tenant-schema
````
If you prefer the [ABP Suite](https://docs.abp.io/en/commercial/latest/abp-suite/create-solution) to create solutions, you can check the *Separated tenant schema* option.
![abp-suite-separate-tenant-schema](abp-suite-separate-tenant-schema.png)
### Creating Tenant Databases On The Fly
With this release, the separate tenant database feature becomes more mature. When you create a new tenant with specifying a connection string, the **new database is automatically created** with all the tables and the initial seed data if available. So, tenants can immediately start to use the new database. With this change, tenant connection string textboxes come in the tenant creation modal:
![new-tenant-modal](new-tenant-modal.png)
Besides, we've added an "**Apply database migrations**" action to the tenant management UI to manually trigger the database creation & migration in case you have a problem with automatic migration:
![tenant-db-migrate](tenant-db-migrate.png)
Automatic migration only tries one time. If it fails, it writes the exception log and discards this request. For example, this can happen if the connection string is wrong or the database server is not available. In this case, you can manually retry with this action.
> Note that this feature requires to **make changes in your solution**, if you upgrade from an older version. Because the tenant database creation and migration code are located in the application startup template. See the [version 4.3 migration guide](https://docs.abp.io/en/commercial/4.3/migration-guides/v4_3) for details.
### New Module: CMS Kit
CMS Kit module initial version has been released with this version. As stated in the ABP Framework 4.3 announcement post (TODO: link), it should be considered premature for now.
For ABP Commercial application startup template, we are providing an option to include the CMS Kit into the solution while creating new solutions:
![cms-kit-selection](cms-kit-selection.png)
It is available only if you select the *Public web site* option. Once you include CMS Kit, a *Cms* item is shown on the menu:
![cms-kit-menu](cms-kit-menu.png)
Each CMS Kit feature can be individually enabled/disabled, using the global feature system. Once you disable a feature, it becomes completely invisible; even the related tables are not included in your database.
CMS Kit features are separated into two categories: Open source (free) features and pro (commercial) features. For now, only newsletter and contact form features are commercial. By the time, we will add more free and commercial features.
> We will create a separate blog post for the CMS Kit module, so I keep it short.
### New Module: Forms
*Forms* is a new module that is being introduced with this version. It looks like the Google Forms application; You dynamically create forms on the UI and send them to people to answer. Then you can get statistics/report and export answers to a CSV file.
Forms module currently supports the following question types;
* **Free text**
* Selecting a **single option** from a **dropdown** list or a **radio button** list
* **Multiple choice**: Selecting multiple options from a checkbox list
**Screenshot: editing form and questions - view responses**
![forms-edit-report](forms-edit-report.png)
**Screenshot: answering to the form**
![forms-answer](forms-answer.png)
### Team License Source Code for Modules
Team License users can't access the source code of modules and themes as a license restriction. You have to buy a Business or Enterprise license to download any module/theme's full source code. However, we got a lot of feedback from the Team License owners on the source code of the account module and the lepton theme. We see that customization of these two modules is highly necessary for most of our customers.
With this version, we decided to allow Team License holders to download the source code of the **Account Module** and the **Lepton Theme** to freely customize them based on their requirements.
You can **Replace these modules with their source code** using the ABP Suite:
![account-lepton-source](account-lepton-source.png)
Remember that; when you include the source code in your solution, it is your responsibility to upgrade them when we release new versions (while you don't have to upgrade them).
### Lepton Theme Public Website Layout
We'd added a public website application in the application starter template in the previous versions. It was using the public website layout of the Lepton Theme. We realized that the layout of this application is customized or completely changed in most of the solutions. So, with this version, the layout is included inside the application in the downloaded solution. You can freely change it. Before, you had to download it separately and include it in your solution manually.
### Enable/Disable Modules
With this release, all modules can be enabled/disabled per edition/tenant. You can allow/disallow modules when you click *Features* action for an edition or tenant:
![enable-disable-features](enable-disable-features.png)
### Other Features/Changes
* ABP Suite now supports defining *required* navigation properties on code generation.
* **Blazor server-side** (with tiered option) is added for the application and microservice starter templates.
* An **"Email"** tab has been added to the Settings page to configure the email settings.
## Feedback
Please check out the ABP Commercial 4.3 RC to help us to release a more stable version. **The planned release date for the 4.3.0 final version is April 15, 2021**.

BIN
docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/abp-suite-separate-tenant-schema.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/account-lepton-source.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/cms-kit-menu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/cms-kit-selection.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/enable-disable-features.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/forms-answer.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/forms-edit-report.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/new-tenant-modal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/tenant-db-migrate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

134
docs/en/Blog-Posts/2021-03-31 v4_3 Preview/POST.md

@ -1,6 +1,6 @@
# ABP Framework 4.3 RC Has Been Published
We are super excited to announce the ABP Framework 4.3 RC (Release Candidate). Here, a list of highlights for this release;
We are super excited to announce the ABP Framework 4.3 RC (Release Candidate). Here, a list of highlights of this release;
* **CMS Kit** module initial release.
* **Blazor UI server-side** support.
@ -9,21 +9,26 @@ We are super excited to announce the ABP Framework 4.3 RC (Release Candidate). H
* **Volo.Abp.EntityFrameworkCore.Oracle** package is now compatible with .NET 5.
* CLI support to easily add the **Basic Theme** into the solution.
* New **IInitLogger** service to write logs before dependency injection phase completed.
* Infrastructure for **multi-lingual entities**.
Beside the new features above, we've done many performance improvements, enhancements and bug fixes on the current features. See the [4.3 milestone](https://github.com/abpframework/abp/milestone/49) on GitHub for all changes made on this version.
Besides the new features above, we've done many performance improvements, enhancements and bug fixes on the current features. See the [4.3 milestone](https://github.com/abpframework/abp/milestone/49) on GitHub for all changes made on this version.
This version was a big development journey for us; [150+ issues](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3A4.3-preview) resolved, [260+ PRs](https://github.com/abpframework/abp/pulls?q=is%3Aopen+is%3Apr+milestone%3A4.3-preview) merged and 1,600+ commits done only in the [main framework repository](https://github.com/abpframework/abp). **Thanks to the ABP Framework team and all the contributors.**
This version was a big development journey for us; [~160 issues](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3A4.3-preview) resolved, [~300 PRs](https://github.com/abpframework/abp/pulls?q=is%3Aopen+is%3Apr+milestone%3A4.3-preview) merged and **~1,700 commits** done only in the [main framework repository](https://github.com/abpframework/abp). **Thanks to the ABP Framework team and all the contributors.**
> ABP Commercial 4.3 RC has also been published. We will write a separate blog post for it.
## The Migration Guide
We normally don't make breaking changes in feature versions. However, this version has some small **breaking changes** mostly related to Blazor UI WebAssembly & Server separation. **Please check the [migration guide](https://docs.abp.io/en/abp/4.3/Migration-Guides/Abp-4_3) before starting with the version 4.3**.
We normally don't make breaking changes in feature versions. However, this version has some small **breaking changes** mostly related to Blazor UI WebAssembly & Server separation. **Please check the [migration guide](https://docs.abp.io/en/abp/4.3/Migration-Guides/Abp-4_3) while upgrading to version 4.3**.
## Known Issues
Some minor issues will be fixed in the stable release. You can see the known issues [here](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3A4.3-final).
## Get Started With The 4.3 RC
If you want to try the version 4.3 today, follow the steps below;
If you want to try version 4.3 today, follow the steps below;
1) **Upgrade** the ABP CLI to the version `4.3.0-rc.1` using a command line terminal:
1) **Upgrade** the ABP CLI to the version `4.3.0-rc.1` using a command-line terminal:
````bash
dotnet tool update Volo.Abp.Cli -g --version 4.3.0-rc.1
@ -49,45 +54,136 @@ See the [ABP CLI documentation](https://docs.abp.io/en/abp/4.3/CLI) for all the
### CMS Kit
CMS Kit was a module we were working for the last couple of months. It is usable now and we are releasing the initial version with this release.
CMS (Content Management System) Kit was a module we worked on for the last couple of months. It is usable now, and we are releasing the initial version with this release. We are considering this module as pre-mature. It will be improved in the next versions. The goal to provide a flexible and extensible CMS infrastructure to .NET community. It currently has the following features;
* **Pages**: Used to create UI pages with a Markdown + WYSIWYG editor. Once you create a page, it becomes available via URL like `/pages/my-page-url`.
* **Blog**: A built-in blog system that supports multiple blogs with blog posts.
* **Comments**: Allows users to write comments under contents. It is used for blog posts.
* **Tags**: To add tag feature to any content/entity. It is used for blog posts.
* **Reactions**: Allows users to react to content via emojis, like a smile, upvote, downvote, etc.
* **Rating**: This component is used to rate content by users.
All features are separately usable. For example, you can create an image gallery and reuse the Comments and Tags features for the images. You can enable/disable features individually using the [Global Features System](https://docs.abp.io/en/abp/4.3/global-features).
> We will create a separate blog post for the CMS Kit module, so I keep it short.
### Blazor Server Side
TODO
We'd implemented Blazor WebAssembly before. With version 4.3, we have the Blazor Server-Side option too. All the current functionalities are available to the Blazor Server.
You can select Blazor Server as the UI type while creating a new solution.
**Example:**
````bash
abp new Acme.BookStore -u blazor-server
````
If you write `blazor` as the UI type, it will create Blazor WebAssembly just as before.
> You can also select the Blazor Server on the [get started](https://abp.io/get-started) page.
Blazor Server applications are mixed applications; You can mix the server-side MVC / Razor Pages with the Blazor SPA. This brings an interesting opportunity: MVC / Razor Pages modules can work seamlessly in the Blazor Server applications. For example, the CMS Kit module has no Blazor UI yet, but you can use its MVC UI inside your Blazor Server application.
> Blazor Server UI has a `--tiered` option just [like](https://docs.abp.io/en/abp/latest/Startup-Templates/Application#tiered-structure) the MVC / Razor Pages UI. This can be used to separate the HTTP API server from the UI server (UI application doesn't directly connect to the database).
### Blazor UI Module Extensibility
TODO
Module Entity Extensions and some other extensibility features was not supported by the Blazor UI. With this version, we've implemented that system for Blazor UI.
For anyone wondering what the module entity extensions is, please check [the document](https://docs.abp.io/en/abp/4.3/Module-Entity-Extensions) or [this community video](https://community.abp.io/articles/overview-of-abp-framework-4.1-module-extensions-part-1-n04f7bhf).
### Email Setting Management UI
With this release, a new item is added to the main menu to navigate to the setting management page. This page contains the email setting management UI, as shown below:
![email-settings-page](email-settings-page.png)
The setting page is provided by the [setting management module](https://docs.abp.io/en/abp/4.3/Modules/Setting-Management), and it is extensible; You can add your tabs to this page for your application settings.
### Angular UI Resource Owner Password Flow
TODO
The login page was removed from the Angular UI in previous versions because Authorization Code flow is the recommended approach for SPAs. However, it requires redirecting the user to the authentication server, logging there, and returning to the application. We got a lot of feedback because this brings overhead for simple applications.
With version 4.3, Angular UI can use its login page with resource owner password flow. Please refer to [the documentation](https://github.com/abpframework/abp/blob/dev/docs/en/UI/Angular/Account-Module.md) to learn how to make it work.
### Volo.Abp.EntityFrameworkCore.Oracle Package
TODO
We couldn't update the [Oracle.EntityFrameworkCore](https://www.nuget.org/packages/Oracle.EntityFrameworkCore/) package on .NET 5.0 upgrade since it was not supporting .NET 5.0 at that time. Now, it supports .NET 5.0 and we've upgraded the package.
See [the documentation](https://docs.abp.io/en/abp/4.3/Entity-Framework-Core-Oracle-Official) to learn how to switch to this package for the Oracle database.
### Add Basic Theme Into Your Solution
TODO
ABP Framework provides a strong theming system. However, the default theme, named the Basic Theme, has a non-styled, base Bootstrap UI. It is expected that you override the styles and UI components of that theme in a serious application.
There are some articles (see for [mvc](https://community.abp.io/articles/creating-a-new-ui-theme-by-copying-the-basic-theme-for-mvc-ui-yt9b18io) & [blazor](https://community.abp.io/articles/creating-a-new-ui-theme-by-copying-the-basic-theme-for-blazor-ui-qaf5ho1b)) to explain how to include the Basic Theme's source code into your solution to modify it fully. However, it still requires some manual work.
With this version, ABP CLI providing a command to add the Basic Theme's source code into your solution. Run the following command in a command-line terminal inside the root directory of your solution:
**MVC UI**
````bash
abp add-package Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic --with-source-code --add-to-solution
````
**Blazor Web Assembly UI**
````bash
abp add-package Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme --with-source-code --add-to-solution
abp add-package Volo.Abp.AspNetCore.Components.Web.BasicTheme --with-source-code --add-to-solution
````
**Blazor Server UI**
````bash
abp add-package Volo.Abp.AspNetCore.Components.Server.BasicTheme --with-source-code --add-to-solution
abp add-package Volo.Abp.AspNetCore.Components.Web.BasicTheme --with-source-code --add-to-solution
````
As you see, Blazor UI developers should add two packages. The Basic Theme consists of two packages for the Blazor UI: one for wasm/server and one shared.
**Angular UI**
Execute the following command in a terminal inside the `angular` folder of your solution:
````bash
abp add-package @abp/ng.theme.basic --with-source-code
````
### IInitLogger
TODO
In ASP.NET Core, logging is not possible before the dependency injection phase is completed. For example, you can't write log in `ConfigureServices` method. However, we sometimes need to write logs in this stage.
We are introducing the `IInitLogger` service, which allows writing logs inside the `ConfigureServices` method.
**Example:**
````csharp
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var logger = context.Services.GetInitLogger<MyModule>();
logger.LogInformation("Some log...");
}
}
````
### Multi-Lingual Entities
Logs are written once the service registration phase is completed. It stores the written logs in memory and then writes logs to the actual `ILogger` when ready.
TODO
> Notice: Startup templates come with [Serilog](https://serilog.net/) pre-installed. So, you can write logs everywhere by directly using its static API (ex: `Log.Information("...");`). The `InitLogger` is a way to write pre-initialization logs without depending on a particular logging library. So, it makes it very handy to write logs inside reusable modules.
### Other News
### Other Features/Changes
* [#7423](https://github.com/abpframework/abp/issues/7423) MongoDB repository base aggregation API.
* [#8163](https://github.com/abpframework/abp/issues/8163) Ignoring files on minification for MVC UI.
* [#8163](https://github.com/abpframework/abp/issues/8163) Ignoring given files on minification for MVC UI.
* [#7799](https://github.com/abpframework/abp/pull/7799) Added `RequiredPermissionName` to `ApplicationMenuItem` for MVC & Blazor UI to easily show/hide menu items based on user permissions. Also added `RequiredPermissionName` to `ToolbarItem` for the MVC UI for the same purpose.
* [#7523](https://github.com/abpframework/abp/pull/7523) Add more bundle methods to the distributed cache.
* [#8013](https://github.com/abpframework/abp/pull/8013) Handle `JsonProperty` attribute on Angular proxy generation.
See the [4.3 milestone](https://github.com/abpframework/abp/milestone/49) on GitHub for all changes made on this version.
## Feedback
Please check out the ABP Framework 4.3 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us to release a more stable version. **The planned release date for the [4.3.0 final](https://github.com/abpframework/abp/milestone/50) version is April 15, 2021**.
Please check out the ABP Framework 4.3 RC and [provide feedback](https://github.com/abpframework/abp/issues/new) to help us release a more stable version. **The planned release date for the [4.3.0 final](https://github.com/abpframework/abp/milestone/50) version is April 15, 2021**.

BIN
docs/en/Blog-Posts/2021-03-31 v4_3 Preview/email-settings-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

3
docs/en/Blog-Posts/2021-04-05 CmsKit/POST.md

@ -0,0 +1,3 @@
# Introducing the CMS Kit Module for the ABP Framework
TODO...

7
docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/POST.md

@ -84,12 +84,13 @@ We added SignalR to the `package.json` but it comes into your `node_modules` fol
#### 4- Usage
We have completed the implementation part. Let's check if it's running...
We will show the current time which comes from server.
To do this replace the `Index.cshtml` and `Index.cshtml.cs` with the followings:
To do this easily, open your `Index.cshtml` which is in the Pages folder of your Web project. And replace the content with the following. Also replace the `Index.cshtml.cs` as well.
- [Index.cshtml](https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-index-cshtml)
[Index.cshtml](https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-index-cshtml)
- [Index.cshtml.cs](https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-index-cshtml-cs)
[Index.cshtml.cs](https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-index-cshtml-cs)
#### 5- See it in action

BIN
docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/result.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 126 KiB

30
docs/en/Migration-Guides/Abp-4_3.md

@ -1,3 +1,31 @@
# ABP Framework 4.x to 4.3 Migration Guide
TODO
## Blazor UI
Implemented the Blazor Server Side support with this release. It required some packages and namespaces arrangements. **Existing Blazor (WebAssembly) applications should done the changes explained in this section**.
### Namespace Changes
- `AbpBlazorMessageLocalizerHelper` -> moved to Volo.Abp.AspNetCore.Components.Web
- `AbpRouterOptions` -> moved to Volo.Abp.AspNetCore.Components.Web.Theming.Routing
- `AbpToolbarOptions` and `IToolbarContributor` -> moved to Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars
- `IAbpUtilsService` -> moved to Volo.Abp.AspNetCore.Components.Web
- `PageHeader` -> moved to `Volo.Abp.AspNetCore.Components.Web.Theming.Layout`.
In practice, if your application is broken because of the `Volo.Abp.AspNetCore.Components.WebAssembly.*` namespace, please try to switch to `Volo.Abp.AspNetCore.Components.Web.*` namespace.
Remember to change namespaces in the `_Imports.razor` files.
### Package Changes
No change on the framework packages, but **module packages are separated as Web Assembly & Server**;
* Use `Volo.Abp.Identity.Blazor.WebAssembly` NuGet package instead of `Volo.Abp.Identity.Blazor` package. Also, change `AbpIdentityBlazorModule` usage to `AbpIdentityBlazorWebAssemblyModule` in the `[DependsOn]` attribute on your module class.
* Use `Volo.Abp.TenantManagement.Blazor.WebAssembly` NuGet package instead of `Volo.Abp.TenantManagement.Blazor` package. Also, change `AbpTenantManagementBlazorModule` usage to `AbpTenantManagementBlazorWebAssemblyModule` in the `[DependsOn]` attribute on your module class.
* Use `Volo.Abp.PermissionManagement.Blazor.WebAssembly` NuGet package instead of `Volo.Abp.PermissionManagement.Blazor` package. Also, change `AbpPermissionManagementBlazorModule` usage to `AbpPermissionManagementBlazorWebAssemblyModule` in the `[DependsOn]` attribute on your module class.
* Use `Volo.Abp.SettingManagement.Blazor.WebAssembly` NuGet package instead of `Volo.Abp.SettingManagement.Blazor` package. Also, change `AbpSettingManagementBlazorModule` usage to `AbpSettingManagementBlazorWebAssemblyModule` in the `[DependsOn]` attribute on your module class.
* Use `Volo.Abp.FeatureManagement.Blazor.WebAssembly` NuGet package instead of `Volo.Abp.FeatureManagement.Blazor` package. Also, change `AbpFeatureManagementBlazorModule` usage to `AbpFeatureManagementBlazorWebAssemblyModule` in the `[DependsOn]` attribute on your module class.
### Other Changes
* `EntityAction.RequiredPermission` has been marked as obsolete, because of performance reasons. It is suggested to use the `Visible` property by checking the permission/policy yourself and assigning to a variable.

6
docs/en/Tutorials/Part-5.md

@ -516,7 +516,7 @@ Wrap the *New Book* button by an `if` block as shown below:
#### Hide the Edit/Delete Actions
`EntityAction` component defines `RequiredPolicy` attribute (parameter) to conditionally show the action based on the user permissions.
`EntityAction` component defines `Visible` attribute (parameter) to conditionally show the action.
Update the `EntityActions` section as shown below:
@ -524,11 +524,11 @@ Update the `EntityActions` section as shown below:
<EntityActions TItem="BookDto" EntityActionsColumn="@EntityActionsColumn">
<EntityAction TItem="BookDto"
Text="@L["Edit"]"
RequiredPolicy="@UpdatePolicyName"
Visible=HasUpdatePermission
Clicked="() => OpenEditModalAsync(context)" />
<EntityAction TItem="BookDto"
Text="@L["Delete"]"
RequiredPolicy="@DeletePolicyName"
Visible=HasDeletePermission
Clicked="() => DeleteEntityAsync(context)"
ConfirmationMessage="()=>GetDeleteConfirmationMessage(context)" />
</EntityActions>

BIN
docs/en/Tutorials/images/blazor-edit-book-action-2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 96 KiB

10
docs/en/UI/Angular/Account-Module.md

@ -2,7 +2,7 @@
Angular UI account module is available as of v4.3. It contains some pages (login, register, manage your profile, etc.).
If you implement the account module to your project;
If you add the account module to your project;
- "Manage your profile" link in the current user dropdown on the top bar will redirect the user to a page in the account module.
- You can switch the authentication flow to the resource owner password flow.
@ -93,15 +93,15 @@ export class AppRoutingModule {}
### Manage Profile Page
Before v4.3, the "Manage Your Profile" link in the current user dropdown on the top bar redirected the user to MVC's profile management page. As of v4.3, if you implemented the account module to your project, the same link will land on a page in the Angular UI account module instead.
Before v4.3, the "Manage Your Profile" link in the current user dropdown on the top bar redirected the user to MVC's profile management page. As of v4.3, if you added the account module to your project, the same link will land on a page in the Angular UI account module instead.
### My Security Logs Page [COMMERCIAL]
Before v4.3, the "My Security Logs" link in the current user dropdown on the top bar redirected the user to MVC's my security logs page. As of v4.3, if you implemented the account module to your project, the same link will land on a page in the Angular UI account public module instead.
Before v4.3, the "My Security Logs" link in the current user dropdown on the top bar redirected the user to MVC's my security logs page. As of v4.3, if you added the account module to your project, the same link will land on a page in the Angular UI account public module instead.
### Resource Owner Password Flow
OAuth is preconfigured as authorization code flow in Angular application templates by default. If you implemented the account module to your project, you can switch the flow to resource owner password flow by changing the OAuth configuration in the _environment.ts_ files as shown below:
OAuth is preconfigured as authorization code flow in Angular application templates by default. If you added the account module to your project, you can switch the flow to resource owner password flow by changing the OAuth configuration in the _environment.ts_ files as shown below:
```js
import { Config } from '@abp/ng.core';
@ -122,4 +122,4 @@ export const environment = {
> Note: The resource owner password flow does not support the two-factor authentication for some technical reasons.
See the [Authorization in Angular UI](./Authorization) document for more details.
See the [Authorization in Angular UI](./Authorization.md) document for more details.

4
docs/en/docs-nav.json

@ -376,10 +376,6 @@
"text": "Entities & Aggregate Roots",
"path": "Entities.md"
},
{
"text": "Multi-Lingual-Entities",
"path": "Multi-Lingual-Entities.md"
},
{
"text": "Value Objects",
"path": "Value-Objects.md"

100
docs/zh-Hans/Multi-Lingual-Entities.md

@ -1,100 +0,0 @@
# 多语言实体
ABP框架为多语言实体定义了两个基本接口用于翻译实体的标准模型.
## IHasMultiLingual
`IHasMultiLingual<TTranslation>` 接口用于标记多语言实体. 通过 `IHasMultiLingual<TTranslation>` 接口被标记为多语言的实体定义与语言无关的信息. 多语言实体包含翻译集合,其中包含与语言有关的信息.
示例:
```csharp
public class Product : Entity<Guid>, IMultiLingualEntity<ProductTranslation>
{
public decimal Price { get; set; }
public ICollection<ProductTranslation> Translations { get; set; }
}
```
## IMultiLingualTranslation
`IMultiLingualTranslation` 接口用于标记多语言实体的翻译. 通过 `IHasMultiLingual<TTranslation>` 接口被标记为的翻译实体定义与语言有关的信息. 翻译实体包含 `Language` 字段,用于翻译的语言代码.
示例:
```csharp
public class ProductTranslation : Entity<Guid>, IMultiLingualTranslation
{
public string Name { get; set; }
public string Language { get; set; }
}
```
## 映射为DTO对象
ABP提供了[对象到对象的映射](Object-To-Object-Mapping.md)系统,你可以通过实现 `IObjectMapper<TSource, TDestination>` 接口将多语言实体映射为DTO.
示例:
```csharp
public class MultiLingualProductObjectMapper : IObjectMapper<Product, ProductDto>, ITransientDependency
{
private readonly IMultiLingualObjectManager _multiLingualObjectManager;
public MultiLingualProductObjectMapper(IMultiLingualObjectManager multiLingualObjectManager)
{
_multiLingualObjectManager = multiLingualObjectManager;
}
public ProductDto Map(Product source)
{
var translation = _multiLingualObjectManager.GetTranslation<Product, ProductDto>(source);
return new ProductDto
{
Price = source.Price,
Id = source.Id,
Name = translation?.Name
};
}
public ProductDto Map(Product source, ProductDto destination)
{
return default;
}
}
```
### AutoMapper集成
ABP提供了 `CreateMultiLingualMap` 扩展方法用于将多语言实体映射为DTO.
示例:
```csharp
public class ProductProfile : Profile
{
public ProductProfile()
{
var mapResult = this.CreateMultiLingualMap<Product, ProductTranslation, ProductDto>();
}
}
```
`CreateMultiLingualMap` 扩展方法返回了一个类型为 `CreateMultiLingualMapResult` 的对象,它包含 `EntityMap``TranslationMap` 字段. 这些字段可以用于自定义多语言映射.
示例:
```csharp
this.CreateMultiLingualMap<Order, OrderTranslation, OrderListDto>(context)
.EntityMap.ForMember(dest => dest.ProductCount, opt => opt.MapFrom(src => src.Products.Count));
```
## IMultiLingualObjectManager
`IMultiLingualObjectManager` 接口定义了 `GetTranslation``GetTranslationAsync` 方法用于获取实体当前的翻译对象.
`IMultiLingualObjectManager` 的默认实现首先使用当前的UI语言寻找翻译, 如果当前的UI语言没有对应的翻译, 那么会搜索默认语言设置(参阅[设置](Settings.md))用于寻找翻译. 如果默认语言没有对应的翻译, 那么它会返回已存在翻译集合中的第一个翻译对象.

4
docs/zh-Hans/docs-nav.json

@ -354,10 +354,6 @@
"text": "实体&聚合根",
"path": "Entities.md"
},
{
"text": "多语言实体",
"path": "Multi-Lingual-Entities.md"
},
{
"text": "值对象"
},

4
framework/Volo.Abp.sln

@ -331,9 +331,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.GlobalFeatures", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.GlobalFeatures.Tests", "test\Volo.Abp.GlobalFeatures.Tests\Volo.Abp.GlobalFeatures.Tests.csproj", "{231F1581-AA21-44C3-BF27-51EB3AD5355C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiLingualObject", "src\Volo.Abp.MultiLingualObject\Volo.Abp.MultiLingualObject.csproj", "{C9142DED-1F6C-4385-A37D-81E46B233306}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiLingualObjects", "src\Volo.Abp.MultiLingualObjects\Volo.Abp.MultiLingualObjects.csproj", "{C9142DED-1F6C-4385-A37D-81E46B233306}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiLingualObject.Tests", "test\Volo.Abp.MultiLingualObject.Tests\Volo.Abp.MultiLingualObject.Tests.csproj", "{A30D63B0-E952-4052-BAEE-38B8BF924093}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiLingualObjects.Tests", "test\Volo.Abp.MultiLingualObjects.Tests\Volo.Abp.MultiLingualObjects.Tests.csproj", "{A30D63B0-E952-4052-BAEE-38B8BF924093}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Http.Client.IdentityModel.WebAssembly", "src\Volo.Abp.Http.Client.IdentityModel.WebAssembly\Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj", "{3D35A1E0-A9A1-404F-9B55-5F1A7EB6D5B8}"
EndProject

3
framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavToolbar.razor.cs

@ -18,11 +18,12 @@ namespace Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic
ToolbarItemRenders.Clear();
var sequence = 0;
foreach (var item in toolbar.Items)
{
ToolbarItemRenders.Add(builder =>
{
builder.OpenComponent(0, item.ComponentType);
builder.OpenComponent(sequence++, item.ComponentType);
builder.CloseComponent();
});
}

5
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor

@ -32,6 +32,11 @@
}
<Column>
<Row Class="justify-content-end mx-n1">
@if (Toolbar == null)
{
@ChildContent
}
@foreach (var toolbarItemRender in ToolbarItemRenders)
{
<Column ColumnSize="ColumnSize.IsAuto" Class="px-1 pt-2">

3
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs

@ -31,9 +31,6 @@ namespace Volo.Abp.AspNetCore.Components.Web.Theming.Layout
[Parameter]
public PageToolbar Toolbar { get; set; }
[Parameter]
public string PageName { get; set; }
public PageHeader()
{
BreadcrumbItems = new List<BreadcrumbItem>();

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj

@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NUglify" Version="1.13.2" />
<PackageReference Include="NUglify" Version="1.13.8" />
</ItemGroup>
<ItemGroup>

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj

@ -30,7 +30,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="4.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
</ItemGroup>
</Project>

3
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentInputFormatter.cs

@ -15,7 +15,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters
protected override bool CanReadType(Type type)
{
return typeof(IRemoteStreamContent) == type;
return type == typeof(IRemoteStreamContent) ||
type == typeof(RemoteStreamContent);
}
public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)

6
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs

@ -28,7 +28,11 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters
using (var stream = remoteStream.GetStream())
{
stream.Position = 0;
if (stream.CanSeek)
{
stream.Position = 0;
}
await stream.CopyToAsync(context.HttpContext.Response.Body);
}
}

2
framework/src/Volo.Abp.AspNetCore.Serilog/Volo.Abp.AspNetCore.Serilog.csproj

@ -22,7 +22,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="2.9.0" />
<PackageReference Include="Serilog" Version="2.10.0" />
</ItemGroup>
</Project>

54
framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperMultiLingualDtoExtensions.cs

@ -1,54 +0,0 @@
using Volo.Abp.MultiLingualObject;
using Volo.Abp.Threading;
namespace AutoMapper
{
public static class AbpAutoMapperMultiLingualDtoExtensions
{
public static CreateMultiLingualMapResult<TSource, TTranslation, TDestination> CreateMultiLingualMap<TSource, TTranslation, TDestination>(this Profile profile)
where TTranslation : class, IMultiLingualTranslation
where TSource : IHasMultiLingual<TTranslation>
{
return new(
profile.CreateMap<TSource, TDestination>().BeforeMap<AbpMultiLingualMapperAction<TSource, TTranslation, TDestination>>(),
profile.CreateMap<TTranslation, TDestination>());
}
}
public class AbpMultiLingualMapperAction<TSource, TTranslation, TDestination> : IMappingAction<TSource, TDestination>
where TTranslation : class, IMultiLingualTranslation
where TSource : IHasMultiLingual<TTranslation>
{
private readonly IMultiLingualObjectManager _multiLingualObjectManager;
public AbpMultiLingualMapperAction(IMultiLingualObjectManager multiLingualObjectManager)
{
_multiLingualObjectManager = multiLingualObjectManager;
}
public void Process(TSource source, TDestination destination, ResolutionContext context)
{
var translation = AsyncHelper.RunSync(() => _multiLingualObjectManager.GetTranslationAsync<TSource, TTranslation>(source));
if (translation != null)
{
context.Mapper.Map(translation, destination);
}
}
}
public class CreateMultiLingualMapResult<TSource, TTranslation, TDestination>
{
public IMappingExpression<TSource, TDestination> EntityMap { get; }
public IMappingExpression<TTranslation, TDestination> TranslateMap { get; }
public CreateMultiLingualMapResult(
IMappingExpression<TSource, TDestination> entityMap,
IMappingExpression<TTranslation, TDestination> translateMap)
{
EntityMap = entityMap;
TranslateMap = translateMap;
}
}
}

1
framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj

@ -16,7 +16,6 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Auditing\Volo.Abp.Auditing.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiLingualObject\Volo.Abp.MultiLingualObject.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectExtending\Volo.Abp.ObjectExtending.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
</ItemGroup>

2
framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs

@ -27,8 +27,6 @@ namespace Volo.Abp.AutoMapper
context.Services.AddSingleton<MapperAccessor>(CreateMappings);
context.Services.AddSingleton<IMapperAccessor>(provider => provider.GetRequiredService<MapperAccessor>());
context.Services.AddTransient(typeof(AbpMultiLingualMapperAction<,,>));
}
private MapperAccessor CreateMappings(IServiceProvider serviceProvider)

4
framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj

@ -15,8 +15,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Autofac" Version="6.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Autofac" Version="6.1.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
<PackageReference Include="Autofac.Extras.DynamicProxy" Version="6.0.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(MicrosoftPackageVersion)" />

4
framework/src/Volo.Abp.BlazoriseUI/Components/EntityAction.razor.cs

@ -10,7 +10,7 @@ namespace Volo.Abp.BlazoriseUI.Components
public partial class EntityAction<TItem> : ComponentBase
{
[Parameter]
public bool Visible { get; set; }
public bool Visible { get; set; } = true;
internal bool HasPermission { get; set; } = true;
@ -24,7 +24,7 @@ namespace Volo.Abp.BlazoriseUI.Components
public EventCallback Clicked { get; set; }
[Parameter]
[Obsolete("Use IsVisible to hide actions based on permissions. Check the permission yourself. It is more performant. This option might be removed in future versions.")]
[Obsolete("Use Visible to hide actions based on permissions. Check the permission yourself. It is more performant. This option might be removed in future versions.")]
public string RequiredPolicy { get; set; }
[Parameter]

2
framework/src/Volo.Abp.BlobStoring.Aliyun/Volo.Abp.BlobStoring.Aliyun.csproj

@ -16,7 +16,7 @@
<ItemGroup>
<PackageReference Include="aliyun-net-sdk-sts" Version="3.0.4" />
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.12.0" />
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
</ItemGroup>
<ItemGroup>

4
framework/src/Volo.Abp.BlobStoring.Aws/Volo.Abp.BlobStoring.Aws.csproj

@ -17,8 +17,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AWSSDK.S3" Version="3.5.6.1" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.5.1.25" />
<PackageReference Include="AWSSDK.S3" Version="3.7.0.2" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.0.1" />
</ItemGroup>
</Project>

2
framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj

@ -16,7 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.BlobStoring\Volo.Abp.BlobStoring.csproj" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.7.0" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.8.0" />
</ItemGroup>
</Project>

6
framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj

@ -13,12 +13,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SharpZipLib" Version="1.2.0" />
<PackageReference Include="SharpZipLib" Version="1.3.1" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="NuGet.Versioning" Version="5.8.0" />
<PackageReference Include="NuGet.Versioning" Version="5.9.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="System.Security.Permissions" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
<PackageReference Include="Polly" Version="7.2.1" />
<PackageReference Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageReference Include="LibGit2Sharp" Version="0.26.2" />

118
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs

@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
@ -17,9 +18,12 @@ namespace Volo.Abp.Cli.Commands
protected ProjectNugetPackageAdder ProjectNugetPackageAdder { get; }
public AddPackageCommand(ProjectNugetPackageAdder projectNugetPackageAdder)
public ProjectNpmPackageAdder ProjectNpmPackageAdder { get; }
public AddPackageCommand(ProjectNugetPackageAdder projectNugetPackageAdder, ProjectNpmPackageAdder projectNpmPackageAdder)
{
ProjectNugetPackageAdder = projectNugetPackageAdder;
ProjectNpmPackageAdder = projectNpmPackageAdder;
Logger = NullLogger<AddPackageCommand>.Instance;
}
@ -34,18 +38,42 @@ namespace Volo.Abp.Cli.Commands
);
}
var isAngularPackage = false;
var isNugetPackage = true;
if (commandLineArgs.Target.StartsWith("@"))
{
isAngularPackage = true;
isNugetPackage = false;
}
var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
var withSourceCode =commandLineArgs.Options.ContainsKey(Options.SourceCode.Long);
var addSourceCodeToSolutionFile = withSourceCode && commandLineArgs.Options.ContainsKey("add-to-solution-file");
await ProjectNugetPackageAdder.AddAsync(
GetProjectFile(commandLineArgs),
commandLineArgs.Target,
version,
true,
withSourceCode,
addSourceCodeToSolutionFile
);
if (isNugetPackage)
{
var addSourceCodeToSolutionFile = withSourceCode && commandLineArgs.Options.ContainsKey("add-to-solution-file");
await ProjectNugetPackageAdder.AddAsync(
GetSolutionFile(commandLineArgs),
GetProjectFile(commandLineArgs),
commandLineArgs.Target,
version,
true,
withSourceCode,
addSourceCodeToSolutionFile
);
}
else if (isAngularPackage)
{
await ProjectNpmPackageAdder.AddAngularPackageAsync(
GetAngularDirectory(commandLineArgs),
commandLineArgs.Target,
version,
withSourceCode
);
}
}
public string GetUsageInfo()
@ -54,7 +82,7 @@ namespace Volo.Abp.Cli.Commands
sb.AppendLine("");
sb.AppendLine("'add-package' command is used to add an ABP package to a project.");
sb.AppendLine("It should be used in a folder containing a .csproj file.");
sb.AppendLine("It should be used in a folder containing a .csproj file, .sln file or angular.json.");
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine("");
@ -62,13 +90,18 @@ namespace Volo.Abp.Cli.Commands
sb.AppendLine("");
sb.AppendLine("Options:");
sb.AppendLine("");
sb.AppendLine(" -p|--project <project-file> Specify the project file explicitly.");
sb.AppendLine(" -v|--version <version> Specify the version of the package. Default is your project's ABP version or latest ABP version.");
sb.AppendLine(" -p|--project <project-file> Specifies the project file explicitly. (Only available for NuGet packages)");
sb.AppendLine(" -s|--solution <solution-file> Specifies the solution file explicitly. (Only available for NuGet packages)");
sb.AppendLine(" --with-source-code Downloads the source code of the NPM/NuGet package and make other projects depends on it.");
sb.AppendLine(" --add-to-solution-file Adds the downloaded project to the .sln file, when source code is downloaded. (Only available for NuGet packages)");
sb.AppendLine(" -ad|--angular-directory <angular-project-directory> Specifies the Angular project directory explicitly. (Only available for Angular packages)");
sb.AppendLine(" -v|--version <version> Specifies the version of the package. Default is your project's ABP version or latest ABP version.");
sb.AppendLine("");
sb.AppendLine("Examples:");
sb.AppendLine("");
sb.AppendLine(" abp add-package Volo.Abp.FluentValidation Adds the package to the current project.");
sb.AppendLine(" abp add-package Volo.Abp.FluentValidation -p Acme.BookStore.Application Adds the package to the given project.");
sb.AppendLine(" abp add-package Volo.Abp.FluentValidation Adds the NuGet package to the current project.");
sb.AppendLine(" abp add-package Volo.Abp.FluentValidation -p Acme.BookStore.Application Adds the NuGet package to the given project.");
sb.AppendLine(" abp add-package @abp/ng.theme.basic Adds the NPM package to the given corresponding project.");
sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");
@ -94,30 +127,41 @@ namespace Volo.Abp.Cli.Commands
return providedProjectFile;
}
var foundProjectFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.csproj");
if (foundProjectFiles.Length == 1)
{
return foundProjectFiles[0];
}
return Directory.GetFiles(Directory.GetCurrentDirectory(), "*.csproj").FirstOrDefault();
}
if (foundProjectFiles.Length == 0)
protected virtual string GetSolutionFile(CommandLineArgs commandLineArgs)
{
var providedSolutionFile = PathHelper.NormalizePath(
commandLineArgs.Options.GetOrNull(
Options.Solution.Short,
Options.Solution.Long
)
);
if (!providedSolutionFile.IsNullOrWhiteSpace())
{
throw new CliUsageException("'abp add-package' command should be used inside a folder contaning a .csproj file!");
return providedSolutionFile;
}
//foundProjectFiles.Length > 1
return Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln").FirstOrDefault();
}
var sb = new StringBuilder("There are multiple project (.csproj) files in the current directory. Please specify one of the files below:");
protected virtual string GetAngularDirectory(CommandLineArgs commandLineArgs)
{
var providedAngularDirectory = PathHelper.NormalizePath(
commandLineArgs.Options.GetOrNull(
Options.AngularDirectory.Short,
Options.AngularDirectory.Long
)
);
foreach (var foundProjectFile in foundProjectFiles)
if (!providedAngularDirectory.IsNullOrWhiteSpace())
{
sb.AppendLine("* " + foundProjectFile);
return providedAngularDirectory;
}
sb.AppendLine("Example:");
sb.AppendLine($"abp add-package {commandLineArgs.Target} -p {foundProjectFiles[0]}");
throw new CliUsageException(sb.ToString());
return Directory.GetCurrentDirectory();
}
public static class Options
@ -128,6 +172,18 @@ namespace Volo.Abp.Cli.Commands
public const string Long = "project";
}
public static class Solution
{
public const string Short = "s";
public const string Long = "solution";
}
public static class AngularDirectory
{
public const string Short = "ad";
public const string Long = "angular-directory";
}
public static class Version
{
public const string Short = "v";

60
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs

@ -17,13 +17,17 @@ namespace Volo.Abp.Cli.Commands.Services
public class SourceCodeDownloadService : ITransientDependency
{
public ModuleProjectBuilder ModuleProjectBuilder { get; }
public PackageProjectBuilder PackageProjectBuilder { get; }
public NugetPackageProjectBuilder NugetPackageProjectBuilder { get; }
public NpmPackageProjectBuilder NpmPackageProjectBuilder { get; }
public ILogger<SourceCodeDownloadService> Logger { get; set; }
public SourceCodeDownloadService(ModuleProjectBuilder moduleProjectBuilder, PackageProjectBuilder packageProjectBuilder)
public SourceCodeDownloadService(ModuleProjectBuilder moduleProjectBuilder,
NugetPackageProjectBuilder nugetPackageProjectBuilder,
NpmPackageProjectBuilder npmPackageProjectBuilder)
{
ModuleProjectBuilder = moduleProjectBuilder;
PackageProjectBuilder = packageProjectBuilder;
NugetPackageProjectBuilder = nugetPackageProjectBuilder;
NpmPackageProjectBuilder = npmPackageProjectBuilder;
Logger = NullLogger<SourceCodeDownloadService>.Instance;
}
@ -92,13 +96,13 @@ namespace Volo.Abp.Cli.Commands.Services
Logger.LogInformation($"'{moduleName}' has been successfully downloaded to '{outputFolder}'");
}
public async Task DownloadPackageAsync(string packageName, string outputFolder, string version)
public async Task DownloadNugetPackageAsync(string packageName, string outputFolder, string version)
{
Logger.LogInformation("Downloading source code of " + packageName);
Logger.LogInformation("Version: " + version);
Logger.LogInformation("Output folder: " + outputFolder);
var result = await PackageProjectBuilder.BuildAsync(
var result = await NugetPackageProjectBuilder.BuildAsync(
new ProjectBuildArgs(
SolutionName.Parse(packageName),
packageName,
@ -113,12 +117,56 @@ namespace Volo.Abp.Cli.Commands.Services
var zipEntry = zipInputStream.GetNextEntry();
while (zipEntry != null)
{
if (IsAngularTestFile(zipEntry.Name))
var fullZipToPath = Path.Combine(outputFolder, zipEntry.Name);
var directoryName = Path.GetDirectoryName(fullZipToPath);
if (!string.IsNullOrEmpty(directoryName))
{
Directory.CreateDirectory(directoryName);
}
var fileName = Path.GetFileName(fullZipToPath);
if (fileName.Length == 0)
{
zipEntry = zipInputStream.GetNextEntry();
continue;
}
var buffer = new byte[4096]; // 4K is optimum
using (var streamWriter = File.Create(fullZipToPath))
{
StreamUtils.Copy(zipInputStream, streamWriter, buffer);
}
zipEntry = zipInputStream.GetNextEntry();
}
}
}
Logger.LogInformation($"'{packageName}' has been successfully downloaded to '{outputFolder}'");
}
public async Task DownloadNpmPackageAsync(string packageName, string outputFolder, string version)
{
Logger.LogInformation("Downloading source code of " + packageName);
Logger.LogInformation("Version: " + version);
Logger.LogInformation("Output folder: " + outputFolder);
var result = await NpmPackageProjectBuilder.BuildAsync(
new ProjectBuildArgs(
SolutionName.Parse(packageName),
packageName,
version
)
);
using (var templateFileStream = new MemoryStream(result.ZipContent))
{
using (var zipInputStream = new ZipInputStream(templateFileStream))
{
var zipEntry = zipInputStream.GetNextEntry();
while (zipEntry != null)
{
var fullZipToPath = Path.Combine(outputFolder, zipEntry.Name);
var directoryName = Path.GetDirectoryName(fullZipToPath);

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs

@ -91,7 +91,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
return new TemplateFile(File.ReadAllBytes(Path.Combine(templateSource, name + "-" + version + ".zip")), version, latestVersion, nugetVersion);
}
var localCacheFile = Path.Combine(CliPaths.TemplateCache, name + "-" + version + ".zip");
var localCacheFile = Path.Combine(CliPaths.TemplateCache, name.Replace("/",".") + "-" + version + ".zip");
#if DEBUG
if (File.Exists(localCacheFile))

18
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/NpmPackageProjectBuildPipelineBuilder.cs

@ -0,0 +1,18 @@
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
using Volo.Abp.Cli.ProjectBuilding.Templates;
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public static class NpmPackageProjectBuildPipelineBuilder
{
public static ProjectBuildPipeline Build(ProjectBuildContext context)
{
var pipeline = new ProjectBuildPipeline(context);
pipeline.Steps.Add(new FileEntryListReadStep());
pipeline.Steps.Add(new CreateProjectResultZipStep());
return pipeline;
}
}
}

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/PackageProjectBuildPipelineBuilder.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/NugetPackageProjectBuildPipelineBuilder.cs

@ -3,7 +3,7 @@ using Volo.Abp.Cli.ProjectBuilding.Templates;
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
public static class PackageProjectBuildPipelineBuilder
public static class NugetPackageProjectBuildPipelineBuilder
{
public static ProjectBuildPipeline Build(ProjectBuildContext context)
{

14
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildContext.cs

@ -17,24 +17,28 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
public ModuleInfo Module { get; }
public NugetPackageInfo Package { get; }
public NugetPackageInfo NugetPackage { get; }
public NpmPackageInfo NpmPackage { get; }
public FileEntryList Files { get; set; }
public ProjectResult Result { get; set; }
public List<string> Symbols { get; } //TODO: Fill the symbols, like "UI-Angular", "CMS-KIT"!
public ProjectBuildContext(
TemplateInfo template,
ModuleInfo module,
NugetPackageInfo package,
NugetPackageInfo nugetPackage,
NpmPackageInfo npmPackage,
[NotNull] TemplateFile templateFile,
[NotNull] ProjectBuildArgs buildArgs)
{
Template = template;
Module = module;
Package = package;
NugetPackage = nugetPackage;
NpmPackage = npmPackage;
TemplateFile = Check.NotNull(templateFile, nameof(templateFile));
BuildArgs = Check.NotNull(buildArgs, nameof(buildArgs));
Symbols = new List<string>();

10
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/INpmPackageInfoProvider.cs

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Volo.Abp.Cli.ProjectModification;
namespace Volo.Abp.Cli.ProjectBuilding
{
public interface INpmPackageInfoProvider
{
Task<NpmPackageInfo> GetAsync(string name);
}
}

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs

@ -68,6 +68,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
null,
moduleInfo,
null,
null,
templateFile,
args
);

62
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/NpmPackageInfoProvider.cs

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Json;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectModification;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace Volo.Abp.Cli.ProjectBuilding
{
public class NpmPackageInfoProvider : INpmPackageInfoProvider, ITransientDependency
{
public IJsonSerializer JsonSerializer { get; }
public ICancellationTokenProvider CancellationTokenProvider { get; }
public IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
private readonly CliHttpClientFactory _cliHttpClientFactory;
public NpmPackageInfoProvider(
IJsonSerializer jsonSerializer,
ICancellationTokenProvider cancellationTokenProvider,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
CliHttpClientFactory cliHttpClientFactory)
{
JsonSerializer = jsonSerializer;
CancellationTokenProvider = cancellationTokenProvider;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
_cliHttpClientFactory = cliHttpClientFactory;
}
public async Task<NpmPackageInfo> GetAsync(string name)
{
var packageList = await GetPackageListInternalAsync();
var package = packageList.FirstOrDefault(m => m.Name == name);
if (package == null)
{
throw new Exception("Package is not found or downloadable!");
}
return package;
}
private async Task<List<NpmPackageInfo>> GetPackageListInternalAsync()
{
var client = _cliHttpClientFactory.CreateClient();
using (var responseMessage = await client.GetAsync(
$"{CliUrls.WwwAbpIo}api/download/npmPackages/",
CancellationTokenProvider.Token
))
{
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
var result = await responseMessage.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<List<NpmPackageInfo>>(result);
}
}
}
}

110
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/NpmPackageProjectBuilder.cs

@ -0,0 +1,110 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Licensing;
using Volo.Abp.Cli.ProjectBuilding.Analyticses;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.ProjectModification;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace Volo.Abp.Cli.ProjectBuilding
{
public class NpmPackageProjectBuilder : IProjectBuilder, ITransientDependency
{
public ILogger<NpmPackageProjectBuilder> Logger { get; set; }
protected ISourceCodeStore SourceCodeStore { get; }
protected INpmPackageInfoProvider NpmPackageInfoProvider { get; }
protected ICliAnalyticsCollect CliAnalyticsCollect { get; }
protected AbpCliOptions Options { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IApiKeyService ApiKeyService { get; }
public NpmPackageProjectBuilder(ISourceCodeStore sourceCodeStore,
INpmPackageInfoProvider npmPackageInfoProvider,
ICliAnalyticsCollect cliAnalyticsCollect,
IOptions<AbpCliOptions> options,
IJsonSerializer jsonSerializer,
IApiKeyService apiKeyService)
{
SourceCodeStore = sourceCodeStore;
NpmPackageInfoProvider = npmPackageInfoProvider;
CliAnalyticsCollect = cliAnalyticsCollect;
Options = options.Value;
JsonSerializer = jsonSerializer;
ApiKeyService = apiKeyService;
Logger = NullLogger<NpmPackageProjectBuilder>.Instance;
}
public async Task<ProjectBuildResult> BuildAsync(ProjectBuildArgs args)
{
var packageInfo = await GetPackageInfoAsync(args);
var templateFile = await SourceCodeStore.GetAsync(
args.TemplateName,
SourceCodeTypes.NpmPackage,
args.Version,
null,
args.ExtraProperties.ContainsKey(GetSourceCommand.Options.Preview.Long)
);
var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync();
if (apiKeyResult?.ApiKey != null)
{
args.ExtraProperties["api-key"] = apiKeyResult.ApiKey;
}
if (apiKeyResult?.LicenseCode != null)
{
args.ExtraProperties["license-code"] = apiKeyResult.LicenseCode;
}
var context = new ProjectBuildContext(
null,
null,
null,
packageInfo,
templateFile,
args
);
NpmPackageProjectBuildPipelineBuilder.Build(context).Execute();
// Exclude unwanted or known options.
var options = args.ExtraProperties
.Where(x => !x.Key.Equals(CliConsts.Command, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.OutputFolder.Long, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.OutputFolder.Short, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.Version.Long, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.Version.Short, StringComparison.InvariantCultureIgnoreCase))
.Where(x => !x.Key.Equals(NewCommand.Options.TemplateSource.Short, StringComparison.InvariantCultureIgnoreCase) &&
!x.Key.Equals(NewCommand.Options.TemplateSource.Long, StringComparison.InvariantCultureIgnoreCase))
.Select(x => x.Key).ToList();
await CliAnalyticsCollect.CollectAsync(new CliAnalyticsCollectInputDto
{
Tool = Options.ToolName,
Command = args.ExtraProperties.ContainsKey(CliConsts.Command) ? args.ExtraProperties[CliConsts.Command] : "",
DatabaseProvider = null,
IsTiered = null,
UiFramework = null,
Options = JsonSerializer.Serialize(options),
ProjectName = null,
TemplateName = args.TemplateName,
TemplateVersion = templateFile.Version
});
return new ProjectBuildResult(context.Result.ZipContent, args.TemplateName);
}
private async Task<NpmPackageInfo> GetPackageInfoAsync(ProjectBuildArgs args)
{
return await NpmPackageInfoProvider.GetAsync(args.TemplateName);
}
}
}

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/NugetPackageInfoProvider.cs

@ -49,7 +49,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
var client = _cliHttpClientFactory.CreateClient();
using (var responseMessage = await client.GetAsync(
$"{CliUrls.WwwAbpIo}api/download/packages/",
$"{CliUrls.WwwAbpIo}api/download/nugetPackages/",
CancellationTokenProvider.Token
))
{

13
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/PackageProjectBuilder.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/NugetPackageProjectBuilder.cs

@ -14,9 +14,9 @@ using Volo.Abp.Json;
namespace Volo.Abp.Cli.ProjectBuilding
{
public class PackageProjectBuilder : IProjectBuilder, ITransientDependency
public class NugetPackageProjectBuilder : IProjectBuilder, ITransientDependency
{
public ILogger<PackageProjectBuilder> Logger { get; set; }
public ILogger<NugetPackageProjectBuilder> Logger { get; set; }
protected ISourceCodeStore SourceCodeStore { get; }
protected INugetPackageInfoProvider NugetPackageInfoProvider { get; }
protected ICliAnalyticsCollect CliAnalyticsCollect { get; }
@ -24,7 +24,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
protected IJsonSerializer JsonSerializer { get; }
protected IApiKeyService ApiKeyService { get; }
public PackageProjectBuilder(ISourceCodeStore sourceCodeStore,
public NugetPackageProjectBuilder(ISourceCodeStore sourceCodeStore,
INugetPackageInfoProvider nugetPackageInfoProvider,
ICliAnalyticsCollect cliAnalyticsCollect,
IOptions<AbpCliOptions> options,
@ -38,7 +38,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
JsonSerializer = jsonSerializer;
ApiKeyService = apiKeyService;
Logger = NullLogger<PackageProjectBuilder>.Instance;
Logger = NullLogger<NugetPackageProjectBuilder>.Instance;
}
public async Task<ProjectBuildResult> BuildAsync(ProjectBuildArgs args)
@ -47,7 +47,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
var templateFile = await SourceCodeStore.GetAsync(
args.TemplateName,
SourceCodeTypes.Package,
SourceCodeTypes.NugetPackage,
args.Version,
null,
args.ExtraProperties.ContainsKey(GetSourceCommand.Options.Preview.Long)
@ -68,11 +68,12 @@ namespace Volo.Abp.Cli.ProjectBuilding
null,
null,
packageInfo,
null,
templateFile,
args
);
PackageProjectBuildPipelineBuilder.Build(context).Execute();
NugetPackageProjectBuildPipelineBuilder.Build(context).Execute();
// Exclude unwanted or known options.
var options = args.ExtraProperties

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/SourceCodeTypes.cs

@ -6,6 +6,8 @@
public const string Module = "module";
public const string Package = "package";
public const string NugetPackage = "nugetPackage";
public const string NpmPackage = "npmPackage";
}
}

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs

@ -106,6 +106,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
templateInfo,
null,
null,
null,
templateFile,
args
);

32
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularModuleSourceCodeAdder.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularSourceCodeAdder.cs

@ -11,16 +11,16 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class AngularModuleSourceCodeAdder : ITransientDependency
public class AngularSourceCodeAdder : ITransientDependency
{
public ILogger<SolutionModuleAdder> Logger { get; set; }
public AngularModuleSourceCodeAdder()
public AngularSourceCodeAdder()
{
Logger = NullLogger<SolutionModuleAdder>.Instance;
}
public async Task AddAsync(string solutionFilePath, string angularPath)
public async Task AddFromModuleAsync(string solutionFilePath, string angularPath)
{
try
{
@ -36,7 +36,7 @@ namespace Volo.Abp.Cli.ProjectModification
await AddPathsToTsConfigAsync(angularPath, angularProjectsPath, projects);
await CreateTsConfigProdJsonAsync(angularPath);
await AddScriptsToPackageJsonAsync(angularPath);
await AddProjectToAngularJsonAsync(angularPath, projects);
await AddProjectsToAngularJsonAsync(angularPath, projects);
}
catch (Exception e)
{
@ -44,7 +44,29 @@ namespace Volo.Abp.Cli.ProjectModification
}
}
private async Task AddProjectToAngularJsonAsync(string angularPath, List<string> projects)
public async Task AddAsync(string angularPath, NpmPackageInfo package)
{
try
{
var angularProjectsPath = Path.Combine(angularPath, "projects");
var projects = new List<string>
{
package.Name.RemovePreFix("@").Replace("/","-")
};
await AddPathsToTsConfigAsync(angularPath, angularProjectsPath, projects);
await CreateTsConfigProdJsonAsync(angularPath);
await AddScriptsToPackageJsonAsync(angularPath);
await AddProjectsToAngularJsonAsync(angularPath, projects);
}
catch (Exception e)
{
Logger.LogError("Unable to add angular source code: " + e.Message + Environment.NewLine + e.StackTrace);
}
}
private async Task AddProjectsToAngularJsonAsync(string angularPath, List<string> projects)
{
var angularJsonFilePath = Path.Combine(angularPath, "angular.json");
var fileContent = File.ReadAllText(angularJsonFilePath);

6
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NuGetPackageInfo.cs

@ -9,5 +9,9 @@
public NuGetPackageTarget Target { get; set; }
public NuGetPackageTarget TieredTarget { get; set; }
public string MinVersion { get; set; }
public string MaxVersion { get; set; }
}
}
}

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs

@ -51,10 +51,10 @@ namespace Volo.Abp.Cli.ProjectModification
return FindProjectEndsWith(projectFiles, assemblyNames, ".Blazor");
case NuGetPackageTarget.BlazorWebAssembly:
var BlazorWebAssemblyTargetProject = FindProjectEndsWith(projectFiles, assemblyNames, ".Blazor");
return !BlazorProjectTypeChecker.IsBlazorServerProject(BlazorWebAssemblyTargetProject) ? BlazorWebAssemblyTargetProject : null;
return BlazorWebAssemblyTargetProject != null && !BlazorProjectTypeChecker.IsBlazorServerProject(BlazorWebAssemblyTargetProject) ? BlazorWebAssemblyTargetProject : null;
case NuGetPackageTarget.BlazorServer:
var BlazorServerTargetProject = FindProjectEndsWith(projectFiles, assemblyNames, ".Blazor");
return BlazorProjectTypeChecker.IsBlazorServerProject(BlazorServerTargetProject) ? BlazorServerTargetProject : null;
return BlazorServerTargetProject != null && BlazorProjectTypeChecker.IsBlazorServerProject(BlazorServerTargetProject) ? BlazorServerTargetProject : null;
default:
return null;
}

118
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNpmPackageAdder.cs

@ -1,23 +1,107 @@
using System.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Xml;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Commands.Services;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
using Volo.Abp.IO;
using Volo.Abp.Json;
namespace Volo.Abp.Cli.ProjectModification
{
public class ProjectNpmPackageAdder : ITransientDependency
{
public IJsonSerializer JsonSerializer { get; }
public SourceCodeDownloadService SourceCodeDownloadService { get; }
public AngularSourceCodeAdder AngularSourceCodeAdder { get; }
public IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
private readonly CliHttpClientFactory _cliHttpClientFactory;
public ILogger<ProjectNpmPackageAdder> Logger { get; set; }
public ProjectNpmPackageAdder()
public ProjectNpmPackageAdder(CliHttpClientFactory cliHttpClientFactory,
IJsonSerializer jsonSerializer,
SourceCodeDownloadService sourceCodeDownloadService,
AngularSourceCodeAdder angularSourceCodeAdder,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler)
{
JsonSerializer = jsonSerializer;
SourceCodeDownloadService = sourceCodeDownloadService;
AngularSourceCodeAdder = angularSourceCodeAdder;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
_cliHttpClientFactory = cliHttpClientFactory;
Logger = NullLogger<ProjectNpmPackageAdder>.Instance;
}
public Task AddAsync(string directory, NpmPackageInfo npmPackage, bool skipGulpCommand = false)
public async Task AddAngularPackageAsync(string directory, string npmPackageName, string version = null, bool withSourceCode = false)
{
await AddAngularPackageAsync(
directory,
await FindNpmPackageInfoAsync(npmPackageName),
version,
withSourceCode
);
}
public async Task AddAngularPackageAsync(string directory, NpmPackageInfo npmPackage, string version = null, bool withSourceCode = false)
{
var packageJsonFilePath = Path.Combine(directory, "package.json");
if (!File.Exists(packageJsonFilePath))
{
Logger.LogError($"package.json not found!");
return;
}
Logger.LogInformation($"Installing '{npmPackage.Name}' package to the project '{packageJsonFilePath}'...");
if (!File.ReadAllText(packageJsonFilePath).Contains($"\"{npmPackage.Name}\""))
{
var versionPostfix = version != null ? $"@{version}" : string.Empty;
using (DirectoryHelper.ChangeCurrentDirectory(directory))
{
Logger.LogInformation("yarn add " + npmPackage.Name + versionPostfix);
CmdHelper.RunCmd("yarn add " + npmPackage.Name + versionPostfix);
}
}
else
{
Logger.LogInformation($"'{npmPackage.Name}' is already installed.");
}
if (withSourceCode)
{
await DownloadAngularSourceCode(directory, npmPackage, version);
await AngularSourceCodeAdder.AddAsync(directory, npmPackage);
}
}
protected virtual async Task DownloadAngularSourceCode(string angularDirectory, NpmPackageInfo package, string version = null)
{
var targetFolder = Path.Combine(angularDirectory, "projects", package.Name.RemovePreFix("@").Replace("/","-"));
if (Directory.Exists(targetFolder))
{
Directory.Delete(targetFolder, true);
}
await SourceCodeDownloadService.DownloadNpmPackageAsync(
package.Name,
targetFolder,
version
);
}
public Task AddMvcPackageAsync(string directory, NpmPackageInfo npmPackage, string version = null, bool skipGulpCommand = false)
{
var packageJsonFilePath = Path.Combine(directory, "package.json");
if (!File.Exists(packageJsonFilePath) ||
@ -29,11 +113,12 @@ namespace Volo.Abp.Cli.ProjectModification
Logger.LogInformation($"Installing '{npmPackage.Name}' package to the project '{packageJsonFilePath}'...");
var versionPostfix = version != null ? $"@{version}" : string.Empty;
using (DirectoryHelper.ChangeCurrentDirectory(directory))
{
Logger.LogInformation("yarn add " + npmPackage.Name);
CmdHelper.RunCmd("yarn add " + npmPackage.Name);
Logger.LogInformation("yarn add " + npmPackage.Name + versionPostfix);
CmdHelper.RunCmd("yarn add " + npmPackage.Name + versionPostfix);
if (skipGulpCommand)
{
@ -46,5 +131,28 @@ namespace Volo.Abp.Cli.ProjectModification
return Task.CompletedTask;
}
private async Task<NpmPackageInfo> FindNpmPackageInfoAsync(string packageName)
{
var url = $"{CliUrls.WwwAbpIo}api/app/npmPackage/byName/?name=" + packageName;
var client = _cliHttpClientFactory.CreateClient();
using (var response = await client.GetAsync(url, _cliHttpClientFactory.GetCancellationToken()))
{
if (!response.IsSuccessStatusCode)
{
if (response.StatusCode == HttpStatusCode.NotFound)
{
throw new CliUsageException($"'{packageName}' npm package could not be found!");
}
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response);
}
var responseContent = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<NpmPackageInfo>(responseContent);
}
}
}
}

79
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs

@ -58,6 +58,7 @@ namespace Volo.Abp.Cli.ProjectModification
}
public async Task AddAsync(
string solutionFile,
string projectFile,
string packageName,
string version = null,
@ -66,6 +67,7 @@ namespace Volo.Abp.Cli.ProjectModification
bool addSourceCodeToSolutionFile = false)
{
await AddAsync(
solutionFile,
projectFile,
await FindNugetPackageInfoAsync(packageName),
version,
@ -76,6 +78,7 @@ namespace Volo.Abp.Cli.ProjectModification
}
public async Task AddAsync(
string solutionFile,
string projectFile,
NugetPackageInfo package,
string version = null,
@ -83,6 +86,23 @@ namespace Volo.Abp.Cli.ProjectModification
bool withSourceCode = false,
bool addSourceCodeToSolutionFile = false)
{
if (projectFile == null)
{
if (solutionFile == null)
{
throw new CliUsageException("Couldn't find any project/solution.");
}
projectFile = GetProjectFile(solutionFile, package);
if (projectFile == null)
{
throw new CliUsageException("Couldn't find any project/solution.");
}
}
solutionFile ??= FindSolutionFile(projectFile);
if (version == null)
{
version = GetAbpVersionOrNull(projectFile);
@ -92,17 +112,30 @@ namespace Volo.Abp.Cli.ProjectModification
if (withSourceCode)
{
await AddSourceCode(projectFile, package, version);
await ConvertPackageReferenceToProjectReference(projectFile, package);
await AddSourceCode(projectFile, solutionFile, package, version);
await ConvertPackageReferenceToProjectReference(projectFile, solutionFile, package);
if (addSourceCodeToSolutionFile)
{
await SolutionFileModifier.AddPackageToSolutionFileAsync(package, FindSolutionFile(projectFile));
await SolutionFileModifier.AddPackageToSolutionFileAsync(package, solutionFile);
}
}
}
private async Task ConvertPackageReferenceToProjectReference(string projectFile, NugetPackageInfo package)
private string GetProjectFile(string solutionFile, NugetPackageInfo package)
{
var projectFiles = Directory.GetFiles(Path.GetDirectoryName(solutionFile), "*.csproj", SearchOption.AllDirectories);
var isSolutionTiered = IsSolutionTiered(projectFiles);
var projectFile = ProjectFinder.FindNuGetTargetProjectFile(
projectFiles,
isSolutionTiered && package.TieredTarget != NuGetPackageTarget.Undefined
? package.TieredTarget
: package.Target);
return projectFile;
}
protected virtual async Task ConvertPackageReferenceToProjectReference(string projectFile,string solutionFile, NugetPackageInfo package)
{
var content = File.ReadAllText(projectFile);
var doc = new XmlDocument() {PreserveWhitespace = true};
@ -117,7 +150,7 @@ namespace Volo.Abp.Cli.ProjectModification
return;
}
var downloadedProjectPath = FindRelativeFolderToDownloadPackage(projectFile, package);
var downloadedProjectPath = FindRelativeFolderToDownloadPackage(projectFile, solutionFile, package);
var oldNodeIncludeValue = nodes[0]?.Attributes?["Include"]?.Value;
if (package.Name == oldNodeIncludeValue)
@ -135,9 +168,9 @@ namespace Volo.Abp.Cli.ProjectModification
File.WriteAllText(projectFile, doc.OuterXml);
}
private async Task AddSourceCode(string projectFile, NugetPackageInfo package, string version = null)
protected virtual async Task AddSourceCode(string projectFile, string solutionFile, NugetPackageInfo package, string version = null)
{
var targetFolder = FindFolderToDownloadPackage(projectFile, package);
var targetFolder = FindFolderToDownloadPackage(solutionFile, package);
if (Directory.Exists(targetFolder))
{
@ -147,35 +180,35 @@ namespace Volo.Abp.Cli.ProjectModification
await DownloadSourceCode(targetFolder, package, version);
}
private string FindFolderToDownloadPackage(string projectFile, NugetPackageInfo package)
protected virtual string FindFolderToDownloadPackage(string solutionFile, NugetPackageInfo package)
{
return Path.Combine(FindSolutionFolder(projectFile), "packages", package.Name);
return Path.Combine(Path.GetDirectoryName(solutionFile), "packages", package.Name);
}
private string FindRelativeFolderToDownloadPackage(string projectFile, NugetPackageInfo package)
protected virtual string FindRelativeFolderToDownloadPackage(string projectFile, string solutionFile, NugetPackageInfo package)
{
var folder = Path.Combine(FindSolutionFolder(projectFile), "packages", package.Name);
var folder = Path.Combine(Path.GetDirectoryName(solutionFile), "packages", package.Name);
return new Uri(projectFile).MakeRelativeUri(new Uri(folder)).ToString().Replace("/", "\\");
}
private async Task DownloadSourceCode(string targetFolder, NugetPackageInfo package, string version = null)
protected virtual async Task DownloadSourceCode(string targetFolder, NugetPackageInfo package, string version = null)
{
await SourceCodeDownloadService.DownloadPackageAsync(
await SourceCodeDownloadService.DownloadNugetPackageAsync(
package.Name,
targetFolder,
version
);
}
private string FindSolutionFile(string projectFile)
protected virtual string FindSolutionFile(string projectFile)
{
var folder = FindSolutionFolder(projectFile);
return Directory.GetFiles(folder, "*.sln", SearchOption.TopDirectoryOnly).FirstOrDefault();
}
private string FindSolutionFolder(string projectFile)
protected virtual string FindSolutionFolder(string projectFile)
{
var targetFolder = Path.GetDirectoryName(projectFile);
@ -199,7 +232,7 @@ namespace Volo.Abp.Cli.ProjectModification
return targetFolder;
}
private async Task AddAsPackageReference(string projectFile, NugetPackageInfo package, string version,
protected virtual async Task AddAsPackageReference(string projectFile, NugetPackageInfo package, string version,
bool useDotnetCliToInstall)
{
var projectFileContent = File.ReadAllText(projectFile);
@ -250,7 +283,7 @@ namespace Volo.Abp.Cli.ProjectModification
Logger.LogInformation("Successfully installed.");
}
private Task AddUsingDotnetCli(NugetPackageInfo package, string version = null)
protected virtual Task AddUsingDotnetCli(NugetPackageInfo package, string version = null)
{
var versionOption = version == null ? "" : $" -v {version}";
@ -259,7 +292,7 @@ namespace Volo.Abp.Cli.ProjectModification
return Task.CompletedTask;
}
private Task AddToCsprojManuallyAsync(string projectFile, NugetPackageInfo package, string version = null)
protected virtual Task AddToCsprojManuallyAsync(string projectFile, NugetPackageInfo package, string version = null)
{
var projectFileContent = File.ReadAllText(projectFile);
var doc = new XmlDocument() {PreserveWhitespace = true};
@ -301,7 +334,7 @@ namespace Volo.Abp.Cli.ProjectModification
return Task.CompletedTask;
}
private string GetAbpVersionOrNull(string projectFile)
protected virtual string GetAbpVersionOrNull(string projectFile)
{
var projectFileContent = File.ReadAllText(projectFile);
@ -345,5 +378,13 @@ namespace Volo.Abp.Cli.ProjectModification
await BundleCommand.ExecuteAsync(args);
}
protected virtual bool IsSolutionTiered(string[] projectFiles)
{
return projectFiles.Select(ProjectFileNameHelper.GetAssemblyNameFromProjectPath)
.Any(p => p.EndsWith(".HttpApi.Host"))
&& projectFiles.Select(ProjectFileNameHelper.GetAssemblyNameFromProjectPath)
.Any(p => p.EndsWith(".IdentityServer"));
}
}
}

49
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs

@ -7,6 +7,7 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using NuGet.Versioning;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Commands.Services;
@ -26,7 +27,7 @@ namespace Volo.Abp.Cli.ProjectModification
public SourceCodeDownloadService SourceCodeDownloadService { get; }
public SolutionFileModifier SolutionFileModifier { get; }
public NugetPackageToLocalReferenceConverter NugetPackageToLocalReferenceConverter { get; }
public AngularModuleSourceCodeAdder AngularModuleSourceCodeAdder { get; }
public AngularSourceCodeAdder AngularSourceCodeAdder { get; }
public NewCommand NewCommand { get; }
public BundleCommand BundleCommand { get; }
@ -54,7 +55,7 @@ namespace Volo.Abp.Cli.ProjectModification
SourceCodeDownloadService sourceCodeDownloadService,
SolutionFileModifier solutionFileModifier,
NugetPackageToLocalReferenceConverter nugetPackageToLocalReferenceConverter,
AngularModuleSourceCodeAdder angularModuleSourceCodeAdder,
AngularSourceCodeAdder angularSourceCodeAdder,
NewCommand newCommand,
BundleCommand bundleCommand,
CliHttpClientFactory cliHttpClientFactory)
@ -70,7 +71,7 @@ namespace Volo.Abp.Cli.ProjectModification
SourceCodeDownloadService = sourceCodeDownloadService;
SolutionFileModifier = solutionFileModifier;
NugetPackageToLocalReferenceConverter = nugetPackageToLocalReferenceConverter;
AngularModuleSourceCodeAdder = angularModuleSourceCodeAdder;
AngularSourceCodeAdder = angularSourceCodeAdder;
NewCommand = newCommand;
BundleCommand = bundleCommand;
_cliHttpClientFactory = cliHttpClientFactory;
@ -91,6 +92,7 @@ namespace Volo.Abp.Cli.ProjectModification
Check.NotNull(moduleName, nameof(moduleName));
var module = await GetModuleInfoAsync(moduleName, newTemplate, newProTemplate);
module = RemoveIncompatiblePackages(module, version);
Logger.LogInformation(
$"Installing module '{module.Name}' to the solution '{Path.GetFileNameWithoutExtension(solutionFile)}'");
@ -131,6 +133,39 @@ namespace Volo.Abp.Cli.ProjectModification
ModifyDbContext(projectFiles, module, skipDbMigrations);
}
private ModuleWithMastersInfo RemoveIncompatiblePackages(ModuleWithMastersInfo module, string version)
{
module.NugetPackages.RemoveAll(np => IsPackageInCompatible(np, version));
return module;
}
private bool IsPackageInCompatible(NugetPackageInfo package, string version)
{
try
{
if (!string.IsNullOrWhiteSpace(package.MinVersion))
{
if (SemanticVersion.Parse(package.MinVersion) > SemanticVersion.Parse(version))
{
return true;
}
}
if (!string.IsNullOrWhiteSpace(package.MaxVersion))
{
if (SemanticVersion.Parse(package.MaxVersion) < SemanticVersion.Parse(version))
{
return true;
}
}
return false;
}
catch (ArgumentException)
{
return false;
}
}
private async Task RunBundleForBlazorAsync(string[] projectFiles, ModuleWithMastersInfo module)
{
var blazorProject = projectFiles.FirstOrDefault(f => f.EndsWith(".Blazor.csproj"));
@ -292,7 +327,7 @@ namespace Volo.Abp.Cli.ProjectModification
{
foreach (var npmPackage in angularPackages)
{
await ProjectNpmPackageAdder.AddAsync(angularPath, npmPackage, true);
await ProjectNpmPackageAdder.AddAngularPackageAsync(angularPath, npmPackage);
}
}
}
@ -312,7 +347,7 @@ namespace Volo.Abp.Cli.ProjectModification
MoveAngularFolderInNewTemplate(modulesFolderInSolution, moduleName);
}
await AngularModuleSourceCodeAdder.AddAsync(solutionFilePath, angularPath);
await AngularSourceCodeAdder.AddFromModuleAsync(solutionFilePath, angularPath);
}
private static void DeleteAngularDirectoriesInModulesFolder(string modulesFolderInSolution)
@ -438,7 +473,7 @@ namespace Volo.Abp.Cli.ProjectModification
continue;
}
await ProjectNugetPackageAdder.AddAsync(targetProjectFile, nugetPackage, null, useDotnetCliToInstall);
await ProjectNugetPackageAdder.AddAsync(null, targetProjectFile, nugetPackage, null, useDotnetCliToInstall);
}
var mvcNpmPackages = module.NpmPackages?.Where(p => p.ApplicationType.HasFlag(NpmApplicationType.Mvc))
@ -455,7 +490,7 @@ namespace Volo.Abp.Cli.ProjectModification
{
foreach (var npmPackage in mvcNpmPackages)
{
await ProjectNpmPackageAdder.AddAsync(Path.GetDirectoryName(targetProject), npmPackage);
await ProjectNpmPackageAdder.AddMvcPackageAsync(Path.GetDirectoryName(targetProject), npmPackage, null, true);
}
}
}

20
framework/src/Volo.Abp.Core/System/Collections/Generic/AbpDictionaryExtensions.cs

@ -67,7 +67,7 @@ namespace System.Collections.Generic
{
return dictionary.TryGetValue(key, out var obj) ? obj : default;
}
/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
@ -100,7 +100,7 @@ namespace System.Collections.Generic
return dictionary[key] = factory(key);
}
/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
@ -114,5 +114,19 @@ namespace System.Collections.Generic
{
return dictionary.GetOrAdd(key, k => factory());
}
/// <summary>
/// Gets a value from the concurrent dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Concurrent dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue GetOrAdd<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> factory)
{
return dictionary.GetOrAdd(key, k => factory());
}
}
}
}

15
framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs

@ -9,7 +9,10 @@ namespace System.IO
{
using (var memoryStream = new MemoryStream())
{
stream.Position = 0;
if (stream.CanSeek)
{
stream.Position = 0;
}
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
@ -19,7 +22,10 @@ namespace System.IO
{
using (var memoryStream = new MemoryStream())
{
stream.Position = 0;
if (stream.CanSeek)
{
stream.Position = 0;
}
await stream.CopyToAsync(memoryStream, cancellationToken);
return memoryStream.ToArray();
}
@ -27,7 +33,10 @@ namespace System.IO
public static Task CopyToAsync(this Stream stream, Stream destination, CancellationToken cancellationToken)
{
stream.Position = 0;
if (stream.CanSeek)
{
stream.Position = 0;
}
return stream.CopyToAsync(
destination,
81920, //this is already the default value, but needed to set to be able to pass the cancellationToken

2
framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj

@ -26,7 +26,7 @@
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.8" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.9" />
<PackageReference Include="System.Linq.Queryable" Version="4.3.0" />
<PackageReference Include="JetBrains.Annotations" Version="2020.3.0" />
<PackageReference Include="Nito.AsyncEx.Coordination" Version="5.1.0" />

1
framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj

@ -20,7 +20,6 @@
<ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" />
<ProjectReference Include="..\Volo.Abp.ExceptionHandling\Volo.Abp.ExceptionHandling.csproj" />
<ProjectReference Include="..\Volo.Abp.Guids\Volo.Abp.Guids.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiLingualObject\Volo.Abp.MultiLingualObject.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Specifications\Volo.Abp.Specifications.csproj" />

2
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/AbpDddDomainModule.cs

@ -6,7 +6,6 @@ using Volo.Abp.EventBus;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Guids;
using Volo.Abp.Modularity;
using Volo.Abp.MultiLingualObject;
using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Specifications;
@ -26,7 +25,6 @@ namespace Volo.Abp.Domain
typeof(AbpTimingModule),
typeof(AbpUnitOfWorkModule),
typeof(AbpObjectMappingModule),
typeof(AbpMultiLingualObjectModule),
typeof(AbpExceptionHandlingModule),
typeof(AbpSpecificationsModule)
)]

4
framework/src/Volo.Abp.EventBus.Rebus/Volo.Abp.EventBus.Rebus.csproj

@ -19,8 +19,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Rebus" Version="6.4.1" />
<PackageReference Include="Rebus.ServiceProvider" Version="5.0.6" />
<PackageReference Include="Rebus" Version="6.5.5" />
<PackageReference Include="Rebus.ServiceProvider" Version="6.4.1" />
</ItemGroup>
</Project>

2
framework/src/Volo.Abp.FluentValidation/Volo.Abp.FluentValidation.csproj

@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentValidation" Version="9.3.0" />
<PackageReference Include="FluentValidation" Version="9.5.3" />
</ItemGroup>
<ItemGroup>

3
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -106,7 +106,8 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{
var responseContent = await MakeRequestAsync(invocation);
if (typeof(T) == typeof(IRemoteStreamContent))
if (typeof(T) == typeof(IRemoteStreamContent) ||
typeof(T) == typeof(RemoteStreamContent))
{
/* returning a class that holds a reference to response
* content just to be sure that GC does not dispose of

2
framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj

@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IdentityModel" Version="4.5.0" />
<PackageReference Include="IdentityModel" Version="5.1.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="$(MicrosoftPackageVersion)" />
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />

2
framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs

@ -232,7 +232,7 @@ namespace Volo.Abp.IdentityModel
{
foreach (var pair in configuration.Where(p => p.Key.StartsWith("[o]", StringComparison.OrdinalIgnoreCase)))
{
request.Parameters[pair.Key] = pair.Value;
request.Parameters.Add(pair);
}
return Task.CompletedTask;

2
framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj

@ -17,7 +17,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.ObjectExtending\Volo.Abp.ObjectExtending.csproj" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>

2
framework/src/Volo.Abp.Kafka/Volo.Abp.Kafka.csproj

@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Confluent.Kafka" Version="1.5.2" />
<PackageReference Include="Confluent.Kafka" Version="1.6.3" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
<ProjectReference Include="..\Volo.Abp.Threading\Volo.Abp.Threading.csproj" />
</ItemGroup>

2
framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj

@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MailKit" Version="2.10.0" />
<PackageReference Include="MailKit" Version="2.11.1" />
</ItemGroup>
<ItemGroup>

2
framework/src/Volo.Abp.Minify/Volo.Abp.Minify.csproj

@ -19,7 +19,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="NUglify" Version="1.13.2" />
<PackageReference Include="NUglify" Version="1.13.8" />
</ItemGroup>
</Project>

2
framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj

@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="2.11.5" />
<PackageReference Include="MongoDB.Driver" Version="2.12.1" />
</ItemGroup>
<ItemGroup>

4
framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs

@ -517,7 +517,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
);
}
public async Task<IMongoQueryable<TEntity>> GetMongoQueryableAsync(CancellationToken cancellationToken = default)
public virtual async Task<IMongoQueryable<TEntity>> GetMongoQueryableAsync(CancellationToken cancellationToken = default)
{
cancellationToken = GetCancellationToken(cancellationToken);
@ -531,7 +531,7 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
);
}
public async Task<IAggregateFluent<TEntity>> GetAggregateAsync(CancellationToken cancellationToken = default)
public virtual async Task<IAggregateFluent<TEntity>> GetAggregateAsync(CancellationToken cancellationToken = default)
{
cancellationToken = GetCancellationToken(cancellationToken);

10
framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IHasMultiLingual.cs

@ -1,10 +0,0 @@
using System.Collections.Generic;
namespace Volo.Abp.MultiLingualObject
{
public interface IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation
{
ICollection<TTranslation> Translations { get; set; }
}
}

21
framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualObjectManager.cs

@ -1,21 +0,0 @@
using System.Threading.Tasks;
namespace Volo.Abp.MultiLingualObject
{
public interface IMultiLingualObjectManager
{
TTranslation GetTranslation<TMultiLingual, TTranslation>(
TMultiLingual multiLingual,
bool fallbackToParentCultures = true,
string culture = null)
where TMultiLingual : IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation;
Task<TTranslation> GetTranslationAsync<TMultiLingual, TTranslation>(
TMultiLingual multiLingual,
bool fallbackToParentCultures = true,
string culture = null)
where TMultiLingual : IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation;
}
}

7
framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/IMultiLingualTranslation.cs

@ -1,7 +0,0 @@
namespace Volo.Abp.MultiLingualObject
{
public interface IMultiLingualTranslation
{
string Language { get; set; }
}
}

0
framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xml → framework/src/Volo.Abp.MultiLingualObjects/FodyWeavers.xml

0
framework/src/Volo.Abp.MultiLingualObject/FodyWeavers.xsd → framework/src/Volo.Abp.MultiLingualObjects/FodyWeavers.xsd

1
framework/src/Volo.Abp.MultiLingualObject/Volo.Abp.MultiLingualObject.csproj → framework/src/Volo.Abp.MultiLingualObjects/Volo.Abp.MultiLingualObjects.csproj

@ -5,7 +5,6 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.MultiLingualObject</AssemblyName>
<PackageId>Volo.Abp.MultiLingualObject</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>

4
framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/AbpMultiLingualObjectModule.cs → framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/AbpMultiLingualObjectsModule.cs

@ -1,11 +1,11 @@
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace Volo.Abp.MultiLingualObject
namespace Volo.Abp.MultiLingualObjects
{
[DependsOn(
typeof(AbpLocalizationModule))]
public class AbpMultiLingualObjectModule : AbpModule
public class AbpMultiLingualObjectsModule : AbpModule
{
}
}

10
framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/IMultiLingualObject.cs

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace Volo.Abp.MultiLingualObjects
{
public interface IMultiLingualObject<TTranslation>
where TTranslation : class, IObjectTranslation
{
ICollection<TTranslation> Translations { get; set; }
}
}

14
framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/IMultiLingualObjectManager.cs

@ -0,0 +1,14 @@
using System.Threading.Tasks;
namespace Volo.Abp.MultiLingualObjects
{
public interface IMultiLingualObjectManager
{
Task<TTranslation> GetTranslationAsync<TMultiLingual, TTranslation>(
TMultiLingual multiLingual,
string culture = null,
bool fallbackToParentCultures = true)
where TMultiLingual : IMultiLingualObject<TTranslation>
where TTranslation : class, IObjectTranslation;
}
}

7
framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/IObjectTranslation.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.MultiLingualObjects
{
public interface IObjectTranslation
{
string Language { get; set; }
}
}

48
framework/src/Volo.Abp.MultiLingualObject/Volo/Abp/MultiLingualObject/MultiLingualObjectManager.cs → framework/src/Volo.Abp.MultiLingualObjects/Volo/Abp/MultiLingualObjects/MultiLingualObjectManager.cs

@ -6,9 +6,8 @@ using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
using Volo.Abp.Settings;
using Volo.Abp.Threading;
namespace Volo.Abp.MultiLingualObject
namespace Volo.Abp.MultiLingualObjects
{
public class MultiLingualObjectManager : IMultiLingualObjectManager, ITransientDependency
{
@ -21,27 +20,16 @@ namespace Volo.Abp.MultiLingualObject
SettingProvider = settingProvider;
}
public TTranslation GetTranslation<TMultiLingual, TTranslation>(
TMultiLingual multiLingual,
bool fallbackToParentCultures = true,
string culture = null)
where TMultiLingual : IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation
{
return AsyncHelper.RunSync(() =>
GetTranslationAsync<TMultiLingual, TTranslation>(multiLingual, fallbackToParentCultures, culture));
}
public virtual async Task<TTranslation> GetTranslationAsync<TMultiLingual, TTranslation>(
TMultiLingual multiLingual,
bool fallbackToParentCultures = true,
string culture = null)
where TMultiLingual : IHasMultiLingual<TTranslation>
where TTranslation : class, IMultiLingualTranslation
string culture = null,
bool fallbackToParentCultures = true)
where TMultiLingual : IMultiLingualObject<TTranslation>
where TTranslation : class, IObjectTranslation
{
culture ??= CultureInfo.CurrentUICulture.Name;
if (multiLingual.Translations == null || !multiLingual.Translations.Any())
if (multiLingual.Translations.IsNullOrEmpty())
{
return null;
}
@ -54,9 +42,12 @@ namespace Volo.Abp.MultiLingualObject
if (fallbackToParentCultures)
{
translation =
GeTranslationBasedOnCulturalRecursive(
CultureInfo.CurrentUICulture.Parent, multiLingual.Translations, 0);
translation = GetTranslationBasedOnCulturalRecursive(
CultureInfo.CurrentUICulture.Parent,
multiLingual.Translations,
0
);
if (translation != null)
{
return translation;
@ -75,21 +66,20 @@ namespace Volo.Abp.MultiLingualObject
return translation;
}
protected virtual TTranslation GeTranslationBasedOnCulturalRecursive<TTranslation>(
protected virtual TTranslation GetTranslationBasedOnCulturalRecursive<TTranslation>(
CultureInfo culture, ICollection<TTranslation> translations, int currentDepth)
where TTranslation : class, IMultiLingualTranslation
where TTranslation : class, IObjectTranslation
{
if (culture == null || culture.Name.IsNullOrWhiteSpace() || translations.IsNullOrEmpty() ||
if (culture == null ||
culture.Name.IsNullOrWhiteSpace() ||
translations.IsNullOrEmpty() ||
currentDepth > MaxCultureFallbackDepth)
{
return null;
}
var translation = translations.FirstOrDefault(pt =>
pt.Language.Equals(culture.Name, StringComparison.OrdinalIgnoreCase));
return translation ??
GeTranslationBasedOnCulturalRecursive(culture.Parent,
translations, currentDepth + 1);
var translation = translations.FirstOrDefault(pt => pt.Language.Equals(culture.Name, StringComparison.OrdinalIgnoreCase));
return translation ?? GetTranslationBasedOnCulturalRecursive(culture.Parent, translations, currentDepth + 1);
}
}
}

6
framework/src/Volo.Abp.Quartz/Volo.Abp.Quartz.csproj

@ -15,9 +15,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Quartz" Version="3.2.3" />
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.2.3" />
<PackageReference Include="Quartz.Plugins.TimeZoneConverter" Version="3.2.3" />
<PackageReference Include="Quartz" Version="3.2.4" />
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.2.4" />
<PackageReference Include="Quartz.Plugins.TimeZoneConverter" Version="3.2.4" />
</ItemGroup>
<ItemGroup>

2
framework/src/Volo.Abp.Swashbuckle/Volo.Abp.Swashbuckle.csproj

@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.0.5" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.1" />
</ItemGroup>
<ItemGroup>

2
framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj

@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Scriban" Version="3.0.5" />
<PackageReference Include="Scriban" Version="3.6.0" />
</ItemGroup>
<ItemGroup>

2
framework/src/Volo.Abp.Timing/Volo.Abp.Timing.csproj

@ -25,7 +25,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="TimeZoneConverter" Version="3.3.0" />
<PackageReference Include="TimeZoneConverter" Version="3.4.0" />
</ItemGroup>
</Project>

4
framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj

@ -8,8 +8,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
</ItemGroup>

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

Loading…
Cancel
Save