ASP.NET HttpContext Cache在插入后立即删除

我有一个ASP.NET 4 Web服务。
它在ImportModule控制器中有一个ImportModule操作。

它是如何工作的:

  1. 用户将模块上载为CSV文件。
  2. 正在使用HttpPostedFileBase.InputStream和自定义CSV读取类读取此文件。
  3. 根据一些规则和validation,此文件正在转换为C#对象。 如果文件有效,则转换为C#对象,存储在具有唯一GUID名称的Cache中,并将用户重定向到CompleteImportModule操作。
  4. 用户检查数据是否正确并确认上传。

长话短说,有一个代码告诉你更多:
ImportModule动作。

 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(moduleInfo, questions), null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(30), CacheItemPriority.NotRemovable, (k, v, r) => { LoggingFactory.GetLogger().Debug("Removed from cache: {0}. Reason: {1}", k, r); }); return View(); } 

在View ImportModule

 // Output data from ViewBag.ModuleInfo and ViewBag.Questions 

CompleteImportModule动作:

 [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"); } 

但是,我遇到了一些问题。 我无法上传模块,因为插入后会立即从缓存中删除该值。 它仅存储一秒钟:

 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 

reason是“删除”意味着它没有过期,并且IIS由于优化没有删除它,但看起来我删除的是我自己。 我很确定我甚至没有在CompleteImportModule之前访问此缓存记录。

我尝试在CacheItemRemovedCallback new StackTrace().ToString() 。 就是这样,如果它能以某种方式提供帮助:

 at CPMAdministrator.Controllers.ModulesReferenceController.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& 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() 

为什么会这样? 它是一种IIS池回收? 如何确保文件未被删除? 或者我如何以另一种方式有效地存储这些数据?

我花了几个小时找到答案并在发布问题后立即找到答案! 让我与您分享我的经验。

根据我的StackTrace,我知道缓存已被清除,因为应用程序已经结束并处理掉:

 at System.Web.HttpRuntime.Dispose() at System.Web.HttpRuntime.ReleaseResourcesAndUnloadAppDomain(Object state) 

我所需要的只是找到它的原因。

我打开了我的Global.asax文件并添加了一个Application_End方法。

 public class MvcApplication : HttpApplication { protected void Application_End() { } } 

它在视图渲染成功后立即触发,并在缓存清除之前触发。 成功! 现在我需要知道应用程序结束的原因。

这篇文章帮助了我:

System.Web.Hosting.HostingEnvironment.ShutdownReason属性,指示应用程序被终止的原因。 它的值可以从Application_End()内部检索。

我在Application_End的开头添加了一个断点,并添加了System.Web.Hosting.HostingEnvironment.ShutdownReason来观察。

这就是它存储的内容: BinDirChangeOrDirectoryRename

之后,我明白原因是我的log4net正在BinDirectory写入日志。 如果bin目录已被更改,我只是不知道IIS正在完成Web应用程序。

我已将我的日志移动到父(应用程序本身)文件夹,现在它可以工作。
看起来我需要阅读有关ASP.NET的更多信息。
我希望它会帮助某人。 感谢所有试图提供帮助的人。

Removed的原因是Removed ,从文档意味着:

通过Remove方法调用或指定相同键的Insert方法调用将项目从缓存中删除。

因此,您要么显式调用其他地方Remove要么使用Insert覆盖它。