Книга: ASP.NET MVC Framework

Реализация подхода MVC в WebForms

Реализация подхода MVC в WebForms

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

Рассмотрим ASPX-страницу, приведенную в листинге 2.1. На этой странице размещены несколько элементов управления Label, TextBox и Button. Логика страницы должна быть простой, и в классической модели WebForms описывается в code-behind-файле, код которого приведен в листинге 2.2.

Листинг 2.1. Страница Default.aspx

<%@ Page Language="C#" AutoEventWireup="true"
  CodeBehind="Default.aspx.cs" Inherits="WebFormsMvc._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
</head>
<body>
  <form runat="server">
    <div>
      <div>
        Ответ сервера:
        <asp:Label runat="server"
          Text="noKa HeT"></asp:Label>
      </div>
      <table>
        <tr>
          <td>
            Имя:
          </td>
          <td>
            <asp:TextBox
              runat="server"></asp:TextBox>
          </td>
        </tr>
        <tr>
          <td>
            Фамилия:
          </td>
          <td>
            <asp:TextBox
              runat="server"></asp:TextBox>
          </td>
        </tr>
        <tr>
          <td colspan="2">
            <asp:Button runat="server"
              Text="Coxpaнить" />
          </td>
        </tr>
      </table>
    </div>
  </form>
</body>
</html>

Листинг 2.2. Файл Default.aspx.cs

using System;
using WebFormsMvc.Controllers;
namespace WebFormsMvc {
{
  protected void btnSave_Click(object sender, EventArgs e) {
    lblResponse.Text = txtFirstName.Text + " "
                     + txtLastName.Text; }
  }
}

Для того чтобы выделить отдельный компонент контроллер, который будет отвечать за логику обработки запросов к странице, таких, например, как щелчок по кнопке или загрузка первоначальных значений в текстовые поля, необходимо обеспечить возможность контроллера модифицировать модель, отображением которой является представление. В случае ASPX-страницы моделью является собственно сама объектная модель страницы, поэтому именно к ней нужно предоставить доступ контроллеру — для этого достаточно отредактировать CS-файл, автоматически создаваемый Visual Studio для страницы, и сделать все поля, соответствующие элементам управления на форме, публичными, как это приведено в листинге 2.3.

Листинг 2.3. Модифицированный файл Default.aspx.designer.cs

namespace WebFormsMvc {
public partial class _Default {
  public global::System.Web.UI.HtmlControls.HtmlForm form1;
    public global::System.Web.UI.WebControls.Label lblResponse;
    public global::System.Web.UI.WebControls.TextBox txtFirstName;
    public global::System.Web.UI.WebControls.TextBox txtLastName;
    public global::System.Web.UI.WebControls.Button btnSave;
  }
}

После этого можно создать отдельный класс-контроллер для страницы Default.aspx, код которого приведен в листинге 2.4, и обращаться к нему из обработчиков событий страницы, как это показано в листинге 2.5. Обработчики событий страницы, в данном случае, выполняют только утилитарную роль привязки вызовов методов контроллера к событиям страницы.

Листинг 2.4. Файл DefaultPageControNer.cs

namespace WebFormsMvc.Controllers {
  public class DefaultPageController {
    public DefaultPageController(_Default pg) { page = pg; }
    public void ButtonSaveClick()
    {
      page.lblResponse.Text = page.txtFirstName.Text + " "
               + page.txtLastName.Text;
    }
    public void PageLoad()
    {
      if (!page.IsPostBack)
      {
        page.txtFirstName.Text = "Иван";
        page.txtLastName.Text = "Кузнецов";
      }
    }
  }
}

Листинг 2.5. Модифицированный файл Default.aspx.cs

using System;
using WebFormsMvc.Controllers;
namespace WebFormsMvc {
public partial class _Default:System.Web.UI.Page {
  protected DefaultPageController controller;
  protected void btnSave_Click(object sender, EventArgs e)
  {
    controller.ButtonSaveClick();
  }
  protected void Page_Load(object sender, EventArgs e)
  {
    controller = new DefaultPageController(this);
    controller.PageLoad();
  }
}

Теперь, когда логика страницы вынесена в отдельную сущность — контроллер, есть возможность тестирования логики в отрыве от представления. Для этого достаточно создать экземпляр класса контроллера и передать ему проинициализированный объект модели. Поскольку в качестве модели выступает ASPX-страница, необходимо создать экземпляр класса страницы и про-инициализировать значащие элементы управления, поскольку при тестировании не будут задействованы внутренние механизмы создания экземпляров страниц.

В листинге 2.6 приведен простейший unit-тест для проверки обработчика события загрузки страницы.

Листинг 2.6. Unit-тест для события загрузки страницы

[TestMethod]
public void TestPageLoad()
  _Default page = new _Default();
  page.txtFirstName = new TextBox();
  page.txtLastName = new TextBox();
  DefaultPageController controller = new DefaultPageController(page);
  controller.PageLoad();
  Assert.AreEqual(page.txtLastName.Text, "Кузнецов");
}

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

Указанный ранее подход может быть применен в веб-приложениях, использующих подход WebForms, с целью упрощения тестирования, однако использование такого подхода не упрощает миграцию на MVC Framework. Поэтому, если вы проектируете приложение на WebForms, но подумываете над будущей миграцией на MVC Framework, лучший совет для вас — откажитесь от планов миграции, либо сразу же пишите на основе MVC Framework.

Оглавление книги


Генерация: 1.224. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз