Практическое лабораторное занятие. Создание одностраничного приложения (SPA) с помощью веб-API ASP.NET и Angular.js

по команде веб-лагерей

Скачивание комплекта обучения для веб-лагерей

В этом практическом задании показано, как создать одностраничное приложение (SPA) с веб-API ASP.NET и Angular.js для ASP.NET 4.x.

В этом практическом задании вы будете использовать эти технологии для реализации Geek Quiz, веб-сайта trivia, основанного на концепции SPA. Сначала вы реализуете уровень служб с веб-API ASP.NET, чтобы предоставить необходимые конечные точки для получения вопросов теста и сохранения ответов. Затем вы создадите полнофункционированный и адаптивный пользовательский интерфейс с помощью эффектов преобразования AngularJS и CSS3.

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

В приложениях Single-Page (SPA) вся страница загружается в браузере после первоначального запроса, но последующие взаимодействия выполняются через запросы Ajax. Это означает, что браузер должен обновить только ту часть страницы, которая была изменена; нет необходимости перезагружать всю страницу. Подход SPA сокращает время, затрачиваемое приложением на реагирование на действия пользователя, что приводит к более гибкому взаимодействию.

Архитектура SPA связана с определенными проблемами, которые отсутствуют в традиционных веб-приложениях. Однако новые технологии, такие как веб-API ASP.NET, платформы JavaScript, такие как AngularJS, и новые функции стилей, предоставляемые CSS3, упрощают проектирование и создание spaas.

Все примеры кода и фрагменты кода включены в комплект для обучения веб-лагерей, доступный по адресу https://aka.ms/webcamps-training-kit.

Общие сведения

Задачи

В этом практическом задании вы узнаете, как:

  • Создание службы веб-API ASP.NET для отправки и получения данных JSON
  • Создание адаптивного пользовательского интерфейса с помощью AngularJS
  • Улучшение пользовательского интерфейса с помощью преобразований CSS3

Предварительные требования

Для выполнения этого практического задания требуется следующее:

Настройка

Чтобы выполнить упражнения в этом практическом задании, сначала необходимо настроить среду.

  1. Откройте Windows Обозреватель и перейдите в папку Source лаборатории.
  2. Щелкните правой кнопкой мыши Setup.cmd и выберите Запуск от имени администратора , чтобы запустить процесс установки, который настроит среду и установит фрагменты кода Visual Studio для этого задания.
  3. Если отображается диалоговое окно Контроль учетных записей, подтвердите действие для продолжения.

Примечание

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

Использование фрагментов кода

Во всем лабораторном документе вам будет предложено вставить блоки кода. Для удобства большая часть этого кода предоставляется в виде фрагментов Visual Studio Code, доступ к которым можно получить из Visual Studio 2013, чтобы избежать необходимости добавлять его вручную.

Примечание

Каждое упражнение сопровождается начальным решением, расположенным в папке Begin упражнения, которое позволяет выполнять каждое упражнение независимо от других. Имейте в виду, что фрагменты кода, добавленные во время упражнения, отсутствуют в этих начальных решениях и могут не работать, пока вы не завершите упражнение. В исходном коде упражнения вы также найдете папку End , содержащую решение Visual Studio с кодом, который является результатом выполнения шагов в соответствующем упражнении. Эти решения можно использовать в качестве руководства, если вам нужна дополнительная помощь при работе с этим практическим занятием.


Упражнения

Это практическое занятие включает в себя следующие упражнения:

  1. Создание веб-API
  2. Создание интерфейса SPA

Предполагаемое время выполнения этого задания: 60 минут

Примечание

При первом запуске Visual Studio необходимо выбрать одну из стандартных коллекций параметров. Каждая предопределенная коллекция предназначена для соответствия определенному стилю разработки и определяет макеты окон, поведение редактора, фрагменты кода IntelliSense и параметры диалоговых окон. Процедуры в этом задании описывают действия, необходимые для выполнения данной задачи в Visual Studio при использовании коллекции Общих параметров разработки . Если выбрать другую коллекцию параметров для среды разработки, возможны различия в действиях, которые следует учитывать.

Упражнение 1. Создание веб-API

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

