2009-12-21 2 views
0

Если у меня есть маршрут:Как получить общие маршруты в ASP.NET MVC, но обрабатывать неизвестные действия?

routes.MapRoute(
    "RouteName",           // route name 
    "{action}",            // url with parameters 
    new { controller = "Home", action = "Index", id = "" } // parameter defaults 
); 

Я хочу, чтобы быть в состоянии поймать URL, формы:

http://sitename.com/about 
http://sitename.com/contact 
http://sitename.com/others 

Это, очевидно, работает, когда действие существует в главном контроллере, который носит название нужный URL. Если я ввожу ошибочный URL-адрес, например http://sitename.com/foo, и действие foo не существует в Домашнем контроллере, я хотел бы направить приложение на 404 страницу, которая не найдена, но, очевидно, если я вхожу в foo, она ищет foo действий в домашнем контроллере. Есть ли способ оставаться общим без жесткого кодирования всех подстраниц в global.asax. Если это вообще возможно, я хочу воздержаться от:

routes.MapRoute(
    "About",            // route name 
    "about",            // url with parameters 
    new { controller = "Home", action = "About", id = "" } // parameter defaults 
); 

routes.MapRoute(
    "Contact",            // route name 
    "contact",            // url with parameters 
    new { controller = "Home", action = "Contact", id = "" } // parameter defaults 
); 

Спасибо.

+0

Рассматривали ли вы с помощью пользовательских страниц ошибок, которые перенаправляют пользователя на определенном месте, когда они вводят неверный URL (среди других ошибок)? http://msdn.microsoft.com/en-us/library/h0hfz6fc(VS.71).aspx – Omar

+0

Да, я добавил это в web.config, но глупо установил его в RemoteOnly. Извините за смешение. Этот вопрос можно закрыть. – user135383

ответ

2

Вы пытались использовать ограничение с помощью одного маршрута? Это позволит вам сопоставить любые действия, существующие на вашем домашнем (или другом) контроллере на верхнем уровне.

routes.MapRoute(
     "TopLevelGeneric", 
     "{action}", 
     new { controller = "Home", action = "Index", id = "" }, 
     new { 
       action = new MatchesHomeControllerConstraint() 
      }); 

Где MatchesHomeControllerConstraint является:

public class MatchesHomeControllerConstraint : IRouteConstraint 
{ 
    public bool Match(HttpContextBase httpContext, 
         Route route, 
         string parameterName, 
         RouteValueDictionary values, 
         RouteDirection routeDirection) 
    { 
      var name = values[parameterName] as string; 
      var method = typeof(HomeController).GetMethod(name,BindingFlags.IgnoreCase); 
      return method != null 
        && method.ReturnType.IsAssignableFrom(typeof(ActionResult)); 
    } 
} 
+0

На практике я бы, вероятно, кешировал набор действий контроллера и сопоставлялся с кешированным набором. Однако я оставляю реализацию как есть, для простоты. – tvanfosson

+0

Нет, я не пробовал это. Очень умный, хотя. Благодаря! – user135383

0

Возможно, я неправильно понимаю ваш вопрос, но маршрут, который у вас есть в верхней части вашего вопроса, уже будет охватывать случаи, которые вы печатаете внизу. Нет необходимости четко определять их. Если они набирают действие, которое не существует, будет вызвана ошибка 404.

Если вы хотите сделать что-то особенное, если кто-то соответствует действительному контроллеру, но не дает действительного действия, вы можете переопределить HandleUnknownError в своем контроллере.