Hi, since in your entity configuration the UserProfile has a not nullable UserId field you can't set the user.Profile as null without deleting the userProfile.
Hi @EngincanV,
and make the UserId as nullable
A UserProfile record can't exist without a reference to a User, so the UserId on UserProfile should not be nullable.
Best regards, Steff Beckers
Hi, then you can directly delete the userProfile instead of setting user.Profile as null. This is the only solution. If you want to set the user's profile as null it should be nullable, or if you directly delete the profile, it will be empty further on.
Regards.
Hello,
I looked over the documentation that you sent and tried using the Audited attribute, but this did not give me what I was looking for.
I am trying to manually add a history log entry to our User entity for changes that are not occurring in the User table. The changes occur on our UserAssignedMerchant join table.
Here is some additional context on our User implementation:
- We implemented our own User class and dtos, but are using IdentityUserManager calls that we adapted from source code to set the properties to still use the built in AbpUsers table and features in our create and update methods.
- Also during those methods, we set the entries in the join table with repository calls for the join table.
- We give the UserAssignedMerchant entries to the end users in a field that is a Guid[] called AssignedMerchantIds, but this only on the dto not the class so it's manually set at the time of retrieval.
Is there a repository call (such as through IAuditLogRepository) that we can make to insert a history log on User that will allow us to manually set what changed in AssignedMerchantIds? Or is there a better way to accomplish this?
Thanks.
Hi, you can configure the AbpAuditingOptions and define an EntityHistorySelector as below:
opt.EntityHistorySelectors.Add(
new NamedTypeSelector(
"UserAssignedMerchant",
type => typeof(UserAssignedMerchant).IsAssignableFrom(type)
));
Hi @EngincanV,
Hi, based on your EfCorePlayground project, you can call _context.UserProfiles.Remove(user.Profile!) method before setting user.Profile to null:
The EfCorePlayground project doesn't have the issue, the AbpEfCorePlayground project has.
Best regards, Steff Beckers
Hi, here is what you need to do to:
1 -) In your UserProfile entity, remove the Id property (because it's already defined by the base class FullAuditedEntity<Guid>), and make the UserId as nullable:
public class UserProfile : FullAuditedEntity<Guid>
{
// public Guid Id { get; set; }
public string Bio { get; set; }
public Guid? UserId { get; set; }
public User User { get; set; }
}
2-) Open your dbcontext class and update the configuration:
b.HasOne(x => x.Profile)
.WithOne(x => x.User)
.HasForeignKey<UserProfile>(x => x.UserId)
.OnDelete(DeleteBehavior.ClientSetNull);
You should use the
ClientSetNullas the delete-behaviour, which is default and allows you to set the Profile as null.
3-) Update your DeleteUserProfileAsync method:
public async Task DeleteUserProfileAsync()
{
var user = await _userRepository.GetAsync(x => x.Id == Guid.Parse("c64b873e-c067-43e0-ae00-07992a880837"));
await _userProfileRepository.DeleteAsync(user.Profile!.Id);
user.Profile = null;
await _userRepository.UpdateAsync(user);
}
Then, it will work as you expected.
Regards.
Hi @EngincanV,
I have the following User aggregate root:
public class User : FullAuditedAggregateRoot<Guid> { public User( Guid id, string name) { Id = id; Name = name; } private User() { } public string Name { get; set; } public UserProfile? Profile { get; set; } }I also have an User record in my database (via IDataSeedContributor):
User user = new User( id: Guid.Parse("c64b873e-c067-43e0-ae00-07992a880837"), name: "Steff Beckers") { Profile = new UserProfile() { Bio = "Software Developer" } }; await _userRepository.InsertAsync(user);Now I want to delete the user's profile. What I'm thinking is:
var user = await _userRepository.GetAsync(userId); user.Profile = null; await _userRepository.UpdateAsync(user);But this results in the error. How else should I delete the user's profile?
Best regards, Steff Beckers
Hi, based on your EfCorePlayground project, you can call _context.UserProfiles.Remove(user.Profile!) method before setting user.Profile to null:
_context.UserProfiles.Remove(user.Profile!);
user.Profile = null;
If you want to do this with repository pattern, then you should inject the profile repository and use its DeleteAsync method:
//inject the interface
private readonly IRepository<UserProfile, Guid> _userProfileRepository;
var user = await _userRepository.GetAsync(userId);
await _userProfileRepository.DeleteAsync(user.Profile!.Id);
user.Profile = null;
await _userRepository.UpdateAsync(user);
Hi @EngincanV,
Any progress on this issue?
Best regards, Steff Beckers
Hi sorry for my late response,
In SQL Server, a foreign key constraint only enforces referential integrity—it does not define what should happen when the navigation property (Profile) is set to null. SQL Server only responds to actual DELETE operations.
Example: If you set user.Profile = null, EF Core only removes the reference, but SQL Server still holds the Profile record because there’s no explicit DELETE query for it.
SQL Server requires an explicit cascade delete at the database level to automatically remove dependent entities.
So, this is not related to ABP or EF Core, instead, it's the design of the SQL Server.
DeleteBehavior.Cascade Only Works When the Principal Entity is Deleted. So, in your case, the relevant profile is deleted whenever the relevant user is being deleted.
Also, there is a good description here that you might want to check: https://stackoverflow.com/a/12886309/10477283
Hi,
PreConfigure<OpenIddictServerBuilder>(serverBuilder => { serverBuilder.SetLogoutEndpointUris("<your-blazor-root-url>"); });Seems to change the "Logout Url" (the url you go to when logging out) rather then "Post Logout Url" (the url you go to after having logged out).
Hi sorry, you are right. After the change you made in the OpenIddictDataSeedContributor, the only thing you need to do is to open the *BlazorModule class and make the following change:
builder.Services.AddOidcAuthentication(options =>
{
builder.Configuration.Bind("AuthServer", options.ProviderOptions);
options.UserOptions.NameClaim = OpenIddictConstants.Claims.Name;
options.UserOptions.RoleClaim = OpenIddictConstants.Claims.Role;
options.ProviderOptions.DefaultScopes.Add("AbpSolution5");
options.ProviderOptions.DefaultScopes.Add("roles");
options.ProviderOptions.DefaultScopes.Add("email");
options.ProviderOptions.DefaultScopes.Add("phone");
//add this line
options.ProviderOptions.PostLogoutRedirectUri = "https://localhost:44353";
});
i am using angular how can find this template i search it in abp suite and can not found it !!!
I've assigned the angular-team to your question. They will assist you.
Regards.
Hi,
I have done as you explained but when i press the logout button now it gives me the following error:
error:invalid_request error_description:The specified 'post_logout_redirect_uri' is invalid. error_uri:https://documentation.openiddict.com/errors/ID2052It looks like in the url 'post_logout_redirect_uri' is still the old PostLoginRedirectUrl. How can i fix this?
You should also configure the OpenIddictServerBuilder in the *HttpApi.Host module (add the following code in your preconfigureservices method):
PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
{
serverBuilder.SetLogoutEndpointUris("<your-blazor-root-url>");
});
how can i add this and this is built in component and not ability to customize its functionality
i am using pickup model of select
Hi, under the Pages/Shared folder, there is a LookupModal.cshtml file, you can edit this file and implement it for your case:
You can edit the template in the ABP Suite, and then it will not be overridden by ABP Suite (Frontend.Mvc.Page.LookupModal_cshtml.txt):
Here are the related documents that you should check: