2017-08-04 6 views
1

私は、ASP.NET IDのカスタムユーザーストアを実装しました。例のセットhereに従っています。これ以外はすべて正常に動作します。カスタムasp.net IDストア - 時にはHttpContext.Currentが空である理由

現在ログインしているユーザーに関するデータにアクセスする必要があります。通常、あなたは彼が、その後、時にASP.NETのアイデンティティを(例えば試してみて、彼/彼女のパスワードを変更する)を管理コントローラに行くユーザーならばAUSERは、ログインした後に、今

HttpContext.Current.User 

にアクセスしているにアクセスしたいです

CustomUserManager.FindByIdAsync(string userId) 

HttpContext.Currentを呼び出すことによって、再び、ユーザを検索しますと、(つまり、ページをレンダリングする前です)完全に空です。では、このシナリオでHttpContextに関する情報を取得するにはどうすればよいですか?ユーザーは適切にログインしているので、どのユーザーがログインしているのか把握するにはどうすればよいですか?

@editは...ここでの問題は... CustomUserStoreであること

public class CustomUserStore<TUser> : IUserStore<TUser>, IUserLoginStore<TUser>, IUserClaimStore<TUser>, IUserPasswordStore<TUser>, IUserSecurityStampStore<TUser>, IUserEmailStore<TUser>, IUserPhoneNumberStore<TUser>, 
    IUserLockoutStore<TUser, string>, IUserTwoFactorStore<TUser, string>//, IQueryableUserStore<TUser> 
    where TUser: CustomUser<string>, IUser<string> 
{ 

    string storageFile = @"c:\temp\aspnetusers.json"; 
    List<TUser> users; 

    public CustomUserStore() 
    { 
     if (File.Exists(storageFile)) 
     { 
      string contents = File.ReadAllText(storageFile); 
      users = JsonConvert.DeserializeObject<List<TUser>>(contents); 
      if (users == null) 
       users = new List<TUser>(); 
     } 
     else 
      users = new List<TUser>(); 
    } 

    #region IUserStore implementation 

    public Task<TUser> FindByIdAsync(string userId) 
    { 
     string sessionId = HttpContext.Current?.Session?.SessionID; 
     return Task.FromResult<TUser>(users.FirstOrDefault(u => u.Id == userId)); 
    } 

    public Task<TUser> FindByNameAsync(string userName) 
    { 
     string sessionId = HttpContext.Current?.Session?.SessionID; 
     return Task.FromResult<TUser>(users.FirstOrDefault(u => string.Compare(u.UserName, userName, true) == 0)); 
    } 

    #endregion 
} 

のビットだし、空にすることもできますHttpContext.Current FindByAsync方法にあります。

モデルは

var model = new IndexViewModel 
     { 
      HasPassword = HasPassword(), 
      PhoneNumber = await UserManager.GetPhoneNumberAsync(userId), 
      TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId), 
      Logins = await UserManager.GetLoginsAsync(userId), 
      BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId) 
     }; 

を作成し、それが問題

private bool HasPassword() 
    { 
     var user = UserManager.FindById(User.Identity.GetUserId()); 
     if (user != null) 
     { 
      return user.PasswordHash != null; 
     } 
     return false; 
    } 

他の4つのリクエストへの原因となるHasPassword方法でFindById要求だされたときにそれはAccountControllerのIndexメソッドで発生ユーザーマネージャにはすべてHttpContext.Currentが書き込まれています。だから、問題を引き起こすのはUserManagerへの呼び出しだと思われます。

+1

'HttpContext.User'が空のコードを表示できますか?ほとんどの場合、その時点でHttpリクエストがないので、あなたの問題 – trailmax

+0

問題がどこで発生したのかを特定して、解決策が明らかになったバグは別の問題を引き起こします。 HasPasswordの非同期メソッドを使用し、UserManager.FindByIdAsyncを使用するように上記を書き直すと、HttpContext.Currentは常に値を持ちます。しかし、UserManager上でsyncメソッドを呼び出すとどうしてそうならないのでしょうか?おそらくUserManagerが内部的にAsyncメソッドを呼び出してコンテキストを復元しないのでしょうか?ソースコードをチェックアウトする時間 – user3566056

答えて

0

問題の正確な原因を特定したので、修正するのは簡単です。

これは、ユーザーがパスワードを持っているかどうかを確認するためにemthod非同期追加:

private async Task<bool> HasPasswordAsync() 
    { 
     var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); 
     if (user != null) 
     { 
      return user.PasswordHash != null; 
     } 
     return false; 
    } 

とインデックスメソッドで新しい非同期Methodeの

var model = new IndexViewModel 
    { 
     HasPassword = await HasPasswordAsync(), 
     PhoneNumber = await UserManager.GetPhoneNumberAsync(userId), 
     TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId), 
     Logins = await UserManager.GetLoginsAsync(userId), 
     BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId) 
    }; 

を使用し、しかし、なぜ同期メソッド呼び出しはありません物事を壊す?同期呼び出しがHttpContext.Currentが利用可能な標準的なコンテキストに実行されると思います。

私は実際のプロジェクトで私がこの問題にもっと頻繁に遭遇するカスタムのユーザーストアを持っています.UserManagerメソッドへのより多くの同期アクセスが含まれているかどうかを確認する必要があります。

関連する問題