Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用ASP.Net标识同步扩展方法时,HttpContext.Current为null_C#_Async Await_Asp.net Identity_Httpcontext - Fatal编程技术网

C# 使用ASP.Net标识同步扩展方法时,HttpContext.Current为null

C# 使用ASP.Net标识同步扩展方法时,HttpContext.Current为null,c#,async-await,asp.net-identity,httpcontext,C#,Async Await,Asp.net Identity,Httpcontext,ASP.Net Identity中的大多数函数都是异步的。有一些帮助程序扩展方法允许您同步运行这些方法(ASP.Net标识引用项目使用这些方法),但是: 如果使用同步扩展方法,HttpContext.Current为空 如果我直接调用异步方法,HttpContext.Current是非空的 所描述的问题与基本相同,但试图理解它为何以这种方式运行,而不仅仅是为了解决问题 我遇到这个问题的原因是我想扩展登录过程,根据用户的白名单IP地址检查请求IP地址——但是如果我不能访问HttpContext

ASP.Net Identity中的大多数函数都是异步的。有一些帮助程序扩展方法允许您同步运行这些方法(ASP.Net标识引用项目使用这些方法),但是:

  • 如果使用同步扩展方法,
    HttpContext.Current
    为空
  • 如果我直接调用异步方法,
    HttpContext.Current
    是非空的
所描述的问题与基本相同,但试图理解它为何以这种方式运行,而不仅仅是为了解决问题

我遇到这个问题的原因是我想扩展登录过程,根据用户的白名单IP地址检查请求IP地址——但是如果我不能访问HttpContext,它就不起作用

在试图找出出现此问题的原因时,我了解到使用同步上下文可以确保
HttpContext.Current
可用于异步调用,这就是为什么我直接调用异步方法时它会起作用

如果异步调用中断了对
HttpContext.Current
的访问,为什么要使用允许异步调用同步运行的扩展方法呢。这是虫子吗

public class LoginPage : Page
{
    public void Login(string user, string password)
    {
        var signInManager = HttpContext.Current.GetOwinContext().Get<MySignInManager>();
        signInManager.PasswordSignIn(user, password, false, false); // this is a synchronous extension method
    }
}

public class MySignInManager<TUser, TKey> : Microsoft.Aspnet.Identity.Owin.SignInManager<TUser, TKey>
{
    public override async Task<SignInStatus> PasswordSignInAsync(string username, string password, bool isPersistent, bool shouldLockout)
    {
        ...
        string ipAddress = GetIpAddress();
        ...
    }

    private string GetIpAddress()
    {
        // HttpContext.Current is null if using the PasswordSignIn extension method
        var request = HttpContext.Current.GetOwinContext().Request;
        return request.RemoteIpAddress;
    }
}

// namespace Microsoft.AspNet.Identity.Owin
public static class SignInManagerExtensions
{
    public static SignInStatus PasswordSignIn(this SignInManager<TUser, TKey> manager, string username, string password, bool isPersistent, bool shouldLockout)
    {
        return AsyncHelper.RunSync(() => manager.PasswordSignInAsync(userName, password, isPersistent, shouldLockout));
    }
}

// namespace Microsoft.AspNet.Identity
internal static class AsyncHelper
{
    public static TResult RunSync<TResult>(Func<Task<TResult>> func)
    {
        var cultureUi = CultureInfo.CurrentUICulture;
        var culture = CultureInfo.CurrentCulture;
        return _myTaskFactory.StartNew(() =>
        {
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = cultureUi;
            return func();
        }).Unwrap().GetAwaiter().GetResult();
    }
}
公共类登录页面:第页
{
公共无效登录(字符串用户、字符串密码)
{
var signInManager=HttpContext.Current.GetOwinContext().Get();
signInManager.PasswordSignIn(user,password,false,false);//这是一个同步扩展方法
}
}
公共类MySignInManager:Microsoft.Aspnet.Identity.Owin.SignInManager
{
public override异步任务PasswordSignInAsync(字符串用户名、字符串密码、bool ispersist、bool shouldllockout)
{
...
字符串ipAddress=GetIpAddress();
...
}
私有字符串GetIpAddress()
{
//如果使用PasswordSignIn扩展方法,则HttpContext.Current为null
var request=HttpContext.Current.GetOwinContext().request;
返回request.RemoteIpAddress;
}
}
//命名空间Microsoft.AspNet.Identity.Owin
公共静态类SignInManager
{
公共静态签名状态PasswordSignIn(此签名管理器管理器、字符串用户名、字符串密码、bool ispersist、bool shouldllockout)
{
返回AsyncHelper.RunSync(()=>manager.PasswordSignInAsync(用户名、密码、isPersistent、shouldLockout));
}
}
//命名空间Microsoft.AspNet.Identity
内部静态类AsyncHelper
{
公共静态TResult RunSync(Func Func)
{
var cultureUi=CultureInfo.currentui culture;
var culture=CultureInfo.CurrentCulture;
return\u myTaskFactory.StartNew(()=>
{
Thread.CurrentThread.CurrentCulture=区域性;
Thread.CurrentThread.CurrentUICulture=cultureUi;
返回func();
}).Unwrap().GetWaiter().GetResult();
}
}

在这种特殊情况下,如果一个人无论如何都不应该“使用允许异步调用同步运行的扩展方法”,那么“为什么”真的很重要吗?@AlexeiLevenkov这很重要,因为参考实现使用扩展方法,这意味着这是正确的方法,即使它会导致这个问题。如果整个事情都基于异步操作,我不会相信
HttpContext
。以前有一些文章介绍如何在worker和主服务器进程之间同步
HttpContext
Identity
。但这对我来说很危险。我所做的是,当一个请求传入时,我将其放入我自己的缓存框架(简而言之是一个静态单例类)。从workers内部,我可以从缓存中访问它。@antepolivian这是登录时身份验证过程的一部分,而不是一些后台worker过程。从DB访问到实际登录,大多数身份验证方法都是异步方法。实际原因非常明显,