如何成功编写MVC路由定义

时间:2013-10-12 23:07:36

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

有人可以帮我找出错误并且仍然向我解释控制器如何知道它应该使用哪个路由定义(因为在很多情况下,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

2 个答案:

答案 0 :(得分:1)

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

  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调用你的动作,这是在这条路线中映射的。

但是你的动作期望其他东西作为参数名称,并且它们也是不可为空的,因此如果失败。

答案 1 :(得分:1)

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

所以你的问题是你的路线与这条路线匹配,你将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+" }
     );