路由中的参数不适用于MVC 3

时间:2012-08-05 20:52:49

标签: c# asp.net-mvc asp.net-mvc-routing

我确信我做错了什么,但是花了几个小时就没有运气,如果有人可以帮我解决这个问题,我会很高兴。

似乎路由系统仅在第一次路由注册中表示参数。

这就是我的global.asax.cs的样子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcApplication4
{


    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

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

            routes.MapRoute(
                     "t", // Route name
                     "{controller}/{action}/{i}/{v}",  
                     new { i = UrlParameter.Optional, v = UrlParameter.Optional }  
                 );

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", 
                new {  id = UrlParameter.Optional } 
            );





        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

这就是家庭控制器的样子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication4.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index(int? id)
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";

            return View();
        }

        public ActionResult About(int? a)
        {
            return View();
        }



    }
}

问题是当我尝试这个网址时

http://localhost:52230/Home/Index/2

id始终为null。但是,如果我尝试 http://localhost:52230/Home/Index?id=2 ....它有效。

如果我在任何其他路线之前注册home / index,它也有效。在这种情况下,稍后注册的路线在接受参数时会遇到同样的问题。

我在这里做错了什么?

更新

我希望这两个控制器都能正常工作,我的路线注册怎么样?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication4.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index(int? id)
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";

            return View();
        }




    }
}

第二个控制器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication4.Controllers
{
    public class VisitorController : Controller
    {
        //
        // GET: /VisitorSecurityPoints/


        public ActionResult Test(string i,string v)
        {

            return View();
        }

    }
}

3 个答案:

答案 0 :(得分:2)

路线按特定顺序排列。这意味着当查看已请求的URL时,MVC将始终尝试匹配最具体的路由。路线列表中的路线将越来越“贪婪”。

如果我们仔细研究一下有问题的两条路线,我们可以看到除非提供v参数,否则MVC无法区分这两条路线。它们都具有controlleraction参数,并且它们都具有可选的第三个参数。如果没有提供v,MVC将无法知道使用哪条路由,除非这样的优先级系统到位,这就是为什么路由表中路由的顺序很重要。

有一些方法可以让MVC区分这样的两条路由,但这取决于相关参数的数据类型。例如,如果iDateTime而不是int,则可以添加仅与日期匹配的Route Constraint。有关约束的更多信息,请参阅this文章。

我也是理查德关于使用RouteDebugger的建议。它对于帮助理解诸如此类的情况非常有用,并且可以实现更清晰的路由表设计。

修改

我还应该提一下,当你在末尾标记?id=2时,URL“工作”的原因是因为MVC尝试将绑定模型直接建模到查询字符串中的匹配操作参数。但是,请注意,匹配路由的参数将优先于查询字符串中提供的值。例如,使用以下路线:

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

导航至http://localhost:50754/home/index/2将导致id为2 导航至http://localhost:50754/home/index/?id=4将导致id为4 导航至http://localhost:50754/home/index/2?id=4将导致id为2.

评论后更新

解决特定问题的最简单方法是更改​​路由表以包含以下路由:

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

    routes.MapRoute(
        "visitors", // Route name
        "visitor/{action}/{i}/{v}", // URL with parameters
        new
        {
            controller = "Visitor", action = "Test",
            i = UrlParameter.Optional, v = UrlParameter.Optional
        }
    );

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

请注意,此新路由中仍存在{action}参数。这样可以更容易地扩展它以满足控制器中的其他操作。如果需要将路径约束到控制器上存在的操作,则需要添加前面提到的路径约束。

这种方法的一个警告是,如果您经常指定新路由以匹配几个URL,则路由表可以非常快速地增长。这可能会因为现有路由而更难以向站点添加新功能,并且还可能使维护更加困难。只要有可能,您应该尝试设计一个匹配默认{controller}/{action}/{id}路由的路由,因为从长远来看,它使维护和调试变得更加容易。

答案 1 :(得分:1)

我相信它是因为你的其他路线(“t”)首先匹配。

答案 2 :(得分:0)

您可以使用RouteDebugger检查匹配的路线。只需使用nuget安装它:

PM> install-package RouteDebugger

当您查看该页面时,它将列出您的所有路线并指出哪些路线匹配。将使用第一个匹配的路线。