Hi all. I want to change the Template (View) that the page during the request based on whether they are Mobile browsers. I dont really have the option to use AltTemplates in their standard form as the URL needs to remain intact.
My initial thoughts were to hijack the routes as described in the documentation.
public class MyWebsiteController : Umbraco.Web.Mvc.RenderMvcController
{
public override ActionResult Index(RenderModel model)
{
//meet the mobile condition change the template
` if(Request.Browser.IsMobileDevice){
}
return base.Index(model);
}
}
But the problem is I just dont know how to specify a different view or set a different template ID. You cant just change the model as Model.Content is read only.
I dont really want to setup a controller for every Doctype either if at all possible.
Any one have any genius clues?
In MasterPages you just used to change the MasterPage that was rendering which was pretty simple.
public class MyWebsiteController : Umbraco.Web.Mvc.RenderMvcController
{
public override ActionResult Index(RenderModel model)
{
//meet the mobile condition change the template
if(Request.Browser.IsMobileDevice){
ControllerContext.RouteData.Values["action"] = newTemplateAlias;
}
return base.Index(model);
}
}
Alternatively you handle the PublishedContentRequest.Prepared event and in there you do contentRequest.TrySetTemplate(newAlias). But I'm not sure you have access to Request.Browser... will check. That way you could switch over to a non-MVC template and avoid messing with the internals of RouteData.
Oh and what happens if your controller just does return View(newTemplateAlias, model) ?
Yep returning the View with the new template works. I don't know why I didn't try that for some reason I thought I should really be calling back to the base action.
So I have updated it now to
public override ActionResult Index(RenderModel model)
{
//detect mobile
if (Request.Browser.IsMobileDevice)
{
var currentTemplate = model.Content.GetTemplateAlias();
var newTemplateAlias = currentTemplate + "_Mobile";
return View(newTemplateAlias, model);
}
return base.Index(model);
}
With the route hijacking you're doing now don't you still need to it for every document type? Just wanted to let you know there is a DefaultController you can use so you don't need to route hijack everything.
Remember that the default controller only is used if you don't route hijack anything. So if you have a document type and template that is route hijacked it won't reach the default controller and you need to do the mobile check during the route hijacking.
So i first answered this from an iPad but don't think it arrived. So here goes again...
Do you know there is a built-in feature in MVC that will display Viewname.Mobile.cshtml in preference to Viewname.cshtml for any mobile device? No coding or hijacking required. This is the MVC4 Display Modes feature. Works for partial views as well. MVC has a predefined "Mobile" display mode, thus using the .Mobile extension, or you can define your own custom display modes and then add views of Viewname.MyDisplayMode.cshtml.
Scott Hanselman talks about it here, although you don't need to add the nuget package for this to work. The nuget package brings down the jQuery mobile stuff, but does install a neat view switcher controller to allow you to override the behaviour (so can have 'view desktop' / 'view mobile' version links).
We have this working in an Umbraco 6.1.3 MVC site. Although the site hasn't gone live yet so keen to hear of any potential issues!
For Umbraco 7 you should look at RenderControllers and Route Hijacking,
If it was me I would hijack the route with a render controller and in the template for the document type load one of two partials (and change the master?) based on a model parameter set in the render controller
If you are asking if MVC Display Modes are still supported in Umbraco 7 then the answer is yes, as this is just standard MVC functionality, nothing Umbraco specific.
A quick way to convince yourself (assuming you have a site you can do this on) is to take a copy of one of your .cshtml templates (e.g. Site.cshtml) and rename it Site.Mobile.cshtml. Then edit Site.Mobile.cshtml to make it clearly different from the original. Then look at the page from a desktop and a mobile device: you should see the difference!
If you then delete Site.Mobile.cshtml and refresh the page on the mobile device you should see it revert to use the normal version. This is beacuse MVC comes with one built-in display mode for mobiles. You can add more if you need.
In what file is this code placed? Still figuring out C#/asp.net after building a site for a client in Umbraco. We now want to do their mobile site and need to change the template rather than the URL. Thanks in advance.
Who do I change MVC View at runtime?
Hi all. I want to change the Template (View) that the page during the request based on whether they are Mobile browsers. I dont really have the option to use AltTemplates in their standard form as the URL needs to remain intact.
My initial thoughts were to hijack the routes as described in the documentation.
But the problem is I just dont know how to specify a different view or set a different template ID. You cant just change the model as Model.Content is read only.
I dont really want to setup a controller for every Doctype either if at all possible.
Any one have any genius clues?
In MasterPages you just used to change the MasterPage that was rendering which was pretty simple.
And now to answer my own question. :)
You just modify the RouteData.
Hopefully this helps someone :)
Alternatively you handle the PublishedContentRequest.Prepared event and in there you do contentRequest.TrySetTemplate(newAlias). But I'm not sure you have access to Request.Browser... will check. That way you could switch over to a non-MVC template and avoid messing with the internals of RouteData.
Oh and what happens if your controller just does return View(newTemplateAlias, model) ?
Stephan
Yep returning the View with the new template works. I don't know why I didn't try that for some reason I thought I should really be calling back to the base action.
So I have updated it now to
Thanks Stephen :)
With the route hijacking you're doing now don't you still need to it for every document type? Just wanted to let you know there is a DefaultController you can use so you don't need to route hijack everything.
Jeroen
Thats what I am doing. I am registering it as the defaultController during startup.
Ok cool I didn't read that. That's the best and easiest solution for mobile detection. I'm doing it the same way :).
Jeroen
Remember that the default controller only is used if you don't route hijack anything. So if you have a document type and template that is route hijacked it won't reach the default controller and you need to do the mobile check during the route hijacking.
Jeroen
So i first answered this from an iPad but don't think it arrived. So here goes again...
Do you know there is a built-in feature in MVC that will display Viewname.Mobile.cshtml in preference to Viewname.cshtml for any mobile device? No coding or hijacking required. This is the MVC4 Display Modes feature. Works for partial views as well. MVC has a predefined "Mobile" display mode, thus using the .Mobile extension, or you can define your own custom display modes and then add views of Viewname.MyDisplayMode.cshtml.
Scott Hanselman talks about it here, although you don't need to add the nuget package for this to work. The nuget package brings down the jQuery mobile stuff, but does install a neat view switcher controller to allow you to override the behaviour (so can have 'view desktop' / 'view mobile' version links).
We have this working in an Umbraco 6.1.3 MVC site. Although the site hasn't gone live yet so keen to hear of any potential issues!
Lotte
Hi, does the feature still work in version 7 ? I haven't used Umbraco yet but it would be a major feature for us!
Thanks Norbert
For Umbraco 7 you should look at RenderControllers and Route Hijacking,
If it was me I would hijack the route with a render controller and in the template for the document type load one of two partials (and change the master?) based on a model parameter set in the render controller
Hi Norbert,
If you are asking if MVC Display Modes are still supported in Umbraco 7 then the answer is yes, as this is just standard MVC functionality, nothing Umbraco specific.
A quick way to convince yourself (assuming you have a site you can do this on) is to take a copy of one of your .cshtml templates (e.g. Site.cshtml) and rename it Site.Mobile.cshtml. Then edit Site.Mobile.cshtml to make it clearly different from the original. Then look at the page from a desktop and a mobile device: you should see the difference!
If you then delete Site.Mobile.cshtml and refresh the page on the mobile device you should see it revert to use the normal version. This is beacuse MVC comes with one built-in display mode for mobiles. You can add more if you need.
Hope this helps!
Lotte
In the end when we did the above we went the way that Lotte describes because there are way less moving parts.
However in saying that we have used the method mentioned above to perform A/B testing to swap out the views at run time.
In what file is this code placed? Still figuring out C#/asp.net after building a site for a client in Umbraco. We now want to do their mobile site and need to change the template rather than the URL. Thanks in advance.
is working on a reply...