【发布时间】:2020-04-10 22:19:42
【问题描述】:
如果我同时调用more than one API 会出错
在前一个异步操作完成之前,在此上下文上启动了第二个操作。在此上下文中调用另一个方法之前,使用“等待”确保任何异步操作都已完成。不保证任何实例成员都是线程安全的。
var identity = await base.currentUserService.CreateIdentity(user); 抛出异常,因为两个请求同时发出,而前一个请求的 CreateIdentity 方法仍未完成!
上述情况如何解决?
我想在上一个请求完成之前等待IsValidRequest 调用CustomKeyAuthenticationAttribute。
这里是示例代码
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);
}
编辑
stackTrace:" 在 System.Data.Entity.Internal.ThrowingMonitor.EnsureNotEntered() 在 System.Data.Entity.Internal.Linq.InternalSet
1.FindAsync(CancellationToken cancellationToken, Object[] keyValues) at System.Data.Entity.DbSet1.FindAsync(CancellationToken cancelToken, Object[] keyValues) 在 System.Data.Entity.DbSet1.FindAsync(Object[] keyValues) at Microsoft.AspNet.Identity.EntityFramework.EntityStore1.GetByIdAsync(对象 身份证)在 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.CultureAwaiter1.GetResult() 在 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.CultureAwaiter1.GetResult() 在 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.TaskAwaiter1.GetResult()
【问题讨论】:
标签: c# asp.net-web-api thread-safety asp.net-identity