Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

ASP.NET MVC client-side routing

Anna | 17.06.2014 | нет комментариев

Постановка задачи

Система маршрутизации ASP.NET MVC освобождает разработчика от необходимости вручную поддерживать URL, используемые в приложении при помощи таблиц маршрутизации и url образцов. Таким образом, с программиста снимается задача по образованию URL вручную. Наоборот, в его распоряжении оказывается богатенький комплект URL-хелперов. Это восхитительно! Но все меняется, когда приходят они — AJAX-запросы.

Задача заключается в том, что таблицы маршрутизации и механизм генерации URL являются частью серверной архитектуры asp.net mvc и недостижимы из Javascript-файлов. 
Как следствие, в скриптах Зачастую дозволено встретить такой код:

    var url="/items/get-items?typeid=" typeId "&groupid=" groupId "&skip=" skip "&take=" take;

Помимо того, что данный код выглядит не дюже прекрасно, его возникновение правда бы в одном месте в ваших скриптах нарушает изолированность информации о финальном виде URL. Сейчас, в случае, если вам понадобится изменить конструкцию URL и, скажем, перенести параметры из query string в тело URL, вам неудовлетворительно будет легко отредактировать образец. Вы обязаны будете пройтись по скриптам и внести нужные метаморфозы. Это может стать поводом ошибок: где-то поменяли, где-то позабыли, где-то опечатались.

Заблаговременная серверная генерация URL

Клиентские скрипты обязаны располагаться в .js файлах, следственно мы сразу отбрасываем вариант с генерацией скриптов при образовании View. Одним из решений в данной обстановки является заблаговременная генерация URL на сервере и запись его в в data-* признак элемента, скажем так:

<div id="some_container"  data-url="@Url.Action("Action","Controller",new {Id=10})">
...
</div>

Тут мы по-бывшему полагаемся на механизм роутинга ASP.NET MVC и избавляемся от ручного образования URL на заказчике, получая его из признака. В определенных случаях этого решения будет довольно, но всецело задачу это не решает. Разглядим обстановку. Вы пишете javascript-модуль, тот, что планируется применять во многих частях приложения, при этом ему нужно будет осуществлять ajax-запросы. В этом случае не хотелось бы переносить информацию об URL для запросов куда-то за пределы этого модуля. Следственно вариант с хранением URL в признаках и передача его вовнутрь модуля нам не подходит. Но и вручную формировать его мы не хотим. Что же делать?

Библиотека RouteJs

В идеале хотелось бы иметь доступ к URL routes напрямую из JavaScript, но встроенного механизма в ASP.NET MVC для этого нет. Впрочем его дозволено добавить, подключив небольшую библиотеку RouteJs. Она работает как с WebForms, так и с ASP.NET MVC (начиная с 2-ой версии) и не требует применения сторонних JavaScript фреймворков. Добавить ее к плану дозволено через Nuget. В этом случае вас останется только включить в страницу ссылку на скрипт:

<script src="@RouteJs.RouteJsHandler.HandlerUrl"></script>

В итоге вы получите доступ к вашим роутам прямо из JavaScript при помощи объекта Router.

Примеры
Дефолтный маршрут
routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

Что получаем:

>Router.action('Home','Index')
"/Home/Index"
>Router.action('Home','Index',{id:1})
"/Home/Index/1"
>Router.action('Home','Index',{type:1, group:2})
"/Home/Index?type=1&group=2"
А если добавить Area?
public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "TestArea_default",
                "TestArea/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
}

Проверяем:

>Router.action('Home','Index',{area:'TestArea'})
"/TestArea/Home/Index"
Constraints

RouteJs может трудиться с дефолтными regexp ограничениями:

routes.MapRoute(
           name: "DefaultWithConstraint",
           url: "constr/{controller}/{action}/{id}",
           defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
           constraints:new {action="^ConstrAction$"}

Проверка:

>Router.action('Home','Index')
"/Home/Index"
>Router.action('Home','ConstrAction')
"/constr/Home/ConstrAction"

Впрочем по внятным причинам он не сумеет обработать ваши кастомные IRouteConstaints. Больше того, в нынешней версии Router перестает трудиться в случае, если в каком-то из маршрутов применяются кастомные Constraints. (Происходит оплошность в JavaScript при обращении к объекту. Дабы обойти это, следует навесить признак [HideRoutesInJavaScript]на проблемный контролер. Я думаю в ближайшем грядущем данный баг будет поправлен).

Кэширование

Сгенерированный скрипт отдается совместно с заголовком Expires, тот, что информирует браузеру о том, что скрипт необходимо закешировать на 1 год. При этом обратите внимание на формат ссылки, которая добавляется на страницу:

  <script src="/routejs.axd/2512dbb48b9018a4c8f9eac5fb92f903800d94da/router.js"></script>

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

Библиотека JsAction

Библиотека JsAction предлагает иной подход к решению задачи client-side маршрутизации. Установить ее также дозволено через Nuget. Позже этого требуется добавить в Layout ссылку (подключать следует позже jQuery):

@Html.JsActionScript()

Дальше Action, тот, что планируется применять для Ajax-запросов помечается особым признаком [JsAction]:

[JsAction]
[HttpGet]
public JsonResult Do(int a, int b)
{
    return Json(a   b, JsonRequestBehavior.AllowGet);
}

Позже этого вы можете вызвать данный Action из JavaScript по имени:

$(function() {
    JsActions.Home.Do(1, 3);
})

Таким образом, эта библиотека делает что-то огромнее, чем легко перенос URL маршрутов на заказчик. Она освобождает разработчика от ручного написания Ajax-запросов. При этом есть ряд славных побочных результатов. Представьте, что способ, тот, что был доступен по GET запросу необходимо заменить на POST. Ваши действия? Вы поменяете признак [HttpGet] на [HttpPost] и потом пойдете искать вызов этого способа в скрипте, Дабы поменять настройки вызова $.Ajax (если вы используете jQuery, безусловно). Эта библиотека освобождает вас от этой необходимости. Отныне эти настройки будут находится только в признаках способа. Обработка итогов ajax-запроса происходит так же как и при обыкновенном вызове $.ajax():

$(document).ready(function () {
     JsActions.Home.Do(1,2).then(function(data){ alert(data); });
});

В случае, если вы используете jQuery до версии 1.5, вам доступен подобный механизм:

$(document).ready(function () {
    var ret = JsActions.Home.Do(1, 2, {
        success: function (data) {
            alert(data);
        }
    });
});
Intellisense

JsAction поддерживает механизм Intellisense в Visual Studio. Работает это дальнейшим образом. Вы добавляете xml-комментарии к вашему способу:

        /// <summary>
        /// Sums two numbers
        /// </summary>
        /// <param name="a">First number</param>
        /// <param name="b">Second number</param>
        /// <returns></returns>
        [JsAction()]
        [HttpGet]
        public JsonResult Do(int a, int b)
        {
            return Json(a   b, JsonRequestBehavior.AllowGet);
        }

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB