Я ищу несколько примеров или образцов маршрутизации для следующего сценария:
Общий пример действий: {controller} / {action} / {id}
Итак, в сценарии поиска продукта для магазина у вас будет:
public class ProductsController: Controller
{
public ActionResult Search(string id) // id being the search string
{ ... }
}
Допустим, у вас было несколько магазинов для этого, и вы хотели, чтобы это происходило постоянно, есть ли какой-либо способ иметь: {category} / {controller} / {action} / {id}
Чтобы вы могли выполнять конкретный поиск для определенного магазина, но использовать другой метод поиска для другого магазина?
(Если вы требовали, чтобы имя магазина было более приоритетным, чем сама функция в URL-адресе)
Или все сводится к:
public class ProductsController: Controller
{
public ActionResult Search(int category, string id) // id being the search string
{
if (category == 1) return Category1Search();
if (category == 2) return Category2Search();
...
}
}
Возможно, это не лучший пример, но в основном идея состоит в том, чтобы использовать одно и то же имя контроллера и, следовательно, иметь простой URL-адрес для нескольких разных сценариев, или вы как бы застряли в том, чтобы требовать уникальные имена контроллеров и не можете их вставить немного разные пространства имен / каталоги?
Отредактируйте, чтобы добавить:
Другая причина, по которой я хочу это, заключается в том, что мне может понадобиться URL-адрес с категориями, и что определенные контроллеры будут работать только с определенными категориями.
IE:
/ this / search / items / search + term <- работает
/ that / search / items / search + term <- не будет работать - потому что контроллер поиска не разрешен.





Лучший способ сделать это без каких-либо компромиссов - реализовать собственный ControllerFactory, унаследовав его от IControllerFactory. Реализуемый вами метод CreateController обеспечивает создание экземпляра контроллера для обработки запроса RouteHandler и ControllerActionInvoker. По соглашению при его создании используется имя контроллера, поэтому вам нужно будет переопределить эту функцию. Здесь вы разместите свою собственную логику для создания контроллера на основе маршрута, поскольку у вас будет несколько контроллеров с одинаковым именем, но в разных папках. Затем вам нужно будет зарегистрировать свою фабрику настраиваемых контроллеров при запуске приложения, как и ваши маршруты.
Еще одна область, которую вам нужно будет принять во внимание, - это поиск ваших представлений при создании контроллера. Если вы планируете использовать одно и то же представление для всех из них, вам не придется делать ничего, кроме используемого соглашения. Если вы планируете также организовать свои представления, вам также потребуется создать свой собственный ViewLocator и назначить его контроллеру при его создании на фабрике контроллеров.
Чтобы получить представление о коде, есть несколько вопросов, которые я ответил по SO, которые относятся к этому вопросу, но этот вопрос в некоторой степени отличается, потому что имена контроллеров будут такими же. Я включил ссылки для справки.
Другой путь, который может потребовать некоторых компромиссов, - это использование нового атрибута AcceptVerbs. Проверьте этот вопрос для более подробной информации. Я еще не играл с этой новой функцией, но это может быть другой путь.
На самом деле я нашел его даже не поиском, а просмотром форумов ASP .NET в этот вопрос.
Используя это, вы можете иметь одноименные контроллеры в любой части пространства имен, при условии, что вы определяете, какие маршруты принадлежат каким пространствам имен (при необходимости вы можете иметь несколько пространств имен для каждого маршрута!)
Но отсюда вы можете поместить каталог под свой контроллер, поэтому, если бы вашим контроллером был «MyWebShop.Controllers», вы бы поместили каталог «Shop1», а пространство имен было бы «MyWebShop.Controllers.Shop1»
Тогда это работает:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
var shop1namespace = new RouteValueDictionary();
shop1namespace.Add("namespaces", new HashSet<string>(new string[]
{
"MyWebShop.Controllers.Shop1"
}));
routes.Add("Shop1", new Route("Shop1/{controller}/{action}/{id}", new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(new
{
action = "Index",
id = (string)null
}),
DataTokens = shop1namespace
});
var shop2namespace = new RouteValueDictionary();
shop2namespace.Add("namespaces", new HashSet<string>(new string[]
{
"MyWebShop.Controllers.Shop2"
}));
routes.Add("Shop2", new Route("Shop2/{controller}/{action}/{id}", new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(new
{
action = "Index",
id = (string)null
}),
DataTokens = shop2namespace
});
var defaultnamespace = new RouteValueDictionary();
defaultnamespace.Add("namespaces", new HashSet<string>(new string[]
{
"MyWebShop.Controllers"
}));
routes.Add("Default", new Route("{controller}/{action}/{id}", new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }),
DataTokens = defaultnamespace
});
}
Единственное другое - это то, что он будет ссылаться на представление, все еще находящееся в базовом каталоге, поэтому, если вы поместите представление в соответствующие каталоги, вам нужно будет указать имя представления, когда вы вернете его в контроллер.
Решает ли это концепция «областей» в версии 1.0?