Hi Tim
Take a look at this article: http://joelabrahamsson.com/custom-routing-for-episerver-content/
Frederik
Tim, you are really close to the solution. You just need to change "en" to {language}, and "Search" to {node} in your route URL.
routes.MapContentRoute(
name: "Search",
url: "{language}/{node}/{location}/{event}",
defaults: new { controller = "Search", action = "Index" }
);
This will add location and event values to all EPiServer routes. You probably want to limit the route to your search controller. In classic MVC you would just add a constraint to {controller} but this doesn't work with Epi (might be a bug), so I created a new route constraint that looks at the content type of the current request. Using that and you should be all set!
H Andreas. That's really helpful thank you. I've implemented your route but I get
The RouteData must contain an item named 'action' with a non-empty string value
But the route below works (I've changed the params but the pronciple is the same)
routes.MapContentRoute(
name: "Search",
url: "{language}/{node}/{action}/{searchTerm}/{page}",
defaults: new { controller = "Search", action = "Index", searchTerm=UrlParameter.Optional, page=UrlParameter.Optional }
);
But the URL then needs to become
/en/MVC/Search/Index/golf/
and I don't want to see Index in the url. But I haven't yet been through your blog post which I will do now.
Many Thanks
To avoid that, I think you could put the action segment as the last segment in your route
{language}/{node}/{searchTerm}/{page}/{action}
Doing that would definitely work, and is probably recommended as you will eventually need to call the other actions.
If you still want to have routes without the action segment (like how classic ASP.NET MVC works) you could add this to an InitializableModule:
public void Initialize(InitializationEngine context)
{
ContentRoute.RoutingContent += RoutingContent;
}
private void RoutingContent(object sender, RoutingEventArgs routingEventArgs)
{
var routeValues = routingEventArgs.RoutingSegmentContext.RouteData.Values;
var defaults = routingEventArgs.RoutingSegmentContext.Defaults;
// copy action key from defaults when route value does not have an action key.
if (!routeValues.ContainsKey(RoutingConstants.ActionKey) && defaults.ContainsKey(RoutingConstants.ActionKey))
routeValues[RoutingConstants.ActionKey] = defaults[RoutingConstants.ActionKey];
}
Hi Andreas
I'm just trying your route constraint in your blog. It's not working for me because the type when it comes into the Match method is Castle.Proxy.SearchPage not SearchPage so the match fails.
That said I tried a bit of a dirty hack to get it working
if (contentType.FullName.ToLower().StartsWith("castle."))
{
return contentType.BaseType == requiredContentType;
}
else
{
return contentType == requiredContentType;
}
Although the match then works the route still gives a 404. The strange think is that I'm convinced I had it working before (unless I dreamt it). I've tried restarting iis to kick it back into live and that does work.
Have you any ideas?
(thank you for your help as well of course)
Good to know about the Castle error! I will have another look at the code.
Does the /en/Search/ url work for you? Does it fail when you add event and location?
That's exactly it - the en/Search is fine. The 404s come when adding the extra parameters i.e. search term and page
Also - correction to previous post. Restarting IIS doesn't bring it into live.
Cheers
Make it implement an interface and check that instead?
Type checking is very unliskovy... :)
That is how I normally check if a pagetype supports a given functionality. Custom routing in this case...
Could it be that you have another route before the search one?
I will setup a test case when I have some time over.
I had a chance to test this now, and I'm not experiencing the error you have. Could it be that you are on a different EPi version?
I created a gist of the exact code I'm using: https://gist.github.com/simplyio/7437996
Edit: Just thought of something. Did you make sure your RouteConfig class is an InitializableModule? See example https://gist.github.com/simplyio/7180218#file-z-routeconfig-cs
Hi Andreas.
Thanks for giving this a go. I'm on EPiServer 7.1. The code I'm using is pretty much yours. It is an InitializableModule.
What is Castle.Proxy? - is that something that EPiServer just generally does. Why i wonder?
Anyway - I'll have another look soonish
Cheers
Upsetting I've upgraded to 7.5 and the routes have stopped working i.e.
routes.MapContentRoute(
name: "Search",
url: "{language}/{node}/{partial}/{action}/{searchTerm}/{page}",
defaults: new { controller = "Search", action = "Index", searchTerm = UrlParameter.Optional, page = UrlParameter.Optional }
);
This used to react to urls in the for of search/index/mysearchTerm. After the upgrade it is now 404s. Does anyone know how I might bring this back to life?
Thanks
I haven't upgraded any site to 7.5 yet but I know that they changed the language handling slightly. If you add the language segment does it work then?
/en/search/index/mysearchterm
That's too bad! Not sure what else could have changed in 7.5. I guess you could try removing parts of the route (like {partial}) and see when it starts working, or create a new simple route.
Interestingly there is another bug with the upgrade with the start page (i.e. loclahost:17000) giving a 404. If I remove the search route
routes.MapContentRoute(
name: "Search",
url: "{language}/{node}/{partial}/{action}/{searchTerm}/{page}",
defaults: new { controller = "Search", action = "Index", searchTerm = UrlParameter.Optional, page = UrlParameter.Optional }
);
the the start page bug disappears i.e the route not only doesn't work but causes the start page to generate 404s. It's definitely an EPiServer 7.5 issue as the start page bug appeared directly after.
Stranger and stranger
I'm going to reask on the 7.5 forum as it is a definite issue with this version
Hi.
I'm using EPiServer 7 MVC. I've a page type that is a search. I want to extend the routing in a search page so that search terms can be embedded into the url in a friendly way for instance
en/Search/{Location}/{Event}/
Obviously when I go there i get a 404. In vanilla MVC I would just extend the route table but since the serach page could be any where I can't really do that. I feel it should be possible.
Could someone give a some pointers about the technique i could use to do this. I don't want a complete set of code (well ok - i'll have the code if you insist) but just a steer to the right area. And an assurance that it is possible - or not possible of course
Many Thanks
Tim Brown