Hi,
Thanks, the new example makes the remaining issue much clearer.
What you found is now a different collision than the first one.
OrganizerToLookupDtoGuidMapper is a shared lookup mapper, not a Fee-specific mapper. ABP Suite generates that class name from only the referenced entity and key type, so any entity that has an Organizer lookup will reuse the same mapper name.
That means in your current setup:
OrganizerToLookupDtoGuidMapper already exists in your custom Mapperly file,OrganizerToLookupDtoGuidMapper again in RiserAdminApplicationMappers.cs,So yes, your diagnosis is correct.
For 10.1.1, the practical workaround is:
RiserAdminApplicationMappers.cs as the single owner of Suite-generated shared lookup mappers.OrganizerToLookupDtoGuidMapper from your custom file and keep only the version in RiserAdminApplicationMappers.cs.VenueToLookupDtoGuidMapper, EventCategoryToLookupDtoGuidMapper, etc.Mappers.cs, rename it to something safer like CustomMapperlyMappings.cs or ManualObjectMappings.cs.One important point: you do not need a separate OrganizerToLookupDtoGuidMapper per entity. A single mapper for Organizer -> LookupDto<Guid> is enough for the whole Application project.
So in short, for shared lookup mappers:
The same caution also applies to other shared fixed-name generated mappers, such as AppFileDescriptorToAppFileDescriptorDtoMapper if your entities use file properties.
At the moment, ABP Suite checks the selected Suite-managed mapper file when replacing/appending mapper classes, but it does not detect the same shared mapper class in a separate custom file. So this behavior is a current Suite limitation, not a mistake in your diagnosis.
If it still fails after removing the shared lookup mapper classes from the custom file, please send us these 3 items:
Application or Blazor),Best regards,
ABP Support Team
Hi,
Thanks for the detailed explanation and the screenshots.
What you are seeing is most likely not a Mapperly problem itself. The issue is that ABP Suite currently updates Mapperly files by looking for very specific file names, class names, and mapper declarations. After an AutoMapper -> Mapperly migration, especially when the old profile files are renamed to *Mappers.cs and contain AI-generated mapper classes, Suite can no longer reliably match the existing classes, so it appends new mappings to the end of the file instead. That is why the file grows and the generated code becomes inconsistent or fails to build.
This is also why adding only a trailing s to some class names does not fully solve the problem. The mismatch is not only about singular/plural naming. It is also about which file Suite chooses to update and whether the existing mapper declarations still match the patterns Suite expects.
Your screenshots support this diagnosis because the same mapper files contain a mix of ...Mapper and ...Mappers classes, and several mappings are already manually migrated rather than Suite-generated. The screenshots also show custom Mapperly attributes such as RequiredMappingStrategy, which is another sign that the files are no longer in the simple shape Suite expects when it tries to update them.
We recommend the following steps:
YourProjectApplicationMappers.cs, YourProjectBlazorMappers.cs, and YourProjectWebMappers.cs if you have MVC.Mappers.cs, BlazorMappers.cs, or WebMappers.cs. For example, names like IdentityUserMapperlyMappings.cs or CustomObjectMappings.cs are safer.ApplicationMappers.cs / BlazorMappers.cs in the build if you excluded them temporarily.So, the practical workaround is:
*Mappers.cs files compete with the files that Suite scans and updates.If you want, you can also simplify this further by keeping your existing migrated mapper classes untouched and creating one dedicated Suite-only file per layer for new CRUD generation.
If the problem continues after this cleanup, please send us these 3 items:
ApplicationMappers.cs,BlazorMappers.cs.Then we can check whether there is an additional naming mismatch in your generated classes.
Best regards,
ABP Support Team
Hi, Thanks for the follow-up. At the moment, this depends on the ABP version you are targeting:
10.1.x, then yes, CMS Kit admin features are not available in Angular out of the box. In that case, admins cannot manage pages, menus, blogs, and similar CMS Kit admin screens from the Angular UI.10.2.x preview/RC, Angular CMS Kit packages have started to become available. The published Angular package @abp/ng.cms-kit includes admin routes for comments, tags, pages, blogs, blog posts, menus, and global resources, so page and menu management can be done from Angular in that version line.@volo/abp.ng.cms-kit-pro starting with 10.2.0-rc.1.
So, to answer your question directly:10.1.x: your understanding is correct. You should not plan on using CMS Kit admin features from Angular.10.2.x preview/RC: Angular support has started to exist, and page/menu-related admin functionality is no longer limited to MVC/Blazor only.
The confusing part here is that the public CMS Kit documentation is still behind the current package state. The current 10.1 and 10.2 CMS Kit module pages still mention MVC/Blazor-oriented support, so the documentation has not fully caught up with the Angular package publication yet.
If you need a stable production plan today on 10.1.x, we recommend using the MVC / Razor Pages or Blazor admin UI for CMS Kit, or building custom Angular screens on top of the CMS Kit admin APIs.
If you want, please share your exact target version (10.1.x or 10.2.x) and we can provide the corresponding Angular installation guidance for that version.
Best regards,
ABP Support TeamHi,
Thanks for the update.
We checked the current ABP Studio behavior on our side. The Open with -> Visual Studio action does not use the Windows .sln / .slnx file association. ABP Studio looks for devenv.exe and launches Visual Studio directly. Because of that, updating the .sln and .slnx associations would not change this specific action.
So, since you already:
devenv /updateConfiguration,the most likely problem is that the Visual Studio registration/path ABP Studio relies on is not matching the current VS 2026 installation anymore.
As the next step, please run these guidance-only troubleshooting checks in a normal terminal:
Get-Item 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\devenv.exe'
Get-Command devenv
pwsh -Command "start devenv 'C:\full\path\to\your-solution.sln'"
If your module uses a .slnx file, please test that file too.
What these checks tell us:
Get-Command devenv fails, then devenv is not resolvable from the shell the way ABP Studio expects.pwsh command also fails, the problem is outside the .sln association and is related to the Visual Studio shell/command registration.If it still persists, please share these 4 details:
.sln and .slnx.Open with -> Visual Studio.Also, please make sure you are testing with the latest ABP Studio version.
As a temporary workaround, you can continue using Open with -> Explorer and open the .sln / .slnx file manually in Visual Studio.
Best regards,
ABP Support Team
Hi,
Thanks for the extra details. We re-checked this in a fresh ABP 8.3.3 commercial MVC/tiered solution and validated that the following customization shape compiles against the generated template.
There are two separate points here:
admin fallback should still work.For the first point: in ABP 8.3.3, the login flow first tries the LDAP external provider, and if that returns false, it falls back to the normal local PasswordSignInAsync. So a failed LDAP bind should not block the built-in local admin user.
Because of that, if admin also fails, please verify these two items first:
As a quick confirmation step, temporarily disable LDAP login and test the built-in admin user alone.
For the LDAP customization itself, the important correction is this: the bind username should not be mydomain\\user, <BaseDc>. For Windows AD simple bind it should generally be only one of these formats:
mydomain\\userNameuserName@mydomain.localSo LdapExternalLoginProvider.NormalizeUserNameAsync should return only the bind name and should not append BaseDc.
For this scenario, the register page is not the correct customization point. In ABP 8.3.3 the relevant flow is:
LoginModel.OnPostAsync(...)AbpSignInManager.PasswordSignInAsync(...)LdapExternalLoginProvider.TryAuthenticateAsync(...)IdentityUserSo for Windows AD you will usually need to customize both:
LdapExternalLoginProviderOpenLdapManagerBelow is the exact code shape we validated. You should adapt the namespace and class names to your solution.
WindowsAdLdapExternalLoginProvider.cs
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.Identity.ExternalLoginProviders.Ldap;
using Volo.Abp.Ldap;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Settings;
namespace YourProject.Identity;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(WindowsAdLdapExternalLoginProvider), typeof(LdapExternalLoginProvider))]
public class WindowsAdLdapExternalLoginProvider : LdapExternalLoginProvider
{
protected WindowsAdLdapManager WindowsAdLdapManager { get; }
public WindowsAdLdapExternalLoginProvider(
IGuidGenerator guidGenerator,
ICurrentTenant currentTenant,
IdentityUserManager userManager,
IIdentityUserRepository identityUserRepository,
OpenLdapManager ldapManager,
ILdapSettingProvider ldapSettingProvider,
IFeatureChecker featureChecker,
ISettingProvider settingProvider,
IOptions<IdentityOptions> identityOptions,
WindowsAdLdapManager windowsAdLdapManager)
: base(
guidGenerator,
currentTenant,
userManager,
identityUserRepository,
ldapManager,
ldapSettingProvider,
featureChecker,
settingProvider,
identityOptions)
{
WindowsAdLdapManager = windowsAdLdapManager;
}
protected override Task<string> NormalizeUserNameAsync(string userName)
{
return WindowsAdLdapManager.NormalizeForActiveDirectoryAsync(userName);
}
}
WindowsAdLdapManager.cs
using System.Text;
using System.Threading.Tasks;
using LdapForNet;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity.ExternalLoginProviders.Ldap;
using Volo.Abp.Ldap;
namespace YourProject.Identity;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(WindowsAdLdapManager), typeof(OpenLdapManager), typeof(ILdapManager), typeof(LdapManager))]
public class WindowsAdLdapManager : OpenLdapManager
{
public WindowsAdLdapManager(ILdapSettingProvider ldapSettingProvider)
: base(ldapSettingProvider)
{
}
protected override async Task<string> NormalizeUserNameAsync(string userName)
{
return await NormalizeForActiveDirectoryAsync(userName);
}
protected override Task<string> GetUserEmailAsync(LdapEntry ldapEntry)
{
var directoryEntry = ldapEntry.ToDirectoryEntry();
return Task.FromResult(
directoryEntry.GetAttribute("mail")?.GetValue<string>()
?? directoryEntry.GetAttribute("userPrincipalName")?.GetValue<string>()
?? string.Empty
);
}
protected override Task<string> GetUserFilterAsync(string userName)
{
return Task.FromResult($"(&(objectClass=user)(sAMAccountName={EscapeFilterValue(userName)}))");
}
public virtual async Task<string> NormalizeForActiveDirectoryAsync(string userName)
{
if (userName.Contains("@") || userName.Contains("\\"))
{
return userName;
}
var domain = await LdapSettingProvider.GetDomainAsync();
if (string.IsNullOrWhiteSpace(domain))
{
return userName;
}
return $"{userName}@{domain}";
}
protected virtual string EscapeFilterValue(string value)
{
var builder = new StringBuilder(value.Length);
foreach (var character in value)
{
builder.Append(character switch
{
'\\' => "\\5c",
'*' => "\\2a",
'(' => "\\28",
')' => "\\29",
'\0' => "\\00",
_ => character
});
}
return builder.ToString();
}
}
Then register the custom provider in your Domain module:
Configure<AbpIdentityOptions>(options =>
{
options.ExternalLoginProviders.Add<WindowsAdLdapExternalLoginProvider>(LdapExternalLoginProvider.Name);
});
Notes:
UserName is already stored as mydomain\\serviceUser or serviceuser@mydomain.local, this code keeps it as-is and does not prefix it againGetUserFilterAsync(...) uses sAMAccountName instead of uidGetUserEmailAsync(...) falls back from mail to userPrincipalNameDetermineProviderCultureResult(...) with an empty ReturnUrl is not the root cause hereAddMicrosoftAccount(...) is unrelated to the LDAP username/password flowOne more thing to verify: after LDAP bind succeeds, ABP still needs to read the user's email to create the IdentityUser. If the AD mail attribute is empty, or your directory uses a different attribute, then adjust GetUserEmailAsync(...) accordingly.
If you share your current OpenLdapManager override and the exact format stored in the LDAP settings UserName field, we can narrow down the last missing part.
Best regards,
ABP Support Team
Hi, Thanks for the follow-up. If you are using the built-in LDAP login in Identity Pro, the place to start is not the register page. The username/password login flow already calls the LDAP provider automatically:
SignInManager.PasswordSignInAsync(...).AbpSignInManager checks the registered external login providers.LdapExternalLoginProvider.TryAuthenticateAsync(...) performs the LDAP bind.IdentityUser and signs the user in.
So, for your scenario, the main hook points are:LdapExternalLoginProvider: customize how the username is normalized before authentication.OpenLdapManager: customize how ABP searches the directory and reads user information.
This is important because the built-in LDAP implementation is OpenLDAP-oriented by default (uid=..., cn=..., and (&(uid=...))). For Windows AD, you usually need a Windows AD-specific format such as DOMAIN\\user, user@domain, or a search based on sAMAccountName / userPrincipalName. So changing only the LDAP server settings is usually not enough.
Also, the register page is not the correct place for LDAP provisioning:OpenLdapManager for your Windows AD bind/search behavior.LdapExternalLoginProvider so the username format matches your AD format.IdentityUser.
If you mean true integrated Windows Authentication (IIS/Negotiate) rather than LDAP username/password, that is a different flow and goes through the external login callback path instead of the LDAP provider.
If login succeeds but the ABP user is still not created, please share these details and we can narrow it down quickly:jsmith, DOMAIN\\jsmith, or jsmith@domain)mail attribute populatedHi,
Thanks for the details.
This behavior is expected.
The File Management menu is not controlled by whether you enabled it on the host side. In the File Management module, the FileManagement.Enable feature is defined with a default value of true, and the MVC menu contributor adds the Files menu item when that feature is enabled for the current tenant and the user has the related File Management permissions.
So, if you only disabled it for the host, tenants can still see the Files menu unless you also disable the feature for the tenant or for the tenant's edition.
To fix it:
Tenant Management -> Tenants -> Actions -> Features and turn off File Management -> Enable."Features": {
"FileManagement.Enable": "false"
}
After disabling that feature, the Files menu should no longer be shown for those tenants.
If it still appears, please send us:
We detected that problem.
It occurs because of docker errors. If an error accured from docker, studio crashes. In the next version it'll be fixed. But for now you can make sure:
Or you can skip starting 'docker-dependencies' section for now
Hi,
For a quick answer, if you login by using ABP Studio CLI, it should work on ABP Studio, too.
As a workaround
dotnet tool update -g volo.abp.studio.cli
abp login
Our team will post whenever they find the real solution, this approach should allow you to use ABP Studio at least
Hi, thanks for reporting.
It's clearly embedding or vectordb problem.
I need more information to understand the problem.
ollama pull llama3.2
ollama pull nomic-embed-text
PgVector extension is properly installed on your posstgres instance?If you can access detailed logs, that will really help