user3767106 user3767106 - 2 months ago 16
Vb.net Question

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

Answer

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.

Comments