NopCommerce 3.4中移动端访问抛弃响应式布局
在Nop3.4中,他抛弃了原来的xxx.Mobile.cshtml的这种写法,而是采用了响应式布局,并且把规则也给改了,你在后台配置不启用响应式布局,在前台你仍然不能写xxx.Mobile.cshtml这样。查了一天的原因,终于查出来了。
首先请大家了解mvc4的新特征:http://www.cnblogs.com/egger/p/3400076.html
看完这个,估计你也会被误导,认为MVC已经自己支持了.Mobile.cshtml这种写法。觉得他肯定是哪里把那个设置给禁用了,反正我就是顺着这种思路找了一个早上无果。最后我断点跟踪他Return View()的方法,发现,他根本没有用MVC自己的那个方法,而是自己重写了一套。
在Return View的时候,他请求到Nop.Web.Framework这个项目下面的Themes文件夹里面的ThemeableVirtualPathProviderViewEngine文件中,在这个文件中有这样两个方法:FindView 和FindPartialView,在这里,他在3.4版本中的做法是直接把Controller丢到FindThemeableView方法中去执行了,然后细看FindThemeableView方法,你会发现,在它这里面,他会用Controller和Aciton组合起来,最后拼成一个Nop中Cshtml的路径。
比如像这样:newLocations.Insert(0, "~/Administration/Views/{1}/{0}.cshtml"); //不是这句代码,不要在这里动手脚。。
所以,只要FindView 和FindPartialView传过来的ControllerName,你给他加上你自己的规则,那他就会生成对应的路径啦。
你看FindView里面的这句
ViewEngineResult result = FindThemeableView(controllerContext, ViewName, masterName, useCache);
很明显的,他是在拼路径,我们只要在这里,把viewName改成ViewName.Mobile就完了。
代码如下:
1 /// <summary> 2 /// 判断当前请求是不是从手机端过来的 3 /// </summary> 4 /// <param name="httpContext">HTTP context</param> 5 /// <returns>Result</returns> 6 public virtual bool IsMobileDevice(HttpContextBase httpContext) 7 { 8 //comment the code below if you want tablets to be recognized as mobile devices. 9 //nopCommerce uses the free edition of the 51degrees.mobi library for detecting browser mobile properties. 10 //by default this property (IsTablet) is always false. you will need the premium edition in order to get it supported. 11 bool isTablet = false; 12 if (bool.TryParse(httpContext.Request.Browser["IsTablet"], out isTablet) && isTablet) 13 return false; 14 15 if (httpContext.Request.Browser.IsMobileDevice) 16 return true; 17 18 return false; 19 }
1 /// <summary> 2 /// 返回View视图 3 /// </summary> 4 /// <param name="controllerContext"></param> 5 /// <param name="viewName"></param> 6 /// <param name="masterName"></param> 7 /// <param name="useCache"></param> 8 /// <returns></returns> 9 public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) 10 { 11 bool useMobileDevice = IsMobileDevice(controllerContext.HttpContext);//判断请求是否从手机过来 12 string overrideViewName = useMobileDevice ? 13 string.Format("{0}.{1}", viewName, _mobileViewModifier) 14 : viewName;//拼路径_mobileViewModifier这是个string类型的变量,你也可以直接写死称Mobile或者Wap等等,到时候,你就是viewName._mobileViewModifier.cshtml 15 ViewEngineResult result = FindThemeableView(controllerContext, overrideViewName, masterName, useCache);//找一下视图 16 if (useMobileDevice && (result == null || result.View == null)) 17 result = FindThemeableView(controllerContext, viewName, masterName, useCache);//没找到,再去找没有带后缀的试图 18 return result; 19 }
1 public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) 2 { 3 bool useMobileDevice = IsMobileDevice(controllerContext.HttpContext); 4 string overrideViewName = useMobileDevice ? 5 string.Format("{0}.{1}", partialViewName, _mobileViewModifier) 6 : partialViewName; 7 ViewEngineResult result = FindThemeablePartialView(controllerContext, overrideViewName, useCache); 8 if (useMobileDevice && (result == null || result.View == null)) 9 result = FindThemeablePartialView(controllerContext, partialViewName, useCache); 10 return result; 11 }