Платформа веб-API является частью стека ASP.NET и предназначена для упрощения реализации служб HTTP, как правило, отправки и получения данных в формате JSON или XML через RESTful API. В этом упражнении вы создадите веб-сайт для размещения приложения Geek Quiz, а затем реализуете серверную службу для предоставления и сохранения данных теста с помощью веб-API ASP.NET.

Задача 1. Создание начального проекта для Geek Quiz

В этой задаче вы начнете создавать проект ASP.NET MVC с поддержкой веб-API ASP.NET на основе типа проекта One ASP.NET, который поставляется в Visual Studio. Один ASP.NET объединяет все ASP.NET технологии и дает возможность сочетать и сопоставлять их по желанию. Затем вы добавите классы моделей Entity Framework и инициализатор базы данных, чтобы вставить вопросы теста.

  1. Откройте Visual Studio Express 2013 для Интернета и выберите Файл | Создать проект... для запуска нового решения.

    Создание нового проекта

    Создание нового проекта

  2. В диалоговом окне Новый проект выберите ASP.NET веб-приложение в разделе Visual C# | Веб-вкладка. Убедитесь, что выбран платформа .NET Framework 4.5, назовите его GeekQuiz, выберите Расположение и нажмите кнопку ОК.

    Создание проекта веб-приложения ASP.NET

    Создание проекта веб-приложения ASP.NET

  3. В диалоговом окне Новый проект ASP.NET выберите шаблон MVC и параметр Веб-API . Кроме того, убедитесь, что для параметра Проверка подлинности задано значение Индивидуальные учетные записи пользователей. Чтобы продолжить, нажмите кнопку ОК .

    Создание проекта с помощью шаблона MVC, включая компоненты веб-API

    Создание проекта с помощью шаблона MVC, включая компоненты веб-API

  4. В Обозреватель решений щелкните правой кнопкой мыши папку Models проекта GeekQuiz и выберите Добавить | Существующий элемент....

    Добавление существующего элемента

    Добавление существующего элемента

  5. В диалоговом окне Добавление существующего элемента перейдите в папку Source/Assets/Models и выберите все файлы. Нажмите кнопку Добавить.

    Добавление ресурсов модели

    Добавление ресурсов модели

    Примечание

    Добавляя эти файлы, вы добавляете модель данных, контекст базы данных Entity Framework и инициализатор базы данных для приложения Geek Quiz.

    Entity Framework (EF) — это объектно-реляционный сопоставителя (ORM), который позволяет создавать приложения для доступа к данным путем программирования с помощью концептуальной модели приложений, а не непосредственно с помощью схемы реляционного хранилища. Дополнительные сведения о Entity Framework см. здесь.

    Ниже приведено описание только что добавленных классов.

    • TriviaOption: представляет один параметр, связанный с вопросом теста.
    • TriviaQuestion: представляет вопрос теста и предоставляет связанные параметры с помощью свойства Options .
    • TriviaAnswer: представляет параметр, выбранный пользователем в ответ на вопрос теста.
    • TriviaContext: представляет контекст базы данных Entity Framework приложения Geek Quiz. Этот класс является производным от DContext и предоставляет свойства DbSet , представляющие коллекции сущностей, описанных выше.
    • TriviaDatabaseInitializer: реализация инициализатора Entity Framework для класса TriviaContext , наследуемого от CreateDatabaseIfNotExists. По умолчанию этот класс создает базу данных только в том случае, если она не существует, вставляя сущности, указанные в методе Seed .
  6. Откройте файл Global.asax.cs и добавьте следующий оператор using.

    using GeekQuiz.Models;
    
  7. Добавьте следующий код в начало метода Application_Start , чтобы задать TriviaDatabaseInitializer в качестве инициализатора базы данных.

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            System.Data.Entity.Database.SetInitializer(new TriviaDatabaseInitializer()); 
    
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
    
  8. Измените контроллер Home , чтобы ограничить доступ для пользователей, прошедших проверку подлинности. Для этого откройте файл HomeController.cs в папке Controllers и добавьте атрибут Authorize в определение класса HomeController .

    namespace GeekQuiz.Controllers
    {
        [Authorize]
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                return View();
            }
    
            ...
        }
    }
    

    Примечание

    Фильтр Авторизовать проверяет, прошел ли пользователь проверку подлинности. Если пользователь не прошел проверку подлинности, он возвращает код состояния HTTP 401 (Не авторизовано) без вызова действия. Фильтр можно применить глобально, на уровне контроллера или на уровне отдельных действий.

  9. Теперь вы настроите макет веб-страниц и фирменную символику. Для этого откройте файл _Layout.cshtml в представлении | Общая папка и обновите содержимое <элемента title> , заменив My ASP.NET Application на Geek Quiz.

    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>@ViewBag.Title - Geek Quiz</title>
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    
    </head>
    
  10. В том же файле обновите панель навигации, удалив ссылки About (О программе ) и Contact (Контакт) и переименовав ссылку Главная в Play (Воспроизвести). Кроме того, переименуйте ссылку Имя приложения в Geek Quiz. HTML-код панели навигации должен выглядеть так, как показано в следующем коде.

    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Geek Quiz", "Index", "Home", null, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Play", "Index", "Home")</li>
                </ul>
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </div>
    
  11. Обновите нижний колонтитул страницы макета, заменив My ASP.NET Application на Geek Quiz. Для этого замените содержимое элемента нижнего< колонтитула> следующим выделенным кодом.

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - Geek Quiz</p>
        </footer>
    </div>
    

