2017-11-03 5 views
0

これはStackOverflowの私の最初の質問です:)私は強く判断しないでください:) OK。さあ。ASP.NET MVC AspNetUserClaimsテーブル内のデータの読み込み、書き込み、更新はどのようにできますか?

私はASP.NET MVCフレームワークで新しく、自分のサイトに多言語を実装しようとしています。だから私は_LoginPartial.cshtmlにドロップダウン言語リストを追加しました:

<li class="dropdown"> 
    <a href="#" class="dropdown-toggle" data-toggle="dropdown">@(MEDONET.Resources.IndexTexts.Language)<b class="caret"></b></a> 
    <ul class="dropdown-menu"> 
     <li>@Html.ActionLink("Кыргызча", "Change", "Language", new { lang = "ky" }, null)</li> 
     <li>@Html.ActionLink("Русский", "Change", "Language", new { lang = "ru" }, null)</li> 
     <li>@Html.ActionLink("English", "Change", "Language", new { lang = "en" }, null)</li> 
     <li>@Html.ActionLink("O'zbekcha", "Change", "Language", new { lang = "uz" }, null)</li> 
    </ul> 
</li> 

あなたが見ることができるように、私は言語コントローラの変更方法を選択した言語の略語を渡しています。 LanguageControllerで私はこのようなコードを持っています:

public ActionResult Change(string lang) 
    { 
     if (lang != null) 
     { 
      if (User.Identity.IsAuthenticated) 
      { 
       //var user = _userManager.FindByName(User.Identity.Name); 
       //_userManager.AddClaim(user.Id, new Claim("Language", lang)); 
       //var claims = _userManager.GetClaims(user.Id); 

       ////User.RemoveClaimIfExists("Language"); 
       ////var claims = new List<Claim>(); 
       ApplicationDbContext mycontext = new ApplicationDbContext(); 
       UserStore<ApplicationUser> mystore = new UserStore<ApplicationUser>(mycontext); 
       ApplicationUserManager UserMan = new ApplicationUserManager(mystore); 
       //ApplicationUser _user = UserMan.FindById(User.Identity.GetUserId()); 
       UserMan.AddClaim(User.Identity.GetUserId(), new Claim("Language", lang)); 

       //UserMan.RemoveClaim(User.Identity.GetUserId(), User.GetClaim("Language")); 
       //User.AddClaim(lang); 

      } 
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(lang); 
      Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang); 

      HttpCookie cookie = new HttpCookie("Language"); 
      cookie.Value = lang; 
      Response.Cookies.Add(cookie); 

      return Redirect(Request.UrlReferrer.ToString()); 
     } 
     return Redirect(Request.UrlReferrer.ToString()); 
    } 

私はこの機能を実装するためにさまざまな方法を試していました。そして、苦痛の日の後、それは働くようになった。しかし、私はFrankenshtainがAspNetUserClaimsテーブルにクレームを書くための最良の方法であるとは確信していません。これは私の最初の質問です:

1)私はどのように私の主張のコードを改善することができますか?

2つ目の質問は非常に最初の近くにある:

2)どのように私は既存のユーザーの主張を更新することができますか?

そして、私の知識レベルの質問に対する明確な最終的には最後の3分の1である:

3)保存されたクレームの読み方?

設定されたクレームは、次のセッションで読み込まれる必要があります。私はクレームクラスを作成しているので、そのため、そこにこの

public static string GetClaimValue(this IPrincipal currentPrincipal, string key) 
    { 
     var identity = currentPrincipal.Identity as ClaimsIdentity; 
     if (identity == null) 
      return null; 

     var claim = identity.Claims.FirstOrDefault(c => c.Type == key); 
     return claim?.Value; 
    } 

コードを追加し、AccountControllerのログイン方法からそれを呼び出す:あなたは、私はいつもの代わりにキルギスのロシア語を得る推測できたとして

[AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) 
    { 
     if (!ModelState.IsValid) 
     { 
      return View(model); 
     } 

     // This doesn't count login failures towards account lockout 
     // To enable password failures to trigger account lockout, change to shouldLockout: true 
     var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false); 
     switch (result) 
     { 
      case SignInStatus.Success: 
       HttpCookie cookie = new HttpCookie("Language"); 
       string lang = GetClaimValue("Language"); 
       if (lang == null) // language was not selected befor 
        lang = "ru"; 
       Response.Cookies.Add(cookie); 

       Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cookie.Value); 
       Thread.CurrentThread.CurrentUICulture = new CultureInfo(cookie.Value); 
       return RedirectToLocal(returnUrl); 
      case SignInStatus.LockedOut: 
       return View("Lockout"); 
      case SignInStatus.RequiresVerification: 
       return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); 
      case SignInStatus.Failure: 
      default: 
       ModelState.AddModelError("", "Invalid login attempt."); 
       return View(model); 
     } 
    } 

富栄ましたabbr "ky" AspNetUserClaimsテーブルに格納されます。

それはそれです:)私はそれがあまりにも多くのテーブルの会談ではなかったことを願っています。私を助けてください!

答えて

0

あなたのクレームコードを使用しているすべての状況を把握せずに私が答えるのは難しいので、最初の質問はスキップします。ただし、その他のご質問:

2)既存のユーザークレームを更新するにはどうすればよいですか?

