14 июня 2012 г.

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

Продолжая тему полезных мелочей ASP.Net MVC, сегодня мы поэкспериментируем с еще одним хелпером - Ajax.BeginForm. Для чего же он нужен? Все довольно просто. В случае с Ajax.ActionLink, по клику на ссылке у нас отрабатывал ajax-запрос, который асинхронно подгружал на страницу некий HTML-контент. Здесь также происходит ajax-запрос на сервер, который возвращает оттуда некий контент, но при этом оправляется вся форма, со всеми ее элементами. Таким образом могут быть переданы введенные пользователем данные.
Для того, чтобы продемонстрировать на что способен хелпер Ajax.BeginForm, и где его можно применять, мы создадим с его помощью динамическую форму поиска товаров в БД. Все банально. У нас будет строка для ввода, и кнопка для начала поиска. После нажатия на кнопку, результаты поиска будут возвращены ajax-запросом на наше представление, и показаны пользователю без перезагрузки страницы.

Начнем с самого хелпера во вьюхе:
   1:  <script src="@Url.Content("/Scripts/jquery.unobtrusive-ajax.min.js")"
   type="text/javascript"></script>
   2:   
   3:  @using (Ajax.BeginForm("Search", "Home", new AjaxOptions
   4:  {
   5:      HttpMethod = "GET",
   6:      InsertionMode = InsertionMode.Replace,
   7:      UpdateTargetId = "productsTable",
   8:      LoadingElementId = "progress"
   9:  }))
  10:  {
  11:      <input name="q" type="text" />
  12:      <input type="submit" value="Search product by name" />
  13:  }
  14:  <table id="productsTable">
  15:  </table>
  16:  <div id="progress" style="display: none;">
  17:      <img src="/Content/loading.gif" alt="loader" />
  18:  </div>

Тут у нас есть сама форма с ее содержимым (поле ввода и кнопка отправки формы), таблица, в которую будут подгружаться результаты, и скрытый див и гифкой, который будет показывать прогресс выполнения запроса.
Поле ввода имеет название "q". По этому названию мы сможем принять введенную строку на сервере.
Самое главное здесь  это форма. Как видите, ее объявление схоже с Ajax.ActionLink. Если пройтись докладно по параметрам, то мы имеем следующее: при отправке формы произойдет GET-запрос в экшн /Home/Search. Пока будет выполняться запрос, для визуализации прогресса будет использован див "progress", а результаты запроса будут вставлены в таблицу "productsTable" (вернее таблица будет заменена на то, что придет с сервера).

Теперь напишем метод для обработки запроса формы:
   1:  public ActionResult Search(string q)
   2:  {
   3:      System.Threading.Thread.Sleep(1500);
   4:   
   5:      NorthwindEntities _db = new NorthwindEntities();
   6:   
   7:      var products = _db.Products.Where(p => p.ProductName.Contains(q) ||
  string.IsNullOrEmpty(q)).Take(10);
   8:   
   9:      return PartialView("_productSearchResult", products);
  10:  }

В контроллере мы делаем задержку в полторы секунды для симуляции продолжительного получения данных (чтобы пользователь успел увидеть наш индикатор прогресса выполнения), а далее просто получаем из БД записи, отвечающие нашему критерию. В нашем случае, критерий - это содержание присланной строки в названии продукта. Результатом выполнения этого экшна будет заполненный продуктами контрол "_productSearchResult".
_productSearchResult принимает список продуктов для возврата на страницу. Внутри него должно будет следующее:
   1:  @model IEnumerable<_MvcApplication.Models.Product>
   2:  <table id="productsTable">
   3:      <tr>
   4:          <th>
   5:              Name
   6:          </th>
   7:          <th>
   8:              Quantity
   9:          </th>
  10:          <th>
  11:              Price
  12:          </th>
  13:      </tr>
  14:      @foreach (var product in Model)
  15:      {
  16:          <tr>
  17:              <td>
  18:                  @product.ProductName
  19:              </td>
  20:              <td>
  21:                  @product.QuantityPerUnit
  22:              </td>
  23:              <td>
  24:                  @Math.Round((decimal)product.UnitPrice, 2)
  25:              </td>
  26:          </tr>
  27:      }
  28:      
  29:  </table>

Тоесть, здесь всего-лишь заполняется таблица результатов из модели. Именно этот заполненный контрол и увидит пользователь, нажавший на кнопку поиска.

Теперь давайте проверим, что у нас вышло.
При запуске проекта мы видим лишь строку ввода и кнопку отправки формы:

После ввода какой-то части названия продукции, и по нажатию на кнопку, мы получаем красивый вывод результатов поиска. А пока данные будут искаться на сервере, мы будем смотреть на крутящийся индикатор.
Вот и конечный результат:


_____
Исходники