ASP.NET MVC Tip #15 – 傳遞瀏覽器Cookies和伺服器變數作為Action參數
ASP.NET MVC Tip #15 – Pass Browser Cookies and Server Variables as Action Parameters
美語原文:http://weblogs.asp.net/stephenwalther/archive/2008/07/08/asp-net-mvc-tip-15-pass-browser-cookies-and-server-variables-as-action-parameters.aspx
國語翻譯:http://www.cnblogs.com/mike108mvp
譯者註:這是我第一次翻譯,翻譯內容若有錯誤或者不妥之處,請大家批評指正。謝謝。
在這篇小貼士中,我將示範如何傳遞瀏覽器Cookies和HTTP伺服器變數給控制器(controller)的Action方法,用傳遞表單(form)及查詢字串(query string)參數的相同的方法。
In this tip, I demonstrate how you can pass browser cookies and HTTP server variables to controller action methods in the same way as you can pass form and query string parameters.
假設你對一個ASP.NET MVC Web應用程式進行下面的瀏覽器請求:
Imagine that you make the following browser request against an ASP.NET MVC web application:
http://localhost/Product/Index
當你進行這個請求時,預設情況下,ASP.NET MVC架構將會調用一個ProductController類中的Index() action方法。ASP.NET MVC架構中有一個ControllerActionInvoker類,它負責調用控制器(controller)的action來對瀏覽器的請求作出反應。
When you make this request, by default, the ASP.NET MVC framework will invoke an action named Index() exposed by a class named ProductController. There is a class in the ASP.NET MVC framework, named the ControllerActionInvoker class, which is responsible for invoking a controller action in response to a browser request.
ControllerActionInvoker類擁有一些職責。這個類必須找到和被呼叫者法相匹配的方法。此外,ControllerActionInvoker還負責構建參數列表傳遞給被調用的方法。
The ControllerActionInvoker class has several responsibilities. This class must find a method that matches the method being invoked. Furthermore, the ControllerActionInvoker is responsible for building the list of parameters that are passed to the invoked method.
假設,例如,在代碼清單1中Details() controller action被調用:
Imagine, for example, that the Details() controller action in Listing 1 is being invoked:
Listing 1 – ProductController.cs (C#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Tip15.Controllers
{
public class ProductController : Controller
{
public ActionResult Details(int productId)
{
return View();
}
}
}
Details() controller action只有一個productId參數。ControllerActionInvoker嘗試從三個地方取得這個參數的值。
The Details() controller action has a single parameter named productId. The ControllerActionInvoker attempts to retrieve the value of this parameter from 3 places:
1、傳遞給InvokeAction()的顯式的額外參數
2、從Route資料中得到的值
3、請求的值
1. Explicit Extra Parameters Passed to InvokeAction()
2. Values from the Route Data
3. Request Values
首先,嘗試從傳遞給ControllerActionInvoker.InvokeAction()方法的參數中擷取productId參數的值。這個方法是被Controller.Execute()方法調用的。預設的controller不會傳遞任何額外的參數。如果你建立了你自己的controller,那麼你就可以傳遞任何你喜歡的參數。
First, an attempt is made to retrieve the value of the productId parameter from the parameters passed to the ControllerActionInvoker.InvokeAction() method. This method is called by the Controller.Execute() method. The default controller does not pass any additional parameters. If you create your own controller, then you can pass any parameters that you please.
第二,嘗試從route data中擷取productId參數的值。route data可能包含一個productId的預設值。或者,你自己的route table可能將url地址的一部分與productId參數的值進行映射。預設的route table不會映射任何值給productId參數。
Second, an attempt is made to retrieve the value of the productId parameter from the route data. The route data might contain a default value for productId. Or, your route table might map a segment of a URL to the productId. The default route table does not map anything to the productId parameter.
最後,嘗試從HttpRequest對象(HttpContext.Request)中擷取productId參數的值。HttpRequest對象代表了查詢字串(Query String)、表單(Form)、Cookie以及伺服器變數項目(按這個順序)。這意味著將嘗試從所有的這些來源中擷取productId參數的值。
Finally, an attempt is made to retrieve the value of productId from the HttpRequest object (HttpContext.Request). The HttpRequest object represents Query String, Form, Cookie, and Server Variable items (in that order). This means that an attempt will be made to retrieve the value of productId from all of these sources.
如果ControllerActionInvoker不能從上面的三個地方獲得一個參數的值,那麼ControllerActionInvoker將會檢測該參數值是否允許為空白。如果一個參數允許為空白,那麼ActionInvoker將傳遞一個空值。否則ControllerActionInvoker將拋出一個非法操作異常(InvalidOperationException )。(見圖1)
If the ControllerActionInvoker cannot retrieve the value of a parameter from these three places then the ControllerActionInvoker checks whether or not the parameter can be null. If a parameter can be null, then the ActionInvoker passes a null value. Otherwise, the ControllerActionInvoker throws an InvalidOperationException (see Figure 1).
圖1-無法匹配參數
Figure 1 – Can’t Match Parameters
直到我審查ControllerActionInvoker類,我才知道controller action方法的參數能夠從瀏覽器cookies和HTTP伺服器變數中獲得。在代碼清單2中,讓我們看看HomeController類中的Index() action方法。
Until I investigated the ControllerActionInvoker class, I did not realize that controller action parameters could be retrieved from browser cookies and HTTP server variables. Consider the Index() action exposed by the HomeController in Listing 2.
Listing 2 – HomeController.cs (C#)
namespace Tip15.Controllers
{
public class HomeController : Controller
{
public ActionResult Index(string HTTP_USER_AGENT, string myCookie)
{
ViewData["HTTP_USER_AGENT"] = HTTP_USER_AGENT;
ViewData["myCookie"] = myCookie;
return View();
}
public ActionResult CreateCookie(string cookieValue)
{
var newCookie = new HttpCookie("myCookie", cookieValue);
newCookie.Expires = DateTime.Now.AddDays(10);
Response.AppendCookie(newCookie);
return RedirectToAction("Index");
}
}
}
Index()方法接收兩個參數:HTTP_USER_AGENT和myCookie。因為HTTP_USER_AGENT參數與一個伺服器變數是一致的,所以它能夠自動獲得一個值。因為myCookie與瀏覽器cookie是一致的,所以它擁有一個值(如果cookie已經被設定)。當Index()方法被調用時,你可以看到圖2的視圖。
The Index() method accepts two parameters named HTTP_USER_AGENT and myCookie. Because the parameter name HTTP_USER_AGENT corresponds to a server variable, this parameter gets a value automatically. Because myCookie corresponds to a browser cookie, this parameter also has a value (if the cookie is set). When the Index() method is invoked, you get the view in Figure 2.
Figure 2 – The Index View
事實上,你能夠傳遞伺服器變數和cookies給controller,在各種各樣不同的情境中是非常有用的。例如,你可能想在瀏覽器請求時,根據當前使用的瀏覽器類型返回不同的內容。你能夠利用HTTP_USER_AGENT伺服器變數在你自己的action方法中瀏覽器的類型並返回不同的內容,或者你可以根據瀏覽器的語言設定來返回不同語言版本的內容。
The fact that you can pass server variables and cookies to controller actions can be useful in a variety of different scenarios. For example, you might want to return different content depending on the type of browser being used to make the request. You can take advantage of the HTTP_USER_AGENT server variable in your action method to detect the type of browser and return different content. Or, you might want to return messages in different spoken languages depending on the user's browser language settings.
傳遞cookie參數也是很有用的。你能夠在cookie中儲存一個使用者的個人化偏好,並且從action方法中取出這些資料。例如,你能夠將一個使用者的暱稱存在瀏覽器cookie中,並且在每一個controller的action方法中自動取出使用者的暱稱。
Passing cookie parameters also can be useful. You could store a user’s preferences in a cookie and retrieve those preferences in an action method automatically. For example, you could store a user’s nick name in a browser cookie and retrieve that nick name in every controller action automatically.
下載示範代碼
Download the Code