Extending routing for a search page

Vote:
 

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

 

 

 

 

#77088
Nov 07, 2013 20:15
Vote:
 

Hi Tim

Take a look at this article: http://joelabrahamsson.com/custom-routing-for-episerver-content/

Frederik

#77089
Nov 07, 2013 21:12
Vote:
 

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!

#77121
Nov 10, 2013 11:10
Vote:
 

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

#77159
Edited, Nov 12, 2013 9:25
Vote:
 

To avoid that, I think you could put the action segment as the last segment in your route
{language}/{node}/{searchTerm}/{page}/{action}

#77160
Nov 12, 2013 9:40
Vote:
 

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];
}
#77165
Edited, Nov 12, 2013 10:14
Vote:
 

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)

 

 

 

#77167
Nov 12, 2013 10:57
Vote:
 

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?

#77168
Nov 12, 2013 11:05
Vote:
 

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

#77169
Nov 12, 2013 11:53
Vote:
 

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...

#77170
Nov 12, 2013 12:45
Vote:
 

Could it be that you have another route before the search one?

I will setup a test case when I have some time over.

#77171
Nov 12, 2013 13:02
Vote:
 

I've only got the one route set up.

#77172
Nov 12, 2013 13:10
Vote:
 

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

#77204
Edited, Nov 12, 2013 21:25
Vote:
 

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

#77244
Nov 13, 2013 15:59
Vote:
 

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

   

 

 

#80019
Jan 13, 2014 17:03
Vote:
 

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

#80020
Jan 13, 2014 17:05
Vote:
 

Unfortunately it doesn't work with or without language

#80021
Jan 13, 2014 17:15
Vote:
 

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.

#80022
Jan 13, 2014 17:20
Vote:
 

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

#80024
Jan 13, 2014 17:41
Vote:
 

I'm going to reask on the 7.5 forum as it is a definite issue with this version

#80025
Jan 13, 2014 17:42
Vote:
 

This thread resolves this for 7.5

http://world.episerver.com/Modules/Forum/Pages/Thread.aspx?id=80026

Cheers

 

 

#80206
Jan 16, 2014 14:56
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.