Asp.net mvc framework
Шрифт:
routes.IgnoreRoute("{file}.txt");
routes.IgnoreRoute("{file}.htm");
routes.IgnoreRoute("{file}.html");
Игнорирование маршрутов — это сильный инструмент, который по умолчанию позволяет создать правила для исключения из обработки запросов к виртуальным или несуществующим файлам. А после изменения RouteExistingFiles и включения механизма маршрутизации для всех запросов игнорирование маршрутов позволяет защитить все файлы от доступа и сформировать свои правила доступа к файлам на сайте.
Советы по использованию маршрутов
В
Маршруты и валидация запросов
Как уже говорилось в этой главе, маршрутизация ASP.NET содержит механизм ограничений, который позволяет более гибко управлять обработкой маршрутов. Но кроме собственно поиска правильного маршрута, этот механизм позволяет также производить валидацию запросов еще на этапе поиска и обработки маршрута.
Представьте себе ситуацию, когда вы создаете маршрут, одним из параметров которого является число, определяющее год. Совершенно очевидно, что такое число имеет допустимые рамки, и его валидность может быть проверена еще на этапе сопоставления маршрутов. В листинге 6.1 приведен фрагмент кода, который определяет экземпляр класса, реализующий IRouteConstraint для такого рода проверки параметра.
Листинг 6.1. Класс, реализующий IRouteConstraint
public class YearConstraint : IRouteConstraint {
public bool Match(HttpContextBase httpContext,
Route route,
string parameterName,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if (parameterName == "year")
{
try
{
object yearValue = values["year"];
int year = Convert.ToInt32(yearValue);
if (year >= 1900 && year <= 2100) return true;
}
catch
{
return false;
}
}
return false;
}
}
Для того чтобы использовать данный класс, необходимо определить маршрут с параметрами ограничения примерно так, как показано во фрагменте:
var constraints = new RouteValueDictionary
{
{"year", new YearConstraint}
};
routes.MapRoute("YearData",
"{controller}/{action}/{year}",
new { controller = "Data", action = "Index" },
new { year = new YearConstraint }
);
Вся прелесть этого механизма заключается в том, что вы можете использовать ограничение для параметров различных маршрутов. Таким образом, вы получаете централизованный механизм обработки и валидации входных параметров, который начинает работать еще до того, как в действие вступит контроллер.
Хранение маршрутов в базе данных
Порой определение маршрутов в файле 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.