失去的HttpContext与异步伺机在ASP.NET身份GetRolesAsync(Losing

2019-10-23 09:31发布

这更多的是一种异步电动机/等待问题比ASP.NET身份。 我使用Asp.Net身份,并有一个自定义UserStore,用定制的GetRolesAsync方法。 该的UserManager从控制器的WebAPI叫。

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? 我想伺机传递的上下文下来? 我已经通过在MyUserStore其他异步方法,加强与它们都具有正确的上下文,代码似乎几乎相同。

Answer 1:

这原来是一个财产TaskExtensions.WithCurrentCulture 。 这些是文档的EF,但他们申请ASP.NET身份,以及:

配置用来等待这个任务,以避免编组持续回原来的语境 ,但保存当前文化和UI文化的awaiter。

这将导致同步上下文不编组,这会导致HttpContextnull

下面是相关的部分从源 :

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;
        }
    });
}


文章来源: Losing HttpContext with async await in ASP.NET Identity GetRolesAsync