Asp.net mvc 3 ASP.NET MVC 3.0路由行为

Asp.net mvc 3 ASP.NET MVC 3.0路由行为,asp.net-mvc-3,routing,asp.net-mvc-routing,Asp.net Mvc 3,Routing,Asp.net Mvc Routing,我有一个控制器BlogController,它有两个操作: 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 因此,如果我在浏览器中键入mysite/blog,如果我键入mysite/blog/postnameid我想查看单个帖子

我有一个控制器BlogController,它有两个操作:

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
因此,如果我在浏览器中键入
mysite/blog
,如果我键入
mysite/blog/postnameid
我想查看单个帖子,那么我可以看到所有帖子

问题是当我键入
mysite/blog/postnameid
时,它是不工作的(
找不到资源。
),但如果我这样键入
mysite/blog/index/postnameid
,它就工作了。我怎样才能使
mysite/blog/postnameid
也起作用呢

这是我在
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 } 
            );
如果我这样改变的话

routes.MapRouteLowercase(
               "Blog", // Route name
               "Blog/{id}", // URL with parameters
               new { controller = "Blog", action = "Index" } // Parameter defaults
            );
mysite/blog/postnameid
正在工作,但所有其他操作(如New()、Delete())在该操作之后停止工作(
找不到资源。

更新:
我忘了提到id是sting,而不是int。所以从@Darin answer我将
new{id=@“\w+”}
更改为
new{id=@“\d+”}
并且所有接缝都在工作,但现在当我键入
blog/new
时,它被路由到
show/new
insteard
blog/new

让一个控制器执行两件事,当然违反了单一责任原则(如果没有指定id,则列出所有帖子;如果指定id,则显示给定帖子),这是一个坏主意,也是违反RESTful约定的。正确的方法是:

  • /blog
    =>BlogController/Index=>列出所有帖子
  • /blog/123
    =>BlogController/Show(id=123)=>显示给定帖子的详细信息
  • /blog/new
    =>BlogController/new()=>开始写一篇新文章
  • /blog/delete/123
    =>BlogController/delete(id=123)=>删除给定帖子
这将通过以下途径实现:

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 }
    );
}
请注意第一个定义上的必需路由约束,它指示所有id必须是什么形式,以便路由引擎可以消除id和操作名称之间的歧义

这就是说,如果您想要违反我前面提到的2条原则,并且拥有您想要的路线,则需要进行轻微的调整:

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 }
    );
}
现在:

  • /blog
    =>BlogController/Index(id=null)=>列出所有帖子
  • /blog/123
    =>BlogController/Index(id=123)=>显示给定帖子的详细信息
  • /blog/new
    =>BlogController/new()=>开始写一篇新文章
  • /blog/delete/123
    =>BlogController/delete(id=123)=>删除给定帖子

有趣的是,感谢您如此详细的回复,所以默认路由它将只处理博客内容,但如果我需要另一个类似于博客路由行为的路由,在这种情况下,我不能有两个“默认”路由映射,不是吗?url/博客不能映射到两个不同的默认路由,这将是不可能的,也没有意义。但是,您可以使用另一个路由,如/page,它将默认为默认页面或其他内容。同样根据Darin的建议,我只会做出一个区别,并将列出帖子的路线命名为/posts。或者,如果您有一个名为“blog”的区域,那么它将是/blog/posts。我喜欢结尾的s表示多重性一些moere细节,我的id是stirng,但是当我键入int时,它工作了
/blog/123
,但是
blog/slagur
没有,我怎么能用字符串参数工作呢?@jason,字符串模式有问题,因为路由引擎无法在
/blog/slagurl
/blog/new
之间消除歧义。他不可能知道,在第一种情况下,您谈论的是一个id,在第二种情况下,您谈论的是一个动作名称。像
\d+
这样的路由约束只有在允许您消除URL歧义时才起作用。看来这不是你的情况。因此,为了解决这个问题,您可以通过从
Route
类派生并重写
GetRouteData
方法来编写自定义
Route
http://nblog.codeplex.com/
,它们有相似之处,但它们使用的路由定义略有不同,我不可能像他们一样,我想。