ASP.NET MVC 3.0 Routing behaviour

蓝咒 提交于 2019-12-24 19:28:24

问题


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 = @"\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


回答1:


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


来源:https://stackoverflow.com/questions/7283622/asp-net-mvc-3-0-routing-behaviour

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!