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

时间:2015-06-22 09:49:39

标签: c# asp.net asp.net-mvc csv caching

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

它是如何运作的:

  1. 用户将模块上传为CSV文件。
  2. 正在使用HttpPostedFileBase.InputStream和自定义CSV阅读课程阅读此文件。
  3. 根据一些规则和验证,此文件正在转换为C#对象。如果文件有效,则转换为C#对象,存储在具有唯一GUID名称的缓存中,并将用户重定向到CompleteImportModule操作。
  4. 用户检查数据是否正确并确认上传。
  5. 长话短说,有一个代码告诉你更多:
    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是&#34;已删除&#34;意味着它没有过期,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池回收?如何确保文件未被删除?或者我如何以另一种方式有效地存储这些数据?

2 个答案:

答案 0 :(得分:2)

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

根据我的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()
    {
    }
}

在视图呈现成功后立即触发,并在缓存清除之前触发。成功!现在我需要知道申请结束的原因。

This post帮助了我:

  

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

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

它存储的内容:BinDirChangeOrDirectoryRename

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

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

答案 1 :(得分:1)

删除的原因是Removeddocumentation表示:

  

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

所以你要么在其他地方明确地调用Remove,要么用Insert覆盖它。