In this tutorial, you will learn how to debug routing issues within Episerver CMS powered websites. If you need to define a custom URL, render non-Episerver content, or handle posted back data you will need to create a custom routing rule within the project. Trying to get a custom routing rule to work can be hard. I can hold my hands up, I have wasted too many hours trying to get custom routing rules working 🤬

I think that one of the main reasons people can struggle to get custom routing rules working within Episerver is a lack of understanding between how normal MVC routing works and how Episerver routing works. Are you aware Episerver overrides the default rule with a bespoke custom one? In this tutorial, you will learn about these differences. You will also learn some techniques to help you diagnose why your routing rules are not triggering. If this sounds useful, read on 🔥🔥🔥

My Form Data Is NOt Posting Back!

One of the nice features of MVC routing is the pre-populating of action parameters 'magically'. This magic works via a thing called the model binder. The model binder takes the values added to the current request object page and then try to map those values to any parameters defined within an action method. Using this technique means that when an action in a controller is hit, if corresponding data exists within the request, any parameters are 'magically' populated with data. The model binder will work on data types like an int or a string. The model binder can also map complex objects. For example in a web form, you may have a textbox with an id of textbox. When the form is posted back to a controller, MVC should auto bind the input value of the textbox to a parameter called textbox. It matches a form elements id/name with that of the input parameters specified on your actions. As seen below:

Trying to get the model binder to work on more complex objects within an Episerver project is usually more frustrating than getting it to work on a plain MVC site. In MVC, the segments within a Url normally map to a controller and an action method. When you install Episerver it overrides the default MVC routing rule with a custom rule. It has to do this because the Url in an Episerver site, does not map to a controller the same way as in MVC.

In an Episerver application, Episerver hi-jacks the HTTP request and based on the URL, tries to find if a page with a matching segment lives within the Episerver database. On a successful match, Episerver creates a CurrentPage object which contains all the information about the current page from the CMS. The request is redirected to a controller based on the page type that was used to create that page, so the page can be rendered. The takeaway is that Episerver uses a very different routing process!

This is why when you try to create your own custom routing rules things can go wrong. If you find yourself in this situation, my first tip is to stick a breakpoint in action method of the controller you expect to be hit. If the breakpoint does not hit, your routing rule is wrong (or missing). If it does hit, use the Add Watch feature in Visual studio to have a look at the RouteData property:


You can inspect this property to check if all the data you think should be in the request is present. To find the route data, have a look here:

If the data you are expecting to see within your RouteData is there and your parameters are not being automatically populated, it is likely that there is an issue with the request type. Make sure you're decorating the action with the correct Verb attribute, e.g. POST or GET,. If things are still not working, you could try manually setting your route data in code to see if the controller will auto bind correctly. This can be done using this code:

If you use the snippet above within your controller, you can add the following code to test that the data is being passed correctly:

If data is not being passed correctly into a controller, the issue is very likely due to your custom routing rule, or, the thing that is generating the request (form). In these scenarios, I'd check the area where you are adding custom rules into the routeing table (usually found in the global.ascx) and check if any custom segments or routes are defined. If so, try disabling them all and retesting that the data passes correctly to the controller you want to get working.

Sometimes a bug in your routing rules or even the order in which the rules are being applied to the request can cause issues. The order of the rules may be accidentally invoking an incorrect controller or action. In these situations, the best tool to try and help figure out what's going wrong is Route Debugger. To install Route Debugger open the 'Nugent Package Manage' console and type this command:

After installing the package, within appsettings in the web.config you should see the following:

Using this package, you should be able to see what route data exists within a request easily. This can be very handy to figure out why your routing is not working.

As you can see, getting routing to work can be very time-consuming. I've seen a number of people fall into the same types of traps when setting up custom routes, so don't get yourself too worked up if you find yourself in the same situation. Make sure the data you expect to exist within a request is actually being passed around. You can do this by looking into the Route collection.

If the data is there, the issue will likely be within your controller, maybe a typo in your parameters or POCOs. You can also try to manually add data into the routeing table to make sure everything is working as it should. If you have manually added data into the route values and it is still missing, I would recommend disabling all of your custom routes and segments and trying again. Continue disabling until the data passes as expected. Then add everything back, one step at a time, to discover where the offending code was hiding. Good luck and happy Coding 🤘