Задача 2. Создание веб-API TriviaController

В предыдущей задаче вы создали начальную структуру веб-приложения Geek Quiz. Теперь вы создадите простую службу веб-API, которая взаимодействует с моделью данных теста и предоставляет следующие действия:

  • GET /api/trivia: извлекает следующий вопрос из списка теста, на который ответит пользователь, прошедший проверку подлинности.
  • POST /api/trivia: хранит ответ теста, указанный пользователем, прошедшим проверку подлинности.

Вы будете использовать средства формирования шаблонов ASP.NET, предоставляемые Visual Studio, для создания базовых показателей для класса контроллера веб-API.

  1. Откройте файл WebApiConfig.cs в папке App_Start . Этот файл определяет конфигурацию службы веб-API, например способ сопоставления маршрутов с действиями контроллера веб-API.

  2. Добавьте следующий оператор using в начало файла.

    using Newtonsoft.Json.Serialization;
    
  3. Добавьте следующий выделенный код в метод Register , чтобы глобально настроить модуль форматирования для данных JSON, полученных методами действий веб-API.

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
    
            // Use camel case for JSON data.
            config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    
            // Web API routes
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
    

    Примечание

    CamelCasePropertyNamesContractResolver автоматически преобразует имена свойств в верблюжий регистр, что является общим соглашением для имен свойств в JavaScript.

  4. В Обозреватель решений щелкните правой кнопкой мыши папку Controllers проекта GeekQuiz и выберите Добавить | Новый шаблонный элемент....

    Создание нового элемента с шаблонами

    Создание нового элемента с шаблонами

  5. В диалоговом окне Добавление шаблона убедитесь, что в левой области выбран узел Общие . Затем выберите шаблон Контроллер веб-API 2 — пустой в центральной области и нажмите кнопку Добавить.

    Выбор пустого шаблона Контроллер веб-API 2

    Выбор пустого шаблона контроллера веб-API 2

    Примечание

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

    Процесс формирования шаблонов также гарантирует, что все необходимые зависимости будут установлены в проекте. Например, если вы начинаете с пустого проекта ASP.NET, а затем используете формирование шаблонов для добавления контроллера веб-API, необходимые пакеты и ссылки NuGet веб-API добавляются в проект автоматически.

  6. В диалоговом окне Добавление контроллера введите TriviaController в текстовом поле Имя контроллера и нажмите кнопку Добавить.

    Добавление контроллера Trivia

    Добавление контроллера Trivia

  7. Затем файл TriviaController.cs добавляется в папку Controllers проекта GeekQuiz , содержащую пустой класс TriviaController . Добавьте следующие операторы using в начало файла.

    (Фрагмент кода — AspNetWebApiSpa — Ex1 — TriviaControllerUsings)

    using System.Data.Entity;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web.Http.Description;
    using GeekQuiz.Models;
    
  8. Добавьте следующий код в начало класса TriviaController , чтобы определить, инициализировать и удалить экземпляр TriviaContext в контроллере.

    (Фрагмент кода — AspNetWebApiSpa — Ex1 — TriviaControllerContext)

    public class TriviaController : ApiController
    {
        private TriviaContext db = new TriviaContext();
    
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                this.db.Dispose();
            }
    
            base.Dispose(disposing);
        }
    }
    

    Примечание

    Метод Disposeобъекта TriviaController вызывает метод Disposeэкземпляра TriviaContext , который гарантирует, что все ресурсы, используемые объектом контекста, освобождаются при удалении экземпляра TriviaContext или сборке мусора. Сюда входит закрытие всех подключения к базе данных, открытых Entity Framework.

  9. Добавьте следующий вспомогательный метод в конец класса TriviaController . Этот метод извлекает из базы данных следующий вопрос теста, на который должен ответить указанный пользователь.

    (Фрагмент кода — AspNetWebApiSpa — Ex1 — TriviaControllerNextQuestion)

    private async Task<TriviaQuestion> NextQuestionAsync(string userId)
    {
        var lastQuestionId = await this.db.TriviaAnswers
            .Where(a => a.UserId == userId)
            .GroupBy(a => a.QuestionId)
            .Select(g => new { QuestionId = g.Key, Count = g.Count() })
            .OrderByDescending(q => new { q.Count, QuestionId = q.QuestionId })
            .Select(q => q.QuestionId)
            .FirstOrDefaultAsync();
    
        var questionsCount = await this.db.TriviaQuestions.CountAsync();
    
        var nextQuestionId = (lastQuestionId % questionsCount) + 1;
        return await this.db.TriviaQuestions.FindAsync(CancellationToken.None, nextQuestionId);
    }
    
  10. Добавьте следующий метод действия Get в класс TriviaController . Этот метод действия вызывает вспомогательный метод NextQuestionAsync , определенный на предыдущем шаге, чтобы получить следующий вопрос для пользователя, прошедшего проверку подлинности.

    (Фрагмент кода — AspNetWebApiSpa — ex1 — TriviaControllerGetAction)

    // GET api/Trivia
    [ResponseType(typeof(TriviaQuestion))]
    public async Task<IHttpActionResult> Get()
    {
        var userId = User.Identity.Name;
    
        TriviaQuestion nextQuestion = await this.NextQuestionAsync(userId);
    
        if (nextQuestion == null)
        {
            return this.NotFound();
        }
    
        return this.Ok(nextQuestion);
    }
    
  11. Добавьте следующий вспомогательный метод в конец класса TriviaController . Этот метод сохраняет указанный ответ в базе данных и возвращает логическое значение, указывающее, является ли ответ правильным.

    (Фрагмент кода — AspNetWebApiSpa — ex1 — TriviaControllerStoreAsync)

    private async Task<bool> StoreAsync(TriviaAnswer answer)
    {
        this.db.TriviaAnswers.Add(answer);
    
        await this.db.SaveChangesAsync();
        var selectedOption = await this.db.TriviaOptions.FirstOrDefaultAsync(o => o.Id == answer.OptionId
            && o.QuestionId == answer.QuestionId);
    
        return selectedOption.IsCorrect;
    }
    
  12. Добавьте следующий метод действия Post в класс TriviaController . Этот метод действия связывает ответ с пользователем, прошедшим проверку подлинности, и вызывает вспомогательный метод StoreAsync . Затем он отправляет ответ с логическим значением, возвращенным вспомогательным методом.

    (Фрагмент кода — AspNetWebApiSpa — ex1 — TriviaControllerPostAction)

    // POST api/Trivia
    [ResponseType(typeof(TriviaAnswer))]
    public async Task<IHttpActionResult> Post(TriviaAnswer answer)
    {
        if (!ModelState.IsValid)
        {
            return this.BadRequest(this.ModelState);
        }
    
        answer.UserId = User.Identity.Name;
    
        var isCorrect = await this.StoreAsync(answer);
        return this.Ok<bool>(isCorrect);
    }
    
  13. Измените контроллер веб-API, чтобы ограничить доступ для пользователей, прошедших проверку подлинности, добавив атрибут Authorize в определение класса TriviaController .

    [Authorize]
    public class TriviaController : ApiController
    {
        ...
    }
    

