Investigation into URL rewriting issue

Topics: Developer Forum, User Forum
Dec 12, 2008 at 6:02 PM
Hi there

First of all I'm completely new to N2 as of today but I'm hugely impressed and after looking at many different content management systems, I know this is the right one for me.

However, I've been having some fun with the URL rewriting...

I began with following the documentation and examples and built a basic site. I started with a root node and a start page node and had a few pages beneath that. Then I decided to make a different ContentItem and created another node beneath the root. This is where the problems started. I exposed the Name property as editable in my new ContentItem so I can change the URL. Unfortunately the URL rewriter is only able to function if the node is beneath the start page node. It doesn't matter what type of page I create outside of the start page node hierachy, the URL rewriting will not work (even using the default naming of [ID].aspx). In all cases, the full URL such as Template.aspx?Item=... works correctly. Incedently, I still have a ~/default.aspx template used by the start page (I've read on here some have pad trouble after removing this default template, this seems to be a different issue).

Not one to be put off by such undocumented features, I've done a little tracing and believe I've narrowed it down to something NHibernate is doing. Putting a break point on line 240 of N2/ContentItem.cs (the setter for the Children property) shows that NHibernate sets the children twice for each request that goes through the URL rewriter. The first time, it assigns a list of children of the root node, and the second time it assigns a list of children from the start page (i.e. first child of root). It does not seem to be building a complete list of children or a list of children appropriate to the URL needing to be rewriten.

The end result is that when ContentItem.FindPath loops over each child ContentItem (at line 525 in N2/ContentItem.cs), the requested page cannot be found and so the URL rewriting never takes place.

I don't know enough about N2 yet nor much about NHibernate, but hopefully this investigation makes some sense and will be useful in diagnosing and fixing the problem. I am wondering if it's related to the multi-site feature and perhaps the children of root actually represent sites rather than 'top' level pages (which would be a shame for a single site system).

Let me know if I can help any more with stack traces etc :)

Many thanks,


..Simon
Coordinator
Dec 13, 2008 at 10:46 AM

I'm sorry, but I don't understand the issue.

The content item uses UrlRewriter class to build it's url and to find the content item associated with an url. To build an url it walks upwards from the node to the start page. If no start page is found it reverts to the rewritten url (templates.aspx?item=). This is the case for nodes not under a start page.

Does this clarify anything? Can you explain with examples?

Dec 16, 2008 at 8:00 PM
Sorry, this was a misunderstanding on my part, I wasn't fully up to speed with how N2 works :)

But I am now and my site build is coming along nicely, although the business of not having multiple 'start pages' doesn't really fit my URL scheme, so I've had to write an external URL rewriter which catches certain URLs before they reach N2, so they can be rewritten to an N2 URL.

E.g. convert http://example.com/contact into http://example.com/Templates/BasicPage.aspx?page=123 (where the latter would normally be http://example.com/home/contact)

The best way I've found to do this is using IHttpHandlerFactory and calling HttpContext.RewritePath followed by System.Web.UI.PageParser.GetCompiledPageInstance. Unforunately there's just one small problem - N2.Web.WebRequestContext. In WebRequestContext.cs on line 80 (getter for Url) there is a small issue:

return new Url(Request.Url.Scheme, Request.Url.Authority, Request.RawUrl);

Request.RawUrl returns the URL before it is rewritten (I appreciate it's not rewritten in the normal sense, but for all intents and purposes...). However, Request.Url.PathAndQuery contains the expected path (including querystring). For me this is working for all URLs be they regular N2 or 'rewritten' via my handler.

Any chance the N2 source can be updated with this change? I will post up full source for the handler once it's finished which might make things clearer...

Cheers,


..Simon
Coordinator
Dec 16, 2008 at 10:25 PM
N2 needs the original url but there are some ways to work around your problem N2:
  • Implement a custom IUrlParser decorator
  • Subscribe to IUrlParser.NotFound
  • Override FindPath on the start page node and return the appropriate item, e.g. by asking "home" when no path is found
  • Add a "redirect" item