Как направить URL с древовидной структурой с Маршрутизацией ASP.NET?

Я хотел бы достигнуть чего-то очень похожего на этот вопрос с некоторыми улучшениями.

Существует веб-приложение MVC ASP.NET.

У меня есть дерево объектов.
Например, a Page класс, который имеет свойство под названием Дети, которое имеет тип IList. (Экземпляр Page класс соответствует строке в базе данных.)

Обратите внимание, что владельцы сайта могут добавить новую страницу в любое время, или удалять существующие, и URL должны отразить те изменения также.

Я хотел бы присвоить уникальный URL каждому Page в базе данных.
Я обрабатываю Page объекты с названным Контроллером PageController.

URL в качестве примера:

http://mysite.com/Page1/
http://mysite.com/Page1/SubPage/
http://mysite.com/Page/ChildPage/GrandChildPage/

Вы получаете изображение.
Так, я хотел бы каждый Page объект иметь его собственный URL, который равен URL его родителя плюс его собственное имя.
В дополнение к этому я также хотел бы способность отобразить сингл Page к / (корневой) URL.

Я хотел бы применить эти правила:

  1. Если URL может быть обработан с каким-либо другим маршрутом, или файл существует в файловой системе в указанном URL, позвольте отображению URL по умолчанию произойти
  2. Если URL может быть обработан поставщиком виртуального тракта, позвольте этому обработать его
  3. Если нет никого другого, отобразите другие URL на PageController класс

Я также нашел этот вопрос, и также этого и этого, но они не помогли, так как они не дают объяснение о моих первых двух точках.

Я вижу следующий возможный soutions:

  • Отобразите маршрут для каждой страницы invidually.
    Это требует, чтобы я пробежался через все дерево, когда приложение запускается, и добавление маршрута точного совпадения в конец таблицы маршрутизации.
  • Я мог добавить маршрут с {*path} и запишите пользовательское IRouteHandler это обрабатывает его, но я не вижу, как я мог иметь дело с первыми двумя правилами затем, так как этот обработчик добрался бы для обработки всего.

До сих пор первое решение, кажется, правильное, потому что это является также самым простым. Но тем не менее, даже в этом случае я не уверен, как я мог сделать PageController обрабатывать запросы.

Я был бы очень признателен за Ваши мысли об этом.

Заранее спасибо!

Править: У меня теперь было время для исследования каждого аспекты каждого ответа, который я получил. Я принял ответ Neal, так как он - тот, дающий лучшее объяснение о том, как работают вещи. Я также upvoted все другие ответы, так как они обеспечивают хорошие идеи.

6
задан Community 23 May 2017 в 11:55
поделиться

4 ответа

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

По умолчанию маршрутизация MVC будет прокладывать маршруты к существующим файлам перед применением любых маршрутов, хранящихся в коллекции маршрутов; см. http://msdn.microsoft.com/en-us/library/system.web.routing.routecollection.routeexistingfiles.aspx. (hattip to Paul - см. комментарии).

Чтобы направить запросы к контроллеру страницы, просто создайте пользовательский маршрут, который исследует виртуальный путь и, если он соответствует шаблону страницы в базе данных, возвращает RouteData. Настройте RouteData с соответствующими значениями, извлеченными из виртуального пути (например, установите ключ Path в /Parent/Child/Grandchild), установите ключ controller в имя контроллера страницы (например, Page) и action в имя действия, которое вы хотите выполнить (например, Show). RouteData должен быть создан с помощью MvcRouteHandler (не уверен, что это правильное название класса).

Чтобы убедиться, что урлы на ваших страницах, управляемых базой данных, возвращаются правильно, переопределите GetVirtualPath( RequestContext, RouteValueDictionary ) метод RouteBase и используйте переданные значения маршрута, чтобы определить, является ли эта страница управляемой базой данных, и если это так, создайте необходимые данные виртуального пути (или верните null в противном случае).

Для помощи в переопределении GetRouteData и GetVirtualPath посмотрите отраженный исходный код System.Web.Routing.RouteBase и System.Web.Routing.Route; после этого Google - ваш друг.

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

3
ответ дан 17 December 2019 в 02:24
поделиться

Еще одна идея - использовать T4 (набор инструментов преобразования текстовых шаблонов), чтобы один раз прочитать ваших детей и сгенерировать содержимое вашего файла Global.asax.

РЕДАКТИРОВАТЬ: В основном с помощью T4 вы можете автоматизировать создание текстовых файлов. Например, вместо того, чтобы вручную копировать элементы какой-то огромной коллекции и вставлять их с определенным контекстом в текстовый файл (например, INSERT INTO [MyTable] (Text) VALUES (@ItemText) ), вы можете иметь Движок T4 считывает коллекцию и генерирует для вас эти операторы вставки.Он статичен и не предназначен для выполнения.

Я считаю, что очень хорошее введение можно найти в книге Pro Entity Framework 4.0 .

Но если вы говорите, что вам нужно делать это динамически, возможно, этот инструмент не для вас.

1
ответ дан 17 December 2019 в 02:24
поделиться

Вы знаете структуру своих страниц, когда сохраняете страницу. Поэтому вы можете сгенерировать URL для каждой страницы и сохранить его в записи базы данных. Затем вы можете использовать правило {*path} и найти точное соответствие в базе данных. Это правило должно быть последним в определении правил, чтобы вы могли сопоставить другие маршруты.

Например, ваша Страница1 не имеет родительской страницы, ее url - Страница1. Ваша SubPage знает свою родительскую страницу, поэтому она может ганарировать url Page1/SubPage и т.д.

1
ответ дан 17 December 2019 в 02:24
поделиться

Вы можете использовать шаблон «Страница / {* путь}» . Затем вы можете либо разложить путь, разделив строку на «/» и пройти по нему, либо вы можете использовать предложение Раруша о сохранении [сгенерированного] пути в БД и выполнить прямой поиск.

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

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

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

Ваш путь будет выглядеть так:

http://mysite.com/Page/Page1/ 
http://mysite.com/Page/Page1/SubPage/ 
http://mysite.com/Page/Page/ChildPage/GrandChildPage/ 

Вы, конечно, можете использовать префикс, отличный от «Page».

1
ответ дан 17 December 2019 в 02:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: