title: Abstract away async calls to IMemoryCache in API
body: <p>I have been using actions that look like Example 1 to async cache json results for my .NET Core API. <code>MemoryCache</code> is an instance of <code>IMemoryCache</code>.</p>
  
  <p><strong>Example 1 (works as expected):</strong></p>
  
  <pre><code>[HttpGet]
  public async Task&lt;IActionResult&gt; MyAction() =&gt;
      Json(await MemoryCache.GetOrCreateAsync(
          "MyController_MyAction", 
          entry =&gt; myService.GetAllAsync()
      ));
  </code></pre>
  
  <p>The calls to <code>Json()</code> and <code>MemoryCache.GetOrCreate()</code> are duplicated in many of my actions. In my real app, there are even more duplicated implementation details such as setting the <code>AbsoluteExpirationRelativeToNow</code> value and returning <code>NotFound()</code> for nulls. I would like to abstract all of this away into a shared method so that each action passes only its unique details to the call of the shared method.</p>
  
  <p>In order to do this, I extracted a variable for each of the two variables that are in my actions. e.g.:</p>
  
  <p><strong>Example 2 (cache neither updated nor retrieved from):</strong></p>
  
  <pre><code>[HttpGet]
  public async Task&lt;IActionResult&gt; MyAction()
  {
      var task = myService.GetAllAsync();
      const string cacheKey = "MyController_MyAction";
      return Json(await MemoryCache.GetOrCreateAsync(cacheKey, entry =&gt; task));
  }
  </code></pre>
  
  <p>The next step would be to extract a shared method <code>Get()</code> like:</p>
  
  <p><strong>Example 3 (doesn't work because Example 2 doesn't work):</strong></p>
  
  <pre><code>[HttpGet]
  public async Task&lt;IActionResult&gt; MyAction()
  {
      var task = myService.GetAllAsync();
      const string cacheKey = "MyController_MyAction";
      return await Get(task, cacheKey);
  }
  
  protected async Task&lt;IActionResult&gt; Get(Task&lt;T&gt; task, string cacheKey =&gt;
      return Json(await MemoryCache.GetOrCreateAsync(cacheKey, entry =&gt; task));
  </code></pre>
  
  <p>Example 1 successfully retrieves subsequent results from the cache. Example 2, however, finds <code>null</code> in the cache on subsequent requests and retrieves the data anew each time (as verified by temp debug <code>TryGetValue()</code> statements as well as monitoring the underlying SQL queries hitting my database).</p>
  
  <p>To me, Example 1 and Example 2 should be identical. However, maybe my understanding of async/await and Tasks is lacking (very likely).</p>
  
  <p>How can I abstract away the duplicated implementation details (such as <code>Json()</code> and <code>MemoryCache.GetOrCreate()</code> calls) from my actions while still successfully updating and retrieving from the <code>IMemoryCache</code> in an async manner?</p>