412 000 произведений, 108 200 авторов.

Электронная библиотека книг » Гайдар Магдануров » Asp.net mvc framework » Текст книги (страница 15)
Asp.net mvc framework
  • Текст добавлен: 8 июля 2026, 17:38

Текст книги "Asp.net mvc framework"


Автор книги: Гайдар Магдануров



сообщить о нарушении

Текущая страница: 15 (всего у книги 17 страниц)

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

Для поддержки возможности замены конкретной реализации необходимо использовать интерфейсы для основных зависимостей действий контроллеров. Например, если в приложении есть выделенный объект, отвечающий за восстановление и сохранение объектов данных DataManager, то в контроллерах следует использовать интерфейс iDataManager, который реализует конкретный класс DataManager. Таким образом, во время проведения тестов объект DataManager может быть подменен объектом DataManagerMock, не содержащим полного функционала работы с данными и, возможно, даже не работающим с базой данных. Этот распространенный подход к тестированию называется имитацией (англ. moking).

Для реализации имитации при тестировании во время разработки удобно использовать фабрику контроллеров и инъекцию зависимостей, когда необходимые контроллеру объекты передаются через вызов конструктора, таким образом контроллер не инициирует создание объектов, а получает все объекты как данность. Другим подходом является реализация нескольких отдельных конструкторов для контроллеров для использования в тестовом окружении.

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

Листинг 8.2. Фрагмент кода класса Accountcontroller

public class Accountcontroller : Controller

{

  public Accountcontroller() : this(null, null)

  {

  }

  public AccountController(IFormsAuthentication formsAuth,

           IMembershipService service)

  {

    FormsAuth = formsAuth ?? new FormsAuthenticationService();

    MembershipService = service ?? new AccountMembershipService();

  }

  public IFormsAuthentication FormsAuth

  {

    get;

    private set;

  }

  public IMembershipService MembershipService

  {

    get;

    private set;

  }

}

Поскольку в контроллере Accountcontroller используются компоненты инфраструктуры ASP.NET, отвечающие за аутентификацию пользователей и управление учетными записями, для них созданы специальные обертки, приведенные в листинге 8.3, реализующие интерфейсы IFormsAuthentication и IMembershipService.

Листинг 8.3. Интерфейсы и реализация поддержки базовых служб

public interface IFormsAuthentication

{

  void SignIn(string userName, bool createPersistentcookie);

  void SignOut();

}

public class FormsAuthenticationService : IFormsAuthentication

{

  public void SignIn(string userName, bool createPersistentCookie)

  {

    FormsAuthentication.SetAuthCookie(userName,

                  createPersistentCookie);

  }

  public void SignOut()

  {

    FormsAuthentication.SignOut();

  }

}

public interface IMembershipService

{

  int MinPasswordLength { get; }

  bool ValidateUser(string userName, string password);

  MembershipCreateStatus CreateUser(string userName,

        string password, string email);

  bool ChangePassword(string userName,

        string oldPassword, string newPassword);

}

public class AccountMembershipService : IMembershipService

{

  private MembershipProvider _provider;

  public AccountMembershipService()

              : this(null)

  {

  }

  public AccountMembershipService(MembershipProvider provider)

  {

    _provider = provider ?? Membership.Provider;

  }

  public int MinPasswordLength

  {

    get

    {

      return _provider.MinRequiredPasswordLength;

    }

  }

  public bool ValidateUser(string userName, string password)

  {

    return _provider.ValidateUser(userName, password);

  }

  public MembershipCreateStatus CreateUser(string userName,

                 string password, string email)

  {

    MembershipCreateStatus status;

    _provider.CreateUser(userName, password,

          email, null, null, true, null, out status);

    return status;

  }

  public bool ChangePassword(string userName,

            string oldPassword, string newPassword)

  {

    MembershipUser currentUser = _provider.GetUser(

            userName, true);

    return currentUser.ChangePassword(oldPassword, newPassword);

  }

}

Выделение обертки над службами ASP.NET позволяет не только получить возможность простого тестирования, но и заменять реализацию в процессе развития приложения. Например, при замене стандартного провайдера Membership на собственную реализацию или изменение провайдера авторизации для поддержки сертификатов, или Windows-аутентификация. Однако в целях тестирования этот подход просто незаменим.

