首页 文章

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

提问于
浏览
3

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

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

这条路线工作正常,匹配 /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/ 时,路由器只是正好通过它并返回catch-all 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/ 会显示"No parameter specified.",而 /banana/ 会给我一个不受欢迎的404 .


到目前为止..

在Route声明中使用 parameter = URLParameter.Optional :Route#1完美运行,没有参数,Route#2不匹配 .

在Route声明中使用 parameter = "" :当参数不在URL时,Route#1和Route#2都不匹配 .

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

删除所有其他路由无效 .

2 回答

  • 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>
    
  • 0

    第二次编辑

    匹配〜/水果/和〜水果/苹果

    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();
    }
    

相关问题