Hi again,
According to my investigations, the fix is already shipped in v10.0.3. If you update your abp suite to version 10.0.3 the problem will be gone.
abp suite update
Hi there! I can see you're encountering an error with ABP Suite when generating DTOs for your microservice template. The error is:
error CS0103: The name 'ProductConsts' does not exist in the current context
This happens in your ProductCreateDto.cs and ProductUpdateDto.cs files.
This is a confirmed bug in ABP Suite (issue was reproduced by the ABP support team).
The problem is a namespace mismatch between where ABP Suite generates the ProductConsts class and where the DTOs expect it to be:
In AppServiceCommand.cs (lines 759-767 and 814-822), ABP Suite adds a using statement for DTOs in microservice projects:
// For microservice, it adds:
using CloudCrm2.CatalogService.Entities.Products;
In EntityGenerateCommand.cs (line 212), the ProductConsts class is generated with a different namespace:
// Creates ProductConsts with namespace: CloudCrm2.CatalogService.Products
// (Missing the ".Entities" part!)
So the DTOs are looking for CloudCrm2.CatalogService.Entities.Products.ProductConsts, but the actual class is generated as CloudCrm2.CatalogService.Products.ProductConsts.
Since the ABP team is working on a fix, here are your options:
Create a ProductConsts.cs file in your Domain project (or where the entity is) with the correct namespace:
namespace CloudCrm2.CatalogService.Entities.Products
{
public static class ProductConsts
{
public const int NameMinLength = 2;
public const int NameMaxLength = 120;
public const int DescriptionMaxLength = 1000;
public const int StockCountMinValue = 0;
public const int StockCountMaxValue = 999999;
}
}
After manually creating this file, you can use Save and Generate in ABP Suite - it will keep your manually created file.
The ABP support team has confirmed this is a bug and is working on a fix. You can track the progress on the ABP GitHub issues.
The fix should be in AppServiceCommand.cs - the code should NOT add .Entities. prefix for microservice projects, or alternatively EntityGenerateCommand.cs should add .Entities. prefix to match.
The correct namespace for microservice templates should be:
CloudCrm2.CatalogService.Products.ProductConsts (not CloudCrm2.CatalogService.Entities.Products.ProductConsts).Entities. namespace prefixNote: The ABP support team has reproduced this issue and is working on a fix. This bug affects microservice templates when using ABP Suite to generate entities with validation properties (MinLength, MaxLength, etc.).
I hope this helps! Let me know if you need any clarification.
Hi there,
As I see you're having trouble getting CmsKit Pro working in your microservice template. Let me help you fix this.
When you add CmsKit Pro to your project, you're only getting the Pro features but missing the base CmsKit (open-source) tables. That's because CmsKit Pro doesn't include the base CmsKit - they're two separate modules that need to be installed together.
In your EntityFrameworkCore project (AdministrationService), make sure you have:
<!-- Base CmsKit (required!) -->
<PackageReference Include="Volo.CmsKit.EntityFrameworkCore" />
<PackageReference Include="Volo.CmsKit.Domain" />
<!-- CmsKit Pro -->
<PackageReference Include="Volo.CmsKit.Pro.EntityFrameworkCore" />
<PackageReference Include="Volo.CmsKit.Pro.Domain" />
The same applies to your Web.Public project.
In your EntityFrameworkCore module, add the base CmsKit module:
[DependsOn(
typeof(CmsKitProEntityFrameworkCoreModule),
typeof(CmsKitEntityFrameworkCoreModule) //👈 Add this!
)]
public class YourServiceEntityFrameworkCoreModule : AbpModule
{
}
In your GlobalFeatureConfigurator (or create a FeatureConfigurer class), enable both:
GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit =>
{
cmsKit.EnableAll();
});
GlobalFeatureManager.Instance.Modules.CmsKitPro(cmsKitPro =>
{
cmsKitPro.EnableAll();
});
After making these changes:
dotnet ef migrations add CmsKit_CompleteNow you should see both CmsKit tables (CmsUsers, BlogPosts, Pages, Tags, Comments, etc.) and CmsKitPro tables (NewsletterRecords, Polls, Faqs, PageFeedbacks, etc.) in your database.
The CmsKit Pro module adds extra features (Newsletter, Polls, FAQ, Page Feedback, etc.) but it doesn't include the base CMS features (Pages, Blogs, Comments, Ratings, etc.). They're designed to work together but remain separate packages.
If you want to create a dedicated CmsService in the future, just follow the same pattern - add both base CmsKit and CmsKit Pro packages to that service's EF Core project.
Let me know if you run into any other issues!
Related Framework change has been done in PR: https://github.com/abpframework/abp/pull/24891
It'll be included as a patch to v10.1 and the future versions
Hi @jhsanc,
Thank you for reporting this. The issue is confirmed -- the ABP AI packages currently reference Microsoft.SemanticKernel version 1.67.1, which has a critical vulnerability (CVE-2026-25592 -- Arbitrary File Write in SessionsPythonPlugin). The fix requires version 1.70.0 or later.
Until a new ABP patch release ships with the updated version, you can override the transitive dependency in your solution's Directory.Packages.props (if using Central Package Management) or add an explicit PackageReference in your EntityFrameworkCore project:
Option A: Central Package Management (Directory.Packages.props)
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.71.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Abstractions" Version="1.71.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Core" Version="1.71.0" />
Option B: Direct PackageReference override (in your .EntityFrameworkCore.csproj)
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.71.0" />
After adding either override, run dotnet restore and then retry your migration command.
We have updated the Semantic Kernel version to 1.71.0 in the ABP framework's central package management. This fix will be included in the next patch release.
Our ABP Studio team is working on it. We hope it'll not happen in the future versions
Hi,
Thank you for reporting this issue. The behavior you’re experiencing is related to Windows Smart App Control, a security feature in Windows 11 that blocks applications it cannot verify. Since ABP Studio currently includes unsigned DLLs, Smart App Control flags the executable (Volo.App.Studio.UI.Host.exe) as potentially unsafe and prevents it from launching.
At this time:
Smart App Control can only be enabled or disabled during Windows installation. If it is enabled, unsigned applications may be blocked.
We are actively working on digitally signing ABP Framework DLLs to ensure compatibility with Smart App Control. This will be available in upcoming releases.
The current version of ABP Studio will remain affected until the signing process is completed.
Workarounds:
If you need immediate access, you can disable Smart App Control (note: this must be done during Windows installation; it cannot be toggled afterward).
Alternatively, you may run ABP Studio on a system where Smart App Control is not enabled.
We understand the inconvenience and appreciate your patience while we finalize the signing process. Your feedback helps us prioritize this fix, and we’ll update you as soon as the signed version is available.
You're absolutely right - there's currently no built-in support for prorated upgrades/downgrades in the ABP SaaS + Payment modules. Let me explain why this is happening and how to fix it.
When you call _subscriptionAppService.CreateSubscriptionAsync(), it creates a brand new Stripe subscription every time. Looking at the source code, it simply creates a new PaymentRequest without checking if the tenant already has an active subscription.
This is why you're seeing:
The Solution
public interface ISubscriptionChangeAppService : IApplicationService
{
Task<PaymentRequestWithDetailsDto?> ChangeSubscriptionAsync(Guid newEditionId, Guid tenantId);
}
public class SubscriptionChangeAppService : YourProjectnameAppService, ISubscriptionChangeAppService
{
protected IPaymentRequestRepository PaymentRequestRepository { get; }
protected IPlanRepository PlanRepository { get; }
protected ITenantRepository TenantRepository { get; }
protected EditionManager EditionManager { get; }
public SubscriptionChangeAppService(
IPaymentRequestRepository paymentRequestRepository,
IPlanRepository planRepository,
ITenantRepository tenantRepository,
EditionManager editionManager)
{
PaymentRequestRepository = paymentRequestRepository;
PlanRepository = planRepository;
TenantRepository = tenantRepository;
EditionManager = editionManager;
}
public virtual async Task<PaymentRequestWithDetailsDto?> ChangeSubscriptionAsync(Guid newEditionId, Guid tenantId)
{
var edition = await EditionManager.GetEditionForSubscriptionAsync(newEditionId);
// Get Stripe price ID for the new edition
var gatewayPlan = await PlanRepository.GetGatewayPlanAsync(edition.PlanId, StripeConsts.GatewayName);
var newPriceId = gatewayPlan.ExternalId;
// Find existing subscription payment request
var tenant = await TenantRepository.GetAsync(tenantId);
// Option 1: Get from tenant's ExtraProperties if you store subscription ID there
// Option 2: Query payment requests by tenant and find one with ExternalSubscriptionId
var existingPaymentRequests = await PaymentRequestRepository.GetListByTenantId(tenantId); // There is no this query in the repository, you'll need to add this kind of query.
var existingSubscription = existingPaymentRequests
.FirstOrDefault(pr => !pr.ExternalSubscriptionId.IsNullOrEmpty() &&
pr.State == PaymentRequestState.Completed);
if (existingSubscription == null || existingSubscription.ExternalSubscriptionId.IsNullOrEmpty())
{
// No existing subscription, create new one
return await SubscriptionAppService.CreateSubscriptionAsync(newEditionId, tenantId);
}
// UPDATE existing Stripe subscription (this handles proration automatically)
var subscriptionService = new SubscriptionService();
var subscription = await subscriptionService.GetAsync(existingSubscription.ExternalSubscriptionId);
var existingItemId = subscription.Items.Data[0].Id;
var options = new SubscriptionUpdateOptions
{
Items = new List<SubscriptionItemOptions>
{
new SubscriptionItemOptions
{
Id = existingItemId, // Required to update existing item
Price = newPriceId, // New plan's Stripe price ID
}
}
// Stripe automatically prorates by default!
};
await subscriptionService.UpdateAsync(existingSubscription.ExternalSubscriptionId, options);
// IMPORTANT: Update the PaymentRequest with the new EditionId
// This ensures the webhook handler knows to update the tenant's edition
existingSubscription.ExtraProperties[EditionConsts.EditionIdParameterName] = newEditionId.ToString();
await PaymentRequestRepository.UpdateAsync(existingSubscription);
// The Stripe webhook will trigger SubscriptionUpdatedHandler
// which will update the tenant's EditionId automatically
return null; // No payment needed - Stripe handles proration in next invoice
}
}
public async Task<IActionResult> OnPostChangeEditionAsync(Guid editionId)
{
try
{
var result = await _subscriptionChangeAppService.ChangeSubscriptionAsync(editionId, _currentTenant.Id);
if (result != null && result.RequiresPayment && result.PaymentRequestId != Guid.Empty)
{
return LocalRedirectPreserveMethod($"/Payment/GatewaySelection?paymentRequestId={result.PaymentRequestId}");
}
Alerts.Success("Plan changed successfully! Stripe will process the prorated amount.");
return RedirectToPage();
}
catch (UserFriendlyException ex)
{
Alerts.Danger(ex.Message);
return RedirectToPage();
}
}
It seems you added following packages to your backend application:
Volo.CmsKit.Pro.Domain
Volo.CmsKit.Pro.Domain.Shared
Volo.CmsKit.Pro.EntityFrameworkCore
Volo.CmsKit.Pro.HttpApi
But Application layer is missing, this is where AppServices are located. Canyou add Volo.CmsKit.Pro.Applicaton package to your project and try again?
For the "http/https"problem on OIDC with AuthServer, this approach by microsoft might help: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-10.0#when-it-isnt-possible-to-add-forwarded-headers-and-all-requests-are-secure
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next(context);
});