Задача 3. Запуск решения

В этой задаче вы убедитесь, что служба веб-API, созданная в предыдущей задаче, работает должным образом. Вы будете использовать интернет-Обозреватель F12 Developer Tools для сбора сетевого трафика и проверки полного ответа от службы веб-API.

Примечание

Убедитесь, что Обозреватель Интернета выбран на кнопке Пуск, расположенной на панели инструментов Visual Studio.

Параметр Обозреватель Интернета

  1. Чтобы запустить решение, нажмите клавишу F5. В браузере должна появиться страница Вход .

    Примечание

    При запуске приложения активируется маршрут MVC по умолчанию, который по умолчанию сопоставляется с действием Index класса HomeController . Так как HomeController ограничен пользователями, прошедшими проверку подлинности (помните, что вы добавили в этот класс атрибут Authorize в упражнении 1) и пользователь еще не прошел проверку подлинности, приложение перенаправляет исходный запрос на страницу входа.

    Запуск решения

    Запуск решения

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

    Регистрация нового пользователя

    Регистрация нового пользователя

  3. На странице Регистрация введите имя пользователя и пароль, а затем нажмите кнопку Зарегистрировать.

    Регистрация страницы

    Страница регистрации

  4. Приложение регистрирует новую учетную запись, и пользователь проходит проверку подлинности и перенаправляется обратно на домашнюю страницу.

    Пользователь прошел проверку подлинности

    Пользователь прошел проверку подлинности

  5. В браузере нажмите клавишу F12 , чтобы открыть панель Средства разработчика . Нажмите клавиши CTRL+4 или щелкните значок Сеть , а затем нажмите зеленую кнопку со стрелкой, чтобы начать сбор сетевого трафика.

    Инициализация записи сети веб-API

    Инициализация сетевого захвата веб-API

  6. Добавьте api/trivia к URL-адресу в адресной строке браузера. Теперь вы проверите сведения об ответе от метода действия Get в TriviaController.

    Получение данных следующего вопроса через веб-API

    Получение данных следующего вопроса через веб-API

    Примечание

    После завершения скачивания вам будет предложено выполнить действие с скачанным файлом. Оставьте диалоговое окно открытым, чтобы watch содержимое ответа в окне Средства разработчиков.

  7. Теперь вы проверите текст ответа. Для этого откройте вкладку Сведения и выберите текст ответа. Вы можете проверка, что загруженные данные являются объектом с параметрами свойств (которые являются списком объектов TriviaOption), идентификатором и заголовком, соответствующими классу TriviaQuestion.

    Просмотр текста ответа веб-API

    Просмотр текста ответа веб-API

  8. Назад в Visual Studio и нажмите клавиши SHIFT+F5, чтобы остановить отладку.

