title: ASP.NET HttpContext Cache removes right after insertion
body: <p>I have an ASP.NET 4 web-service.<br>
  It has an <code>ImportModule</code> action in a <code>ModuleController</code> controller. </p>
  
  <p>That's how it works:  </p>
  
  <ol>
  <li>The user uploads a module as a CSV-file.  </li>
  <li>This file is being read using <code>HttpPostedFileBase.InputStream</code> and custom CSV-reading class.  </li>
  <li>This file is being transformed to a C# object according to some rules and validations. If a file is valid, then it transforms to C# object, stores in a Cache with unique GUID name and a user is redirected to <code>CompleteImportModule</code> action.</li>
  <li>User checks if data is correct and he confirms uploading.</li>
  </ol>
  
  <p>Long story short, there is a code which tells you more:<br>
  <code>ImportModule</code> action.</p>
  
  <pre><code>public ActionResult ImportModule(HttpPostedFileBase file)
  {
      if (!ModelState.IsValid) 
      {
          return RedirectToAction("Index");
      }
  
      ModuleQuestion[] questions;
      ModuleInfo moduleInfo;
      string uploadId = Guid.NewGuid().ToString();
  
      // It is my custom CSV-reader and it works. Values are assigned
      FormDataCsvReader csvReader = new FormDataCsvReader(file.InputStream);
      if (!csvReader.Process(out questions, out moduleInfo))
      {
          // File is invalid
          return RedirectToAction("Index");
      }
  
      ViewBag.UploadId = uploadId;
      ViewBag.ModuleInfo = moduleInfo;
      ViewBag.Questions = questions;
  
      HttpContext.Cache.Add("UploadModule_" + uploadId,
          new Tuple&lt;ModuleInfo, ModuleQuestion[]&gt;(moduleInfo, questions),
          null,
          Cache.NoAbsoluteExpiration,
          TimeSpan.FromMinutes(30),
          CacheItemPriority.NotRemovable,
          (k, v, r) =&gt; 
          {
              LoggingFactory.GetLogger().Debug("Removed from cache: {0}. Reason: {1}", k, r);
          });     
  
      return View();   
  }
  </code></pre>
  
  <p>In View <code>ImportModule</code>:</p>
  
  <pre><code>// Output data from ViewBag.ModuleInfo and ViewBag.Questions
  
  &lt;form method="POST" action="@Url.Action("CompleteImportModule")"&gt;
      &lt;input type="hidden" name="uploadId" value="@ViewBag.UploadId"/&gt;
      &lt;input type="submit" value="Send"&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p><code>CompleteImportModule</code> action:</p>
  
  <pre><code>[HttpPost]
  public ActionResult CompleteImportModule(string uploadId)
  {
      var item = HttpContext.Cache["UploadModule_" + uploadId];
      if (item == null) RedirectToAction("Index");
      // upload module 
      HttpContext.Cache.Remove("UploadModule_" + uploadId);
      return RedirectToAction("Index");
  }
  </code></pre>
  
  <p>However, I met some problems. I cannot upload the module because the value is removed from a Cache right after being inserted. It is stored only for a second:</p>
  
  <pre><code>DEBUG 2015-06-22 15:00:18,696 thread 85: Added to cache:
  UploadModule_c843077d-21d0-4e9f-9e5e-3df82da4bac8
  
  DEBUG 2015-06-22 15:00:19,935 thread 48: Removed from cache:
  UploadModule_c843077d-21d0-4e9f-9e5e-3df82da4bac8. Reason: Removed
  </code></pre>
  
  <p>The <code>reason</code> is "Removed" meaning that it is not expired and IIS hasn't removed it due to optimization but it looks like I removed is myself. 
  I am pretty sure that I am even not accessing this cache record before <code>CompleteImportModule</code>.</p>
  
  <p>I have tried putting <code>new StackTrace().ToString()</code> in a <code>CacheItemRemovedCallback</code>. That's it, if it can help somehow:   </p>
  
  <pre><code>at CPMAdministrator.Controllers.ModulesReferenceController.&lt;ImportModule&gt;b__9(String key, Object value, CacheItemRemovedReason reason)
     at System.Web.Caching.CacheEntry.CallCacheItemRemovedCallback(CacheItemRemovedCallback callback, CacheItemRemovedReason reason)
     at System.Web.Caching.CacheEntry.Close(CacheItemRemovedReason reason)
     at System.Web.Caching.CacheSingle.UpdateCache(CacheKey cacheKey, CacheEntry newEntry, Boolean replace, CacheItemRemovedReason removedReason, Object&amp; valueOld)
     at System.Web.Caching.CacheSingle.Dispose(Boolean disposing)
     at System.Web.Caching.CacheMultiple.Dispose(Boolean disposing)
     at System.Web.HttpRuntime.Dispose()
     at System.Web.HttpRuntime.ReleaseResourcesAndUnloadAppDomain(Object state)
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
     at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
     at System.Threading.ThreadPoolWorkQueue.Dispatch()
  </code></pre>
  
  <p>Why is it happening? Is it sort of IIS pool recycling? How can I ensure that the file is not being removed? Or how can I effictively store this data another way?</p>