Во время работы веб-приложения, созданного из шаблона, используется стандартная фабрика контроллеров, не передающая дополнительных параметров конструктору класса Accountcontroller, в тестовом же окружении используется имитация – код классов, имитирующих бурную деятельность. Пример классов, реализующих подход имитации, приведен в листинге 8.4.

Листинг 8.4. Классы для имитации в условиях тестирования

public class MockFormsAuthenticationService :

          IFormsAuthentication

{

  public void SignIn(string userName,

      bool createPersistentcookie) { }

  public void SignOut() { }

}

public class MockHttpContext : HttpContextBase

{

  private IPrincipal _user;

  public override IPrincipal User

  {

    get

    {

      if (_user == null)

      {

        _user = new MockPrincipal();

      }

      return _user;

    }

    set

    {

      _user = value;

    }

  }

}

Аналогично коду, приведенному в листинге 8.4, строятся остальные классы, используемые для тестирования. Основной принцип их создания состоит в том, чтобы развязать процесс тестирования с реальным функционалом – вместо работы с базами данных не делать ничего, либо возвращать стандартные значения, используемые для тестирования, и т. п.

Пример использования имитирующих классов в целях тестирования приведен в листинге 8.5. Процесс подготовки объектов выделен в отдельный метод GetAccountController() .

Листинг 8.5. Несколько методов для тестирования AccountController

private static AccountController GetAccountController()

{

  IFormsAuthentication formsAuth = new

                 MockFormsAuthenticationService();

  MembershipProvider membershipProvider = new MockMembershipProvider();

  AccountMembershipService membershipService = new

  AccountMembershipService(membershipProvider);

  AccountController controller = new

  AccountController(formsAuth, membershipService);

  ControllerContext controllerContext = new

      ControllerContext(new MockHttpContext(),

                  new RouteData(),

                  controller);

  controller.ControllerContext = controllerContext;

  return controller;

}

[Test]

public void RegisterPostReturnsViewIfPasswordIsNull()

{

  AccountController controller = GetAccountController();

  ViewResult result = (ViewResult)controller.Register("username",

             "email", null, null);

  Assert.AreEqual(6, result.ViewData["PasswordLength"]);

  Assert.AreEqual(

    "You must specify a password of 6 or more characters.",

    result.ViewData.ModelState["password"].Errors[0].ErrorMessage);

}

[Test]

public void

    RegisterPostReturnsViewIfNewPasswordDoesNotMatchConfirmPassword()

{

  AccountController controller = GetAccountController();

  ViewResult result = (ViewResult)controller.Register("username",

                            "email", "password", "password2");

  Assert.AreEqual (6, result.ViewData["PassworcLLength"] );

  Assert.AreEqual(

      "The new password and confirmation password do not match.",

      result.ViewData.ModelState["_FORM"].Errors[0].ErrorMessage);

}

[Test]

public void RegisterPostReturnsViewIfPasswordIsTooShort()

{

  AccountController controller = GetAccountController();

  ViewResult result = (ViewResult)controller.Register("username",

                "email", "12345", "12345");

  Assert.AreEqual(6, result.ViewData["PasswordLength"]);

  Assert.AreEqual(

      "You must specify a password of 6 or more characters.",

      result.ViewData.ModelState["password"].Errors[0].ErrorMessage);

}

[Test]

public void RegisterPostReturnsViewIfRegistrationFails()

{

  AccountController controller = GetAccountController();

  ViewResult result = (ViewResult)controller.Register("someUser",

    "DuplicateUserName" /* error */, "badPass", "badPass");

  Assert.AreEqual(6, result.ViewData["PasswordLength"]);

  Assert.AreEqual(

      "Username already exists. Please enter a different user name.",

      result.ViewData.ModelState["_FORM"].Errors[0].ErrorMessage);

}

[Test]

public void RegisterPostReturnsViewIfUsernameNotSpecified()

{

  AccountController controller = GetAccountController();

  ViewResult result = (ViewResult)controller.Register("", "email",

                "password", "password");

  Assert.AreEqual(6, result.ViewData["PasswordLength"]);

  Assert.AreEqual("You must specify a username.",

      result.ViewData.ModelState["username"].Errors[0].ErrorMessage);

}

