title: Async load server side html into a page (server-side) using ViewComponents
body: <p>I am trying to attempt something which I am not sure is even possible using basic ASP.NET Core MVC and ViewComponents that comes with it.</p>
  
  <p>I am quite new to async await and still haven't completely grasped the concept yet. Plus I am also new to ASP.NET Core and the new ViewComponents features. So please bear with me trying to explain what I am trying to achieve.</p>
  
  <p><strong>The main goal here is to inject HTML from external endpoints into an ASP.NET Core MVC site asynchronously.</strong></p>
  
  <p>Lets say I have the following end points that serve plain snippets of HTML:</p>
  
  <pre><code>http://fragments.mydomain.com/component1 --&gt; Returns &lt;div&gt;Component 1&lt;/div&gt; in 1000ms
  http://fragments.mydomain.com/component2 --&gt; Returns &lt;div&gt;Component 2&lt;/div&gt; in 500ms
  </code></pre>
  
  <p>Note that the first one takes <strong>1000ms</strong> to respond and the second one takes <strong>500ms</strong> to respond.</p>
  
  <p>Now, I'd like to inject the response of these end points in various parts of an ASP.NET Core MVC. Following is how I am trying to achieve this.</p>
  
  <p>First, I created a ViewComponents that sucks in the HTML from the endpoints, for example:</p>
  
  <pre><code>public class PieceViewComponent : ViewComponent
  {
      public async Task&lt;IHtmlContent&gt; InvokeAsync(string pieceUrl)
      {
          var contentString = "";
          try
          {
              using (var client = new HttpClient())
              {
                  // Make the call to the html end point
                  contentString = await client.GetStringAsync(url);
  
                  // Return the Piece to the caller
                  return new HtmlString(contentString);
              }
  
          }
          catch (Exception)
          {
              // TODO: Handle, log exceptions
              return new HtmlString("");
          }
      }
  }
  </code></pre>
  
  <p>Then, I call the view component(s) in a View, for example <strong>Views/Home/Index.cshtml</strong></p>
  
  <pre><code>&lt;p&gt;Render Component 1 here:&lt;p&gt;
  @await Component.InvokeAsync("Piece", new {pieceUrl="http://fragments.mydomain.com/component1"});
  
  &lt;p&gt;Render Component 2 here:&lt;p&gt;
  @await Component.InvokeAsync("Piece", new {pieceUrl="http://fragments.mydomain.com/component2"});
  </code></pre>
  
  <p>As you'd expect, the result when running the above is:</p>
  
  <pre><code>&lt;p&gt;Render Component 1 here:&lt;p&gt;
  &lt;div&gt;Component 1&lt;/div&gt;
  
  &lt;p&gt;Render Component 2 here:&lt;p&gt;
  &lt;div&gt;Component 2&lt;/div&gt;
  </code></pre>
  
  <p>...but, the result was built in a synchronous fashion, it took 1500ms to return a result, 1000ms + 500ms (endpoint1 + endpoint2). I want it to return in 1000ms (the time of the slowest endpoint, in this case endpoint1</p>
  
  <p>So I tried the following changes in <strong>Views/Home/Index.cshtml</strong>:</p>
  
  <pre><code>@{
      var piece1Task = Component.InvokeAsync("Piece", new {pieceUrl="http://fragments.mydomain.com/component1"});
      var piece2Task = Component.InvokeAsync("Piece", new {pieceUrl="http://fragments.mydomain.com/component2"});
  }
  
  &lt;p&gt;Render Component 1 here:&lt;p&gt;
  @await piece1Task
  
  &lt;p&gt;Render Component 2 here:&lt;p&gt;
  @await piece1Task
  </code></pre>
  
  <p><strong>GREAT!</strong> The result returns in 1000ms, the desired time I want it to return in.</p>
  
  <p>.... but, this only works when all your calls to ComponentInvokeAsync() are in the same View File. When trying to sprinkle your calls around various Views within your application you end up with synchronous result again. For example:</p>
  
  <p><strong>Views/Home/Index.cshtml:</strong></p>
  
  <pre><code>@{
      var piece1Task = Component.InvokeAsync("Piece", new {pieceUrl="http://fragments.mydomain.com/component1"});
  }
  &lt;p&gt;Render Component 1 here:&lt;p&gt;
  @await piece1Task
  </code></pre>
  
  <p><strong>Views/Shared/_Layout.cshtml:</strong></p>
  
  <pre><code>@{
      var piece2Task = Component.InvokeAsync("Piece", new {pieceUrl="http://fragments.mydomain.com/component2"});
  }
  
  &lt;html&gt;
      ....
  
      &lt;p&gt;Render Component 2 here:&lt;p&gt;
      @await piece1Task
  
      @RenderBody()
  
      ....
  &lt;/html&gt;
  </code></pre>
  
  <p>Again, as you'd expect the result would look like this:</p>
  
  <pre><code>&lt;html&gt;
      ...
  
      &lt;p&gt;Render Component 2 here:&lt;p&gt;
      &lt;div&gt;Component 2&lt;/div&gt;
  
      &lt;p&gt;Render Component 1 here:&lt;p&gt;
      &lt;div&gt;Component 1&lt;/div&gt;
  
      ...
  &lt;/html&gt;
  </code></pre>
  
  <p>Unfortunately, the above returns in 1500ms.</p>
  
  <p>I might be tackling this problem in completely the wrong way, but it would be extremely handy working with ViewComponents to asynchronously pull in external pieces of HTML into your Website application like I have above (especially in todays Service oriented world). Basically, the response time should be (or there about) the time of the slowest external end point.</p>
  
  <p>If I could get the above to work as desired, we could probably extend it further to TagHelpers and have something like this:</p>
  
  <pre><code>&lt;piece url="http://fragment.mydomain.com/component1" paramters="..." client-async="true" /&gt;
  </code></pre>
  
  <p>... wouldn't that be nice.</p>
  
  <p>Where, for example, when client-async = true, load that piece of html asynchronously on the client instead of the server. </p>
  
  <p>Has anybody ever tried to do this or something similar using ASP.NET MVC Core + ViewComponents, or am I trying to be too ambitious.</p>
  
  <p>Maybe this has already been achieved by somebody else?</p>
  
  <p>Thanks in advance, and I am really sorry about the long post, but I couldn't find a shorter way to explain myself</p>