If I made more than one
API call at the same time getting error
A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method in this context. Any instance members are not guaranteed to be thread-safe.
Exception is thrown from var identity = await base.currentUserService.CreateIdentity(user);
as both requests are made at the same time and CreateIdentity method of the previous request is still not finished!
How to solve the above scenario?
I want to wait for IsValidRequest
calling in CustomKeyAuthenticationAttribute
before the previous request finish.
Here is sample code
public class CustomKeyAuthenticationAttribute : AuthorizeAttribute
{
[Dependency]
public IAuthService AuthService { get; set; }
public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
var isValid = await AuthService.IsValidRequest(key-from-request-header);
if(!isValid){
return;
}
await base.OnAuthorizationAsync(actionContext, cancellationToken);
}
}
// In side AuthService
public async Task<bool> IsValidRequest(string key)
{
if (key-in-db)
{
var user = await base.currentUserService.GetUserById(userId-from-request-headers);
var identity = await base.currentUserService.CreateIdentity(user);
var principal = new GenericPrincipal(identity.Result, new string[0]);
HttpContext.Current.User = principal;
return true;
}
return false
}
// Inside currentUserService.CreateIdentity method
public async Task<ClaimsIdentity> CreateIdentity(CustomUser user) {
return await userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
}
Edit
stackTrace: " at System.Data.Entity.Internal.ThrowingMonitor.EnsureNotEntered() at System.Data.Entity.Internal.Linq.InternalSet
1.FindAsync(CancellationToken cancellationToken, Object[] keyValues) at System.Data.Entity.DbSet
1.FindAsync(CancellationToken cancellationToken, Object[] keyValues) at System.Data.Entity.DbSet1.FindAsync(Object[] keyValues) at Microsoft.AspNet.Identity.EntityFramework.EntityStore
1.GetByIdAsync(Object id) at Microsoft.AspNet.Identity.EntityFramework.UserStore6.<GetUserAggregateAsync>d__6c.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Identity.TaskExtensions.CultureAwaiter
1.GetResult() at Microsoft.AspNet.Identity.UserManager2.<GetRolesAsync>d__ac.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNet.Identity.TaskExtensions.CultureAwaiter
1.GetResult() at Microsoft.AspNet.Identity.ClaimsIdentityFactory2.<CreateAsync>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()