StackOverflow exception when overriding a Task ret

2019-07-29 11:45发布

I have a custom user manager class (ASP .NET Identity). I want to override the FindByIdMethod, so that it automatically loads the role names for the user model. This is the only method I am overriding. I am using Microsoft.Identity nuget packages version 2.2.1, Asp.Net Framework.

However, the code below throws a StackOverflow exception - at await base.FindByIdAsync(userId);

 public class MyUserManager : UserManager<MyUser>, IMyUserManager
 {
    public override async Task<MyUser> FindByIdAsync(string userId)
    {
        var user = await base.FindByIdAsync(userId);
        user.RoleNames = await this.GetRolesAsync(user.Id);
        return user;
    }
 }

When I try similar code without adding 'async' to the overriden signature it works OK - however, I cannot load my role names in this method:

public override Task<MyUser> FindByIdAsync(string userId)
{
    var userTask = base.FindByIdAsync(userId); //no errors in this approach
    return userTask; //but also no custom behaviour 
}

I suspect maybe the IMyUserManager might be problematic, but I need it for the IOC/DI. This was an autogenerated interface, so it has all the public members of the UserManager class.

The user class:

public class MyUser: IdentityUser
{
    public string DisplayName { get; set; }
    public bool IsActivated { get; set; }
    public bool MustChangePassword { get; set; }
    public IList<string> RoleNames { get; set; } = new List<string>();
}

Exception details: enter image description here

Call stack (TelimenaUserManager = MyUserManager, I simplified the name)

enter image description here

UPDATE:

Thanks to Henk's suggestions in the comments, I see that recursion happens in the GetRolesAsync method... enter image description here

1条回答
ゆ 、 Hurt°
2楼-- · 2019-07-29 12:28

For completeness, I am posting the working code.

I had to cast the current 'IUserStore' to be the 'IUserRoleStore' (Both generic arguments are needed!).

Then get the roles based on the user instance (which avoids the recursion of 'Finding the user')

 public override async Task<MyUser> FindByIdAsync(string userId)
        {
            var user = await base.FindByIdAsync(userId);
            var roleStore = this.Store as IUserRoleStore<MyUser, string>;
            user.RoleNames = await roleStore.GetRolesAsync(user);
            return user;
        }

Thanks @HenkHolterman!

查看更多
登录 后发表回答