Большинство функций в ASP. Net Идентификация асинхронна. Существуют вспомогательные методы расширения, которые позволяют вам запускать их синхронно (которые использует справочный проект ASP. Net Identity), однако:
- Если я использую методы синхронного расширения,
HttpContext.Current
нулевой. - Если я вызываю асинхронные c методы напрямую,
HttpContext.Current
не равен нулю.
Описанная проблема в значительной степени идентична этому вопросу , но пытается понять, почему он так себя ведет, а не просто решить проблему.
Причина, по которой я сталкиваюсь с этой проблемой, заключается в том, что я хочу расширить процесс входа в систему, чтобы проверить IP-адрес запроса на соответствие IP-адреса белого списка пользователя - но он не работает, если я не могу получить доступ к HttpContext.
Пытаясь выяснить, почему возникает эта проблема, я узнал, что ASP. Net делает свое дело с контекстами синхронизации, чтобы убедиться, что HttpContext.Current
доступен для асинхронных c вызовов, поэтому он работает, когда я вызываю асин c метод напрямую.
Зачем вам использовать методы расширения, которые позволяют асинхронным c вызовам выполняться синхронно, если это нарушает доступ к 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();
}
}