31 мая 2012 г.

Использование Ajax.ActionLink в ASP.Net MVC

Очень часто все забывают, или по какой-то причине не знают, всех возможностей используемой платформы, потому и продолжают использовать старые, дедовские методы для решения большинства задач. Одна из таких задач - асинхронная подгрузка контента через Ajax. Только хардкор - только яваскрипт и jquery? Нет! Сегодня мы начнем делать это с помощью встроенныех в asp.net mvc хэлперов.
Итак, что нам нужно сделать?
На странице должна быть ссылка, по клику на которую, на эту же страницу подгрузиться какой-то контрол, заполненный нужными данными. Естественно, что все это должно происходить быстро, красиво, понятно и самое главное - асинхронно, без перезагрузки страницы.

Для приготовления, необходимо подключить в проект (или на нужную страницу) скрипт jquery.unobtrusive-ajax.min.js. Он входит в стандартный набор скриптов нового проекта asp.net mvc, поэтому найти его проблем не составит.

Начнем с представления, и описанном в нем хэлпере:
   1:  <p>
   2:      @Ajax.ActionLink("Click here to load control via ajax",
   3:          "NewControl", new AjaxOptions
   4:          {
   5:              UpdateTargetId = "controlsHolder",
   6:              InsertionMode = InsertionMode.InsertAfter,
   7:              HttpMethod = "GET"
   8:          })
   9:  </p>
  10:  <div id="controlsHolder">
  11:  </div>

Здесь определяется Ajax-ссылка, которая будет обращаться к экшну NewControl. Также заданы базовые параметры: айди элемента на странице, куда будет помещен результат, способ помещения результата (доступны замена, вставка перед, и вставка после), и метод доступа к экшну.
Ниже есть пустой див, который и выступит в роли контейнера, куда будут помещаться все загруженные контролы.

Ссылка будет обращаться по адресу /home/newcontrol, так давайте реализуем этот метод:
   1:  public PartialViewResult NewControl()
   2:  {
   3:      Thread.Sleep(2000);
   4:      var model = new Product
   5:      {
   6:          Name = "Some product",
   7:          Count = 9
   8:      };
   9:   
  10:      return PartialView("_Product", model);
  11:  }

Мы указали, что результатом возврата экшна будет именно PatrialViewResult т.к. возвращать будем контрол. Далее просто создаем, и заполняем модель для контрола необходимыми данными. Я приостанавливаю поток на 2 секунды, чтобы симулировать длительное получение данных из БД. Как уже говорилось выше, этот экшн возвращает "наружу" заполненный контрол.

Смотрим, все ли у нас получилось. А у нас, конечно же, все вышло. Есть ссылка, и если на нее нажимать, то ниже появляются подгружаемые контролы:
Прекрасно, но на этом еще не все. Дабы не отпугнуть пользователя, и не ввести его в замешательство, мы должны показать, что после нажатия им на ссылку, и до появления нового контрола, на странице что-то вообще происходит. Иначе он начнет тыкать в ссылку с космической скоростью, не дожидаясь результатов. Другими словами, давайте еще добавим сюда визуальный индикатор, который будет появляться на время загрузки контента.

Делается это очень просто.
Добавим на нашу страницу скрытый див, в котором будет крутиться индикатор:
<div id="progress" style="display: none;">
    <img src="/Content/loading.gif" alt="loader" />
</div>

А сейчас, ко всем параметрам Ajax.ActionLink добавим еще один:
   1:  @Ajax.ActionLink("Click here to load control via ajax",
   2:          "NewControl", new AjaxOptions
   3:          {
   4:              UpdateTargetId = "controlsHolder",
   5:              InsertionMode = InsertionMode.InsertAfter,
   6:              HttpMethod = "GET",
   7:              LoadingElementId = "progress"
   8:          })

LoadingElementId указывает на айди элемента, который будет использован как индикатор.

Теперь проверяем снова. Итак, пока на сервере будет формироваться и заполняться новый контрол, мы увидим, что что-то все-таки происходит, и нужно еще чуток подождать:
Согласитесь, что такой способ реализации механизма подгрузки контента очень хорош. Ведь нет нужды писать десяток строк в Javascript, формируя свой ajax-запрос, и реализуя индикатор процесса с самой вставкой. Все в представлении, и все на родном, удобном языке.
_____
Исходники