.net 4.0 任何人都可以重新创建以下bug I';我在.NET 4.0/MVC3中遇到了具有2个或更多可选参数的路由?

.net 4.0 任何人都可以重新创建以下bug I';我在.NET 4.0/MVC3中遇到了具有2个或更多可选参数的路由?,.net-4.0,routing,asp.net-mvc-3,asp.net-mvc-routing,.net 4.0,Routing,Asp.net Mvc 3,Asp.net Mvc Routing,我知道如果你认为你在.NET框架中发现了一个bug,那么你很可能是错的,但这就是我为什么要写这个问题的原因,所以请听我说完 我相当肯定.NET3.5和.NET4.0中的路由在可选参数方面存在差异。特别是当路由中有多个可选参数时。我在.NET 4.0或MVC 3的任何发行说明中都找不到这种突破性的变化,所以我称之为bug EDIT:只有当您尝试使用诸如mvc中的url或html帮助程序之类的代码构建路由url时,才会出现此错误。如果你真的在浏览器中请求url,在实际的mvc应用程序中,它可以正常工

我知道如果你认为你在.NET框架中发现了一个bug,那么你很可能是错的,但这就是我为什么要写这个问题的原因,所以请听我说完

我相当肯定.NET3.5和.NET4.0中的路由在可选参数方面存在差异。特别是当路由中有多个可选参数时。我在.NET 4.0或MVC 3的任何发行说明中都找不到这种突破性的变化,所以我称之为bug

EDIT:只有当您尝试使用诸如mvc中的url或html帮助程序之类的代码构建路由url时,才会出现此错误。如果你真的在浏览器中请求url,在实际的mvc应用程序中,它可以正常工作。因此,如果我下面的测试应用程序是一个实际的mvc应用程序,那么如果您尝试请求“/root/test1”,就不会出现问题

我需要你做的是运行下面的测试程序,它应该是相当自解释的,但基本上它只是设置了一个带有一些可选参数的路由

  • 创建新的.NET4控制台应用程序

  • 将目标框架更改为“.NET framework 4”,而不是“.NET framework 4客户端配置文件”

  • 添加对以下内容的引用:
    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();
        }
    }
    
  • 所以在我看来,在.NET4或MVC3中似乎有一个bug。如果您发现相同的问题,请在connect中对以下问题进行投票:


    如果您认为测试程序中有问题,可以在常规MVC应用程序中测试此问题。

    只有路由定义的最后一个参数是可选的,并且此规则已在ASP.NET MVC 3中强制执行。在您的示例中,
    test2
    test3
    都是可选的,这是不可能的。考虑下面的URL:

    root/test1/test2
    
    给定此URL,路由引擎无法说明是
    test2=“test2”和test3=”“
    还是
    test2=“”和test3=“test2”
    。那么,为什么要生成一个永远无法解析回其组成标记的URL呢


    现在,也许这是一个bug或一个特性,或者叫它什么的,但在所有情况下,你都应该避免这样的路由。这里的错误是框架没有抛出异常,告诉您只有路由定义中的最后一个参数是可选的,但这当然只是我的意见。

    因此,Phil Haack刚刚发布了一个详细说明,这是一个已知问题,将在下一版本的.NET framework中修复,或者,如果幸运的话,我们可以修复特定dll的错误。不过,我不确定他们将如何解决这个问题。他们是否会取缔一个以上的可选参数,或者他们是否会按照我在对Darin答案的评论中概述的方式解决它。至少他们知道这一点,并且可以采取措施在将来使用多个可选参数指定预期行为。

    你好,Darin,谢谢你的回答。在您的示例中,MVC2将设置test2=“test2”,这是解决问题的直观方法,并且允许几个可选参数。我不明白,只要有明确的文件记录,将其指定为可接受的解决方案会有什么问题。正如你所说,很难知道它是否是一个bug。我唯一可以肯定的是,MVC2和MVC3之间存在一个未记录的(突破性的)差异。此外,MVC3中的路由引擎正确路由特定url没有问题。。。是url生成失败了。@JohannesH,我同意你的意见,就是有一个未记录的更改。但当你谈论一种直观的解决问题的方法时,我不同意你的观点:对我来说,两者都是同样可能的。如果
    test2
    可以为空,并且我们想给
    test3
    一个值,那么为什么这是一种直观的方法呢?你会怎么做?如果两者都是可选的,那么这只是一种情况:
    test2
    为空,
    test3
    有一个值,假设请求此url:
    root/test1/test2
    。对我来说,直观的规则是:“必须按照使用的顺序指定可选参数。”。我同意在指定test3而不是test2的情况下,应该抛出一些异常。在MVC2中,仅将test2参数值设置为“test2”时调用Url.Action的结果就是Url:“/root/test1/test2”,我喜欢这样。但是,只使用test3参数值(设置为“test3”)调用Url.Action会导致Url:“/root/test1/System.Web.Mvc.UrlParameter/test3”,正如我所说,在这种情况下,我宁愿让它抛出一个异常。我相信@Darin Dimitrov关于UrlParameter是错误的。可选误用。这应该是一个错误。文档中没有提到管线定义中最后一个可选参数。同时,C#4.0允许许多方法的可选参数-
    Test 1: Success ('/root/test1')  
    Test 2: Success ('/root/test1/test2')  
    Test 3: Success ('/root/test1/test2/test3')
    
    root/test1/test2