あなたは、このようなアプローチを使用することができます保存されたクレームの読み方)

User.AddUpdateClaim("Language", "ru"); 

3:

public static void AddUpdateClaim(this IPrincipal currentPrincipal, string key, string value) 
    { 
     var identity = currentPrincipal.Identity as ClaimsIdentity; 
     if (identity == null) 
      return; 

     // check for existing claim and remove it 
     var existingClaim = identity.FindFirst(key); 
     if (existingClaim != null) 
      identity.RemoveClaim(existingClaim); 

     // add new claim 
     identity.AddClaim(new Claim(key, value)); 
     var authenticationManager = HttpContext.Current.GetOwinContext().Authentication; 
     authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true }); 
    } 

今、あなたは、このような任意のコントローラからそれを使用することができますか?このような

何か:

public static string GetClaimValue(this IPrincipal principal, string type) 
    { 
     var user = principal as ClaimsPrincipal; 
     var claim = user.Claims.FirstOrDefault(x => x.Type == type); 

     if (claim != null) return claim.Value; 

     throw new Exception($"Claim with type {type} not set"); 
    } 

両方の方法が使用可能Controller.Userオブジェクトの拡張-metodsです。

EDIT:あなたのコメントへの応答として、これはあなたが開始するために、クレームアイデンティティを作成することができます方法です。この変更で

var ident = new ClaimsIdentity(
       new[] { 
        new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),    
       }, 
       DefaultAuthenticationTypes.ApplicationCookie); 

//Add default language to claims 
ident.AddClaim(new Claim("Language", "ru")); 

HttpContext.GetOwinContext().Authentication.SignIn(ident); 
+0

ありがとうございます。私はすでにこのコードを試しましたが、理由はありません。それは動作しません。 –

+0

このコードは、var user = currentPrincipalをClaimsPrincipalとして返します。 var claim = user.Claims.FirstOrDefault(x => x.Type == type); if(claim!= null)return claim.Value; それ以外の場合は "uz"を返します。テーブルに格納されている「en」の代わりに常に「uz」を返す –

+0

例として、いくつかの追加コードを追加しました。これは通常、私はあなたが成功した値を追加しているように、彼らがnullの場合まあ、それは、いないよう – MichaelCleverly

0
更新する債権については

// GET: Language 
    public ActionResult Change(string lang) 
    { 
     if(lang != null) 
     { 

      if(User.Identity.IsAuthenticated) 
      { 
       var claims = new List<Claim>(); 

       ApplicationDbContext mycontext = new ApplicationDbContext(); 
       UserStore<ApplicationUser> mystore = new UserStore<ApplicationUser>(mycontext); 
       ApplicationUserManager UserMan = new ApplicationUserManager(mystore); 
       ApplicationUser _user = UserMan.FindById(User.Identity.GetUserId()); 

       var claim = _user.Claims.FirstOrDefault(c => c.ClaimType == "Language"); 

       if (claim != null) // User have Language claim the table 
       { 
        if (claim.ClaimValue != lang) // and chosen language doesn't match it 
        { 
         UserMan.RemoveClaim(User.Identity.GetUserId(), new Claim("Language", claim.ClaimValue)); 
         UserMan.AddClaimAsync(User.Identity.GetUserId(), new Claim("Language", lang)); 
        } 
       } 
       else if(claim == null) 
       { 
        UserMan.AddClaimAsync(User.Identity.GetUserId(), new Claim("Language", lang)); 
       } 

      } 
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(lang); 
      Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang); 

      HttpCookie cookie = new HttpCookie("Language"); 
      cookie.Value = lang; 
      Response.Cookies.Add(cookie); 


      return Redirect(Request.UrlReferrer.ToString()); 
     } 
     return Redirect(Request.UrlReferrer.ToString()); 
    } 

アクション私は実際に主張を読んでいますが、ログイン中にそれを読んでみたい場合、私は次のようなことをします:

[HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) 
    { 
     if (!ModelState.IsValid) 
     { 
      return View(model); 
     } 

     // This doesn't count login failures towards account lockout 
     // To enable password failures to trigger account lockout, change to shouldLockout: true 
     var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false); 
     switch (result) 
     { 
      case SignInStatus.Success: 
       HttpCookie cookie = new HttpCookie("Language"); 
       cookie.Value = "ru"; 
       var user = UserManager.FindByEmail(model.Email); 

        var claim = user.Claims.FirstOrDefault(c => c.ClaimType == "Language"); 

        if (claim == null) 
        { 
         cookie.Value = Thread.CurrentThread.CurrentCulture.Name.ToString(); // interface language used befor logining in 
        } 
        else 
         cookie.Value = claim.ClaimValue; // Language from the UserClaim 

       Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cookie.Value); 
       Thread.CurrentThread.CurrentUICulture = new CultureInfo(cookie.Value); 
       Response.Cookies.Add(cookie); 
       return RedirectToLocal(returnUrl); 
      case SignInStatus.LockedOut: 
       return View("Lockout"); 
      case SignInStatus.RequiresVerification: 
       return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); 
      case SignInStatus.Failure: 
      default: 
       ModelState.AddModelError("", "Invalid login attempt."); 
       return View(model); 
     } 
    } 
関連する問題