Is there an existing issue for this?
Description
On the Identity Users → Edit modal (/Identity/Users/EditModal), EditModalModel.OnGetAsync resolves the audit "Created by" / "Modified by" user names by calling IdentityUserAppService.GetAsync(...). If the referenced user (the creator or last modifier) has been soft-deleted, GetAsync throws EntityNotFoundException, so the edit modal cannot be opened at all, even though the user being edited is perfectly valid.
The error shown to the end user references the creator's id (not the edited user's id), which makes it very confusing to diagnose, e.g.:
There is no entity of type IdentityUser with id <soft-deleted-creator-id>!
Root cause is in modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs:
Detail.CreatedBy = await GetUserNameOrNullAsync(user.CreatorId);
Detail.ModifiedBy = await GetUserNameOrNullAsync(user.LastModifierId);
private async Task<string> GetUserNameOrNullAsync(Guid? userId)
{
if (!userId.HasValue)
{
return null;
}
var user = await IdentityUserAppService.GetAsync(userId.Value); // throws if the user is soft-deleted / missing
return user.UserName;
}
Despite the OrNull name, the method does not tolerate a missing user: IdentityUserAppService.GetAsync excludes soft-deleted users (global ISoftDelete filter) and throws EntityNotFoundException. The only guard is the userId == null check.
Reproduction Steps
- With user A (e.g. an admin), create user B. Now
B.CreatorId == A.Id.
- Soft-delete user A from the Identity Users UI (standard ABP soft delete,
IsDeleted = true, the row stays in AbpUsers).
- Identity → Users → Actions → Edit on user B.
GET /Identity/Users/EditModal?id={B.Id} returns 404; the modal fails to open.
Expected behavior
The edit modal opens. "Created by" should show the creator's name if resolvable, or be empty/blank if it cannot be resolved (e.g. the creator was soft-deleted). A missing/soft-deleted audit reference must not block editing.
Actual behavior
EntityNotFoundException is thrown for the creator's id and the modal never opens, so user B, and every other user created by the deleted user A, becomes uneditable.
Regression?
No. Not a regression, the code has always used GetAsync. Confirmed present in 8.1.1 and still present on the dev branch (GetUserNameOrNullAsync unchanged).
Known Workarounds
- Repoint the dangling audit reference to an existing user:
UPDATE AbpUsers SET CreatorId = '<an-active-user-id>'
WHERE CreatorId = '<soft-deleted-user-id>';
- Or override
IIdentityUserAppService.GetAsync in the application layer to fall back to a soft-delete-ignoring lookup so it returns the record instead of throwing.
Version
8.1.1
User Interface
MVC
Database Provider
EF Core (Default)
Tiered or separate authentication server
Separate Auth Server
Operation System
Windows (Default)
Other information
Suggested fix: make GetUserNameOrNullAsync honor its name and return null when the user can't be resolved:
private async Task<string> GetUserNameOrNullAsync(Guid? userId)
{
if (!userId.HasValue)
{
return null;
}
try
{
var user = await IdentityUserAppService.GetAsync(userId.Value);
return user.UserName;
}
catch (EntityNotFoundException)
{
return null;
}
}
A cleaner alternative is a null-returning lookup (e.g. a FindAsync-style method, optionally ignoring the soft-delete filter) so the creator/modifier name can still be displayed for soft-deleted users instead of being silently dropped.
Is there an existing issue for this?
Description
On the Identity Users → Edit modal (
/Identity/Users/EditModal),EditModalModel.OnGetAsyncresolves the audit "Created by" / "Modified by" user names by callingIdentityUserAppService.GetAsync(...). If the referenced user (the creator or last modifier) has been soft-deleted,GetAsyncthrowsEntityNotFoundException, so the edit modal cannot be opened at all, even though the user being edited is perfectly valid.The error shown to the end user references the creator's id (not the edited user's id), which makes it very confusing to diagnose, e.g.:
There is no entity of type IdentityUser with id <soft-deleted-creator-id>!Root cause is in
modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs:Despite the
OrNullname, the method does not tolerate a missing user:IdentityUserAppService.GetAsyncexcludes soft-deleted users (globalISoftDeletefilter) and throwsEntityNotFoundException. The only guard is theuserId == nullcheck.Reproduction Steps
B.CreatorId == A.Id.IsDeleted = true, the row stays inAbpUsers).GET /Identity/Users/EditModal?id={B.Id}returns 404; the modal fails to open.Expected behavior
The edit modal opens. "Created by" should show the creator's name if resolvable, or be empty/blank if it cannot be resolved (e.g. the creator was soft-deleted). A missing/soft-deleted audit reference must not block editing.
Actual behavior
EntityNotFoundExceptionis thrown for the creator's id and the modal never opens, so user B, and every other user created by the deleted user A, becomes uneditable.Regression?
No. Not a regression, the code has always used
GetAsync. Confirmed present in 8.1.1 and still present on thedevbranch (GetUserNameOrNullAsyncunchanged).Known Workarounds
IIdentityUserAppService.GetAsyncin the application layer to fall back to a soft-delete-ignoring lookup so it returns the record instead of throwing.Version
8.1.1
User Interface
MVC
Database Provider
EF Core (Default)
Tiered or separate authentication server
Separate Auth Server
Operation System
Windows (Default)
Other information
Suggested fix: make
GetUserNameOrNullAsynchonor its name and returnnullwhen the user can't be resolved:A cleaner alternative is a null-returning lookup (e.g. a
FindAsync-style method, optionally ignoring the soft-delete filter) so the creator/modifier name can still be displayed for soft-deleted users instead of being silently dropped.