【问题标题】:How to successfully write an MVC Route definition如何成功编写 MVC 路由定义
【发布时间】:2013-10-12 23:07:36
【问题描述】:

谁能帮我找出问题所在,并且仍然向我解释控制器如何知道它应该使用哪个路由定义(因为在很多情况下,一个 URI 可以适应多个路由定义)?

这是我的问题...

控制器方法:

[HttpGet]
public ActionResult PreencherFormulario(int idPacientePesquisa, int idFormularioPesquisa) 

路线(所有在 Global.asax 中定义):

protected void Application_Start()
{
    RouteTable.Routes.MapRoute(
        "Busca",
        "{controller}/{action}/{SearchString}/{SearchSubString}/{id}"
    );
    RouteTable.Routes.MapRoute(
        "Participacao",
        "{controller}/{action}/{id}"
    );
    RouteTable.Routes.MapRoute(
        "ParticipacaoPesquisa",
        "{controller}/{action}/{idPesquisa}/{nrProntuario}",
        null,
        new { idPesquisa = @"\d+" }
     );

    //!!! This should be the one used...
    RouteTable.Routes.MapRoute(
        name: "PreencherForm",
        url: "{controller}/{action}/{idPacientePesquisa}/{idFormularioPesquisa}",
        defaults: new { idPacientePesquisa = 1, idFormularioPesquisa = 1 },
        constraints: new { idPacientePesquisa = @"\d+", idFormularioPesquisa = @"\d+" }
     );

    RouteTable.Routes.MapRoute(
        "AdicionarRegraCID",
        "{controller}/{action}/{a}/{b}/{c}",
        new { controller = "Pesquisas", action = "AdicionarRegraCID", MetodoResultado = "", MetodoCancelar = "" }
    );

网址:

http://localhost:61404/RealizacaoPesquisa/PreencherFormulario/1/1

错误:

The parameters dictionary contains a null entry for parameter 'idPacientePesquisa' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult PreencherFormulario(Int32, Int32)' in 'Prometheus.Controllers.RealizacaoPesquisaController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Nome do parâmetro: parameters

【问题讨论】:

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


    【解决方案1】:

    您的问题在于以下路由,该路由默认为 null,因为该路由位于您怀疑的路由之前,并且 routeurl 的格式与下一个路由的格式相同。此路由被考虑,但在路由时失败,因为您的操作参数是不可为空的 int。

      RouteTable.Routes.MapRoute(
            "ParticipacaoPesquisa",
            "{controller}/{action}/{idPesquisa}/{nrProntuario}",
            null, /*<--- This is the culprit*/
            new { idPesquisa = @"\d+" }
      );
    

    请记住路由的顺序很重要,您也应该将默认路由保留在底部。将路线上方的路线移至相关路线下方。您需要重新安排路线。这是发生了什么:

    你点击了网址:http://localhost:61404/RealizacaoPesquisa/PreencherFormulario/1/1

    它查看路由表并找到第一个匹配项

    "{controller}/{action}/{idPesquisa}/{nrProntuario}",
    

    然后它会尝试使用参数idPesquisa 调用您的操作,这就是该路由中映射的内容。

    但是您的操作需要其他名称作为参数名称,并且它们也不能为空,因此如果失败。

    【讨论】:

    • 好的,我现在明白了...但是即使我描述了一些默认值,我也无法理解这有什么帮助 - 因为两个 URL 都是完整的(所有部分都存在),默认值会没关系,对吧?
    • @MarceloMyara 问题在于路线的顺序。由于该路由模式也与您的 url 模式匹配,并且它位于预期路由之前,因此它采用第一个。这就是为什么还建议将默认路由移到底部的原因。尝试始终将更通用的路由放在底部,将特定的路由放在它们上方。
    【解决方案2】:

    首先,您要编写从更具体到更一般的路线。它使用匹配的第一个。

    所以您的问题是您的路线与此路线匹配,并且您将 idPacientPesqusa 设置为 null。

     RouteTable.Routes.MapRoute(
            "ParticipacaoPesquisa",
            "{controller}/{action}/{idPesquisa}/{nrProntuario}",
            null, <-- here!!
            new { idPesquisa = @"\d+" }
         );
    

    您似乎正在尝试为每个控制器/操作设置一个路由,以便您可以执行类似的操作

     RouteTable.Routes.MapRoute(
            name: "PreencherForm",
            url:"RealizacaoPesquisa/PreencherFormulario/{idPacientePesquisa}/{idFormularioPesquisa}",
            defaults: new { controller = "RealizacaoPesquisa", action = "PreencherFormulario", idPacientePesquisa = 1, idFormularioPesquisa = 1 },
            constraints: new { idPacientePesquisa = @"\d+", idFormularioPesquisa = @"\d+" }
         );
    

    【讨论】:

    • Jared,是的,我想到了类似的东西。不幸的是,它不起作用。我只是发现要让它工作,我必须为“控制器”和“动作”指定一个默认值,否则我会收到一个错误,指出 URL 模式中缺少动作或控制器字。
    • @MarceloMyara 啊,是的。请原谅我的复制和粘贴错误。我已经更新了我的答案。
    猜你喜欢
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多