Категории контроллеров в маршрутизации MVC? (Повторяющиеся имена контроллеров в отдельных пространствах имен)

Я ищу несколько примеров или образцов маршрутизации для следующего сценария:

Общий пример действий: {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 ‹-- не будет работать, потому что контроллер поиска не разрешен.


person crucible    schedule 04.09.2008    source источник
comment
Учитывает ли это концепцию областей в версии 1.0?   -  person hometoast    schedule 01.06.2009


Ответы (2)


На самом деле я нашел его даже не поиском, а просматривая форумы 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            
        });
    }

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

person crucible    schedule 05.09.2008

Лучший способ сделать это без каких-либо компромиссов — реализовать собственный ControllerFactory, унаследовав его от IControllerFactory. Метод CreateController, который вы реализуете, обрабатывает создание экземпляра контроллера для обработки запроса RouteHandler и ControllerActionInvoker. Соглашение состоит в том, чтобы использовать имя контроллера при его создании, поэтому вам нужно будет переопределить эту функцию. Здесь вы поместите свою пользовательскую логику для создания контроллера на основе маршрута, поскольку у вас будет несколько контроллеров с одинаковым именем, но в разных папках. Затем вам нужно будет зарегистрировать свою собственную фабрику контроллеров при запуске приложения, как и ваши маршруты.

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

Чтобы получить представление о коде, есть несколько вопросов, на которые я ответил в SO, которые относятся к этому вопросу, но этот вопрос в некоторой степени отличается, потому что имена контроллеров будут одинаковыми. Я включил ссылки для ознакомления.

Другой маршрут, но может потребовать некоторых компромиссов, заключается в использовании нового атрибута AcceptVerbs. Проверьте этот вопрос для получения более подробной информации. Я еще не играл с этой новой функцией, но это может быть другой путь.

person Dale Ragan    schedule 04.09.2008