移動互聯網的興起,導致越來越多的網站開始看中自己的mobile站點(m站),例如我們用手機瀏覽器訪問58,美團等網站都會看到適配的m站點,隨之而來響應式布局,h5等技術隨之興起,對於一些大型網站來說,可能會投入專門的人力來研發,對於一些小型網站,或者個人網站為了更好的瀏覽體驗可能在你用移動設備訪問時候給你轉到一個H5適配頁面,對網站進行一些介紹引導用戶注冊app等。
本章目的:利用MVC的路由以便你的網站在用移動設備瀏覽時候指定到相應H5或者mobile頁面,完善體驗.
HTTP協議中UserAgent
快速簡潔,我們需要找到能幫助我們區分當前請求來源的部分
(1.1)HTTP協議詳解之消息報頭篇->UserAgent
用戶代理 User Agent,是指瀏覽器,它的信息包括硬件平台、系統軟件、應用軟件和用戶個人偏好。在X.400電子系統中,用戶代理是一種對數據打包、創造分組頭,以及編址、傳遞消息的部件。用戶代理並不是僅指瀏覽器,還包括搜索引擎。當前文章主要指瀏覽器中
(1.2)UserAgent舉例說明
我們上網登陸論壇的時候,往往會看到一些歡迎信息,其中列出了你的操作系統的名稱和版本,你所使用的瀏覽器的名稱和版本,這往往讓很多人感到很神奇,實際上,服務器應用程序就是從User-Agent這個請求報頭域中獲取到這些信息。User-Agent請求報頭域允許客戶端將它的操作系統、瀏覽器和其它屬性告訴服務器。大家看一下下邊的例子
舉例我的幾個測試:大家按照我截圖的就可以觀察到相應的不同
(1)apple iphone6
User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4
(2)Samsung Galaxy Note3
User-Agent:Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
(3)Nokia Lumia520
User-Agent:Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)
(4)PC瀏覽器
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.23
MVC中處理請求,判別請求來源
說到asp.net mvc我們最先想到的就是 路由系統,或者filter,目標只有一個,就是找到一個在請求處理管道靠前的位置來判斷請求,進行相應url重寫,請求來自pc,網站指向PC站點,請求來自mobile網站指向mobile站點。
(2.1)梳理一下mvc路由流程
引用蔣老師的話,HttpModule和httpHandler是asp.net管道的兩個重要組件,請求的最終處理通過Handler來完成,asp.net mvc就是通過一個名為mvcHandler的自定義httpHandler實現了對controller的激活和acion的執行,但是在這之前對controller和action的解析是通過asp.net mvc的url路由系統完成的,而整個url路由系統是通過一個名為urlRoutingModule的自定義httpModule實現的。
(2.2)流程圖
我們思路在路由的層面,通過userAgent進行判定,將所有來自移動設備請求轉到我們mobile頁面的控制器
(2.3)項目實踐
(1)新建一個mvc項目,創建一個pc index和一個mobile index頁面
pc首頁:HomeController
mobile首頁:MobileController
(2)編寫路由規則
新建urlProvider繼承RouteBase重寫GetRouteData方法用來判斷userAgent
public override RouteData GetRouteData(HttpContextBase httpContext) { string agent = httpContext.Request.UserAgent; //Mobile HttpRequest User-Agent 通過上邊總結出的關鍵字 string[] keywords = { "Android", "iPhone", "iPod", "Windows Phone", "MQQBrowser" }; //下邊邏輯:1:請求PC的控制器 2:請求來自移動設備 if (!httpContext.Request.RawUrl.ToLower().Contains("/mobile/")) { foreach (string item in keywords) { if (agent.ToLower().Contains(item.ToLower())) { //如果是從移動設備訪問該PC站點統一跳轉到mobile首頁 var data = new RouteData(this, new MvcRouteHandler()); data.Values.Add("controller", "Mobile"); data.Values.Add("action", "Index"); return data; } } } return null; }
(3)注冊我們自定義的路由重寫規則Global.asax
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.Add(new UrlProvider()); //我們自定義的規則 routes.MapRoute( "Default", // 路由名稱 "{controller}/{action}/{id}", // 帶有參數的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 參數默認值 ); }
(4)進行測試
直接通過瀏覽器模擬PC訪問
我們用谷歌最新版本手機模式瀏覽 PC主頁Home/index,我們期望的結果是返回的Mobile頁面
下圖結果我們可以看到雖然地址是PC的地址,但是返回的效果是我們的Mobile頁面。
總結:
(1)這是一篇很糾結的博客,因為自己的方案不是常規的,某種程度手機的頁面或許只能放在mobile控制器下,所以我給這篇文章定位為小型網站希望增加移動設備訪問頁面的一種折中辦法。也可以當做一篇了解http協議中userAgent這一屬性的講解。
(2)個人認為好的方案是通過nginx服務器(負載服務器)判定請求來源,apache服務器也有類似功能。然后轉到相應的pc站點或者m站點,當然如果你有更好的方案或者你們的項目中有更好的方案可以分享一下。
(3)回歸本源,無論是在服務器判斷還是在程序中判斷,我們區別的方法還是通過http,最終定位到userAgent。
(4)這里感謝群友大哥:蕭秦的建議 mvc中的全局過濾器GlobalFilterCollection也可以實現對請求攔截判定,也可以用FilterProvider去添加,總之原理都是通過對請求攔截,判斷userAgent