2011-03-20 72 views
2

我嘗試在靜態類上構建一個靜態屬性,該靜態類基本上會返回一個cookie值,以用於我的MVC網站(如果它很重要)。這樣的事情:有關HttpContext,HttpContextBase和Action過濾器的問題

public static class SharedData 
{ 
    public static string SomeValue 
    { 
     get 
     { 
      if (HttpContext.Current.Request.Cookies["SomeValue"] == null) 
      { 
       CreateNewSomeValue(); 
      } 

      return HttpContext.Current.Request.Cookies["SomeValue"].Value.ToString(); 
     } 
    } 
} 

我需要從控制器操作,global.asax方法和操作過濾器訪問此。但問題是,當運行過濾器運行時,HttpContext不可用。現在,我必須有一個單獨的靜態方法來從我傳入的過濾器上下文中取出cookie,這看起來很尷尬。

什麼是建立這樣一個靜態方法來檢索這樣一個cookie值的最佳解決方案,從控制器動作和動作過濾器這兩個工作?還是有更好的方法來做這樣的事情?

在此先感謝。

+1

運行過濾器時,HttpContext.Current應該可用。你遇到了什麼錯誤? – 2011-03-20 04:11:01

+0

哇,你是對的。我不知道爲什麼我認爲它不是。也許它不是用於不同的動作過濾器,或者是「執行」而不是「執行」?我不知道,但是我可以發誓,當我正在處理這件事的時候,它是空的。謝謝! – 2011-03-20 04:15:56

回答

1

正如JohnnyO指出的那樣,我可以從我的動作過濾器中一直訪問HttpContext。至少,在需要此功能的特定操作過濾器方法中。可能有一些其他過濾器/方法在一個時間點沒有訪問權限,但現在,這是按我需要的方式工作的。

2

致電靜態HttpContext.Current是不好的設計。相反,請創建一個擴展方法來訪問來自HttpContextHttpContextBase的實例的cookie。

我給你寫了個小幫手。您可以使用它在一個操作過濾器中執行您的功能。

public static class CookieHelper 
{ 
    private const string SomeValue = "SomeValue"; 
    public static string get_SomeValue(this HttpContextBase httpContext) 
    { 
     if(httpContext.Request.Cookies[SomeValue]==null) 
     { 
      string value = CreateNewSomeValue(); 
      httpContext.set_SomeValue(value); 
      return value; 
     } 
     return httpContext.Request.Cookies[SomeValue].Value; 
    } 
    public static void set_SomeValue(this HttpContextBase httpContext, string value) 
    { 
     var someValueCookie = new HttpCookie(SomeValue, value); 
     if (httpContext.Request.Cookies.AllKeys.Contains(SR.session)) 
     { 
      httpContext.Response.Cookies.Set(someValueCookie); 
     } 
     else 
     { 
      httpContext.Response.Cookies.Add(someValueCookie); 
     } 
    } 
} 

注:你可以很容易地使這些方法在HttpContext工作,而不是隻用HttpContext更換HttpContextBase參數。

+1

感謝您的回覆。但有幾個問題。從我讀過的內容來看,如果你想讓你的MVC應用程序易於測試,你需要儘可能地從HttpContext中移除依賴項。拋出你的應用程序引用HttpContext或filterContext.HttpContext,是不是更糟?另外,必須有兩個方法完成相同的事情似乎很愚蠢,因爲HttpContext不是從HttpContextBase派生的(這是filterContext.HttpContext的派生方法)。我也試圖避免這種情況。再次感謝。 – 2011-03-20 04:09:28

+0

(1)爲了使您的應用程序可測試,請移除對「HttpContext」的引用。另一方面,'HttpContextBase'完全可以測試。即使該屬性被稱爲「HttpContext」,它也會返回一個「HttpContextBase」對象。 (2)是的,擁有兩種完全相同的方法是愚蠢的。用兩種方法做同樣的事情?如果你的意思是在'HttpContext'或'HttpContextBase'上創建擴展方法,那麼我並不是建議你這樣做,只是讓你知道你可以,怎麼做。 – smartcaveman 2011-03-20 04:22:43

+0

此外,您可能必須使用依賴於'HttpContext'而不是'HttpContextBase'的應用程序,並且您可以只使用'new HttpContextWrapper(context).get_SomeValue()',它會更有效在'HttpContext'實例上只需要一個擴展方法。 – smartcaveman 2011-03-20 04:24:22