Uniform way of get item's url after 1.4 (and AutoRoute)?

Topics: Core, Writing modules
Developer
Jan 8, 2012 at 12:05 PM

Will there be some standard way of retrieving an item's url (if it has one) after the release of v1.4 and the AutoRoute module? I mean, now there is RoutePart, but as far as I understand in the future there will be two ways for a content item to have an url. But will there be an API to get the item's url, regardless of the routing engine used?

Thanks.

Jan 8, 2012 at 12:25 PM
Edited Jan 8, 2012 at 12:27 PM

There already is; well two ways actually.

One is @Url.ItemDisplayUrl(...).

The other way is:

 

var metadata = ContentManager.GetContentItemMetadata(content);

@Url.Action(metadata.DisplayRouteValues)

Because of the Routing engine's reverse routing of route values into the most appropriate URL, this will correctly display the Alias path under Autoroute, just as it will now display the Routable path when you do the same.

Developer
Jan 8, 2012 at 12:41 PM

How could I missed that, I've already seen this in action. Thank you!

Jan 9, 2012 at 7:33 AM

Maybe a little bit off topic but i still wondering if it's better to to this in the driver/action and add it to the viewmodel so you can cache the total viewmodel or do this url resolving in the view. In view you can't cache it because it's database hot. Which method do you guys prefer?

Coordinator
Jan 9, 2012 at 8:23 AM

What do you mean database hot?

Jan 9, 2012 at 8:26 AM

Not a DTO file where all fields already have been queried. So with a database hot object i mean a object which has properties which are begin loaded from database when accessed

Coordinator
Jan 9, 2012 at 8:34 AM

Gee, thanks ;) How does Url.Action qualify?

Jan 9, 2012 at 12:57 PM

Alias holds all the urls and routevalues in memory after the site has been loaded; so the Url.Action call will be purely in-memory processing from a concurrent dictionary. Actually this is by design, it's pretty much impossible to perform any DB access in the Routing layer in Orchard.

The only problem is ContentManager.GetItemMetadata(...) - this dispatches off to all the content handlers which, for all we know, could be performing all kinds of DB access; and it's not cached. For this reason it's worth noting that you should always keep GetContentItemMetadata as light as possible in your own handlers.

Actually I've been meaning to raise a workitem for caching ContentItemMetadata per item, but I wanted to run some profiling on it first to see how big a problem it is.

 

Jan 9, 2012 at 1:09 PM

Ok thanks for clarifying. Isn't the memory usage very high when all the routes are in-memory when you have let's say 100.000 content items? just wondering.

Jan 9, 2012 at 2:11 PM

Potentially yes; but that's no different to the current situation where the IRoutablePathConstraint holds all RoutePart urls in memory (and there are similar workings for blogs and containers). With Alias the system will be much more efficient than the current one due to a) only having to read all the paths from one table and b) use of ConcurrentDictionary instead of a lock(...). The tradeoff will be higher memory usage, yes, but I think we're only talking a few mb for 100,000s of items. We want to run some profiling to discover performance and memory numerics at even millions of items (if you're interested in helping with this, Autoroute is available and working, see the Feature Team thread for details on how to get hold of it).

This of course is an extreme situation and for a website that large, requiring some extra RAM is kind of expected. The big problem is how long it will take for the website to load. The entire Alias table has to be read from the database before the first request can be processed, so if we're talking about millions of records that could start getting noticable. At this time there is no obviously good solution and any suggestions are welcome. I have some vague ideas but it's not something I can commit to tackling yet!