2015-06-22 26 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