开发者

ASP.NET MVC 3.0 Routing behaviour

I have controller BlogController with a couple of actions:

1)Index(string id) - show all posts/show single post if parameter id specified
2)New() - add new post
3)Delete() - delete post
4)And some more another actions

So if i type in browser mysite/blog i could see all posts if i type mysite/blog/postnameid i want to see single post.

the problem is when i type mysite/blog/postnameid it is not working (The resource cannot be found.), but if i type mysite/blog/index/postnameid this way it is working. How could i make mysite/blog/postnameidto work as well.

Here is my blog route in global.ascx

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

            routes.MapRouteLowercase(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
            );

Than if i change it like that

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

the mysite/blog/postnameid working but all another actions like New(), Delete() stop working after that (The resource cannot be found. )

UPDATE: I forgot to mention that id is sting, not int. so from @Darin answer i changed new { id = @"\w+" } to new { id = @开发者_C百科"\d+" } and all seams to be working but now when i typed blog/new for example, it is routing to show/new insteard blog/new


It is a bad idea and against RESTful conventions to have a single controller action that do 2 things and of course violating the single responsibility principle (list all posts if no id is specified and show a given post if an id is specified). The correct way would be to have the following:

  • /blog => BlogController/Index => list all posts
  • /blog/123 => BlogController/Show(id = 123) => show details of a given post
  • /blog/new => BlogController/New() => start writing a new post
  • /blog/delete/123 => BlogController/Delete(id = 123) => delete given post

which would be achieved with the following routes:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Blog",
        "blog/{id}",
        new { controller = "Blog", action = "Show" },
        new { id = @"\d+" }
    );

    routes.MapRoute(
        "Default",
        "blog/{action}/{id}",
        new { controller = "Blog", action = "Index", id = UrlParameter.Optional }
    );
}

Notice the required route constraint on the first definition which indicates what form all ids must be so that the routing engine could disambiguate between an id and an action name.

This being said if you want to violate the 2 principles I mentioned earlier and have the routes you want a slight adaptation would be required:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Blog",
        "blog/{id}",
        new { controller = "Blog", action = "Index" },
        new { id = @"\d+" }
    );

    routes.MapRoute(
        "Default",
        "blog/{action}/{id}",
        new { controller = "Blog", action = "Index", id = UrlParameter.Optional }
    );
}

Now:

  • /blog => BlogController/Index(id = null) => list all posts
  • /blog/123 => BlogController/Index(id = 123) => show details of a given post
  • /blog/new => BlogController/New() => start writing a new post
  • /blog/delete/123 => BlogController/Delete(id = 123) => delete given post
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