2010-08-18 59 views
2

tldr>一旦選擇了客戶,所有其他控制器如何在客戶的「上下文」中始終執行其操作,而無需手動傳遞ID?ASP.NET MVC:在頁面之間傳遞價值

我想弄清楚'正確'的方式是處理一個整個控制器(或更多)都依賴於前一個控制器的想法的情況。例如,假設您正在構建某種客戶管理系統。會有各種各樣的客戶功能,可能位於CustomerController上。但是當你進入訂單管理時,你可能想要一個OrderController。

如果你只有一個OrderController,你的方法可能會是這樣的:

公衆的ActionResult編輯(串號){...}

的ID是訂單的ID,對不對?當我需要回到客戶那裏時,我有些失落。這就像發生在顧客身上的所有行爲的「背景」一樣。你可以通過不斷添加客戶ID到行動(URL)的做到這一點:

http://site.com/Orders/Edit/1234?customerId=abc

但這似乎它變得相當繁瑣要抓住這個值和干擾到它的每一個動作。有像Session這樣的選項,但似乎馬虎。

什麼是正確的方法來做到這一點?

+2

你爲什麼認爲使用會話是馬虎?聽起來像是一個完美的用例。 – Necros 2010-08-18 02:05:16

+1

我想我只是通過這種方式查看會話。是的,它會在這裏工作,但是如果你嘗試擴展等等,那麼會出現問題。我通常以避免使用全局變量的方式來避開會話 - 它們可以工作,但它們有它們自己的問題。 – Jim 2010-08-18 02:27:04

+0

使用會話的另一個重要因素是用戶無法爲任何子頁面添加書籤,因爲它們需要創建該上下文。通過在URL中嵌入您需要的所有內容,用戶可以直接回到他們想要的任何頁面。 – Jim 2010-08-19 02:57:28

回答

0

如果你真的想避免你的值存儲到會話中,你可以使用一個動作過濾器均採用值的照顧。我用過這種方法一次,它是這樣的:

  1. 創建一個包含您的值的佔位符的新路線,例如,客戶ID。
  2. 選擇客戶後,添加要路由的下一個GET或POST呼叫的ID。
  3. 創建一個動作過濾器,該動作過濾器從路由讀取id並在動作發生之前將其添加到動作參數(OnActionExecuting)。當操作完成時,相同的過濾器將操作參數中的標識添加回路由數據(OnActionExecuted)。
  4. 使用這個新的動作過濾器,無論你希望,可能在控制器級別。

現在,即使您不手動將其添加到所有鏈接,您的客戶ID也很容易保留在網址中。如果您需要在操作方法中使用客戶ID,則只需添加具有正確名稱的參數即可。即使您不將其作爲參數,它仍會保留在操作方法調用之上。

如果您想更進一步,在新的操作過濾器中,您可以從數據庫獲取數據並將其添加到操作參數中,而不是僅添加標識。這樣你可以進一步簡化你的操作方法。

3

您可以通過在會話中編寫一個包裝來減少一般會話的鬆散度,這會暴露強類型屬性。

//Sloppy weak typing: 
int userId = (int)HttpContext.Current.Session["UserId"]; 

//Strongly typed goodness 
int userId = SessionWrapper.UserId; 
+0

是的,當我玩弄這條路線時,我已經將幾種方法烘焙到基礎控制器中來完成這個任務。確實讓它好一點。儘管如此,一旦這種情況發生在3臺服務器上,我就會遇到一個棘手的問題。從來沒有與Sql會話存儲擴展的好運。 – Jim 2010-08-18 04:11:12

+1

我很確定這是一個解決的問題,有一種方法可以將會話存儲在SQL Server中,以便它可以在羣集中保存。也許這可能是有用的:http://support.microsoft.com/kb/317604 – 2010-08-18 04:34:45

+1

是的,它存在,它只是負荷很重。 – Jim 2010-08-18 05:18:53

0

會話是一個存儲這樣的東西的地方。

您也可以使用擴展性好的分佈式緩存(http://msdn.microsoft.com/library/cc645013.aspx)。來自以上鍊接的示例代碼

// CacheFactory class provides methods to return cache objects 
// Create instance of CacheFactory (reads appconfig) 
DataCacheFactory fac = new DataCacheFactory(); 
// Get a named cache from the factory 
DataCache catalog = fac.GetCache("catalogcache"); 
//------------------------------------------------------- 
// Simple Get/Put 
catalog.Put("toy-101", new Toy("thomas", .,.)); 
// From the same or a different client 
Toy toyObj = (Toy)catalog.Get("toy-101"); 
// ------------------------------------------------------ 
// Region based Get/Put 
catalog.CreateRegion("toyRegion", true); 
// Both toy and toyparts are put in the same region 
catalog.Put("toy-101", new Toy(.,.), "toyRegion"); 
catalog.Put("toypart-100", new ToyParts(…), "toyRegion"); 
Toy toyObj = (Toy)catalog.Get("toy-101", "toyRegion"); 
0

將會話信息序列化爲加密會話cookie是另一種解決方案。做的好處是避免服務器資源的消耗,達到同樣的目標的能力:

private void setSessionCookie() { 
     HttpCookie ck = new HttpCookie(XConstants.X_SESSION_COOKIE_KEY) { 
      Expires = DateTime.Now.AddMinutes(_sessionInfo.SessionTimeoutMinutes) 
     }; 
     DateTime now = DateTime.UtcNow; 
     _sessionInfo.SessionLastValidatedAt = now; 
     ck.HttpOnly = true; // server-only cookie 
     ck["LastCheck"] = now.ToString(XConstants.XDATEFORMAT); 
     ck["Content"] = new Cipher().Encrypt(Serializer.Serialize(_sessionInfo).OuterXml, 
      ConfigurationManager.AppSettings[XConstants.X_APPKEY_KEY]); 
     System.Web.HttpContext.Current.Response.Cookies.Add(ck); 
    }