Using Umbraco Route Hijacking and posting to it

Simple usage of Umbraco route hijacking allows you to add more features to your website and respond to your viewers request in a better way. It will also allow you to use custom models and populate them before the view gets called/rendered.

To start with route hyjacking you need to create a document type for your page, the name of the document type is important because your controller will need to have the same name as the document type in order for the Umbraco routing engine to pick it up.

Tip: Say we create a document type called NewsLister, we would need to create a controller called NewsListerController within a class file called anything, I'll call mine, NewsListerController.cs.

Now you need to create a template that the document type will allow, I'll also call my template NewsLister.

Tip: The name of the template only matters if you're planning on handling multiple templates from one controller.

Assign your template to the document type and create a page in the content area that used your new document type and template.

Now, in NewsListerController.cs, add the following code:

public class NewsListerController : RenderMvcController
{
    // The default action to render the front-end view, will populate the model and return the view.
    public override ActionResult Index(RenderModel objModel)
    {
        // Construct a new model to work with.
        MyModel objModel = new MyModel() { MyVariable = "Some value." };

        // Return the search results view with the populated model. (The template dropdown becomes irrelevent in a hybrid controller.)
        return CurrentTemplate(objModel);
    }
}

Now all you need to do is make sure that your template has the following at the top of the file:

@inherits Umbraco.Web.Mvc.UmbracoViewPage

The index method is called if a method does not exist with the same name as the template used, so to do something else with a different template, just add another method witht hat templates name and add some similar code.

Tip: Replace MyModel with the name of the class that will contain the data you need to use in your page.

See the following code as an example of a model you could use.

// Minimal routing model, contains a parameterless constructor so that it can be used for postbacks.
public class MyModel : RenderModel
{
    // Parameterless constructor to handle postbacks, will call the main constructor.
    public MyModel() : this(UmbracoContext.Current.PublishedContentRequest.PublishedContent) { }
        
    // Main constructor.
    public MyModel(IPublishedContent content) : base(content) { }

    public String MyVariable { get; set; }
}

That's it!

You might run into an issue some people get where you want to post to the page that's been rendered via a route hijack, but the controller is of type RenderMvcController and not SurfaceController. Don't worry I've got you covered, add the following class to your website somewhere and extend your controller with it instead of the RenderMvcController, as it implements both SurfaceController and RenderMvcController, you will be able to use route hijacking on and post a form to the same controller, pretty neat eh?

// The base route controller allows the use of a surface controller and a rendermvc controller in one.
// This allows us to create a controller that can be used for both route hyjacking and and form posting.
public class BaseRouteController : SurfaceController, IRenderMvcController
{
    // The default action to render the front-end view.
    public virtual ActionResult Index(RenderModel model)
    {
        // Just return the chosen template from the back office.
        return CurrentTemplate(model);
    }

    // Checks to make sure the physical view file exists on disk.
    protected bool EnsurePhysicalViewExists(string template)
    {
        var result = ViewEngines.Engines.FindView(ControllerContext, template, null);
        if (result.View == null)
        {
            LogHelper.Warn("No physical template file was found for template " + template);
            return false;
        }
        return true;
    }

    // Returns an ActionResult based on the template name found in the route values and the given model.
    // If the template found in the route values doesn't physically exist, then an empty ContentResult will be returned.
    protected ActionResult CurrentTemplate(T model)
    {
        var template = ControllerContext.RouteData.Values["action"].ToString();
        if (!EnsurePhysicalViewExists(template))
        {
            return Content("");
        }
        return View(template, model);
    }
}

See more on this, here: https://our.umbraco.org/documentation/reference/routing/custom-controllers


By Luke Alderton at 11 Feb 2016, 13:38 PM

Tags: Umbraco

Comments

phuong
Thanks for this. Was really helpful when i wanted to decouple my views from umbraco. Typo in BaseRouteController - you need to specify the protected ActionResult CurrentTemplate < T > (T model) - brilliant class!
15/11/2016
Post a comment
Sit tight...
We're adding your comment.
Thank you.
Your comment has been added.
There's been a problem.
Please try again later.
Share with
Tags
Latest Comments
By dipbleds on Raspberry Pi - Bluetooth using Bluecove on Raspbian
12 Dec 2017, 21:29 PM
By Ich on Replacing the Xamarin Header/Navigation bar with a custom view/template
26 Nov 2017, 17:11 PM
By Ravi Motha on My experience at Umbraco UK Festival 2017
12 Dec 2017, 08:39 AM
By Borges on How to add a Xamarin Forms Loading Screen/Overlay
7 Nov 2017, 19:11 PM
By Rutul Mehta on Auto/Custom height on Xamarin Forms WebView for Android and iOS
4 Nov 2017, 03:15 AM
By Pablo on Xamarin MasterDetailPage has large margin/padding at top
26 Oct 2017, 15:31 PM
By faiza on Using MaryTTS or OpenMary in Java
22 Oct 2017, 12:54 PM
By Nietoperz on Using MaryTTS or OpenMary in Java
29 Sep 2017, 14:34 PM
Categories
App Development
Event
Game Development
Mapping
Modelling
Programming
Review
Robotics
Tutorial
Web Development