I would like to achieve something very similar to this question, with some enhancements.
There is an ASP.NET MVC web application.
I have a tree of entities.
For example, a Page
class which has a property called Children, which is of type IList<Page>
. (An instance of the Page
class corresponds to a row in a database.)
Note that the owners of the site can add a new page anytime, or delete existing ones, and the URLs should reflect those changes as well.
I would like to assign a unique URL to every Page
in the database.
I handle Page
objects with a Controller called PageController
.
Example URLs:
http://mysite.com/Page1/
http://mysite.com/Page1/SubPage/
http://mysite.com/Page/ChildPage/GrandChildPage/
You get the picture.
So, I'd like every single Page
object to have its own URL that is equal to its parent's URL plus its own name.
In addition to that, I also would like the ability to map a single Page
to the /
(root) URL.
I would like to apply these rules:
PageController
classI also found this question, and also this one and this one, but they weren't of much help, since they don't provide an explanation about my first two points.
I see the following possible soutions:
{*path}
and write a custom IRouteHandler
that handles it, but I can't see how could I deal with the first two rules then, since this handler would get to handle everything.So far, the first solution seems to be the right one, because it is also the simplest. But still, even in that case I'm not sure how could I make the PageController
to handle the requests.
I would really appreciate your thoughts on this.
Thank you in advance!
EDIT: I now had the time to examine every aspects of every answer I received. I accepted Neal's answer, since he is the one providing the best explanation about how things work. I also upvoted all other answers, since they provide good ideas.
Routes are processed in the order they are added to the collection. You could add your custom route after the existing routes to ensure it is the last one to get a chance at handling the request. This will allow you to add routes for existing files (virtual or otherwise) before it and therefore meet criteria 1 and 2.
By default, MVC routing will route to existing files before applying any routes stored in the route collection; see http://msdn.microsoft.com/en-us/library/system.web.routing.routecollection.routeexistingfiles.aspx. (hattip to Paul - see comments).
To route requests to your page controller, simply create a custom route that examines the virtual path and if it matches the pattern for a page in the database returns the RouteData
. Set up your RouteData
with the appropriate values extracted from the virtual path (e.g. set the Path key to /Parent/Child/Grandchild), set the controller key to your page controller name (e.g. Page) and the action to the name of the action that you want executed (e.g. Show). The RouteData
should be created with the MvcRouteHandler
(not sure if that is the correct class name).
To ensure that urls to your database driven pages are returned correctly, override the GetVirtualPath( RequestContext, RouteValueDictionary )
method of RouteBase
and use the route values passed in to determine if this is a database driven page and if it is create the virtual path data required (or return null otherwise).
For help with overriding GetRouteData
and GetVirtualPath
, look at the reflected source code of System.Web.Routing.RouteBase
and System.Web.Routing.Route
; after that Google is your friend.
Routes are used in reverse to determine the url given the controller, action and any other route values. You should be able to utilise this to build the url of the page within the context that it is being requested.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With