8

При попытке создать захват всего маршрута в MVC 4 (что-то я нашел несколько примеров и основал мой код), он возвращает ошибку 404. Я запускаю это на IIS 7.5. Это похоже на прямое решение, и что мне не хватает?MVC 4 поймать весь маршрут, который никогда не был достигнут

Одно замечание, если я переведу маршрут «CatchAll» выше маршрута «По умолчанию», он работает. Но, конечно же, никто из других контроллеров не достигнут.

Вот код:

Route.Config:

 routes.MapRoute(
      name: "Default", 
      url: "{controller}/{action}/{id}", 
      defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
     ); 

     routes.MapRoute(
      "CatchAll", 
      "{*dynamicRoute}", 
      new { controller = "CatchAll", action = "ChoosePage" } 
     ); 

Контроллер:

public class CatchAllController : Controller 
{ 

    public ActionResult ChoosePage(string dynamicRoute) 
    { 
     ViewBag.Path = dynamicRoute; 
     return View(); 
    } 

} 

ответ

9

Поскольку конечная целью создания маршрута приема всего должны была быть в состоянии обрабатывать динамические URL, и я не смог найти прямой ответ на оригинальный вопрос выше, я подошел к моим исследованиям с другой точки зрения. При этом я наткнулся на этот блог: Custom 404 when no route matches

Это решение позволяет обработку нескольких секций в пределах данного URL (т.е. www.mysite.com/this/is/a/dynamic/route)

Здесь является окончательным кодом пользовательского контроллера:

public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) 
{ 
    if (requestContext == null) 
    { 
     throw new ArgumentNullException("requestContext"); 
    } 

    if (String.IsNullOrEmpty(controllerName)) 
    { 
     throw new ArgumentException("MissingControllerName"); 
    } 

    var controllerType = GetControllerType(requestContext, controllerName); 

    // This is where a 404 is normally returned 
    // Replaced with route to catchall controller 
    if (controllerType == null) 
    { 
     // Build the dynamic route variable with all segments 
     var dynamicRoute = string.Join("/", requestContext.RouteData.Values.Values); 

     // Route to the Catchall controller 
     controllerName = "CatchAll"; 
     controllerType = GetControllerType(requestContext, controllerName); 
     requestContext.RouteData.Values["Controller"] = controllerName; 
     requestContext.RouteData.Values["action"] = "ChoosePage"; 
     requestContext.RouteData.Values["dynamicRoute"] = dynamicRoute; 
    } 

    IController controller = GetControllerInstance(requestContext, controllerType); 
    return controller; 
} 
+2

Это хорошо работает. Вы можете избежать foreach и подстроки, если вы это сделаете: 'var dynamicRoute = string.Join ("/", requestContext.RouteData.Values.Values);' –

+0

Хорошо назовите Натана. Некоторое время назад я посмотрел на этот код. Я всегда нахожу способы улучшить старый код. Это, безусловно, один из тех времен. Я обновил ответ с вашим предложением. Благодаря! – gsxrboy73

+0

SO отлично подходит для этого, я узнаю что-то почти каждый раз, когда я прихожу сюда. Этот код был отличным, я пытался понять, хочу ли я обращаться с этим в базовом контроллере, но его продвижение на фабрику контроллеров - это лучшая идея! –

4

Это, вероятно, потому, что любой маршрут вы как раз тестируем с сопрягает ваш 1-ый - по умолчанию маршрут. Как работает маршрутизация в MVC, любой адрес, который вы передаете, будет пытаться сопоставить маршруты в вашей коллекции маршрутов в порядке их появления. Как только он найдет первый соответствующий маршрут, он прекратит дальнейшее выполнение. В этом случае ваш маршрут по умолчанию - первый в списке, поэтому, если он соответствует вашему второму маршруту, он никогда не будет проверен.

Впишите в адресную строку что-то вроде http://www.mysite.com/Home/Testing/Item/Page, и это не должно соответствовать вашему маршруту по умолчанию, а затем попытаться выполнить маршрут CatchAll.

+1

Это маршрут, который я тестирую: http://mysite.com/hello, для которого у меня нет контроллеров. – gsxrboy73

+1

Неважно, если у вас нет контроллера для маршрута, он все равно будет выбирать первый последовательный соответствующий маршрут независимо (в данном случае - «По умолчанию»). Он будет искать класс HelloController: Controller with Index, и если он его не найдет, вы получите 404. – cchamberlain

0

Попробуйте определение необязательного параметра строки dynamicRoute по маршруту:

routes.MapRoute( 
     "CatchAll", 
     "{*dynamicRoute}", 
     new { controller = "CatchAll", action = "ChoosePage", dynamicRoute = UrlParameter.Optional }); 
+0

Просто попробовал тот же результат. Спасибо за попытку. – gsxrboy73

Смежные вопросы