Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
411 views
in Technique[技术] by (71.8m points)

routing - Can anyone recreate the following bug I'm experiencing in routes with 2 or more optional parameters, in .NET 4.0 / MVC3?

I know that if you think you found a bug in the .NET framework you are most likely wrong, but that's why I'm writing this question, so please hear me out.

I am fairly certain that there is a difference between the routes in .NET 3.5 and .NET 4.0 when it comes to optional parameters. Specifically if you have more than one optional parameter in your route. I have not been able to find this breaking change noted in any release notes of either .NET 4.0 or MVC 3 so thats why I call it a bug.

EDIT: This bug only manifests itself when you try to build a route url using code like the url or html helpers in mvc. If you actually request the url in a browser, in an actual mvc app, it works just fine. So if my test app below were an actual mvc app there wouldn't be a problem if you tried to request '/root/test1'.

What I need you to do is run the following test program, it should be fairly self-explanatory, but basically it just sets up a route with some optional paramters.

  1. Create a new .NET 4 console application

  2. Change the target framework to '.NET Framework 4' instead of '.NET Framework 4 Client Profile'

  3. Add references to:
    System.Web 4.0
    System.Web.Routing 4.0
    System.Web.Mvc 3.0

  4. Paste following code to the program.cs file, overwriting any previous content:

    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();
        }
    }
    
  5. Run program, and note the resulting urls.
    On my machine the result is:

    Test 1: Fail    (expected '/root/test1' but was '<null>')
    Test 2: Success ('/root/test1/test2')
    Test 3: Success ('/root/test1/test2/test3')
    
  6. Now change the target framework to .NET 3.5 add references to:
    System.Web.Mvc 2.0
    System.Web.Routing 3.5
    System.Web.Abstrations 3.5

  7. Run the program again and see the 3 test cases all succeed.
    This time the result is:

    Test 1: Success ('/root/test1')  
    Test 2: Success ('/root/test1/test2')  
    Test 3: Success ('/root/test1/test2/test3')
    

So it seems to me there is a bug in the .NET 4 or MVC 3. If you find the same issue please vote on the following issue in connect: https://connect.microsoft.com/VisualStudio/feedback/details/630568/url-routing-with-two-optional-parameters-unspecified-fails-on-asp-net-mvc3-rc2#details

Feel free to test this out in a regular MVC application if you think theres something wrong in the test program.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So, Phil Haack just released a blog post detailing that this is a known issue and will be fixed in the next release of the .NET framework, or maybe if we are lucky as a bug fix to the particular dll. I'm not exactly sure how they will fix it though. Whether they will outlaw more than 1 optional parameter, or whether they will resolve it in the manner I've outlined in the comments to Darin's answer. At least they know about it and can take steps to specify the expected behavior with more than one optional parameter more in the future.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...