Игорь Чакрыгин Игорь Чакрыгин

У любой задачи существует по крайней мере одно очевидное и невероятно простое для понимания неправильное решение

ASP.NET - Добавление search engine friendly адресов на сайт

Сейчас, наверное, очень сложно себе представить хороший сайт без «красивых» адресов страниц. Они одновременно и радуют глаз, и помогают поисковикам лучше ориентироваться на сайте.

Для asp.net существует несколько библиотек, позволяющих добавить поддержку таких адресов на сайт. Все они имеют свои плюсы и минусы, но я хотел бы поделиться своим методом, который мне кажется наиболее простым, поскольку не требует большого количества кода и позволяет автоматически обрабатывать все aspx-файлы на сайте без необходимости прописывать маршруты для каждого из них.

Суть метода

Суть метода достаточно проста. Если пользователь зашёл на сайт по какому-то адресу, то этот адрес разбивается на две части: обработчик и параметры. Обработчиком считается та часть адреса, которую можно сопоставить с каким-то файлом на сервере, параметрами - всё остальное.

Например, если пользователь зашёл на сайт по адресу ~/forum/asp.net/42/, то в качестве обработчика может быть выбран один из следующих файлов с соответствующими параметрами:

  • ~/forum/asp.net/42/default.aspx (без параметров);
  • ~/forum/asp.net/42.aspx (без параметров);
  • ~/forum/asp.net/default.aspx (с параметром 42);
  • ~/forum/asp.net.aspx (с параметром 42);
  • ~/forum/default.aspx (c параметрами asp.net и 42);
  • ~/forum.aspx (c параметрами asp.net и 42).

Эти виртуальные пути проверяются в указанном порядке, пока не будет найден тот, который соответствует существующему на сервере файлу. Он и считается обработчиком.

Так же по аналогии можно искать файлы других типов, например ashx-файлы.

Реализация

Как я уже отметил в самом начале, реализация не требует большого количества кода и может быть добавлена в проект всего за несколько минут. Все изменения необходимо вносить в файл Global.asax.

Прежде всего подпишемся на событие PostResolveRequestCache, переопределив метод Init.

В обработчике этого события получим текущий виртуальный путь и проверим, соответствует ли он существующему на сервере файлу. Если это не так, то при помощи метода MapSefPathToExistingPath попробуем сопоставить его с другим виртуальным путём, который соответствует существующему файлу.

В случае успеха при помощи метода RewritePath заменим текущий виртуальный путь на тот, который вернёт метод MapSefPathToExistingPath, а параметры сохраним в коллекции Items.

Хотел бы отметить, что коллекция Items имеет тип IDictionary, поэтому хорошей практикой считается в качестве ключей использовать не строки, а экземпляры класса Object. В данном случае я просто упростил код.

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

Всё готово. Теперь для всех запросов к несуществующим файлам будет автоматически определяться подходящий обработчик.

Заключение

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

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

Скачать демо (ASP.NET 4.0, Web Site)

© Игорь Чакрыгин. Все права защищены при помощи чёрной магии. Технологии Blogger.