title: How to use async/await in webforms page and library code without getting Thread Abort error on Response.Redirect
body: <p>We have a well established ASP.NET webforms site (not project, not MVC, not .NET Core) based on the .NET Framework 4.8. We would like to start integrating some REST based services which quickly gets into <code>HttpClient</code> and <code>async</code> based methods.</p>
  <p>I have a test page that appears to &quot;work&quot; but I am concerned the pattern is not set up right based on a &quot;thread abort error&quot; that is being caught.</p>
  <p>The idea is, there is a webforms page that has a button on it; the user clicks the button, the code-behind for that button ends up making a REST call to an endpoint to get back some data. That all works.</p>
  <p>But, we'd like to shuffle the user to another page at the end of that, so a &quot;redirect&quot; is called. And that ends up causing the &quot;Thread was being aborted&quot; exception.</p>
  <p>Here is a fairly representative bit of code:</p>
  <pre><code>// test class library
  namespace TestLibrary
  {
      public class TestClient
      {
          .
          .
          .
          public async Task&lt;SomeResponse&gt; DoAsyncWork()
          {
              // actual code happens to use Flurl which is a light wrapper around HttpClient
  
              string baseUrl = @&quot;https://api.somewhere.com/v1/testendpoint/&quot;;
              string somedata = &quot;some test data&quot;;
  
              var response = await baseUrl
                                       .WithHeader(&quot;Content-Type&quot;, &quot;application/json&quot;)
                                       .PostStringAsync(somedata)
                                       .ReceiveJson&lt;SomeResponse&gt;()
                                       .ConfigureAwait(false);
  
              return response;
          }
      }
      .
      .
      .
  }
  </code></pre>
  <p>.
  .
  .</p>
  <pre><code>// in ASP.NET webforms site 
  // .NET Framework 4.8
  // Page directive includes Async=&quot;true&quot;    
  protected async void btnTest_Click(object sender, EventArgs e)
  {
      TestClient client = new TestClient();
      SomeResponse response = await client.DoAsyncWork();
  
      // do something with the response (update database, whatever)
      // ... all working so far ...
  
      // now go to another page 
      // (for example, for extended messaging or another &quot;step&quot; in the process)
  
      // this &quot;works&quot; in that the user is redirected to the right page, but...
      // &quot;Thread was being aborted&quot; error is caught and logged (global exception handler implemented)
       Response.Redirect(&quot;somepage.aspx&quot;);  
  
  }
  .
  .
  .
  </code></pre>
  <p>I realize I could ignore the error (or perhaps rework it so there is no redirect), but what I'm wondering is if there is a &quot;right&quot; way to do this.</p>
  <p>I should mention that I have tried passing in a boolean (false) to the Redirect call and that does circumvent the exception (although that does introduce other potential &quot;gotchas&quot;...).</p>
  <p>I'm just &quot;concerned&quot; that reason we're getting a Thread Abort error here (and not on other pages that don't do async) is that there's an &quot;uncompleted&quot; task of some sort.  Or that I'm not &quot;waiting&quot; in the right way...</p>
  <p>I have read many articles by Stephen Cleary, but if you'll pardon the pun, I am not very clear on structuring up async/await code in ASP.NET webforms ... yet!</p>