Основная концепция, продемонстрированная в листинге 8.5, заключается в использовании «подставных» реализаций везде, где применяются реализации, не зависящие от кода, описанного в самом контроллере, а также в создании отдельных тестовых методов для разных сценариев выполнения одного и того же действия контроллера.

Заключение

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

ГЛАВА 9

ASP.NET MVC 2 и Visual Studio 2010


 Пока писалась эта книга, процесс разработки ASP.NET MVC Framework не стоял на месте. Сначала вышла предварительная версия ASP.NET MVC Preview 1, а затем и ASP.NET MVC Preview 2. Некоторое время спустя была выпущена и новая версия инструмента разработчиков Visual Studio 2010 Beta 2. На момент написания этой части книги Visual Studio 2010 Beta 2 и ASP.NET MVC Preview 2 – последние версии, доступные широкой аудитории разработчиков.

Новая вторая версия ASP.NET MVC принесла во Framework значительную порцию нового функционала, новых концепций, новых удобных инструментов и API. В этой части книги мы бы хотели кратко осветить то, что предлагается разработчиками ASP.NET в предварительных версиях Framework.

Области


Понятие областей (areas) для ASP.NET MVC – новая концепция. Суть областей сводится к тому, чтобы предоставить возможность разделить чрезмерно большой проект на несколько групп, которые продолжали бы взаимодействовать друг с другом. Например, в компании работает несколько групп разработчиков, которые создают большой проект, включающий в себя: основной сайт, магазин, обзоры товаров, форум, внутренний сайт по администрированию и пр. Для создания такого проекта ASP.NET MVC 2 предлагает выделить каждую отдельную часть проекта в область, вместе эти области продолжали бы представлять собой один взаимосвязанный проект. Выделение из большого проекта отдельных проектов-областей позволит разным группам разработчиков более независимо разрабатывать свои части приложения.

Предположим, что в крупной компании разрабатывается большой проект на базе ASP.NET MVC. Обычно группы, работающие над разными частями проекта, независимы друг от друга и связаны только спецификацией. Поэтому очень важно не допустить возможных конфликтов в программном коде, которые могут возникнуть, когда несколько частей большого проекта сливаются в одно целое. Так, например, группы, разрабатывающие части, отвечающие за магазин и за блог сайта, могут независимо друг от друга создать одноименные контроллеры AdminController. В случае, когда проект не основан на областях, слияние двух независимых частей с одноименным контроллером может быть сильно затруднено или невозможно. С использованием областей данная проблема решается, т. к. каждая область может иметь свой собственный независимый набор контроллеров.

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

Концепция областей появилась в ASP.NET MVC 2 Preview 1 в виде областей в решении с несколькими проектами. После выхода ASP.NET MVC 2 Preview 2 применение областей было расширено возможностью создавать области в одном проекте. Рассмотрим оба варианта.

Области для нескольких проектов

При создании решения с использованием областей, работающих для нескольких проектов, необходимо следовать следующим шагам:

1. Создать проект, который будет родительским (или главным) по отношению к проектам-областям.

2. Создать проекты-области, например, для форума, блога, магазина и т. д. В этих проектах требуется удалить файлы Global.asax, кроме того, можно удалить созданные по умолчанию файлы в папку Scripts, поскольку все скрипты будут браться из родительского проекта.

3. Добавить ссылки на проекты-области в родительском проекте.

4. Создать для каждого из проектов класс, наследующий от класса AreaRegistration, в котором перегрузить два элемента: метод RegisterArea и свойство AreaName. RegisterArea должен реализовать логику по регистрированию области в контексте приложения, свойство AreaName должно вернуть название области.

5. В родительском проекте в Global.asax необходимо вызвать метод AreaRegistration.RegisterAllAreas(); для регистрации областей в контексте приложения во время запуска.

6. Заключительным шагом, который требуется для успешного запуска проекта с областями, является модификация файлов проекта *.csproj (*.vbproj для проектов на Visual Basic) каждого из проектов. В каждого таком файле необходимо раскомментировать относящиеся к областям строки кода (будет показано далее).

Рассмотрим шаги немного подробнее. На рис. 9.1 показана структура решения, в котором содержится три проекта: родительский проект AreasProject и два проекта-области – Forum и Store, которые реализуют логику форума и магазина соответственно.

