Может кто-нибудь воссоздать следующую ошибку, с которой я сталкиваюсь в маршрутах с 2 или более дополнительными параметрами, в .NET 4.0 / MVC3? - PullRequest
6 голосов
/ 31 января 2011

Я знаю, что если вы считаете, что нашли ошибку в .NET Framework, вы, скорее всего, ошибаетесь, но именно поэтому я пишу этот вопрос, поэтому, пожалуйста, выслушайте меня.

Я совершенно уверенчто есть разница между маршрутами в .NET 3.5 и .NET 4.0, когда дело касается необязательных параметров.В частности, если у вас есть несколько дополнительных параметров в вашем маршруте.Мне не удалось найти это критическое изменение, отмеченное в каких-либо примечаниях к выпуску .NET 4.0 или MVC 3, поэтому я называю это ошибкой.

РЕДАКТИРОВАТЬ: Эта ошибка проявляется толькосам, когда вы пытаетесь построить URL-адрес маршрута, используя код, такой как url ​​или html помощники в mvc.Если вы действительно запрашиваете URL в браузере, в реальном приложении mvc, это работает просто отлично.Так что, если бы мое тестовое приложение, приведенное ниже, было настоящим приложением mvc, не было бы проблемы, если бы вы попытались запросить '/root/test1'.

. Мне нужно, чтобы вы запустили следующую тестовую программу:должно быть достаточно понятным, но в основном он просто устанавливает маршрут с некоторыми необязательными параметрами.

  1. Создание нового консольного приложения .NET 4

  2. Измените целевую платформу на «.NET Framework 4» вместо «.NET Framework 4 Client Profile»

  3. Добавьте ссылки на:
    System.Web 4.0
    Система.Web.Routing 4.0
    System.Web.Mvc 3.0

  4. Вставьте следующий код в файл 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();
        }
    }
    
  5. Запустите программу и запишите получающиеся URL.
    На моем компьютере результат будет:

    Test 1: Fail    (expected '/root/test1' but was '<null>')
    Test 2: Success ('/root/test1/test2')
    Test 3: Success ('/root/test1/test2/test3')
    
  6. Теперь измените целевую платформу на .NET 3.5 addссылки на:
    System.Web.Mvc 2.0
    System.Web.Routing 3.5
    System.Web.Abstrations 3.5

  7. Запустите программу еще раз и увидите, что все 3 теста успешно завершены.
    На этот раз результат будет следующим:

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

Так что мне кажется, что естьошибка в .NET 4 или MVC 3. Если вы обнаружите ту же проблему, пожалуйста, проголосуйте за следующую проблему в Connect: https://connect.microsoft.com/VisualStudio/feedback/details/630568/url-routing-with-two-optional-parameters-unspecified-fails-on-asp-net-mvc3-rc2#details

Не стесняйтесь проверить это в обычном приложении MVC, если вы думаете, что-то естьнеправильно в тестовой программе.

Ответы [ 2 ]

4 голосов
/ 21 февраля 2011

Итак, Фил Хаак только что выпустил сообщение в блоге , в котором подробно описывается, что это известная проблема, и она будет исправлена ​​в следующем выпуске .NET Framework, или, возможно, если нам повезет, как исправление ошибки конкретная длл. Я не совсем уверен, как они это исправят, хотя. Будут ли они запрещать более 1 необязательного параметра или разрешат ли они его так, как я обрисовал в комментариях к ответу Дарина. По крайней мере, они знают об этом и могут предпринять шаги для определения ожидаемого поведения с более чем одним необязательным параметром в будущем.

2 голосов
/ 31 января 2011

Только последний параметр определения маршрута может быть необязательным, и это правило было применено в ASP.NET MVC 3. В вашем примере у вас есть необязательные значения test2 и test3, что невозможно.Рассмотрим следующий URL:

root/test1/test2

С учетом этого URL механизм маршрутизации не может сказать, test2="test2" and test3="" или test2="" and test3="test2".Так зачем генерировать URL-адрес, который никогда не сможет быть проанализирован обратно в составляющие его токены?

Теперь, может быть, это ошибка или особенность, или называйте ее как угодно, но во всех случаях следует избегать таких маршрутов.ИМХО ошибка здесь в том, что фреймворк не выдает исключение, говорящее вам, что только последний параметр в определении маршрута может быть необязательным, но, конечно, это только мое мнение.

...