Как стать автором
Обновить

Комментарии 14

Хорошая статья!

Хотя, в статье не хватает ответа на вопрос- как тестировать(unit test-ами, т.к. как тестить через вызов из браузера-fiddler всем понятно и так.)
Не в смысле, что я не знаю, а в смысле- в статье было полезно рассказать
Спасибо.
Согласен, вопрос тестирования надо было бы затронуть, но я совсем забыл о нем.
Хорошая тема для следующей статьи :-)
Что с поиском подходящего маршрута по скорости? В MVC ASP.NET «старом» после 500 маршрутов уже начинаются проблемы. Полностью статические пути из разряда Friendly URL задавать вообще не вариант, приходится изобретать костыли.
Я думаю на performance до RC1 в ноябре тестировать смысла нет.
А что вызвало необходимость 500 роутов создать? Не праздный интерес, хочется понять сценарий.

Для MVC(не web API) как-то представить тяжело. Для Web API- в restfull охотно верю
Легко, если вы мне подскажете решение окромя: «ну создай отдельные роуты с параметрами (что я сейчас и делаю)», то я даже не знаю, как благодарить.
Что необходимо:
Есть набор страниц, в виде иерархии. Все пути url на сайте должны быть так же иерархично выстроены. Некоторые страницы могут иметь фильтрационные параметры, но они не включаются в иерархию. Роутинг должен меняться пользователем и быть динамическим.
Пример:
Главная — "/"
Категория — «Категория»
Подкатегория — «Подкатегория»
Необходимый результат: Для страницы подкатегория ссылка "/Категория/Подкатегория/" и так далее.
Результат:
1. Данный пример легко реализовать, если засунуть в таблицу маршрутизации прямо целиком ссылки, статично. Но, после 500 начинаются проблемы со скоростью поиска роута. При 10000 все умирает на секунды. Для чего же надо все это засовывать в маршруты? — Потому что по адресу мне всегда нужно узнавать идентификатор страницы, то самое наименование, какие-то параметры (допустим Title и Description страницы) и так далее. В этом варианте пишем просто параметр, при инициализации роутинга, вида Id = IdFromDatabase и все, потом его выгребаем везде, где надо. Но, это плохой вариант
2. Данный пример можно реализовать с построением маршутов с параметрами, классических. Т.е. Берем и делаем маршрут вида: /Категория/{subcategory}/, уменьшаем резко количество маршрутов. Но, сталкиваемся с тем, что мы больше не можем использовать id как параметр, ведь у нас 1 маршрут на n страницы, причем n принадлежит N. И тут начинается самое интересное, раз мы хотим универсально получать этот идентификатор и данные по нему, то нам нужно каким-то образом у маршрута знать, по каким параметрам искать в базе страницу. В этом случае это subcategory, в другом случае это category, в третьем это вообще что-то иное, да и больше 1 параметра может быть. Получаем достаточно сложную логику, как по мне. Конечно, она будет быстрее работать, там не будет простого поиска сверху — вниз по таблице маршрутизации. Но почему нельзя ускорить поиск самого MVC.
Если я правильно понял ваш кейс — то вам нужен всегда правильно заполненный параметр id в RouteData.
Я думаю вам нужно идти с другой стороны:
Хранить соответствие «данные маршрута => Id» (Категория, Субкатегория => Id) в какой-нибудь статической коллекции.
А Id заполнять в RouteData в какой-то момент до того как оно вам понадобиться, поиском по этой статической коллекции, исходя из того, что система маршрутизации вам уже заполнит все необходимые параметры для поиска распарсив маршрут.

По поводу скорости поиска подходящего маршрута — там никаких супералгоритмов не применяется, а просто перебор всех зарегистрированных маршрутов пока какой-то не подойдет, так что в худшем случае время поиска будет увеличиваться пропорционально количеству зарегистрированных маршрутов и их сложности (количество переменных частей и сегментов).
Вы мне описали 2 мой вариант. Да, но при этому алгоритмы поиска нетривиальные + работа с маршрутизацией вылазит на уровень пользователя, а ему мои {param} непонятны чуть больше, чем полностью. В добавок к этому иерархии маршрутов придется строить в ручную. Например:
Есть страница каталога и подкаталога. Обе страницы должны открываться в браузере. И получаем, что пользователь для первой страницы должен дать маршрут и для второй страницы тоже дать маршрут и потом искать по одному параметру данные в базе. Или же дать один маршрут на две страницы, но с двумя параметрами и искать в базе по двум параметрам. Адина:( А если бы какой-то поиск побыстрее был в MVC, то пользователь написал Friendly name и все, забыл об этом, а ты просто маршруты переписал вида a\b\c\d\...\n.

По поводу поиска я в курсе как он происходит. От этого жить не легче, учитывая, что многие не понимают, что роутинг работает в обе стороны. И всевозможные Url.Action тоже используют роутинг. Учитывая, что на странице могут быть десятки ссылок (и бывают в 99.9% случаев), то тормозить ваше творение будет безбожно. Но, хочу сказать, что лично я не знаю, как быстро ускорить поиск, но если бы у меня была возможность вмешаться в этот поиск, я бы его построил через хэши строк, ведь я знаю, что у меня параметров нет и достаточно полного совпадения строк.
но если бы у меня была возможность вмешаться в этот поиск, я бы его построил через хэши строк, ведь я знаю, что у меня параметров нет и достаточно полного совпадения строк.

А почему тогда не рассмотрите вариант с регистрацией маршрутов на основе своей реализации RouteBase, которая будет осуществлять такой поиск?
Что мне даст RouteBase, если поиск осуществляется перебором тех самых RouteBase? Мне не перебор нужен, линейный, а хотя бы Dictionary подобная структура.
Да, верно. Ну во всяком случае в ASP.NET 5 есть возможность использовать свою реализацию RouteCollection.
Подумал еще над вашим случаем. Если от системы маршрутизации все что требуется — это определить id по полному совпадению строки маршрута, то может быть свести ее использование к минимуму? Создать единственный маршрут и задать ему только «жадный» сегмент в качестве шаблона, чтобы он «съел» весь адрес. А маршрут введенный пользователем, хэш маршрута и id страницы, хранить где-то в приложении в удобной структуре. Ну и собственно, как в предыдущем моем варианте — перед использованием id в приложении заполнять его в RouteData, а искать создавая хэш из строки полученного запроса и ищя его в этой структуре — как вы и хотите.
Да, я в курсе об этом варианте, его самым первым предлагают, но опять же, хочется все таки и параметры оставить. И рыбку съесть и гвоздь не трогать.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий