Хранение маршрутов в базе данных

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

Таким хранилищем может быть любой источник данных: от текстовых файлов и XML до отдельной базы данных, в таблицах которой хранятся определения маршрутов. Рассмотрим создание такой базы данных для хранения простейших маршрутов.

Для начала определим две таблицы, Routeitem и Param, для хранения данных о маршрутах так, как продемонстрировано на рис. 6.1 и 6.2.

Таблица Routeitem будет содержать информацию о маршрутах, а Param — соответственно, о параметрах для каждого маршрута.

Чтобы добавить в проект поддержку этих таблиц, создадим с помощью мастера Linq To Sql классы для работы. Получившийся DBML-файл будет представлять схему, показанную на рис. 6.3.

После создания классов Linq To Sql настало время создать логику по регистрации маршрутов в механизме маршрутизации. Для этого создадим класс DatabaseRoutes, представленный в листинге 6.2.

Листинг 6.2. Класс DatabaseRoutes

using System.Linq;

using System.Web.Mvc;

using System.Web.Routing;

namespace Routing {

  public class DatabaseRoutes

  {

    readonly RouteDbDataContext db = new RouteDbDataContext();

    private readonly RouteCollection Routes;

    public DatabaseRoutes(RouteCollection routes)

    {

      Routes = routes;

    }

    public void Register()

    {

      var routes = db.RouteItems.Where(x => x.State).OrderBy(x => x.LoadOrder);

      foreach (var route in routes)

      {

        RouteValueDictionary defaults = new RouteValueDictionary();

        foreach (var param in route.Params)

          defaults.Add(param.ParamKey, param.ParamValue);

        Routes.Add(route.Name, new Route(

            route.Template,

            defaults,

            new MvcRouteHandler()

        ));

      }

    }

  }

}

Обратите внимание, конструктор-класс DatabaseRoute принимает параметр типа RouteColection, для того чтобы произвести регистрацию маршрутов. Единственный метод класса Register предназначен для выборки данных из базы данных и инициализации механизма маршрутизации в виде полученного экземпляра RouteColection.

Для того чтобы использовать наш класс, необходимо заполнить таблицы значениями. Сделаем это для определения стандартного маршрута Default так, как представлено на рис. 6.4 и 6.5.

После того как данные внесены в базу данных, можно интегрировать механизм в проект. Для этого следует в global.asax удалить старое определение маршрута Default и добавить инициализацию класса DatabaseRotes так, как показано в следующем фрагменте кода:

public static void RegisterRoutes(RouteCollection routes)

{

  routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

  DatabaseRoutes dbRoutes = new DatabaseRoutes(routes);

  dbRoutes.Register();

}

Если вы сделали все правильно, то результатом будет работа вашего проекта на основе маршрута, полученного из базы данных. Теперь, реализовав каким-либо образом доступ к базе данных маршрутов, вы получите возможность предоставить функции редактирования маршрутов администратору без модификации исходных кодов в виде global.asax.

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