Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Azure Active Directory question

Azure Active Directory question

Scheduled Pinned Locked Moved C#
questioncsharpasp-netwinformsdesign
10 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • pkfoxP Offline
    pkfoxP Offline
    pkfox
    wrote on last edited by
    #1

    Hi all I have this method in a class which tries to get an access token from Azure Active Directory - it works if I use it in a Net Core app but hangs forever when I try to use it in a Winforms app

    private async Task GetAccessToken()
    {
    // Utils.GetAppConfigSetting just reads keys in App.config
    string Instance = Utils.GetAppConfigSetting("Instance");
    string TenantID = Utils.GetAppConfigSetting("TenantID");
    string ClientID = Utils.GetAppConfigSetting("ClientID");
    string ClientSecret = Utils.GetAppConfigSetting("ClientSecret");
    string BaseAddress = Utils.GetAppConfigSetting("BaseAddress");
    string ResourceID = Utils.GetAppConfigSetting("ResourceID");
    string APIServer = Utils.GetAppConfigSetting("APIServer");
    string Authority = String.Format(CultureInfo.InvariantCulture,Instance, TenantID);

            this.App = ConfidentialClientApplicationBuilder.Create(ClientID)
                .WithClientSecret(ClientSecret)
                .WithAuthority(new Uri(Authority))
                .Build();
    
            this.ResourceIds = new string\[\] { ResourceID };
    
            // this is where it hangs !!
            this.Result = await this.App.AcquireTokenForClient(this.ResourceIds).ExecuteAsync();
            this.AccessToken = this.Result.AccessToken;
           
            // this.Client is a RestSharp client
            this.Client.Authenticator = new JwtAuthenticator(this.AccessToken);
        }
    

    // I call it with this code

    this.GetAccessToken().GetAwaiter().GetResult();

    there is no error it just hangs - any ideas ? Edit It must be the UI thread in Winforms as I just tried the same code in a Console App and it worked perfectly

    "We can't stop here - this is bat country" - Hunter S Thompson - RIP

    Richard DeemingR 1 Reply Last reply
    0
    • pkfoxP pkfox

      Hi all I have this method in a class which tries to get an access token from Azure Active Directory - it works if I use it in a Net Core app but hangs forever when I try to use it in a Winforms app

      private async Task GetAccessToken()
      {
      // Utils.GetAppConfigSetting just reads keys in App.config
      string Instance = Utils.GetAppConfigSetting("Instance");
      string TenantID = Utils.GetAppConfigSetting("TenantID");
      string ClientID = Utils.GetAppConfigSetting("ClientID");
      string ClientSecret = Utils.GetAppConfigSetting("ClientSecret");
      string BaseAddress = Utils.GetAppConfigSetting("BaseAddress");
      string ResourceID = Utils.GetAppConfigSetting("ResourceID");
      string APIServer = Utils.GetAppConfigSetting("APIServer");
      string Authority = String.Format(CultureInfo.InvariantCulture,Instance, TenantID);

              this.App = ConfidentialClientApplicationBuilder.Create(ClientID)
                  .WithClientSecret(ClientSecret)
                  .WithAuthority(new Uri(Authority))
                  .Build();
      
              this.ResourceIds = new string\[\] { ResourceID };
      
              // this is where it hangs !!
              this.Result = await this.App.AcquireTokenForClient(this.ResourceIds).ExecuteAsync();
              this.AccessToken = this.Result.AccessToken;
             
              // this.Client is a RestSharp client
              this.Client.Authenticator = new JwtAuthenticator(this.AccessToken);
          }
      

      // I call it with this code

      this.GetAccessToken().GetAwaiter().GetResult();

      there is no error it just hangs - any ideas ? Edit It must be the UI thread in Winforms as I just tried the same code in a Console App and it worked perfectly

      "We can't stop here - this is bat country" - Hunter S Thompson - RIP

      Richard DeemingR Offline
      Richard DeemingR Offline
      Richard Deeming
      wrote on last edited by
      #2

      pkfox wrote:

      It must be the UI thread in Winforms

      Correct. Your async method tries to return to the current "execution context" after the await. In a WinForms app, when the async method was called from the UI thread, it tries to return to the UI thread. But you've blocked the UI thread by trying to execute the async method synchronously:

      this.GetAccessToken().GetAwaiter().GetResult(); // Blocks the UI thread

      Therefore, the async method can never complete. If you're not accessing the UI from your GetAccessToken method, you can add .ConfigureAwait(false) to your ExecuteAsync call, so that the rest of the method can complete on a thread-pool thread:

      this.Result = await this.App.AcquireTokenForClient(this.ResourceIds).ExecuteAsync().ConfigureAwait(false);

      Otherwise, you'll need to find a way to avoid blocking the UI thread. You'd need to make the calling method async. However, you want to avoid async void methods[^]. A simple solution is to move the code into a task-returning async method, and assign the returned task to a "discard" variable to avoid the compiler warning. Old code, don't use:

      private void ButtonClick(object sender, EventArgs e)
      {
      // Some code...
      this.GetAccessToken().GetAwaiter().GetResult();
      // Some more code...
      }

      Bad fix, don't use:

      private async void ButtonClick(object sender, EventArgs e)
      {
      // Some code...
      await this.GetAccessToken();
      // Some more code
      }

      Better fix:

      private void ButtonClick(object sender, EventArgs e)
      {
      _ = SomeMethodAsync();
      }

      private async Task SomeMethodAsync()
      {
      // Some code...
      await this.GetAccessToken();
      // Some more code
      }

      ConfigureAwait FAQ | .NET Blog[^]


      "These people looked deep within my soul and as

      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

      pkfoxP 2 Replies Last reply
      0
      • Richard DeemingR Richard Deeming

        pkfox wrote:

        It must be the UI thread in Winforms

        Correct. Your async method tries to return to the current "execution context" after the await. In a WinForms app, when the async method was called from the UI thread, it tries to return to the UI thread. But you've blocked the UI thread by trying to execute the async method synchronously:

        this.GetAccessToken().GetAwaiter().GetResult(); // Blocks the UI thread

        Therefore, the async method can never complete. If you're not accessing the UI from your GetAccessToken method, you can add .ConfigureAwait(false) to your ExecuteAsync call, so that the rest of the method can complete on a thread-pool thread:

        this.Result = await this.App.AcquireTokenForClient(this.ResourceIds).ExecuteAsync().ConfigureAwait(false);

        Otherwise, you'll need to find a way to avoid blocking the UI thread. You'd need to make the calling method async. However, you want to avoid async void methods[^]. A simple solution is to move the code into a task-returning async method, and assign the returned task to a "discard" variable to avoid the compiler warning. Old code, don't use:

        private void ButtonClick(object sender, EventArgs e)
        {
        // Some code...
        this.GetAccessToken().GetAwaiter().GetResult();
        // Some more code...
        }

        Bad fix, don't use:

        private async void ButtonClick(object sender, EventArgs e)
        {
        // Some code...
        await this.GetAccessToken();
        // Some more code
        }

        Better fix:

        private void ButtonClick(object sender, EventArgs e)
        {
        _ = SomeMethodAsync();
        }

        private async Task SomeMethodAsync()
        {
        // Some code...
        await this.GetAccessToken();
        // Some more code
        }

        ConfigureAwait FAQ | .NET Blog[^]


        "These people looked deep within my soul and as

        pkfoxP Offline
        pkfoxP Offline
        pkfox
        wrote on last edited by
        #3

        Thanks Richard should I leave the code as is in GetAccessToken() ? I got around it by using a BackGroundWorker but I think maybe your way is better

        "We can't stop here - this is bat country" - Hunter S Thompson - RIP

        Richard DeemingR 1 Reply Last reply
        0
        • pkfoxP pkfox

          Thanks Richard should I leave the code as is in GetAccessToken() ? I got around it by using a BackGroundWorker but I think maybe your way is better

          "We can't stop here - this is bat country" - Hunter S Thompson - RIP

          Richard DeemingR Offline
          Richard DeemingR Offline
          Richard Deeming
          wrote on last edited by
          #4

          If you're moving the code to a task-returning async method, and getting rid of the .GetAwaiter().GetResult() call in favour of awaiting the operation, then the GetAccessToken code should be fine.


          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

          "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

          pkfoxP 1 Reply Last reply
          0
          • Richard DeemingR Richard Deeming

            If you're moving the code to a task-returning async method, and getting rid of the .GetAwaiter().GetResult() call in favour of awaiting the operation, then the GetAccessToken code should be fine.


            "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

            pkfoxP Offline
            pkfoxP Offline
            pkfox
            wrote on last edited by
            #5

            How will I know when the job has finished ?

            "We can't stop here - this is bat country" - Hunter S Thompson - RIP

            Richard DeemingR 1 Reply Last reply
            0
            • pkfoxP pkfox

              How will I know when the job has finished ?

              "We can't stop here - this is bat country" - Hunter S Thompson - RIP

              Richard DeemingR Offline
              Richard DeemingR Offline
              Richard Deeming
              wrote on last edited by
              #6

              That depends what you're trying to do. If you just want to run some code immediately after GetAccessToken has finished, you can put it in the new async method after the await this.GetAccessToken(); line.


              "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

              "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

              pkfoxP 1 Reply Last reply
              0
              • Richard DeemingR Richard Deeming

                That depends what you're trying to do. If you just want to run some code immediately after GetAccessToken has finished, you can put it in the new async method after the await this.GetAccessToken(); line.


                "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                pkfoxP Offline
                pkfoxP Offline
                pkfox
                wrote on last edited by
                #7

                Except GetAccessToken() is in a separate class from the form

                "We can't stop here - this is bat country" - Hunter S Thompson - RIP

                Richard DeemingR 1 Reply Last reply
                0
                • Richard DeemingR Richard Deeming

                  pkfox wrote:

                  It must be the UI thread in Winforms

                  Correct. Your async method tries to return to the current "execution context" after the await. In a WinForms app, when the async method was called from the UI thread, it tries to return to the UI thread. But you've blocked the UI thread by trying to execute the async method synchronously:

                  this.GetAccessToken().GetAwaiter().GetResult(); // Blocks the UI thread

                  Therefore, the async method can never complete. If you're not accessing the UI from your GetAccessToken method, you can add .ConfigureAwait(false) to your ExecuteAsync call, so that the rest of the method can complete on a thread-pool thread:

                  this.Result = await this.App.AcquireTokenForClient(this.ResourceIds).ExecuteAsync().ConfigureAwait(false);

                  Otherwise, you'll need to find a way to avoid blocking the UI thread. You'd need to make the calling method async. However, you want to avoid async void methods[^]. A simple solution is to move the code into a task-returning async method, and assign the returned task to a "discard" variable to avoid the compiler warning. Old code, don't use:

                  private void ButtonClick(object sender, EventArgs e)
                  {
                  // Some code...
                  this.GetAccessToken().GetAwaiter().GetResult();
                  // Some more code...
                  }

                  Bad fix, don't use:

                  private async void ButtonClick(object sender, EventArgs e)
                  {
                  // Some code...
                  await this.GetAccessToken();
                  // Some more code
                  }

                  Better fix:

                  private void ButtonClick(object sender, EventArgs e)
                  {
                  _ = SomeMethodAsync();
                  }

                  private async Task SomeMethodAsync()
                  {
                  // Some code...
                  await this.GetAccessToken();
                  // Some more code
                  }

                  ConfigureAwait FAQ | .NET Blog[^]


                  "These people looked deep within my soul and as

                  pkfoxP Offline
                  pkfoxP Offline
                  pkfox
                  wrote on last edited by
                  #8

                  Hi Richard , thanks for the link lots of good stuff in there - I understand it a lot more now

                  "We can't stop here - this is bat country" - Hunter S Thompson - RIP

                  1 Reply Last reply
                  0
                  • pkfoxP pkfox

                    Except GetAccessToken() is in a separate class from the form

                    "We can't stop here - this is bat country" - Hunter S Thompson - RIP

                    Richard DeemingR Offline
                    Richard DeemingR Offline
                    Richard Deeming
                    wrote on last edited by
                    #9

                    That doesn't matter. You have a task-returning async method which calls it, and put any code you need to run after it's returned after the await. If you need to run code in the form after the async method in another class returns, you also use a task-returning async method, and put the code after the await.

                    class SomeClass
                    {
                    private async Task GetAccessToken() { ... }

                    public async Task DoSomething()
                    {
                        // Code to run in this class before getting the access token here...
                        
                        await GetAccessToken();
                        
                        // Code to run in this class after getting the access token here...
                    }
                    

                    }

                    class YourForm
                    {
                    private SomeClass _someClass;

                    private void FormLoad(object sender, EventArgs e)
                    {
                        \_someClass = new SomeClass();
                        \_ = DoSomethingInTheForm();
                    }
                    
                    private async Task DoSomethingInTheForm()
                    {
                        // Code to run in the form before getting the access token here...
                        
                        await \_someClass.DoSomething();
                        
                        // Code to run in the form after getting the access token here...
                    }
                    

                    }


                    "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                    "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                    pkfoxP 1 Reply Last reply
                    0
                    • Richard DeemingR Richard Deeming

                      That doesn't matter. You have a task-returning async method which calls it, and put any code you need to run after it's returned after the await. If you need to run code in the form after the async method in another class returns, you also use a task-returning async method, and put the code after the await.

                      class SomeClass
                      {
                      private async Task GetAccessToken() { ... }

                      public async Task DoSomething()
                      {
                          // Code to run in this class before getting the access token here...
                          
                          await GetAccessToken();
                          
                          // Code to run in this class after getting the access token here...
                      }
                      

                      }

                      class YourForm
                      {
                      private SomeClass _someClass;

                      private void FormLoad(object sender, EventArgs e)
                      {
                          \_someClass = new SomeClass();
                          \_ = DoSomethingInTheForm();
                      }
                      
                      private async Task DoSomethingInTheForm()
                      {
                          // Code to run in the form before getting the access token here...
                          
                          await \_someClass.DoSomething();
                          
                          // Code to run in the form after getting the access token here...
                      }
                      

                      }


                      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                      pkfoxP Offline
                      pkfoxP Offline
                      pkfox
                      wrote on last edited by
                      #10

                      Thanks Richard that's pretty much what I've ended up with - brilliant article in the link you posted

                      "We can't stop here - this is bat country" - Hunter S Thompson - RIP

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups