diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
index b81733d247..456e8ebd05 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
@@ -987,7 +987,7 @@
"Summary": "Summary",
"TrainingPack": "Training pack",
"TrainingPackDiscount": "Training pack discount",
- "Purchase_OnboardingTraining_Description": "This live training is valid for a class of 8 students and this discount is only valid when purchased with the new license. Learn more ",
+ "Purchase_OnboardingTraining_Description": "This live training is valid for a class of 8 students and this discount is only valid when purchased with the new license. Learn more ",
"Purchase_Save": "{0}% Save {1}",
"RemoveBasket": "Remove from basket",
"WhyABPIOPlatform?": "Why ABP.IO Platform?",
diff --git a/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md b/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md
index c499f6e33c..2f5cde6d2d 100644
--- a/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md
+++ b/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md
@@ -1,5 +1,7 @@
# Using Elsa Workflow with ABP Framework
+> **UPDATE:** There is a newer version of this article, which covers Elsa 3 with ABP Framework. You can check it at https://abp.io/community/articles/using-elsa-3-workflow-with-abp-framework-usqk8afg
+
**Elsa Core** is an open-source workflows library that can be used in any kind of .NET Core application. Using such a workflow library can be useful to implement business rules visually or programmatically.

@@ -465,4 +467,4 @@ namespace ElsaDemo.Web.Menus
> 🛠Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design.
> 👉 Subscribe here → engincanveske.substack.com
> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv
----
\ No newline at end of file
+---
diff --git a/docs/en/framework/infrastructure/features.md b/docs/en/framework/infrastructure/features.md
index ef5d97bd91..a6bc52e48b 100644
--- a/docs/en/framework/infrastructure/features.md
+++ b/docs/en/framework/infrastructure/features.md
@@ -424,7 +424,7 @@ namespace FeaturesDemo
return Task.FromResult("true");
}
- return null;
+ return Task.FromResult(null);
}
}
}
diff --git a/docs/en/studio/release-notes.md b/docs/en/studio/release-notes.md
index ef498fcac5..cfb8e9fb61 100644
--- a/docs/en/studio/release-notes.md
+++ b/docs/en/studio/release-notes.md
@@ -2,6 +2,19 @@
This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version.
+## 0.9.26 (2025-04-30)
+
+* Fixed the issue where C# applications would not stop when requested.
+* Added idle session timeout feature to Blazor WebAssembly applications.
+* Added “Setup as a modular solution” option to application startup templates.
+* Automatically added remote service base URL after generating C# proxies.
+* Configured Helm charts for Kubernetes health check endpoints.
+* Fixed auditing issue in Blazor WebAssembly applications.
+* Fixed login error after registering a new user in Blazor WebApp.
+* Implemented password login flow in Studio CLI.
+* Supported non-root user mode in Docker Compose configurations.
+* Upgraded templates to version `9.1.1`.
+
## 0.9.25 (2025-03-12)
* Added ready/health check for solution runner.
diff --git a/docs/en/studio/version-mapping.md b/docs/en/studio/version-mapping.md
index cd82da602a..88d9be25fe 100644
--- a/docs/en/studio/version-mapping.md
+++ b/docs/en/studio/version-mapping.md
@@ -4,6 +4,7 @@ This document provides a general overview of the relationship between various ve
| **ABP Studio Version** | **ABP Version of Startup Template** |
|------------------------|---------------------------|
+| 0.9.26 | 9.1.1 |
| 0.9.24 - 0.9.25 | 9.1.0 |
| 0.9.22 - 0.9.23 | 9.0.4 |
| 0.9.20 - 0.9.21 | 9.0.3 |
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js
index e11a8f4d99..d232dbd28a 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js
@@ -55,7 +55,7 @@ $.validator.defaults.ignore = ''; //TODO: Would be better if we can apply only f
function _createContainer() {
_removeContainer();
- _$modalContainer = $('');
+ _$modalContainer = $('');
var existsModals = $('[id^="Abp_Modal_"]');
if (existsModals.length) {
existsModals.last().after(_$modalContainer)
diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs
index 6c4fcf07f9..a2c7193437 100644
--- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs
+++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs
@@ -357,10 +357,10 @@ public abstract class AbpCrudPageBase<
}
}
- protected virtual Task CloseCreateModalAsync()
+ protected virtual async Task CloseCreateModalAsync()
{
+ await InvokeAsync(CreateModal!.Hide);
NewEntity = new TCreateViewModel();
- return InvokeAsync(CreateModal!.Hide);
}
protected virtual Task ClosingCreateModal(ModalClosingEventArgs eventArgs)
@@ -474,11 +474,11 @@ public abstract class AbpCrudPageBase<
protected virtual async Task OnCreatedEntityAsync()
{
- NewEntity = new TCreateViewModel();
await GetEntitiesAsync();
await InvokeAsync(CreateModal!.Hide);
await Notify.Success(GetCreateMessage());
+ NewEntity = new TCreateViewModel();
}
protected virtual string GetCreateMessage()
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
index 63d6aa82ad..dd5df32b8a 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
@@ -236,6 +236,8 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert
errorInfo.ValidationErrors = GetValidationErrorInfos((exception as AbpValidationException)!);
}
+ TryToLocalizeExceptionMessage(exception, errorInfo);
+
return errorInfo;
}
diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs
index 9d1b706d8b..e5d726526b 100644
--- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs
+++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs
@@ -64,7 +64,7 @@ public class MongoDbContextEventInbox : IMongoDbContextEventInb
var outgoingEventRecords = await dbContext
.IncomingEvents
.AsQueryable()
- .Where(x => !x.Processed)
+ .Where(x => x.Processed == false)
.WhereIf(transformedFilter != null, transformedFilter!)
.OrderBy(x => x.CreationTime)
.Take(maxCount)
diff --git a/latest-versions.json b/latest-versions.json
index 340ed62653..da8c7b754d 100644
--- a/latest-versions.json
+++ b/latest-versions.json
@@ -1,5 +1,14 @@
[
- {
+ {
+ "version": "9.1.3",
+ "releaseDate": "",
+ "type": "stable",
+ "message": "",
+ "leptonx": {
+ "version": "4.1.3"
+ }
+ },
+ {
"version": "9.1.1",
"releaseDate": "",
"type": "stable",
diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/GeneratePdf.cshtml.cs b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/GeneratePdf.cshtml.cs
index ffd189546c..231f7c56eb 100644
--- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/GeneratePdf.cshtml.cs
+++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/GeneratePdf.cshtml.cs
@@ -13,18 +13,15 @@ namespace Volo.Docs.Admin.Pages.Docs.Admin.Projects;
public class GeneratePdfModal : DocsAdminPageModel
{
- protected IDocumentPdfGeneratorAppService DocumentPdfGeneratorAppService { get; }
protected IProjectAppService ProjectAppService { get; }
protected IProjectAdminAppService ProjectAdminAppService { get; }
public GeneratePdfViewModel ViewModel { get; set; }
public GeneratePdfModal(
- IDocumentPdfGeneratorAppService documentPdfGeneratorAppService,
IProjectAppService projectAppService,
IProjectAdminAppService projectAdminAppService)
{
- DocumentPdfGeneratorAppService = documentPdfGeneratorAppService;
ProjectAppService = projectAppService;
ProjectAdminAppService = projectAdminAppService;
}
diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/generatePdf.js b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/generatePdf.js
index 7b7f4b1bbf..91015b1584 100644
--- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/generatePdf.js
+++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/generatePdf.js
@@ -37,7 +37,7 @@ $(function () {
abpHandleError : false,
error: function (jqXHR) {
if (jqXHR.status === 200) {
- abp.message.success(l('PdfFileDeletedSuccessfully'));
+ abp.message.success(l('PdfFileGeneratedSuccessfully'));
$btn.buttonBusy(false);
$("#GenerateAndDownloadPdfBtn").buttonBusy(false);
} else {
diff --git a/modules/docs/src/Volo.Docs.Common.Application/Volo/Docs/Common/Documents/DocumentPdfGeneratorAppService.cs b/modules/docs/src/Volo.Docs.Common.Application/Volo/Docs/Common/Documents/DocumentPdfGeneratorAppService.cs
index 7787185b50..3960a16179 100644
--- a/modules/docs/src/Volo.Docs.Common.Application/Volo/Docs/Common/Documents/DocumentPdfGeneratorAppService.cs
+++ b/modules/docs/src/Volo.Docs.Common.Application/Volo/Docs/Common/Documents/DocumentPdfGeneratorAppService.cs
@@ -1,7 +1,9 @@
+using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services;
using Volo.Abp.Content;
+using Volo.Abp.Data;
using Volo.Docs.Projects;
using Volo.Docs.Projects.Pdf;
@@ -24,6 +26,27 @@ public class DocumentPdfGeneratorAppService : ApplicationService, IDocumentPdfGe
public virtual async Task GeneratePdfAsync(DocumentPdfGeneratorInput input)
{
var project = await ProjectRepository.GetAsync(input.ProjectId, includeDetails: true);
+
+ // https://github.com/abpframework/abp/blob/e96f601641ab8a4bb7d704d3b9df2c00517d96f6/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs#L73
+ var inputVersionStringBuilder = new StringBuilder();
+ input.Version = inputVersionStringBuilder.Append(GetProjectVersionPrefixIfExist(project)).Append(input.Version).ToString();
return await ProjectPdfGenerator.GenerateAsync(project, input.Version, input.LanguageCode);
}
+
+ private string GetProjectVersionPrefixIfExist(Project project)
+ {
+ if (GetGithubVersionProviderSource(project) != GithubVersionProviderSource.Branches)
+ {
+ return string.Empty;
+ }
+
+ return project.GetProperty("VersionBranchPrefix");
+ }
+
+ private GithubVersionProviderSource GetGithubVersionProviderSource(Project project)
+ {
+ return project.HasProperty("GithubVersionProviderSource")
+ ? project.GetProperty("GithubVersionProviderSource")
+ : GithubVersionProviderSource.Releases;
+ }
}
\ No newline at end of file
diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs
index e16f81d2c9..ca5c1221ad 100644
--- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs
+++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs
@@ -32,7 +32,8 @@ namespace Volo.Docs.FileSystem.Documents
localDirectory = documentName.Substring(0, documentName.LastIndexOf('/'));
}
- version = File.GetLastWriteTime(path).ToString("yyyyMMddHHmmss");
+ // The version is intentionally set to "1.0.0" as part of the versioning strategy for file system documents.
+ version = "1.0.0";
return new Document(GuidGenerator.Create(),
project.Id,
diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json
index 73b07169f8..6715146b50 100644
--- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json
+++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json
@@ -44,6 +44,7 @@
"Docs_Page_Title": "ABP Documentation",
"Docs_Page_Description": "Access comprehensive guides and API references in the ABP Documentation, aiding in development and troubleshooting.",
"GoogleTranslate": "Google Translate",
- "DownloadPDF": "Download PDF"
+ "DownloadPDF": "Download PDF",
+ "PdfFileGeneratedSuccessfully": "The PDF file is generated successfully."
}
}
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs
index b0b7b6f70f..8a48db4b4a 100644
--- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs
@@ -152,10 +152,13 @@ public partial class FeatureManagementModal
protected virtual bool IsDisabled(FeatureDto feature)
{
- return feature.Provider.Name != ProviderName && feature.Provider.Name != DefaultValueFeatureValueProvider.ProviderName;
+ return feature.Value != null &&
+ feature.Provider.Name != null &&
+ feature.Provider.Name != ProviderName &&
+ feature.Provider.Name != DefaultValueFeatureValueProvider.ProviderName;
}
- public string GetShownName(FeatureDto featureDto)
+ public virtual string GetShownName(FeatureDto featureDto)
{
return !IsDisabled(featureDto)
? featureDto.DisplayName
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs
index 39bb3ad4f0..eb27c63aae 100644
--- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs
@@ -85,12 +85,15 @@ public class FeatureManagementModal : AbpPageModel
return NoContent();
}
- public bool IsDisabled(FeatureDto featureDto)
+ public virtual bool IsDisabled(FeatureDto feature)
{
- return featureDto.Provider.Name != ProviderName && featureDto.Provider.Name != DefaultValueFeatureValueProvider.ProviderName;
+ return feature.Value != null &&
+ feature.Provider.Name != null &&
+ feature.Provider.Name != ProviderName &&
+ feature.Provider.Name != DefaultValueFeatureValueProvider.ProviderName;
}
- public string GetShownName(FeatureDto featureDto)
+ public virtual string GetShownName(FeatureDto featureDto)
{
return !IsDisabled(featureDto)
? featureDto.DisplayName
diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts
index 9e27d31c9f..cb6a216d66 100644
--- a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts
+++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts
@@ -15,6 +15,7 @@ import {
getAppConfigPath,
cleanEmptyExprFromModule,
cleanEmptyExprFromProviders,
+ getWorkspace,
} from '../../utils';
import { ThemeOptionsEnum } from './theme-options.enum';
import { findNodes, getDecoratorMetadata, getMetadataField } from '../../utils/angular/ast-utils';
@@ -82,6 +83,7 @@ function updateAppModule(selectedProject: string, targetThemeName: ThemeOptionsE
insertImports(selectedProject, targetThemeName),
insertProviders(selectedProject, targetThemeName),
adjustProvideAbpThemeShared(appModulePath, targetThemeName),
+ updateIndexHtml(selectedProject, targetThemeName),
formatFile(appModulePath),
cleanEmptyExpressions(appModulePath, isStandalone),
]);
@@ -534,3 +536,39 @@ function findProvideAbpThemeSharedCalls(source: ts.SourceFile): ts.CallExpressio
return result;
}
+
+export function updateIndexHtml(projectName: string, themeName: ThemeOptionsEnum): Rule {
+ return async (host: Tree) => {
+ const workspace = await getWorkspace(host);
+ const project = workspace.projects.get(projectName);
+
+ if (!project) {
+ throw new Error(`Project "${projectName}" not found in workspace.`);
+ }
+
+ const buildOptions = project.targets.get('build')?.options;
+ const indexPath = buildOptions?.index as string;
+
+ if (!indexPath || !host.exists(indexPath)) {
+ throw new Error(`index.html not found at path: ${indexPath}`);
+ }
+
+ const buffer = host.read(indexPath);
+ if (!buffer) return;
+ const content = buffer.toString('utf-8');
+
+ const loaderDiv = ``;
+ let updatedContent = content;
+
+ if (themeName === ThemeOptionsEnum.LeptonX) {
+ if (!content.includes(loaderDiv)) {
+ updatedContent = content.replace(/]*)>/i, `\n ${loaderDiv}`);
+ }
+ } else {
+ if (content.includes(loaderDiv)) {
+ updatedContent = content.replace(loaderDiv, '');
+ }
+ }
+ host.overwrite(indexPath, updatedContent);
+ };
+}