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

本文关键字:删除 插入 存在 NET HttpContext 缓存 ASP | 更新日期: 2023-09-27 17:57:25

我有一个ASP.NET 4 web服务
它在ModuleController控制器中具有ImportModule动作。

这就是它的工作原理:

  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();   
}

视图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池回收吗?如何确保文件不会被删除?或者,我如何以另一种方式有效地存储这些数据?

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

我花了几个小时寻找答案,并在发布问题后立即找到!让我和大家分享一下我的经验。

根据我的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属性,指示终止应用程序的原因。它的可以从CCD_ 15内部检索值。

我在Application_End的开头添加了一个断点,并添加了要监视的System.Web.Hosting.HostingEnvironment.ShutdownReason

这就是它存储的内容:BinDirChangeOrDirectoryRename

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

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

给出的删除原因是Removed,从文档中可以看出:

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

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