这个MVC路线有什么问题

时间:2012-11-15 12:12:22

标签: asp.net-mvc asp.net-mvc-3 asp.net-mvc-routing

有了这个

routes.MapRoute(
    "ShowPage",
    "default.aspx/{page}/{pagetype}",
    new {
        controller = "Info",
        action = "PageASPX",
        page = "emptypage",
        pagetype = "emptypagetype"
    }
);

抓住default.aspx?page=order (我需要生成一个permanet重定向,从旧站点到我的新MVC站点)

我可以在路由调试器中看到匹配的路由,但是路由中没有得到任何值

Key          Value
page         emptypage 
pagetype     emptypagetype 
controller   Info 
action       PageASPX 

怎么了?

1 个答案:

答案 0 :(得分:1)

MVC路由定义具有URL段。您的路线如下:

default.aspx/{page}/{pagetype}

这意味着像default.aspx/order这样的请求应该在路由解析期间填充page值,因为它是作为URL段提供的。这并不意味着稍后在模型绑定发生并且调用控制器操作时将不会填充page

如果您的控制器操作签名与此类似:

public ActionResult PageASPX(string page, string pagetype)
{
    ...
}

即使您将它们作为查询变量而非URL段提供,这两个参数仍可能会被填充。唯一的要求是路由不提供缺失段值的默认值(或者它们被设置为可选)。然后,默认MVC模型绑定器将使用实际查询变量值填充page操作参数。

所以最重要的是你应该改变路由定义(参见我的回答的最后一节)。

应该有效的请求

为了让您的路由能够识别pagepagetype网址段变量,您的请求应如下所示:

default.aspx/somepage
default.aspx/somepage/sometype

如果您的路由没有定义pagepagetype的默认值,那么当您的请求看起来时,您的控制器操作会获得pagepagetype参数的正确值像:

default.aspx/somepage
default.aspx/somepage/sometype
default.aspx?page=somepage
default.aspx?pagetype=sometype
default.aspx?page=somepage&pagetype=sometype

混合路由值和查询字符串变量

正如我的测试所示,当Asp.net MVC有一个值(在URL本身作为段或路由默认值提供)时,它不提供路由值覆盖。在您的情况下,如果您要求此URL:

default.aspx/routepage?page=querypage

您的操作方法会看到page参数的值为 routepage 始终

更重要的一点是当您在路由定义中提供默认值时,即使从URL中省略它,您也无法将其设置为查询字符串。要避免此问题,您有两种选择:

  1. pagepagetype设置为UrlParameter.Optional,这将允许您在URL不具有查询字符串变量时覆盖其值 - 这意味着您始终可以仅使用网址细分或查询字符串,但不能同时使用两者,因为网址细分优先于

  2. 具有不同的URL段变量和查询字符串变量的名称 - 缺点是您需要使用双参数执行操作,这是不受欢迎的:

    public ActionResult PageASPX(string routePage, string routeType, string queryPage, string queryType)
    {
        string page = routePage ?? queryPage ?? string.Empty;
        string type = routeType ?? queryType ?? string.Emtpy;
        ...
    }
    
  3. 最佳解决方案

    更改路由,以便为作为URL段提供的变量提供单独的路由定义,为提供作为查询字符串变量的变量提供另一个路由定义。然后将这些路由连接到相同的控制器操作,只要所有变量(在段和查询字符串中)共享相同的名称:

    route.MapRoute(
        "InSegmentsBoth",
        "default.aspx/{page}/{pagetype}",
        new { controller = "Info", action = "PageASPX" }
    );
    route.MapRoute(
        "InSegmentsPage",
        "default.aspx/{page}",
        new { controller = Info"", action = "PageASPX" }
    );
    route.MapRoute(
        "InQueryString",
        "default.aspx",
        new { controller = "Info", action = "PageASPX" }
    );
    

    如果您的请求提供了值(段和查询变量),如

    default.aspx/segmentpage?page=querypage
    

    然后细分值具有优先级,因此对于此请求,操作参数page将具有 segmentpage 的值。