Search code examples
asp.netvb.netasp.net-web-apientity-framework-6asp.net-identity-2

Issue with EF IdentityDbContext when using async Methods


why does the following code always produce an "An asynchronous module or handler completed while an asynchronous operation was still pending"?

When I use 'Dim OriginalUser As ApplicationUser = db.Users.Where(Function(p) p.Id = id).ToList(0)' it works fine.

Lazy Loading is disabled on the ApplicationDBContext which inherits from IdentityDbContext. Why isn't the Context available anymore for the SaveChanges-Part? What am I missing?

    Public Async Sub PatchUser(id As String, <FromBody> ChangedUserAttributes As Delta(Of ApplicationUser))
    Using ctx As New ApplicationDbContext
        Validate(ChangedUserAttributes.GetEntity())

        If Not ModelState.IsValid Then
            Throw New HttpResponseException(New HttpResponseMessage(HttpStatusCode.BadRequest))
        End If

        Dim OriginalUser As ApplicationUser = Await ctx.Users.SingleOrDefaultAsync(Function(p) p.Id = id)
        If OriginalUser Is Nothing Then
            Throw New HttpResponseException(HttpStatusCode.NotFound)
        End If

        Try
            ChangedUserAttributes.TrySetPropertyValue("Email", "Emil") 
            ChangedUserAttributes.Patch(OriginalUser)
            Await ctx.SaveChangesAsync
            Return
        Catch ex As Exception
            Throw New HttpResponseException(New HttpResponseMessage(HttpStatusCode.BadRequest))
        End Try
    End Using
End Sub

Solution

  • It's because of Async Sub. This method should be an asynchronous function returning Task, and (if you call it yourself) it would need to be called with Await.

    You may find my article on async on ASP.NET helpful:

    When an asynchronous handler completes the request, but ASP.NET detects asynchronous work that hasn’t completed, you get an Invalid­OperationException with the message, “An asynchronous module or handler completed while an asynchronous operation was still pending.” This is usually due to asynchronous code calling an async void method

    As well as my article on async best practices:

    Avoid async void... Async methods returning void don’t provide an easy way to notify the calling code that they’ve completed. It’s easy to start several async void methods, but it’s not easy to determine when they’ve finished.