Упражнение 2. Создание интерфейса SPA

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

Задача 1. Создание интерфейса SPA с помощью AngularJS

В этой задаче вы будете использовать AngularJS для реализации клиентской части приложения Geek Quiz. AngularJS — это платформа JavaScript с открытым кодом, которая расширяет браузерные приложения с помощью возможностей model-view-controller (MVC), упрощая как разработку, так и тестирование.

Начните с установки AngularJS из консоли диспетчера пакетов Visual Studio. Затем вы создадите контроллер для предоставления поведения приложения Geek Quiz и представления для отрисовки вопросов и ответов теста с помощью обработчика шаблонов AngularJS.

Примечание

Дополнительные сведения об AngularJS см. в разделе [http://angularjs.org/](http://angularjs.org/).

  1. Откройте Visual Studio Express 2013 для Web и откройте решение GeekQuiz.sln, расположенное в папке Source/Ex2-CreatingASPAInterface/Begin. Кроме того, можно продолжить работу с решением, полученным в предыдущем упражнении.

  2. Откройте консоль диспетчера пакетов из раздела Сервис>Диспетчер пакетов NuGet. Введите следующую команду, чтобы установить пакет NuGet AngularJS.Core .

    Install-Package AngularJS.Core
    
  3. В Обозреватель решений щелкните правой кнопкой мыши папку Scripts проекта GeekQuiz и выберите Добавить | Новая папка. Назовите приложение папки и нажмите клавишу ВВОД.

  4. Щелкните правой кнопкой мыши только что созданную папку приложения и выберите Добавить | Файл JavaScript.

    Создание файла JavaScript

    Создание файла JavaScript

  5. В диалоговом окне Укажите имя элемента в текстовом поле Имя элемента введите quiz-controller и нажмите кнопку ОК.

    Присвоение имени новому файлу JavaScript

    Присвоение имени новому файлу JavaScript

  6. В файлеquiz-controller.js добавьте следующий код для объявления и инициализации контроллера AngularJS QuizCtrl .

    (Фрагмент кода — AspNetWebApiSpa — Ex2 — AngularQuizController)

    angular.module('QuizApp', [])
        .controller('QuizCtrl', function ($scope, $http) {
            $scope.answered = false;
            $scope.title = "loading question...";
            $scope.options = [];
            $scope.correctAnswer = false;
            $scope.working = false;
    
            $scope.answer = function () {
                return $scope.correctAnswer ? 'correct' : 'incorrect';
            };
        });
    

    Примечание

    Функция конструктора контроллера QuizCtrl ожидает внедренный параметр с именем $область. Начальное состояние область следует настроить в функции конструктора путем присоединения свойств к объекту $область. Свойства содержат модель представления и будут доступны шаблону при регистрации контроллера.

    Контроллер QuizCtrl определяется в модуле с именем QuizApp. Модули — это единицы работы, которые позволяют разбить приложение на отдельные компоненты. Main преимущества использования модулей заключается в том, что код проще понять и упрощает модульное тестирование, повторное использование и удобство обслуживания.

  7. Теперь вы добавите поведение в область, чтобы реагировать на события, активированные из представления. Добавьте следующий код в конец контроллера QuizCtrl, чтобы определить функцию nextQuestion в объекте $область.

    (Фрагмент кода — AspNetWebApiSpa — Ex2 — AngularQuizControllerNextQuestion)

    .controller('QuizCtrl', function ($scope, $http) { 
        ...
    
        $scope.nextQuestion = function () {
            $scope.working = true;
            $scope.answered = false;
            $scope.title = "loading question...";
            $scope.options = [];
    
            $http.get("/api/trivia").success(function (data, status, headers, config) {
                $scope.options = data.options;
                $scope.title = data.title;
                $scope.answered = false;
                $scope.working = false;
            }).error(function (data, status, headers, config) {
                $scope.title = "Oops... something went wrong";
                $scope.working = false;
            });
        };
    };
    

    Примечание

    Эта функция извлекает следующий вопрос из веб-API Trivia, созданного в предыдущем упражнении, и присоединяет данные вопроса к объекту $область.

  8. Вставьте следующий код в конец контроллера QuizCtrl, чтобы определить функцию sendAnswer в объекте $область.

    (Фрагмент кода — AspNetWebApiSpa — Ex2 — AngularQuizControllerSendAnswer)

    .controller('QuizCtrl', function ($scope, $http) { 
        ...
    
        $scope.sendAnswer = function (option) {
            $scope.working = true;
            $scope.answered = true;
    
            $http.post('/api/trivia', { 'questionId': option.questionId, 'optionId': option.id }).success(function (data, status, headers, config) {
                $scope.correctAnswer = (data === true);
                $scope.working = false;
            }).error(function (data, status, headers, config) {
                $scope.title = "Oops... something went wrong";
                $scope.working = false;
            });
        };
    };
    

    Примечание

    Эта функция отправляет ответ, выбранный пользователем, в веб-API Trivia и сохраняет результат (т. е. если ответ правильный или нет) в объекте $область.

    Функции nextQuestion и sendAnswer, приведенные выше, используют объект $http AngularJS для абстрагирования взаимодействия с веб-API через объект XMLHttpRequest JavaScript из браузера. AngularJS поддерживает другую службу, которая обеспечивает более высокий уровень абстракции для выполнения операций CRUD с ресурсом через API RESTful. Объект $resource AngularJS имеет методы действий, которые обеспечивают высокоуровневое поведение без необходимости взаимодействовать с объектом $http . Рассмотрите возможность использования объекта $resource в сценариях, требующих использования модели CRUD (дополнительные сведения см. в документации по $resource).

  9. Следующим шагом является создание шаблона AngularJS, который определяет представление для теста. Для этого откройте файл Index.cshtml в представлении | Домашняя папка и замените содержимое приведенным ниже кодом.

    (Фрагмент кода — AspNetWebApiSpa — Ex2 — GeekQuizView)

    @{
        ViewBag.Title = "Play";
    }
    
    <div id="bodyContainer" ng-app="QuizApp">
        <section id="content">
            <div class="container" >
                <div class="row">
                    <div class="flip-container text-center col-md-12" ng-controller="QuizCtrl" ng-init="nextQuestion()">
                        <div class="back" ng-class="{flip: answered, correct: correctAnswer, incorrect:!correctAnswer}">
                            <p class="lead">{{answer()}}</p>
                            <p>
                                <button class="btn btn-info btn-lg next option" ng-click="nextQuestion()" ng-disabled="working">Next Question</button>
                            </p>
                        </div>
                        <div class="front" ng-class="{flip: answered}">
                            <p class="lead">{{title}}</p>
                            <div class="row text-center">
                                <button class="btn btn-info btn-lg option" ng-repeat="option in options" ng-click="sendAnswer(option)" ng-disabled="working">{{option.title}}</button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </div>
    
    @section scripts {
        @Scripts.Render("~/Scripts/angular.js")
        @Scripts.Render("~/Scripts/app/quiz-controller.js")
    }
    

    Примечание

    Шаблон AngularJS — это декларативная спецификация, которая использует сведения из модели и контроллера для преобразования статической разметки в динамическое представление, которое пользователь видит в браузере. Ниже приведены примеры элементов AngularJS и атрибутов элементов, которые можно использовать в шаблоне:

    • Директива ng-app сообщает AngularJS элемент DOM, представляющий корневой элемент приложения.
    • Директива ng-controller присоединяет контроллер к модели DOM в точке объявления директивы.
    • Фигурная скобка {{ }} обозначает привязки к свойствам область, определенным в контроллере.
    • Директива ng-click используется для вызова функций, определенных в область в ответ на щелчки пользователем.
  10. Откройте файл Site.css в папке Содержимое и добавьте следующие выделенные стили в конец файла, чтобы обеспечить внешний вид представления теста.

    (Фрагмент кода — AspNetWebApiSpa — Ex2 — GeekQuizStyles)

    .validation-summary-valid {
         display: none;
    }
    
    /* Geek Quiz styles */
    .flip-container .back,
    .flip-container .front {
         border: 5px solid #00bcf2;
         padding-bottom: 30px;
         padding-top: 30px;
    }
    
    #content {
        position:relative;
        background:#fff;
        padding:50px 0 0 0;
    }
    
    .option {
         width:140px;
         margin: 5px;
    }
    
    div.correct p {
         color: green;
    }
    
    div.incorrect p {
         color: red;
    }
    
    .btn {
         border-radius: 0;
    }
    
    .flip-container div.front, .flip-container div.back.flip {
        display: block;
    }
    
    .flip-container div.front.flip, .flip-container div.back {
        display: none;
    }
    

Задача 2. Запуск решения

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

  1. Чтобы запустить решение, нажмите клавишу F5.

  2. Зарегистрируйте новую учетную запись пользователя. Для этого выполните действия по регистрации, описанные в упражнении 1, задача 3.

    Примечание

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

  3. Должна появиться домашняя страница с первым вопросом теста. Ответьте на вопрос, щелкнув один из вариантов. Это активирует функцию sendAnswer , определенную ранее, которая отправляет выбранный параметр в веб-API Trivia .

    Ответ на вопрос

    Ответ на вопрос

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

    Запрос следующего вопроса

    Запрос следующего вопроса

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

    Другой вопрос

    Следующий вопрос

  6. Назад в Visual Studio и нажмите клавиши SHIFT+F5, чтобы остановить отладку.

Задача 3. Создание анимации flip с помощью CSS3

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

  1. В Обозреватель решений щелкните правой кнопкой мыши папку Content проекта GeekQuiz и выберите Добавить | Существующий элемент....

    Добавление существующего элемента в папку Содержимое

    Добавление существующего элемента в папку Содержимое

  2. В диалоговом окне Добавление существующего элемента перейдите в папку Source/Assets и выберите Flip.css. Нажмите кнопку Добавить.

    Добавление файла Flip.css из ресурсов

    Добавление файла Flip.css из ресурсов

  3. Откройте только что добавленный файл Flip.css и проверьте его содержимое.

  4. Найдите комментарий к преобразованию flip . Стили, приведенные ниже, используют перспективу CSS и преобразования rotateY для создания эффекта "карта flip".

    /* flip transformation */
    .flip-container div.front {
        -moz-transform: perspective(2000px) rotateY(0deg);
        -webkit-transform: perspective(2000px) rotateY(0deg);
        -o-transform: perspective(2000px) rotateY(0deg);
        transform: perspective(2000px) rotateY(0deg);
    }
    
        .flip-container div.front.flip {
            -moz-transform: perspective(2000px) rotateY(179.9deg);
            -webkit-transform: perspective(2000px) rotateY(179.9deg);
            -o-transform: perspective(2000px) rotateY(179.9deg);
            transform: perspective(2000px) rotateY(179.9deg);
        }
    
    .flip-container div.back {
        -moz-transform: perspective(2000px) rotateY(-180deg);
        -webkit-transform: perspective(2000px) rotateY(-180deg);
        -o-transform: perspective(2000px) rotateY(-180deg);
        transform: perspective(2000px) rotateY(-180deg);
    }
    
        .flip-container div.back.flip {
            -moz-transform: perspective(2000px) rotateY(0deg);
            -webkit-transform: perspective(2000px) rotateY(0deg);
            -ms-transform: perspective(2000px) rotateY(0);
            -o-transform: perspective(2000px) rotateY(0);
            transform: perspective(2000px) rotateY(0);
        }
    
  5. Найдите скрытую заднюю часть области во время пролистывания комментария. Стиль, приведенный ниже, скрывает заднюю сторону лиц, когда они обращены от зрителя, задав свойству CSS backface-visibilityзначение hidden.

    /* hide back of pane during flip */
    .front, .back {
        -moz-backface-visibility: hidden;
        -webkit-backface-visibility: hidden;
        backface-visibility: hidden;
    }
    
  6. Откройте файл BundleConfig.cs в папке App_Start и добавьте ссылку на файл Flip.css в пакет стилей ~/Content/css.

    bundles.Add(new StyleBundle("~/Content/css").Include(
        "~/Content/bootstrap.css",
        "~/Content/site.css",
        "~/Content/Flip.css"));
    
  7. Нажмите клавишу F5 , чтобы запустить решение и войти с учетными данными.

  8. Ответьте на вопрос, щелкнув один из вариантов. Обратите внимание на эффект переворачивания при переходе между представлениями.

    Ответ на вопрос с эффектом " "

    Ответ на вопрос с помощью эффекта "перевернуть"

  9. Нажмите кнопку Следующий вопрос , чтобы получить следующий вопрос. Эффект переворачивания должен появиться снова.

    Получение следующего вопроса с эффектом " "

    Получение следующего вопроса с эффектом "флип"


Итоги

Завершив это практическое занятие, вы узнали, как:

  • Создание контроллера веб-API ASP.NET с помощью формирования шаблонов ASP.NET
  • Реализация действия Получения веб-API для получения следующего вопроса теста
  • Реализация действия post веб-API для хранения ответов на тесты
  • Установка AngularJS из консоли диспетчера пакетов Visual Studio
  • Реализация шаблонов и контроллеров AngularJS
  • Использование переходов CSS3 для выполнения эффектов анимации