Dynamic layout for mobile visitors on ASP.NET MVC 3?
-
06-06-2021 - |
سؤال
I want to dynamically change the layout, based on whether the user is accessing the site from a mobile device or not. I have a few questions on the subject.
I would like to change the layout once it's determined, but before the view is rendered. That is, is there some hook I can use where I can change
layout.cshtml
tolayout.mobile.cshtml
"recursively" for any nested layouts that there might be.Is overriding
RazorViewEngine
'sCreateView
method enough? It takes amasterPath
parameter, so maybe I could implement a customRazorViewEngine
and override this method, right?The second question would be regarding mobile browser detection. I don't really care that much about specific devices. I just want to differentiate desktop from mobile. Is something like
WURFL
a necessity in this case?Is checking something like
Request.Browser.ScreenPixelsWidth
andScreenPixelsHeigth
ridiculous? (since most I'd be changing would be using or notjQuery.mobile
and it's data-attributes.
المحلول
This functionality is built-into ASP.NET MVC 4 so you get it out-of-the-box.
Scott Hansleman blogged about how you could achieve the same in ASP.NET MVC 3 and be ready for the upgrade because the NuGet he suggested is spec-compatible with ASP.NET MVC 4.
نصائح أخرى
If you can, use ASP MVC 4 as Darin Dimitrov pointed out. It supports this out of the box.
If you are stuck on MVC 3, here's how we do it in our product:
1) Install WURFL
2) Implement an HttpCapabilitiesProvider which calls WURFL and resolves device capabilities; stuff resolved caps into the result. Be sure to add a property called isMobileBrowser (wurfl exposes this)
3) Tell .NET to use your capabilities provider instead of default HttpCapabilitiesBase.BrowserCapabilitiesProvider = new YourBrowserCapabilitiesProvider(_wurflManager);
4) Create a CustomViewEngine (inherit RazorViewEngine). Override FindPartialView & FindView. These should look at controllerContext.RequestContext.HttpContext.Request.Browser.Capabilities["isMobileBrowser"] and map to appropriate name, eg myView.cshtml.mobile. You need to resolve both viewName and masterName.
4.1) Still in CustomViewEngine's FindPartialView & FindView, search search ~/Views/{0}/{1} and ~/Views/Shared/{0}/{1} where {0} is the controller (controllerContext.RouteData.GetRequiredString("controller")) and {1} is your mapped view name
4.2) Return return new ViewEngineResult(CreateView(controllerContext, viewPath, masterPath), this);