Рис. 9.1. Структура проекта ASP.NET MVC с областями

В проекте-области Forum создан контроллер ForumController, который реализует три действия: Index, AddPost, EditPost. Точно так же в проекте Store создан контроллер ProductsController с действиями List, AddReview и Details. Для отображения результатов действий созданы соответствующие представления. После создания проектов-областей в проект AreasProject были добавлены ссылки на эти проекты.

На рис. 9.1 вы можете заметить в проектах Store и Forum файл Routes.cs. Этот файл добавлен в проекты для того, чтобы реализовать класс AreaRegistration. Рассмотрим содержимое файла Routes.cs в проекте Store в листинге 9.1.

Листинг 9.1. Содержимое файла Routes.cs проекта Store

namespace Store

{

  using System.Web.Mvc;

  using System.Web.Routing;

  public class Routes : AreaRegistration

  {

    public override void RegisterArea(

               AreaRegistrationContext context)

    {

      context.MapRoute(

            «Store_Default»,

            «Store/{controller}/{action}/{id}»,

            new {controller = «Products»,

            action = «List», id = ""},

            new string[] { «Store.Controllers» }

      );

    }

    public override string AreaName

    {

      get { return «Store»; }

    }

  }

}

Обратите внимание, класс Routes наследуется от AreaRegistration, что позволит подсистеме ASP.NET MVC в дальнейшем проинициализировать с помощью него подсистему областей. В классе Routes содержится два перегруженных члена: метод RegisterArea и свойство AreaName.

В RegisterArea производится регистрация маршрутов в контексте приложения с областями. С помощью context.MapRoute создается маршрут под названием store_Default. Последнее значение параметра new string[] { "Store.Controllers" } определяет пространство имен, в котором находятся контроллеры, сопоставленные данному маршруту.

Перегруженное свойство AreaName возвращает название области. Это имя в дальнейшем используется как ASP.NET MVC, так и разработчиком для указания области, из которой необходимо вызвать требуемый функционал.

Классы, подобные Routes для проекта Store, необходимо создать для каждого проекта в решении с областями.

Следующим шагом будет добавление в родительском проекте AreasProject в Global.asax следующей строки кода:

protected void Application_Start()

{

  AreaReg±stration.Reg±sterAllAreas();

  RegisterRoutes(RouteTable.Routes);

}

Вызов AreaRegistration.RegisterAllAreas() при запуске приложения позволит ASP.NET MVC инициализировать все имеющиеся области и их маршруты в приложении.

Последним шагом, необходимым для запуска проекта с областями, является модификация файлов проекта *.csproj (или *.vbproj, если ваши проекты написаны на Visual Basic) для каждого из проектов в решении. Для того чтобы получить доступ к этим файлам, последовательно выгрузите проекты из решения с помощью команды UnloadProject. В контекстном меню на выгруженном проекте выберите Edit***.csproj (рис. 9.2), где *** – название проекта.

Рис. 9.2. Контекстное меню, позволяющее редактировать файл проекта

В файлах проектов содержится часть закомментированных определений, которые требуется раскомментировать для использования решения на базе областей. Для проектов-областей это куски кода с комментариями:

 и

Для родительского проекта необходимо раскомментировать куски кода, помеченные:

и


Примечание

Возможно, что в следующих релизах ASP.NET MVC 2 действие с редактированием файлов проекта будет излишним. Ожидается, что работа с областями будет поддерживаться на уровне Solution Explorer, что облегчит создание новых областей и проектов на их базе.

*****************************

Теперь, когда проект подготовлен полностью, можно использовать проекты-области в родительском проекте следующим образом. Видоизменим в файл Site.Master в родительском проекте блок кода списка вкладок так, чтобы он выглядел, как во фрагменте:

Обратите внимание, что построение ссылок с помощью Html.ActionLink теперь требует указания области, в которой нужно найти контроллер и действие. Если мы запустим проект, то увидим следующее (рис. 9.3).

Новые вкладки Store и Forum будут работать согласно заданным правилам и отображать представления из проектов-областей.

Области в одном проекте

Если в решении предыдущего примера областей для нескольких проектов включить опцию показа скрытых файлов для родительского проекта, то мы увидим следующую картину (рис. 9.4).

