Search code examples
c#asp.net-coreasync-awaitasp.net-identityblazor-server-side

How to prevent Deadlock with Usermanager?


I have a registration page on blazor (server). On that Page I want to implement a register function using AspnetCor.Identity

This is the Method: (_usermanager is of type AspNetCore.Identity.UserManager<>)

  public bool Register(RegisterUser regUser)
    {
        var newUser = new ApplicationUser { Email = regUser.Mail, UserName = regUser.Mail};           
        var sd= _userManager.CreateAsync(newUser, "password").Result;
        if (!sd.Succeeded)
        {                
            return false;
        }
        return true;
    }

The method is called from within HandleValidSubmit on the blazor-page:

<EditForm Model="@_registerUser" OnValidSubmit="HandleValidSubmit">
//...
</EditForm>
@code {
      private void HandleValidSubmit()
        {
            if (identity.Register(_registerUser)) {
              NaviationManager.NavigateTo($"/manage/registersent");
            }
        }
}

When Registration fails it works just as designed returning false. But when registration would be fine I end up in a Deadlock at _userManager.CreateAsync(newUser, "password").Result;

When I do not try to make the async-call synchronous and replace the call by _userManager.CreateAsync(newUser, "password") (and simply ignore any return value) the user gets created without an issue.

How should I handle an async-call with return-value from within HandleValidSubmit?


Solution

  • Make everything async - returning Tasks and awaiting them as appropriate. Don't call .Result or .Success. Let the compiler help you write better async code.

    For instance make HandleValidSubmit async.

    private async void HandleValidSubmit()
    {
        if (await identity.RegisterAsync(_registerUser)) 
        {
            NaviationManager.NavigateTo($"/manage/registersent");
        }
    }
    

    async void should be only used for event-type things since they are akin to "fire and forget".