3

我确定我做错了什么,但是在没有运气的情况下花了几个小时之后,如果有人可以帮助我解决这个问题,我会非常高兴。

似乎路由系统仅在第一次路由注册时才接受参数。

这就是我的 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 始终为空。但是,如果我尝试 http://localhost:52230/Home/Index?id=2 ……它会起作用。

如果我在任何其他路线之前注册主页/索引,它也可以工作。在这种情况下,稍后注册的路由在接受参数时也会出现同样的问题。

我在这里做错了什么?

更新:

我希望这两个控制器都能工作,我的路由注册会是什么样子?

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();
        }

    }
}
4

3 回答 3

2

路线从特定到一般排序。这意味着 MVC 在查看已请求的 URL 时将始终尝试匹配最具体的路由。路线将在路线列表中越往下越“贪婪”。

如果我们仔细看看有问题的两条路由,我们可以看到 MVC 无法区分这两者,除非v提供了参数。它们都有controllerandaction参数,而且它们都有一个可选的第三个参数。如果v没有提供,MVC 将无法知道要使用哪个路由,除非有这样的优先级系统,这就是路由表中路由的顺序很重要的原因。

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

我也赞同 Richard 关于使用 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}路由匹配的路由,因为从长远来看,它会使维护和调试变得更加容易。

于 2012-08-05T21:25:32.900 回答
1

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

于 2012-08-05T20:55:12.910 回答
0

您可以使用RouteDebugger检查哪些路由正在匹配。只需使用 nuget 安装它:

PM> install-package RouteDebugger

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

于 2012-08-05T20:57:54.017 回答