Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Peter Gregory 408 posts 1614 karma points MVP 3x admin c-trib
    Aug 22, 2013 @ 16:57
    Peter Gregory
    0

    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.

    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.

  • Peter Gregory 408 posts 1614 karma points MVP 3x admin c-trib
    Aug 22, 2013 @ 17:26
    Peter Gregory
    102

    And now to answer my own question. :)

    You just modify the RouteData.

    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);
            }
    
     }
    

    Hopefully this helps someone :)

  • Stephen 767 posts 2273 karma points c-trib
    Aug 22, 2013 @ 17:36
    Stephen
    2

    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

  • Peter Gregory 408 posts 1614 karma points MVP 3x admin c-trib
    Aug 22, 2013 @ 17:44
    Peter Gregory
    1

    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);
        }
    

    Thanks Stephen :)

  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Aug 22, 2013 @ 19:58
    Jeroen Breuer
    0

    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

  • Peter Gregory 408 posts 1614 karma points MVP 3x admin c-trib
    Aug 22, 2013 @ 20:02
    Peter Gregory
    0

    Thats what I am doing. I am registering it as the defaultController during startup.

  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Aug 22, 2013 @ 20:04
    Jeroen Breuer
    0

    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

  • Jeroen Breuer 4908 posts 12265 karma points MVP 4x admin c-trib
    Aug 22, 2013 @ 20:05
    Jeroen Breuer
    0

    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

  • Lotte Pitcher 49 posts 242 karma points MVP 7x c-trib
    Aug 23, 2013 @ 00:54
    Lotte Pitcher
    1

    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

  • Norbert Haberl 32 posts 115 karma points
    Jun 18, 2015 @ 14:52
    Norbert Haberl
    0

    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

  • Carl Jackson 139 posts 478 karma points
    Jun 18, 2015 @ 16:18
    Carl Jackson
    0

    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

  • Lotte Pitcher 49 posts 242 karma points MVP 7x c-trib
    Jun 18, 2015 @ 16:33
    Lotte Pitcher
    0

    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

  • Peter Gregory 408 posts 1614 karma points MVP 3x admin c-trib
    Jun 18, 2015 @ 16:41
    Peter Gregory
    0

    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.

  • Ashley Andersen 45 posts 88 karma points
    Sep 11, 2013 @ 17:37
    Ashley Andersen
    0

    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.

Please Sign in or register to post replies

Write your reply to:

Draft