В родительском проекте AreasProject в папке Views/Areas создаются скрытые элементы из проектов-областей. Это требуется для того, чтобы родительский проект самостоятельно отображал представления проектов-областей.

Однако эта структура скрытых файлов может быть использована и напрямую. В ASP.NET MVC 2 Preview 2 появилась возможность создания решений с одиночными проектами на базе областей. Такие решения содержат только один проект, в котором реализованы все области. На рис. 9.5 представлена структура одиночного проекта, где реализованы те же самые области, которые были реализованы в предыдущем разделе с помощью нескольких проектов-областей.

Чтобы создать такой проект, по аналогии с предыдущим примером, мы должны создать вместо нескольких проектов иерархию областей в одном проекте. Для этого в корне проекта необходимо создать папку Areas, в которой каждая созданная папка будет являться отдельной областью. На рис. 9.5 такими папками являются Forum и Store. В них следует создать папку Controllers и Views для контроллеров и представлений и реализовать их подобно тому, как мы сделали это в предыдущем разделе. Обратите внимание, что для каждой папки-области также нужно создать файл Routes.cs с реализацией класса AreaRegistration. Необходимо обновить и Global.asax, добавив в него вызов AreaRegistration.RegisterAllAreas ().

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

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

Шаблонные помощники


Шаблонные помощники (templated helpers) – это новое средство в MVC 2, которое призвано сократить время разработки представлений. Шаблонные помощники строго типизированы и основаны на моделях приложения, кроме того, для вывода информации и валидации модели используется механизм DataAnnotations. В общем, шаблонных помощников можно представить себе как генератор разметки на базе определенной модели и правил, указанных с помощью атрибутов DataAnnotations.

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

Для примера рассмотрим следующую модель данных:

public class Product

{

  public int Id { get; set; }

  public string Name { get; set; }

  public string Description { get; set; }

  public decimal Cost { get; set; }

  public DateTime UpdatedAt { get; set; }

}

Класс Product представляет собой модель продукта для некого магазина. Модель содержит идентификатор, название, описание, стоимость и дату обновления.

Механизм шаблонных помощников устроен так, что позволяет отображать разметку для модели всего одной строчкой кода. Например, создадим контроллер StoreController и строготипизированное представление Info, основанное на Product, которое отображает информацию о продукте (листинг 9.2).

Листинг 9.2. Представление с использованием шаблонных помощников

<%@ Page Title="" Language="C#"

    MasterPageFile="~/Views/Shared/Site.Master"

    Inherits="System.Web.Mvc.ViewPage " %>

      runat="server">

  Информация о продукте

      runat="server">

 

Info

  <%= Html.DisplayFor(x => Model)%>

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

Код контроллера StoreController для примера будет таким, как в листинге 9.3.

Листинг 9.3. Контроллер StoreController

namespace TemplatedHelpersProject.Controllers

{

  using System;

  using System.Web.Mvc;

  using TemplatedHelpersProj ect.Models;

  public class StoreController : Controller

  {

    public ActionResult Info()

    {

      var product = new Product() { Cost = 1,

           Description = "Описание",

           Id = 1, Name = "Товар",

           UpdatedAt = DateTime.Now };

      return View(product);

    }

  }

}

Запустим приложение на выполнение и перейдем на представление Store/Info. Результатом будет полная информация, заведенная нами в экземпляре Product (рис. 9.6).

Как вы можете увидеть, написав всего одну строчку кода в представлении, мы сформировали разметку для целой комплексной модели данных.

Шаблоны по умолчанию

Для работы с шаблонами по умолчанию ASP.NET MVC предлагает несколько стандартных методов расширения:

□ Html.LabelFor – производит рендеринг описательной информации для данных модели. По умолчанию выводит название поля модели;

□ Html.DisplayFor – производит рендеринг значений данных модели в соответствии с их типом;

□ Html.EditorFor – производит рендеринг элементов управления с данными модели для возможности редактирования.

Примечание

Кроме перечисленных стандартных методов расширения, в будущем планируется добавить методы: ValidationMessageFor, TextAreaFor, TextBoxFor, HiddenFor, DropDownListFor для соответствующей поддержки валидации и элементов управления в различных представлениях.

************************

