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


Published at

Tags: Umbraco

Luke Alderton

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
efsef
wqadadadasd
31/01/2018
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 PS on Replacing the Xamarin Header/Navigation bar with a custom view/template
16 Apr 2018, 07:53 AM
By Srusti Thakkar on How to add a Xamarin Forms Loading Screen/Overlay
27 Mar 2018, 18:22 PM
By Luke on How to add a Xamarin Forms Loading Screen/Overlay
23 Mar 2018, 15:03 PM
By Srusti Thakkar on How to add a Xamarin Forms Loading Screen/Overlay
23 Mar 2018, 13:16 PM
By Marco Teodoro on Custom section tree nodes and routes - Umbraco
21 Mar 2018, 11:08 AM
By ttt asd on Limit Google Autocomplete results to country and city
20 Mar 2018, 11:53 AM
By hamid on Limit Google Autocomplete results to country and city
19 Mar 2018, 21:13 PM
By matt on Auto/Custom height on Xamarin Forms WebView for Android and iOS
17 Mar 2018, 02:18 AM
Categories
App Development
Event
Game Development
Mapping
Modelling
Programming
Review
Robotics
Tutorial
Web Development