我知道如果您认为在.NET框架中发现了一个错误,那么您很可能是错的,但这就是我写这个问题的原因,所以请听我说。
我很确定.NET 3.5和.NET 4.0中的路由在可选参数方面存在差异。特别是如果您的路线中有多个可选参数。我无法在.NET 4.0或MVC 3的任何发行说明中找到这种突破性更改,因此我将其称为错误。
编辑:当您尝试使用mvc中的url或html帮助程序等代码构建路径网址时,此错误仅会显示。如果您实际在浏览器中请求网址,在实际的mvc应用程序中,它可以正常工作。因此,如果我的测试应用程序是真正的mvc应用程序,那么如果您尝试请求'/ root / test1'就不会有问题。
我需要你做的是运行以下测试程序,它应该是相当不言自明的,但基本上它只是设置一个带有一些可选参数的路径。
创建新的.NET 4控制台应用程序
将目标框架更改为“.NET Framework 4”而不是“.NET Framework 4 Client Profile”
添加引用:
System.Web 4.0
System.Web.Routing 4.0
System.Web.Mvc 3.0
将以下代码粘贴到program.cs文件中,覆盖以前的任何内容:
using System;
using System.IO;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
public class Program
{
static void Main()
{
var httpCtx = new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://localhost/", null), new HttpResponse(new StringWriter())));
var routes = RouteTable.Routes;
routes.MapRoute("Test", "root/{test1}/{test2}/{test3}", new { test2 = UrlParameter.Optional, test3 = UrlParameter.Optional });
var context = new RequestContext(httpCtx , new RouteData());
var url = new UrlHelper(context);
var expected1 = "/root/test1";
var expected2 = "/root/test1/test2";
var expected3 = "/root/test1/test2/test3";
var actual1 = url.RouteUrl("Test", new { test1 = "test1" });
var actual2 = url.RouteUrl("Test", new { test1 = "test1", test2 = "test2" });
var actual3 = url.RouteUrl("Test", new { test1 = "test1", test2 = "test2", test3 = "test3" });
var result1 = actual1 == expected1;
var result2 = actual2 == expected2;
var result3 = actual3 == expected3;
Console.WriteLine("Test 1: {0} ({1})", result1 ? "Success" : "Fail", result1 ? string.Format("'{0}'", actual1) : string.Format("Expected '{0}' but was '{1}'", expected1, actual1 ?? "<null>"));
Console.WriteLine("Test 2: {0} ({1})", result2 ? "Success" : "Fail", result2 ? string.Format("'{0}'", actual2) : string.Format("Expected '{0}' but was '{1}'", expected2, actual2 ?? "<null>"));
Console.WriteLine("Test 3: {0} ({1})", result3 ? "Success" : "Fail", result3 ? string.Format("'{0}'", actual3) : string.Format("Expected '{0}' but was '{1}'", expected3, actual3 ?? "<null>" ));
Console.ReadLine();
}
}
运行程序,并记下生成的网址 在我的机器上,结果是:
Test 1: Fail (expected '/root/test1' but was '<null>')
Test 2: Success ('/root/test1/test2')
Test 3: Success ('/root/test1/test2/test3')
现在将目标框架更改为.NET 3.5添加对以下内容的引用:
System.Web.Mvc 2.0
System.Web.Routing 3.5
System.Web.Abstrations 3.5
再次运行程序,看到3个测试用例全部成功 这次的结果是:
Test 1: Success ('/root/test1')
Test 2: Success ('/root/test1/test2')
Test 3: Success ('/root/test1/test2/test3')
所以在我看来.NET 4或MVC 3中存在一个错误。如果您发现同样的问题,请在连接中对以下问题进行投票:https://connect.microsoft.com/VisualStudio/feedback/details/630568/url-routing-with-two-optional-parameters-unspecified-fails-on-asp-net-mvc3-rc2#details
如果您认为测试程序中存在错误,请随意在常规MVC应用程序中对此进行测试。
答案 0 :(得分:4)
所以,Phil Haack刚刚发布了一个blog post详细说明这是一个已知问题,将在.NET框架的下一个版本中修复,或者如果我们幸运的话,可以修复特定的dll 。我不确定他们将如何修复它。他们是否会取缔一个以上的可选参数,或者他们是否会按照我在Darin的答案评论中概述的方式解决它。至少他们知道它并且可以采取措施来指定未来更多可选参数的预期行为。
答案 1 :(得分:2)
只有路由定义的最后一个参数可以是可选的,并且此规则已在ASP.NET MVC 3中强制实施。在您的示例中,您同时选择test2
和test3
这是不可能的。请考虑以下网址:
root/test1/test2
根据此网址,路由引擎无法说明test2="test2" and test3=""
还是test2="" and test3="test2"
。那么为什么要生成一个永远无法解析为其成分标记的URL呢?
现在也许这是一个错误或一个功能或调用它,但在所有情况下你应该避免使用这样的路线。恕我直言这里的错误是框架没有抛出异常,告诉你只有路由定义中的最后一个参数是可选的,但当然这只是我的看法。