5

We've got an area on our site where people can sign up and be given their own page on the site which we want to host at ~/pageSlug. I've tried doing it with a rule in Global.asax, but that broke the fundamental default route that allows ~/Controller to map directly to the Index action. I'm not being allowed to put any kind of separator in front of the userSlug, so ~/p/pageSlug isn't really an option here.

In terms of getting the user pages added to the routes, I'm cycling through the pages at App_Start and explicitly adding them to the RoutesTable. This is working fine, and we've got AppPool refreshes set long enough to make this a once a day task. This does leave us with a 24-hour turnaround to "get pages live" for our users though, which I'm trying to solve.

Ideally, what I'd like to do is add the relevant route to the RouteTable dynamically once a user has signed up. I've tried doing that with:

RouteTable.Routes.Add(
    RouteTable.Routes.MapRoute(
        toAdd.UrlSlug + "Homepage", 
        toAdd.UrlSlug, 
        new { controller = "Controller", View = "View", urlSlug = toAdd.UrlSlug }
    )
);

but that didn't seem to work. I can't find a solution anywhere else, and I'm sure my code is both horribly naive and betrays a lack of understanding of routing - please help!

jonsidnell
  • 1,210
  • 1
  • 10
  • 20
  • I've resolved this one, but don't the code immediately to hand, and wasn't sure of the etiquette of answering my own question! If anyone can advise on the latter part, I'd be happy to let people know how I fixed it :) – jonsidnell Mar 04 '11 at 16:44
  • 2
    Answering your own question and marking it as correct is valid. Old question, but could you post your solution if possible? Both for completeness, and the fact that I have the exact same problem :) – Will Feb 26 '13 at 20:01

3 Answers3

5

What if you try this, using route constraint. Get out list of all users and constraint the chosen route to match entries in that list

public class UserPageConstraint : IRouteConstraint
{
    public static IList<string> UserPageNames = (Container.ResolveShared<IUserService>()).GetUserPageNames();

    bool _IsUserPage;
    public UserPageConstraint(bool IsUserPage)
    {
        _IsUserPage = IsUserPage;            
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (_IsUserPage)
            return UserPageNames.Contains(values[parameterName].ToString().ToLower());
        else
            return !UserPageNames.Contains(values[parameterName].ToString().ToLower());
    }
}

Then in the Global.asax.cs, set up a route for users as follows:

routes.MapRoute("UserHome", "{userPage}", new { controller = "UserPageController", action = "Index" }, new { userPage = new UserPageConstraint(true) });

For this above route, in the action 'index' of the UserPageController, we will have the userPage as the parameter.

For other routes relative to the userPage Home, we can add routes accordingly. for example, the userdetails page route can be added as follows:

routes.MapRoute("UserHome", "{userPage}/mydetails", new { controller = "UserPageController", action = "Details" }, new { userPage = new UserPageConstraint(true) });

You can try this and see.

Gboyega Sulaiman
  • 631
  • 5
  • 15
2

I recently just realized it too, instead of adding routes dynamically which I am not sure can be done so without using external libraries such as Route Magic . I am confident that if you design your architecture right, Routing Constraint is all you might just need. Since my application is small, I am using only one implemented controller and dynamically creating the rest (experimental at the moment but it should work).

Consider following routes

routes.MapRoute(
  name: "ContactRequests_Operations",
  url: "ContactRequests-{operation}",
  defaults: new { controller = "Content", action = "Module_Direct", id =  "ContactRequests" , operation = "Get" }
  );

 routes.MapRoute(
    name: "Messages",
    url: "Messages",
    defaults: new { controller = "Content", action = "Direct", id ="Messages" }
);
N_E
  • 743
  • 10
  • 16
0

I don't think you can add route dynamically.

Take a look at this question, maybe it will help you: ASP.NET MVC custom routing for search

Community
  • 1
  • 1
Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
  • Hmm, I'm starting to think this might be true - debugging through the code, it looks like RouteTable.Routes.Add() successfully increases the number of routes, but apparently only for that Request cycle. It doesn't seem to persist it to the RouteTable that's used throughout the app. – jonsidnell Jan 31 '11 at 10:52
  • @jsidnell - I remember people asking for dynamic creation of Areas (which boils down to new routes) and the answer was 'not supported'. For my multitenant application I ended up creating generic route with slug and custom mvc handler to pick up slug's value – Jakub Konecki Jan 31 '11 at 12:56