【问题标题】:parameters in routing do not work MVC 3路由中的参数不起作用 MVC 3
【发布时间】:2012-08-05 20:52:49
【问题描述】:

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

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

这就是我的 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();
        }

    }
}

【问题讨论】:

  • iv 是否都是可选参数,或者有效的 URL 是否应该只包含两者(例如 /home/index/i/v 而不仅仅是 /home/index/i)?另外,i 是否可以保证保存一个无法转换为整数的值?
  • 可以说 i 和 v 是可选的,可以是任何东西(字符串 int 等)。还让我们考虑 id 将始终为 int。

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


【解决方案1】:

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

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

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

我也赞同 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。

cmets 后更新

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

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} 路由匹配的路由,因为从长远来看,这会使维护和调试变得更加容易。

【讨论】:

  • 我尝试了您更新的答案,但它不起作用.....但是,嘿,我真的很感激您抽出这么多时间来提供帮助。谢谢你:)
  • @developer747 没问题,但你能告诉我什么不工作吗?我有一个测试项目在这里工作。
  • 当我尝试localhost:52230/Visitor/Test/x/d 时,它说找不到资源:(
  • @developer747 在这里工作。确保您有 test 操作的对应视图:/Views/Visitor/Test.cshtml
  • @developer747 那是我的错误,我再次更新了我的答案(更新了路线并在其下方添加了一段)。我贴错了,抱歉。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    您可以使用RouteDebugger 来检查正在匹配的路由。只需使用 nuget 安装即可:

    PM> install-package RouteDebugger
    

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

    【讨论】:

      猜你喜欢
      • 2020-03-26
      • 1970-01-01
      • 1970-01-01
      • 2013-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-13
      • 1970-01-01
      相关资源
      最近更新 更多