4

I'd like to put together a forum/message board with ASP.NET MVC. Pretty common on these types of forums are hierarchical board categories, so for instance:

-General Discussion
-Technical Support
--Website Technical support
--Product Technical Support
---Product A Technical Support
---Product B Technical Support

Below each category are then topics and messages belong to those topics. What I'm primarily concerned with is 1.) getting to the correct place, given a URL, 2.) not including boatloads of unnecessary information in my URL, and 3.) being able to recreate a URL from code.

I'd like a URL to be something like this:

mysite.com/Forum/ - forum index
mysite.com/Forum/General-Discussion/ - board index of "general discussion" 
mysite.com/Forum/Technical-Support/Product/Product-A/ - board index of "Product A Tech Support"
mysite.com/Forum/Technical-Support/Website/Topic1004/ - Topic index of topic with ID 1004 in the "Website Technical Support" board
mysite.com/Forum/Technical-Support/Website/Topic1004/3 - Page 3 of Topic with ID 1004

Now, I've excluded Action names from this because they can be inferred based on where I am. Each Board entity in my database has a "UrlPart" column, which is indexed, so I expect to be able to do relatively fast queries against that table to figure out where I am.

The question is: in order to figure out the correct place, should I use a custom route handler, a custom route binder, or should I just create obscure routing rules?

This suggestion looks pretty good but it also looks like a lot of work for little benefit: ASP.NET MVC custom routing for search

This seems to indicate that creating a model binding would be easier: MVC Dynamic Routes

To fulfill #3 I'm going to have to create my own custom URL generation logic, right?

Community
  • 1
  • 1
Rob
  • 3,276
  • 2
  • 22
  • 25
  • One thing I've been thinking about doing is to populate my route table dynamically at runtime - constructing my routes based on the database. Would that work? – Rob Jun 20 '09 at 00:38
  • I've answered a similar question [here](http://stackoverflow.com/questions/1023252/asp-net-mvc-complex-routing-for-tree-path/1023602#1023602) Maybe that can help you as well – chris166 Jun 22 '09 at 17:24
  • What I had done in the meantime was dynamically create the routes based on board IDs. I don't know that route handlers will do it for me, because they don't actually help construct routes, but it seems like a pretty good way to handle them as they come in. Thanks! – Rob Jun 26 '09 at 16:37
  • @Brad Larson: Marking as duplicate five years after the fact seems a little lame, particularly when, if you look at the timestamps of "asked," my question was asked first. This question: asked Jun 19 '09; this question is a duplicate of: asked Jun 21 '09. :-X Now to go invent my time machine.... – Rob Apr 22 '16 at 18:34
  • @Rob - You had marked chris166's answer (now converted to a comment) as the accepted answer for this question. All that answer did was point to an answer on another question. That seemed to indicate that you thought your question was better answered by that, so when chris166's answer was flagged as "not an answer" by the community, it seemed to make sense to direct people there. Older questions can be closed as duplicates of newer ones if people feel there is a better answer being provided in the newer question. – Brad Larson Apr 22 '16 at 19:02

2 Answers2

5

If you need deep and/or non-conforming URLs, I would suggest that you employ attribute based routing, such as the solution discussed here.

I prefer an attribute based approach over putting every route in Application_Start, because you have better locality of reference, meaning the route specification and the controller which handles it is close together.

Here is how your controller actions would look for your example, using the UrlRoute framework I implemented (available on codeplex):

[UrlRoute(Path = "Forum")]
public ActionResult Index()
{
    ...
}

[UrlRoute(Path = "Forum/General-Discussion")]
public ActionResult GeneralDiscussion()
{
    ...
}

[UrlRoute(Path = "Forum/Technical-Support/Product/{productId}")]
public ActionResult ProductDetails(string productId)
{
    ...
}

[UrlRoute(Path = "Forum/Technical-Support/Website/{topicId}/{pageNum}")]
[UrlRouteParameterDefault(Name = "pageNum", Value = "1")]
public ActionResult SupportTopic(string topicId, int pageNum)
{
    ...
}

With this approach you can generate outbound URLs using the same helpers (Url.Route*, Url.Action*) that you would use if you manually added the routes using the default route handler, no extra work needed there.

Community
  • 1
  • 1
dso
  • 9,463
  • 10
  • 53
  • 59
  • Thanks DSO, but that's not quite what I was looking for; you can imagine people create forums with all manners of middle areas. All I need in a URL is the /Forum marker, to know to marshal to the Forum controller; and optionally, the topic ID and page number, to indicate whether I want to go to the index, a board, or a topic. I want the board names in there for SEO reasons. Arguably I could make only the current board be part of the URL, but chomping part of it off wouldn't obey the REST principal of getting to the parent section. – Rob Jun 20 '09 at 00:34
  • OK maybe I took your examples too literally. You're saying that you want the entire middle part of the URL be totally free-form with absolutely no predefined structure? – dso Jun 20 '09 at 03:44
  • 1
    Yes. Part of it is that I'd like my URLs to get their structure from the database. This seems to be working... I'll post what I came up with a bit later today. – Rob Jun 22 '09 at 16:59
  • Hey Rob, Sorry to dig this up. Any chance if you could post some code showing how you achieved it? Thanks – Varinder Jan 14 '14 at 03:43
1

You could have them all go to one controller action which handles the route handling for you by manually splitting the rest of the url out and calls what a method on your BLL which then delegates tasks to other methods finally returning a View() depending on your needs.

Schotime
  • 15,707
  • 10
  • 46
  • 75