簡體   English   中英

ASP.NET MVC - 在控制器之間共享會話狀態

[英]ASP.NET MVC - Sharing Session State Between Controllers

我仍然大多不熟悉控制反轉(雖然我現在正在學習它)所以如果這是我的問題的解決方案,請告訴我,我會回過頭來學習它。

我有一對控制器需要一個Session變量,自然沒有什么特別的事情發生,因為Session首先工作,但這讓我想知道在兩個獨立的控制器之間共享相關對象最干凈的方法是什么。 在我的特定場景中,我有一個UploadController和一個ProductController,它們相互配合使用來上傳圖像文件。 當UploadController上傳文件時,有關上傳的數據存儲在Session中。 發生這種情況后,我需要在ProductController中訪問該Session數據。 如果我在兩個控制器中為包含我的上傳信息的Session變量創建一個get / set屬性,我將能夠訪問該數據,但同時我將違反各種DRY,更不用說創建一個,充其量,令人困惑的設計,其中一個對象由兩個完全斷開連接的對象共享和修改。

你有什么建議?

確切的背景:

文件上載View將文件發布到UploadController.ImageWithpreview(),然后讀取已發布的文件並將其復制到臨時目錄。 保存文件后,另一個類生成上傳圖像的縮略圖。 然后,使用JsonResult將原始文件和生成的縮略圖的路徑返回到javascript回調,該回調更新頁面上可以“已保存”或“已取消”的表單中的某些動態內容。 無論上傳的圖像是保存還是被跳過,我都需要從臨時目錄中移動或刪除它和生成的縮略圖。 為此,UploadController在Session維護的Queue對象中跟蹤所有上傳文件及其縮略圖。

返回視圖:在使用生成的圖像縮略圖填充表單后,表單將回發到ProductsController,其中標識了所選文件(目前我將文件名存儲在隱藏字段中,我意識到這是一個可怕的漏洞),然后從臨時目錄復制到永久位置。 理想情況下,我想簡單地訪問我存儲在Session中的隊列,這樣表單就不需要像現在一樣包含圖像位置。 這就是我設想我的解決方案的方式,但我會熱切地傾聽任何評論或批評。

我想到了幾個解決方案。 您可以使用映射到請求的“SessionState”類並獲取/設置信息(我從內存中執行此操作,因此這不太可能編譯並且意味着傳達這一點):

internal class SessionState
{
  string ImageName
  {
    get { return HttpContext.Current.Session["ImageName"]; }
    set { HttpContext.Current.Session["ImageName"] = value; }
  }
}

然后從控制器,執行以下操作:

  var sessionState = new SessionState();
  sessionState.ImageName = "xyz";
  /* Or */
  var imageName = sessionState.ImageName;

或者,您可以創建控制器擴展方法:

public static class SessionControllerExtensions
{
  public static string GetImageName(this IController controller)
  {
    return HttpContext.Current.Session["ImageName"];
  }

  public static string SetImageName(this IController controller, string imageName)
  {
    HttpContext.Current.Session["ImageName"] = imageName;
  }
}

然后從控制器:

  this.SetImageName("xyz");
  /* or */
  var imageName = this.GetImageName();

這肯定是干的。 也就是說,我並不特別喜歡這些解決方案中的任何一個,因為我更喜歡在會話中存儲盡可能少的數據(如果有的話)。 但是如果你的意圖是保留所有這些信息而不必從其他來源加載/辨別它,這是我能想到的最快(最臟)的方式。 我非常肯定有一個更優雅的解決方案,但我沒有關於你正在嘗試做什么以及問題域是什么的所有信息。

請記住,在會話中存儲信息時,您必須通過序列化對對象進行脫水/再水化,並且您可能無法通過這種方式獲得您認為自己的性能。

希望這可以幫助。

編輯:回應其他信息不確定你要在哪里部署它,但處理圖像“實時”是一個肯定的火災方式被DoS攻擊擊中。 我給你的建議如下 - 假設這是面向公眾的,任何人都可以上傳圖片:

1)允許用戶上傳圖像。 該圖像進入處理隊列以供應用程序或某些服務進行后台處理。 此外,圖像的名稱會進入用戶的個人處理隊列 - 可能是數據庫中的表。 有關Web應用程序中后台處理的信息,請參閱@ 在托管Web服務器中安排作業

2)處理這些圖像,並在處理時顯示“處理圖形”。 您可以在產品頁面上有一個ajax請求,用於檢查正在處理的圖像,並嘗試每隔X秒重新加載一次。

3)當圖像被“處理”時,用戶可以選擇退出處理,假設他們是上傳圖像的那個。 這可以在顯示圖像的產品頁面上顯示,也可以在單獨的“用戶隊列”視圖中使用,以便從圖像中刪除圖像。

因此,您最終會得到更多域對象,並且這些對象由隊列管理。 我是約會優於配置的強烈倡導者,因此應預先定義產品圖像的最終目的地。 就像是:

images / products / {id} .jpg或者,如果是集合,images / products / {id} / {sequence} .jpg。

然后,您無需知道表單中的目的地。 所有圖像都是一樣的。

然后,隊列需要知道臨時圖像的上傳位置以及產品ID。 隊列工作程序從隊列中彈出項目,處理它們並相應地存儲它們。

我知道這聽起來比你原定的更“結構化”,但我認為它更清潔一些。

UploadController和ProductController之間是否完全等價?

當UploadController上傳文件時,有關上傳的數據存儲在Session中。 發生這種情況后,我需要在ProductController中訪問該Session數據。

當我讀到UploadControl需要對上傳數據的讀寫訪問時,ProductController只需要讀取。

如果這是真的那么你可以通過在上傳信息周圍使用一個不可移動的包裝器並讓UploadController將它放入會話中來表明它。

會話本身定義為公共共享布告板,以允許任何人獲取和放置的成本分離顯式關系。 您可以允許ProductController了解UploadController,因此無需通過會話傳遞上載信息。 我的直覺是上傳信息對公眾很有趣,所以使用Session是合理的。

我沒有看到任何DRY違規行為,我們明確地試圖分離責任。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM