2015-06-22 44 views
2

我有一个ASP.NET 4 Web服务。
它在ModuleController控制器中有一个ImportModule动作。ASP.NET HttpContext缓存在插入后立即删除

这就是它是如何工作的:

  1. 用户上传模块作为CSV文件。
  2. 此文件正在使用HttpPostedFileBase.InputStream和自定义CSV阅读课程阅读。
  3. 根据一些规则和验证,将此文件转换为C#对象。如果文件有效,那么它将转换为C#对象,将其存储在具有唯一GUID名称的缓存中,并将用户重定向到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, ModuleQuestion[]>(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 

<form method="POST" action="@Url.Action("CompleteImportModule")"> 
    <input type="hidden" name="uploadId" value="@ViewBag.UploadId"/> 
    <input type="submit" value="Send"> 
</form> 

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

我试图把new StackTrace().ToString()CacheItemRemovedCallback。就是这样,如果它能够以某种方式帮助:

at CPMAdministrator.Controllers.ModulesReferenceController.<ImportModule>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池回收?我如何确保文件不被删除?或者我怎样才能以另一种方式有效地存储这些数据?

+0

这是在生产环境还是通过VS进行调试? – heymega

+0

@heymega这是VS开发人员的机器上调试。 –

回答

0

除去的理由是Removed,从documentation这意味着:

该项目是从由删除方法调用或者通过指定的相同密钥的插入方法调用缓存中移除。

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

+0

谢谢。我找到了解决方案!阅读我自己的答案。 –

2

我花了好几个小时找到答案,发现问题后发现它正确!让我与你分享我的经验。

根据我的堆栈跟踪,我理解的是,缓存已被清除,因为应用程序已结束并设置:

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

所有我需要的是找到一个理由吧。

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

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

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

This post帮我:

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

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

这就是它存储的内容:BinDirChangeOrDirectoryRename

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

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

+0

确实,远离你的bin目录! :) – DavidG

相关问题