Для всех этих методов расширения есть дополнительные методы LabelForModel, DisplayForModel и EditorForModel, которые являются сокращенным вариантом своих аналогов. Эти методы предназначены для рендеринга всей модели данных целиком без указания параметров.

Рассмотрим вариант рендеринга модели с помощью стандартных методов расширения. Для этого сформируем следующее представление (листинг 9.4).

Листинг 9.4. Модифицированное представление

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"

  Inherits="System.Web.Mvc.ViewPage " %>

     runat="server">

  Info

     runat="server">

 

   

      Информация

     

       

<%= Html.LabelFor(x => Model.Name) %>

       

<%= Html.DisplayFor(x => Model.Name) %>

       

<%= Html.LabelFor(x => Model.Cost) %>

       

<%= Html.DisplayFor(x => Model.Cost) %>

       

<%= Html.LabelFor(x => Model.Description) %>

        

<%= Html.DisplayFor(x => Model.Description) %>

      

   

 

Результат работы данного кода представлен на рис. 9.7.

Обратите внимание, что с использованием методов Html.LabelFor и Html.EditorFor для каждого элемента модели мы получили возможность осуществлять рендеринг данных в таком виде, в котором нам бы этого хотелось. Вместо стандартной разметки с использованием

, которая производится при автоматическом рендеринге всей модели, мы использовали тег
для представления только той ее части, которая нужна нам.

Создание шаблонов

Существует большая вероятность того, что один и тот же рендеринг одного и того же типа данных вам предстоит выполнить в разных представлениях. Для того чтобы поддержать такой сценарий, ASP.NET MVC предлагает разработчику создать один-единственный шаблон рендеринга типа данных, а затем использовать его во всех необходимых местах.

Для того чтобы создать шаблон представления типа данных, необходимо в папке нужного контроллера в папке представлений Views создать одну из папок: DisplayTemplates или EditorTemplates. DisplayTemplates должна содержать шаблоны для рендеринга представлений для просмотра, а EditorTemplates – для редактирования. Папки DisplayTemplates и EditorTemplates содержат частичные представления *.ascx, наименование которых соответствуют типам данных, с которыми необходимо работать.

Например, на рис. 9.8 в папке Views/Store представлена папка DisplayTemplates, которая содержит частичное представление Product.ascx. Это означает, что для рендеринга данных типа Product при работе в контроллере storeController будет использоваться шаблон Product.ascx.

Содержимое Product.ascx представлено в листинге 9.5.

Листинг 9.5. Содержимое Product.ascx

<%@ Control Language="C#"

  Inherits="System.Web.Mvc.ViewUserControl"

%>

 

    ИНформация

   

     

        <%= Html.LabelFor(x => Model.Name) %>

     

     

        <%= Html.DisplayFor(x => Model.Name) %>

     

     

        <%= Html.LabelFor(x => Model.Cost) %>

     

     

        <%= Html.DisplayFor(x => Model.Cost) %>

     

     

        <%= Html.LabelFor(x => Model.Description) %>

     

     

        <%= Html.DisplayFor(x => Model.Description) %>

      

    

 

Как вы можете убедиться, шаблон Product.ascx соответствует той разметке, которую мы создавали для рендеринга в листинге 9.4. Однако если теперь модифицировать код листинга 9.4 до простого варианта <%= Html.DisplayFor (x => Model) %>, то результат останется неизменным, т. к. механизм ASP.NET MVC, обнаружив имеющийся шаблон Product.ascx, использует его для рендеринга представления модели с типом Product.

Аннотация данных и валидация



ASP.NET MVC 2 имеет поддержку валидации данных на основании аннотации с помощью атрибутов из пространства имен System.ComponentModel.DataAnnotations.

Давайте улучшим наше представление, внеся изменение в модель так, как показано в листинге 9.6.

Листинг 9.6. Модель данных с аннотациями

namespace TemplatedHelpersProj ect.Models

{

  using System;

  using System.ComponentModel;

  using System.ComponentModel.DataAnnotations;

  using System.Web.Mvc;

  public class Product

  {

    [DisplayName("Идентификатор")]

    [HiddenInput]

    public int Id { get; set; }

    [DisplayName(«Наименование товара»)]


    Ваша оценка произведения:

Популярные книги за неделю