使用此正则表达式时,为什么忽略ASP.NET-MVC Routing的UrlParameter.Optional?

时间:2011-02-10 15:01:54

标签: asp.net-mvc regex asp.net-mvc-2 routing url-routing

这是我今天早上使用ASP.NET MVC的URL路由时遇到的问题的简要示例。

相当简单,我想要调用路径的动作,无论是否提供了最后的参数。

此路线正常,与 / apple / / apple / test /

相匹配
routes.MapRoute(
    "Working Route",
    "apple/{parameter}",
    new { 
        controller = "Apple", 
        action = "Action", 
        parameter = UrlParameter.Optional
    },
    new { parameter = @"([a-z0-9\.-]+)" }
);

但是,第二条路线只会匹配 / banana / test / 等。当我尝试 / banana / 时,路由器只是直接通过它并返回全部404错误。

routes.MapRoute(
    "Non-Working Route",
    "banana/{parameter}",
    new { 
        controller = "Banana", 
        action = "Action", 
        parameter = UrlParameter.Optional
    },
    new { parameter = @"([a-z0-9]+)" }
);

唯一的区别是参数的正则表达式验证,但由于它是一个非常简单的正则表达式匹配,它们应该对像 / banana / 这样的URL完全正常工作,但第二条路线只是失败认识到它。

我通过改变路线#2上的正则表达式以匹配路线#1上的正则表达式来解决我的问题,并接受'。'和' - '字符,我只是想知道是否有人知道为什么这似乎正在发生。

编辑:

以下是我用于示例的控制器和操作。没什么好看的。

public class AppleController : Controller
{
    public ActionResult Action(string parameter)
    {
        if (parameter == null)
        {
            parameter = "No parameter specified.";
        }
        ViewData["parameter"] = parameter;
        return View();
    }
}

public class BananaController : Controller
{
    public ActionResult Action(string parameter)
    {
        if (parameter == null)
        {
            parameter = "No parameter specified.";
        }
        ViewData["parameter"] = parameter;
        return View();
    }
}

所以我的问题是 / apple / 会显示“没有指定参数。”,而 / banana / 会给我一个不需要的404。

<小时/> 到目前为止..

在路线声明中使用 parameter = URLParameter.Optional : 路线#1运行良好,没有参数,路线#2不匹配。

在路线声明中使用参数=“”: 路线#1和路线都是当参数不在URL时,路径#2无法匹配。

在Action方法签名中声明 parameter =“”: 由于.NET版本不可能。

删除所有其他路线无效。

2 个答案:

答案 0 :(得分:4)

如果令牌是可选的,那么您使用的任何正则表达式约束也必须反映,例如(foo)?

<小时/> 我能够在.NET 4上使用ASP.NET MVC 2重现这个问题。然后我升级到ASP.NET MVC 3,一切都按预期工作。我上面提到的解决方案不适用于ASP.NET MVC 2,但它适用于ASP.NET MVC 3,因此我只能假设这是v2上的一个错误,现在已在v3中修复。

您可以引用v2,并在web.config上使用它来测试v3:

<runtime>
   <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
         <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
         <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
   </assemblyBinding>
</runtime>

答案 1 :(得分:0)

第二次编辑

匹配〜/ fruit /和~fruit / apple

routes.MapRoute(
    "Working Route",
    "Fruit/{fruit}",
    new
    {
        controller = "Fruit",
        action = "Index",
        fruit = ""
    },
    new { fruit = @"([a-z0-9\.-]+)" }
);

public ActionResult Index(string fruit)
{
    ViewData["fruit"] = !String.IsNullOrEmpty(fruit) ? fruit : "None specified.";
    return View();
}

匹配〜/ banana /和〜/ banana / yellow

routes.MapRoute(
    "Non-Working Route",
    "Banana/{color}",
    new
    {
        controller = "Banana",
        action = "Index",
        color = ""
    },
    new { color = @"([a-z0-9]+)" }
);

public ActionResult Index(string color)
    {
        ViewData["Color"] = color;
        return View();
    }

第一次编辑

尝试在动作签名上实际将参数设置为可选,例如:string parameter = ""


我没有得到那种行为。当你描述它们时,这两条路线都适用于我(如果我在路线上添加“ - ”,则第二条路线会抛出404,但这是预期的)。你的行动方法签名是什么样的?

我将路线(和控制器/视图)设置为:

routes.MapRoute(
    "Working Route",
    "Fruit/{fruit}",
    new
    {
        controller = "Fruit",
        action = "Index",
        fruit = UrlParameter.Optional
    },
    new { fruit = @"([a-z0-9]+)" }
);

我的Index()动作如下:

public ActionResult Index(string fruit = "")
{
    ViewData["fruit"] = fruit;
    return View();
}