【问题标题】:Losing HttpContext with async await in ASP.NET Identity GetRolesAsync在 ASP.NET 标识 GetRolesAsync 中使用异步等待丢失 HttpContext
【发布时间】:2015-09-01 16:43:21
【问题描述】:

这比 ASP.NET 身份更像是一个异步/等待问题。我正在使用 Asp.Net Identity,并且有一个自定义的 UserStore,以及一个自定义的 GetRolesAsync 方法。从 WebApi 控制器调用 UserManager。

public class MyWebApiController {
    private MyUserManager manager = new MyUserManager(new MyUserStore());
    [HttpGet]
    public async Task<bool> MyWebApiMethod(int x) {
        IList<string> roles = await manager.GetRolesAsync(x);
        return true;
    }
}
public class MyUserManager : UserManager<MyUser, int> {

    // I do not implement a custom GetRolesAsync in the UserManager, but 
    // from looking at the identity source, this is what the base class is doing:

    // public virtual async Task<IList<string>> GetRolesAsync(TKey userId)
    // {
    //     ThrowIfDisposed();
    //     var userRoleStore = GetUserRoleStore();
    //     var user = await FindByIdAsync(userId).WithCurrentCulture();
    //     if (user == null)
    //     {
    //         throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound,userId));
    //     }
    //     return await userRoleStore.GetRolesAsync(user).WithCurrentCulture();
    // }
}

public class MyUserStore {
    public async Task<IList<string>> GetRolesAsync(TUser user) {

        // I need HttpContext here and it is NULL. WHY??
        var currentContext = System.Web.HttpContext.Current; // NULL!

         var query = from userRole in _userRoles
                    where userRole.UserId.Equals(userId)
                    join role in _roleStore.DbEntitySet on userRole.RoleId equals role.Id
                    select role.Name;

        return await query.ToListAsync();
    }
}

为什么 MyUserStore.GetRolesAsync 中的上下文为空?我以为 await 传递了上下文?我已经在 MyUserStore 中逐步完成了其他异步方法,它们都有正确的上下文,并且代码看起来几乎相同。

【问题讨论】:

  • 您使用的目标框架版本是什么?
  • 4.5.1 在项目设置中,-web.config:
  • 尝试在您的 app.config 中将 aspnet:UseTaskFriendlySynchronizationContext 设置为 true
  • 很奇怪。你在哪里打电话给Task.Run
  • 我想知道WithCurrentCulture 是否阻止了常规的 SyncCtx 捕获。

标签: c# asp.net-web-api async-await asp.net-identity


【解决方案1】:

这原来是TaskExtensions.WithCurrentCulture 的一个属性。这些是 EF 的 docs,但它们也适用于 ASP.NET 身份:

配置用于等待此任务的等待器以避免将延续编组回原始上下文,但保留当前文化和 UI 文化。

这会导致同步上下文不编组,从而导致HttpContext 变为null

这是来自the source的相关部分:

public void UnsafeOnCompleted(Action continuation)
{
    var currentCulture = Thread.CurrentThread.CurrentCulture;
    var currentUiCulture = Thread.CurrentThread.CurrentUICulture;

    // This part is critical.
    _task.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted(() =>
    {
        var originalCulture = Thread.CurrentThread.CurrentCulture;
        var originalUiCulture = Thread.CurrentThread.CurrentUICulture;
        Thread.CurrentThread.CurrentCulture = currentCulture;
        Thread.CurrentThread.CurrentUICulture = currentUiCulture;
        try
        {
            continuation();
        }
        finally
        {
            Thread.CurrentThread.CurrentCulture = originalCulture;
            Thread.CurrentThread.CurrentUICulture = originalUiCulture;
        }
    });
}

【讨论】:

  • @user 绝对是。至少它是记录在案的:)
猜你喜欢
  • 2017-02-03
  • 2017-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-22
  • 2018-07-21
  • 2020-07-10
相关资源
最近更新 更多