移动互联网的兴起,导致越来越多的网站开始看中自己的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