views:

141

answers:

1

I'd like to have URLs that are even shorter than /{Controller}/{Action}/{Id}.

For example, I'd like {Controller}/{Id}, where {Id} is a string.

This would allow for simple paths, e.g. Users/Username, Pages/Pagename, News/Newsname. I like this better than requiring the /Details action in the URL (Users/Details/Username), which is less elegant for the end-user.

I can easily make this work by setting up custom routes for any controller that I want this level of simplicity for. However, this causes headaches when it comes to implementing other actions, such as {Controller}/{Action}, where {Action} = 'Create', since, in this case the string {Action} conflicts with the string {Id}.

My question: how can I have 'reserved' words, so that if the URL is /News/Create, it is treated as an action, but if the URL is anything else, e.g. /News/A-gorilla-ate-my-thesis, then it is treated as an Id.

I'm hoping I can define this when setting up my routes?

Update:

Using Ben Griswold's answer, I have updated the default ASP.NET MVC routes to be:

    routes.MapRoute(
    "CreateRoute",                                            // route name
    "{controller}/Create",                                    // url with parameters
    new { action = "Create" }                                 // parameter defaults
);

routes.MapRoute(
    "DetailsRoute",                                           // route name
    "{controller}/{id}",                                      // url with parameters
    new { action = "Details" }                                // parameter defaults
);

routes.MapRoute(
    "Default",                                              // Route name
    "{controller}/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);

This works a charm and means, by default, the details pages will use the simplified URL, but I will still be able to target a specific action if I want to (update/delete/details).

Of course, you will need to disallow the reserved "Create" word as an Id, otherwise a user may try to create an article, for example, with the name "Create", which can never be accessed.

This is really nice. If anyone sees that there is something wrong with this approach, chime in, but I like it so far.

+2  A: 

I think you're left with creating a route for each reserved word. For example,

routes.MapRoute("CreateRoute",
               "{controller}/Create",
                new { action = "Create" }
            );

would handle /News/Create, /Users/Create, etc. As long as this route is listed before your other custom route, I think you're covered.

I imagine you will need addition routes for various CRUD operations which will follow a similar pattern.

Ben Griswold
This is exactly what I needed, and simple too. Works a charm. Thanks!
Roger Rogers
Happy to help. Glad it worked for you.
Ben Griswold