none
【C# WPF MVVM】Thread.CurrentPrincipalが途中で破棄されてしまう RRS feed

  • 質問

  • C# WPF MVVM(Prism)で、Thread.CurrentPrincipalを使用してログイン処理を作成していますが、

    MenuとMainへ移動したタイミングでは、Thread.CurrentPrincipalオブジェクトの情報は残っているのですが、(移動先のViewModelで使用できる)

    Menuから別のViewを呼び出した時にその情報が破棄されてしまって、使えなくなります。(移動先のViewModelで使用できない)

    どなたかご教授お願いします。

    TestViewModel.cs

    namespace Main.ViewModels { public class TestViewModel : BindableBase { IUnityContainer _container; private readonly IRegionManager _regionManager; public TestViewModel(IUnityContainer container, IRegionManager regionManager) { _container = container; _regionManager = regionManager; LoginCommand = new DelegateCommand(executeLogin);
    } public DelegateCommand LoginCommand { get; private set; }
    public void executeLogin() {
    // 実際はDB問い合わせで一致していればログイン string name = "test"; string[] roleArray = { "SA" }; try { Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(name), roleArray); Console.WriteLine("Name: {0}\nIsAuthenticated: {1}" + "\nAuthenticationType: {2}", Thread.CurrentPrincipal.Identity.Name, Thread.CurrentPrincipal.Identity.IsAuthenticated, Thread.CurrentPrincipal.Identity.AuthenticationType); _regionManager.RequestNavigate("MenuRegion", "Menu"); _regionManager.RequestNavigate("ContentRegion", "Main"); } catch (SecurityException secureException) { Console.WriteLine("{0}: Permission to set Principal is denied.", secureException.GetType().Name); } } } }

    Main, ViewのViewModel(例としてMainのみ)

    namespace Main.ViewModels { public class MainViewModel : BindableBase { IUnityContainer _container; private readonly IRegionManager _regionManager; public MainViewModel(IUnityContainer container, IRegionManager regionManager) { _container = container; _regionManager = regionManager; string LoginUserName = Thread.CurrentPrincipal.Identity.Name; // test       bool isAuth = Thread.CurrentPrincipal.Identity.IsAuthenticated; // true bool isInRole = Thread.CurrentPrincipal.IsInRole("SA");  // true } }

    別のViewModelのコンストラクタ (Menu, Main以外の移動先)

    namespace Main.ViewModels { public class EtcViewModel : BindableBase { IUnityContainer _container; private readonly IRegionManager _regionManager; public EtcViewModel(IUnityContainer container, IRegionManager regionManager) { _container = container; _regionManager = regionManager;       // Thread.CurrentPrincipalが破棄されてしまっている
    string LoginUserName = Thread.CurrentPrincipal.Identity.Name; // 空になる       bool isAuth = Thread.CurrentPrincipal.Identity.IsAuthenticated; // falseになる bool isInRole = Thread.CurrentPrincipal.IsInRole("SA");  // falseになる } }



    • 編集済み yuchan01 2018年8月17日 8:10
    2018年8月9日 4:02

回答

  • 対策としては、初回の取得処理で得たデータを、自前で準備したプロパティにバックアップしておいて自前管理するか、
    毎回以下をおこなって再設定するか、ですかね・・・。
    Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(name), roleArray); 

    _regionManager.RequestNavigate() がポイントだと思うのですが、Github 見てもよく分からずorz
    (カレントスレッド絡みでごにょごにょしているのかなと思ったのですが、怪しそうな個所は見当たりませんでした)
    https://github.com/PrismLibrary/Prism/blob/master/Source/Wpf/Prism.Wpf/Regions/RegionManager.cs
    • 回答としてマーク yuchan01 2018年8月17日 7:58
    2018年8月13日 8:05

すべての返信

  • 対策としては、初回の取得処理で得たデータを、自前で準備したプロパティにバックアップしておいて自前管理するか、
    毎回以下をおこなって再設定するか、ですかね・・・。
    Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(name), roleArray); 

    _regionManager.RequestNavigate() がポイントだと思うのですが、Github 見てもよく分からずorz
    (カレントスレッド絡みでごにょごにょしているのかなと思ったのですが、怪しそうな個所は見当たりませんでした)
    https://github.com/PrismLibrary/Prism/blob/master/Source/Wpf/Prism.Wpf/Regions/RegionManager.cs
    • 回答としてマーク yuchan01 2018年8月17日 7:58
    2018年8月13日 8:05
  • ご回答ありがとうございます。

    自前でバックアップするしかなさそうですね。

    MainWindowViewModelはアプリケーション終了まで破棄されないので、

    一旦、LoginViewModelから MainWindowViewModelにstaticプロパティでバックアップしました。
    ※この実装が良いかはわからないですが。


    LoginViewModel.cs

    namespace Main.ViewModels {
        public class TestViewModel : BindableBase {
            
            IUnityContainer _container;
            private readonly IRegionManager _regionManager;
    
            public TestViewModel(IUnityContainer container, IRegionManager regionManager) {
                _container = container;
                _regionManager = regionManager;       
                LoginCommand = new DelegateCommand(executeLogin);
            }
            
            public DelegateCommand LoginCommand { get; private set; }
    
            public void executeLogin() {
                // 実際はDB問い合わせで一致していればログイン
                string name = "test";
                string[] roleArray = { "SA" };
    
                try {
                    MainWindowViewModel.MyPrincipal = new GenericPrincipal(new GenericIdentity(name), roleArray);
    
                    _regionManager.RequestNavigate("MenuRegion", "Menu");
                    _regionManager.RequestNavigate("ContentRegion", "Main");
    
                } catch (SecurityException secureException) {
                    Console.WriteLine("{0}: Permission to set Principal is denied.", secureException.GetType().Name);
                }
            }
        }
    }


    MainWindowViewModel.cs

    namespace Main.ViewModels {
    public class MainWindowViewModel : BindableBase { // ・・・省略・・・ public static IPrincipal MyPrincipal { get; set; }
    } }


    • 回答としてマーク yuchan01 2018年8月17日 7:58
    • 回答としてマークされていない yuchan01 2018年8月17日 7:58
    • 編集済み yuchan01 2018年8月17日 8:10
    2018年8月17日 7:52