Laboratório prático: Criar um SPA (aplicativo de página única) com o ASP.NET Web API e o Angular.js
Baixar o Kit de Treinamento do Web Camps
Este laboratório prático mostra como criar um SPA (Aplicativo de Página Única) com ASP.NET Web API e Angular.js para ASP.NET 4.x.
Neste laboratório prático, você aproveitará essas tecnologias para implementar o Geek Quiz, um site de curiosidades baseado no conceito de SPA. Primeiro, você implementará a camada de serviço com ASP.NET Web API para expor os pontos de extremidade necessários para recuperar as perguntas do teste e armazenar as respostas. Em seguida, você criará uma interface do usuário avançada e responsiva usando os efeitos de transformação AngularJS e CSS3.
Em aplicativos Web tradicionais, o cliente (navegador) inicia a comunicação com o servidor solicitando uma página. Em seguida, o servidor processa a solicitação e envia o HTML da página para o cliente. Em interações subsequentes com a página – por exemplo, o usuário navega até um link ou envia um formulário com dados – uma nova solicitação é enviada ao servidor e o fluxo é iniciado novamente: o servidor processa a solicitação e envia uma nova página para o navegador em resposta à nova ação solicitada pelo cliente.
Em aplicativos Single-Page (SPAs), toda a página é carregada no navegador após a solicitação inicial, mas as interações subsequentes ocorrem por meio de solicitações do Ajax. Isso significa que o navegador precisa atualizar apenas a parte da página que foi alterada; não é necessário recarregar a página inteira. A abordagem spa reduz o tempo gasto pelo aplicativo para responder às ações do usuário, resultando em uma experiência mais fluida.
A arquitetura de um SPA envolve determinados desafios que não estão presentes em aplicativos Web tradicionais. No entanto, tecnologias emergentes como ASP.NET Web API, estruturas JavaScript como AngularJS e novos recursos de estilo fornecidos pelo CSS3 facilitam muito o design e a criação de SPAs.
Todos os snippets e código de exemplo estão incluídos no Kit de Treinamento de Campos da Web, disponível em https://aka.ms/webcamps-training-kit.
Visão geral
Objetivos
Neste laboratório prático, você aprenderá a:
- Criar um serviço ASP.NET Web API para enviar e receber dados JSON
- Criar uma interface do usuário responsiva usando AngularJS
- Aprimorar a experiência de interface do usuário com transformações do CSS3
Pré-requisitos
O seguinte é necessário para concluir este laboratório prático:
- Visual Studio Express 2013 para Web ou superior
Instalação
Para executar os exercícios neste laboratório prático, você precisará configurar seu ambiente primeiro.
- Abra o Windows Explorer e navegue até a pasta Origem do laboratório.
- Clique com o botão direito do mouse em Setup.cmd e selecione Executar como administrador para iniciar o processo de instalação que configurará seu ambiente e instalará os snippets de código do Visual Studio para este laboratório.
- Se a caixa de diálogo Controle de Conta de Usuário for mostrada, confirme a ação para continuar.
Observação
Verifique se você verificou todas as dependências deste laboratório antes de executar a instalação.
Usando os snippets de código
Ao longo do documento de laboratório, você será instruído a inserir blocos de código. Para sua conveniência, a maior parte desse código é fornecida como snippets de Visual Studio Code, que você pode acessar de dentro de Visual Studio 2013 para evitar a necessidade de adicioná-lo manualmente.
Observação
Cada exercício é acompanhado por uma solução inicial localizada na pasta Begin do exercício que permite que você siga cada exercício independentemente dos outros. Lembre-se de que os snippets de código adicionados durante um exercício estão ausentes dessas soluções iniciais e podem não funcionar até que você tenha concluído o exercício. Dentro do código-fonte de um exercício, você também encontrará uma pasta End contendo uma solução do Visual Studio com o código que resulta da conclusão das etapas no exercício correspondente. Você pode usar essas soluções como diretrizes se precisar de ajuda adicional enquanto trabalha neste laboratório prático.
Exercícios
Este laboratório prático inclui os seguintes exercícios:
Tempo estimado para concluir este laboratório: 60 minutos
Observação
Ao iniciar o Visual Studio pela primeira vez, você deve selecionar uma das coleções de configurações predefinidas. Cada coleção predefinida foi projetada para corresponder a um estilo de desenvolvimento específico e determina layouts de janela, comportamento do editor, snippets de código do IntelliSense e opções de caixa de diálogo. Os procedimentos neste laboratório descrevem as ações necessárias para realizar uma determinada tarefa no Visual Studio ao usar a coleção Configurações gerais de desenvolvimento . Se você escolher uma coleção de configurações diferente para seu ambiente de desenvolvimento, poderá haver diferenças nas etapas que você deve levar em conta.
Exercício 1: Criando uma API Web
Uma das principais partes de um SPA é a camada de serviço. Ele é responsável por processar as chamadas do Ajax enviadas pela interface do usuário e retornar dados em resposta a essa chamada. Os dados recuperados devem ser apresentados em um formato legível por computador para serem analisados e consumidos pelo cliente.
A estrutura da API Web faz parte do ASP.NET Stack e foi projetada para facilitar a implementação de serviços HTTP, geralmente enviando e recebendo dados formatados em JSON ou XML por meio de uma API RESTful. Neste exercício, você criará o site para hospedar o aplicativo Geek Quiz e, em seguida, implementará o serviço de back-end para expor e persistir os dados do teste usando ASP.NET Web API.
Tarefa 1 – Criando o projeto inicial para o teste nerd
Nesta tarefa, você começará a criar um novo projeto ASP.NET MVC com suporte para ASP.NET Web API com base no tipo de projeto One ASP.NET fornecido com o Visual Studio. Uma ASP.NET unifica todas as tecnologias ASP.NET e oferece a opção de misturá-las e combiná-las conforme desejado. Em seguida, você adicionará as classes de modelo do Entity Framework e o inicializador de banco de dados para inserir as perguntas do teste.
Abra Visual Studio Express 2013 para Web e selecione Arquivo | Novo Projeto... para iniciar uma nova solução.
Criando um novo projeto
Na caixa de diálogo Novo Projeto, selecione ASP.NET Aplicativo Web no Visual C# | Guia Web. Verifique se .NET Framework 4.5 está selecionado, nomeie-o como GeekQuiz, escolha um Local e clique em OK.
Criando um novo projeto de aplicativo Web ASP.NET
Na caixa de diálogo Novo projeto ASP.NET , selecione o modelo MVC e selecione a opção API Web . Além disso, verifique se a opção Autenticação está definida como Contas de Usuário Individuais. Clique em OK para continuar.
Criando um novo projeto com o modelo MVC, incluindo componentes da API Web
Em Gerenciador de Soluções, clique com o botão direito do mouse na pasta Modelos do projeto GeekQuiz e selecione Adicionar | Item existente....
Adicionando um item existente
Na caixa de diálogo Adicionar Item Existente , navegue até a pasta Origem/Ativos/Modelos e selecione todos os arquivos. Clique em Adicionar.
Adicionando os ativos do modelo
Observação
Ao adicionar esses arquivos, você está adicionando o modelo de dados, o contexto de banco de dados do Entity Framework e o inicializador de banco de dados para o aplicativo Geek Quiz.
O Entity Framework (EF) é um ORM (mapeador relacional de objeto) que permite criar aplicativos de acesso a dados programando com um modelo de aplicativo conceitual em vez de programar diretamente usando um esquema de armazenamento relacional. Você pode saber mais sobre o Entity Framework aqui.
Veja a seguir uma descrição das classes que você acabou de adicionar:
- TriviaOption: representa uma única opção associada a uma pergunta de teste
- TriviaQuestion: representa uma pergunta de teste e expõe as opções associadas por meio da propriedade Options
- TriviaAnswer: representa a opção selecionada pelo usuário em resposta a uma pergunta de teste
- TriviaContext: representa o contexto de banco de dados do Entity Framework do aplicativo Geek Quiz. Essa classe deriva de DContext e expõe propriedades DbSet que representam coleções das entidades descritas acima.
- TriviaDatabaseInitializer: a implementação do inicializador do Entity Framework para a classe TriviaContext que herda de CreateDatabaseIfNotExists. O comportamento padrão dessa classe é criar o banco de dados somente se ele não existir, inserindo as entidades especificadas no método Seed .
Abra o arquivo Global.asax.cs e adicione a instrução using a seguir.
using GeekQuiz.Models;
Adicione o código a seguir no início do método Application_Start para definir o TriviaDatabaseInitializer como o inicializador de banco de dados.
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); } }
Modifique o controlador Home para restringir o acesso a usuários autenticados. Para fazer isso, abra o arquivo HomeController.cs dentro da pasta Controladores e adicione o atributo Authorize à definição da classe HomeController .
namespace GeekQuiz.Controllers { [Authorize] public class HomeController : Controller { public ActionResult Index() { return View(); } ... } }
Observação
O filtro Autorizar verifica se o usuário está autenticado. Se o usuário não for autenticado, ele retornará HTTP status código 401 (Não autorizado) sem invocar a ação. Você pode aplicar o filtro globalmente, no nível do controlador ou no nível de ações individuais.
Agora você personalizará o layout das páginas da Web e da identidade visual. Para fazer isso, abra o arquivo _Layout.cshtml dentro das Exibições | Pasta compartilhada e atualizar o conteúdo do <elemento title> substituindo My ASP.NET Application por 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>
No mesmo arquivo, atualize a barra de navegação removendo os links Sobre e Contato e renomeando o link Página Inicial para Reprodução. Além disso, renomeie o link Nome do aplicativo para Quiz Geek. O HTML para a barra de navegação deve ser semelhante ao código a seguir.
<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>
Atualize o rodapé da página de layout substituindo My ASP.NET Application por Geek Quiz. Para fazer isso, substitua o conteúdo do <elemento footer> pelo código realçado a seguir.
<div class="container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - Geek Quiz</p> </footer> </div>
Tarefa 2 – Criando a API Web TriviaController
Na tarefa anterior, você criou a estrutura inicial do aplicativo Web Quiz Do Geek. Agora você criará um serviço de API Web simples que interage com o modelo de dados de teste e expõe as seguintes ações:
- GET /api/trivia: recupera a próxima pergunta da lista de testes a ser respondida pelo usuário autenticado.
- POST /api/trivia: armazena a resposta do teste especificada pelo usuário autenticado.
Você usará as ferramentas ASP.NET Scaffolding fornecidas pelo Visual Studio para criar a linha de base para a classe de controlador de API Web.
Abra o arquivo WebApiConfig.cs dentro da pasta App_Start . Esse arquivo define a configuração do serviço de API Web, como como as rotas são mapeadas para ações do controlador de API Web.
Adicione a instrução using a seguir no início do arquivo.
using Newtonsoft.Json.Serialization;
Adicione o seguinte código realçado ao método Register para configurar globalmente o formatador para os dados JSON recuperados pelos métodos de ação da API Web.
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 } ); } }
Observação
O CamelCasePropertyNamesContractResolver converte automaticamente nomes de propriedade em maiúsculas e minúsculas, que é a convenção geral para nomes de propriedade em JavaScript.
Em Gerenciador de Soluções, clique com o botão direito do mouse na pasta Controladores do projeto GeekQuiz e selecione Adicionar | Novo item scaffolded....
Criando um novo item scaffolded
Na caixa de diálogo Adicionar Scaffold , verifique se o nó Comum está selecionado no painel esquerdo. Em seguida, selecione o modelo Controlador da API Web 2 – Vazio no painel central e clique em Adicionar.
Selecionando o modelo Controlador vazio da API Web 2
Observação
ASP.NET Scaffolding é uma estrutura de geração de código para aplicativos Web ASP.NET. Visual Studio 2013 inclui geradores de código pré-instalados para projetos de MVC e API Web. Você deve usar scaffolding em seu projeto quando quiser adicionar rapidamente o código que interage com modelos de dados para reduzir o tempo necessário para desenvolver operações de dados padrão.
O processo de scaffolding também garante que todas as dependências necessárias sejam instaladas no projeto. Por exemplo, se você começar com um projeto de ASP.NET vazio e usar scaffolding para adicionar um controlador de API Web, os pacotes e referências da API Web necessários serão adicionados ao projeto automaticamente.
Na caixa de diálogo Adicionar Controlador , digite TriviaController na caixa de texto Nome do controlador e clique em Adicionar.
Adicionando o Controlador trivia
O arquivo TriviaController.cs é adicionado à pasta Controladores do projeto GeekQuiz , contendo uma classe TriviaController vazia. Adicione as instruções using a seguir no início do arquivo.
(Snippet de código - AspNetWebApiSpa - Ex1 - TriviaControllerUsings)
using System.Data.Entity; using System.Threading; using System.Threading.Tasks; using System.Web.Http.Description; using GeekQuiz.Models;
Adicione o código a seguir no início da classe TriviaController para definir, inicializar e descartar a instância TriviaContext no controlador.
(Snippet de código - 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); } }
Observação
O método Dispose de TriviaController invoca o método Dispose da instância TriviaContext , que garante que todos os recursos usados pelo objeto de contexto sejam liberados quando a instância TriviaContext for descartada ou coletada por lixo. Isso inclui o fechamento de todos os conexões de banco de dados abertos pelo Entity Framework.
Adicione o seguinte método auxiliar ao final da classe TriviaController . Esse método recupera a pergunta do teste a seguir do banco de dados a ser respondida pelo usuário especificado.
(Snippet de código - 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); }
Adicione o seguinte método de ação Obter à classe TriviaController . Esse método de ação chama o método auxiliar NextQuestionAsync definido na etapa anterior para recuperar a próxima pergunta para o usuário autenticado.
(Snippet de código - 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); }
Adicione o seguinte método auxiliar ao final da classe TriviaController . Esse método armazena a resposta especificada no banco de dados e retorna um valor booliano que indica se a resposta está correta ou não.
(Snippet de código - 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; }
Adicione o seguinte método de ação Post à classe TriviaController . Esse método de ação associa a resposta ao usuário autenticado e chama o método auxiliar StoreAsync . Em seguida, ele envia uma resposta com o valor booliano retornado pelo método auxiliar.
(Snippet de código - 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); }
Modifique o controlador de API Web para restringir o acesso a usuários autenticados adicionando o atributo Authorize à definição da classe TriviaController .
[Authorize] public class TriviaController : ApiController { ... }
Tarefa 3 – Executando a solução
Nesta tarefa, você verificará se o serviço de API Web criado na tarefa anterior está funcionando conforme o esperado. Você usará a Internet Explorer F12 Developer Tools para capturar o tráfego de rede e inspecionar a resposta completa do serviço de API Web.
Observação
Verifique se o Explorer da Internet está selecionado no botão Iniciar localizado na barra de ferramentas do Visual Studio.
Pressione F5 para executar a solução. A página Fazer logon deve aparecer no navegador.
Observação
Quando o aplicativo é iniciado, a rota MVC padrão é disparada, que por padrão é mapeada para a ação Index da classe HomeController . Como HomeController é restrito a usuários autenticados (lembre-se de que você decorou essa classe com o atributo Authorize no Exercício 1) e ainda não há nenhum usuário autenticado, o aplicativo redireciona a solicitação original para a página de logon.
Executar a solução
Clique em Registrar para criar um novo usuário.
Registrar um novo usuário
Na página Registrar , insira um Nome de usuário e senha e clique em Registrar.
Página Registrar
O aplicativo registra a nova conta e o usuário é autenticado e redirecionado de volta para a home page.
O usuário é autenticado
No navegador, pressione F12 para abrir o painel Ferramentas de Desenvolvedor . Pressione CTRL + 4 ou clique no ícone Rede e clique no botão de seta verde para começar a capturar o tráfego de rede.
Iniciando a captura de rede da API Web
Acrescente api/trivia à URL na barra de endereços do navegador. Agora você inspecionará os detalhes da resposta do método Obter ação em TriviaController.
Recuperando os próximos dados de pergunta por meio da API Web
Observação
Depois que o download for concluído, você será solicitado a fazer uma ação com o arquivo baixado. Deixe a caixa de diálogo aberta para poder watch o conteúdo da resposta por meio da janela Ferramenta de Desenvolvedores.
Agora você inspecionará o corpo da resposta. Para fazer isso, clique na guia Detalhes e clique em Corpo da resposta. Você pode marcar que os dados baixados são um objeto com as opções de propriedades (que é uma lista de objetos TriviaOption), id e título que correspondem à classe TriviaQuestion.
Exibindo o corpo da resposta da API Web
Voltar para o Visual Studio e pressione SHIFT + F5 para interromper a depuração.
Exercício 2: Criando a interface SPA
Neste exercício, você criará primeiro a parte de front-end da Web do Quiz Geek, focando na interação do aplicativo Single-Page usando o AngularJS. Em seguida, você aprimorará a experiência do usuário com o CSS3 para executar animações avançadas e fornecerá um efeito visual da alternância de contexto ao fazer a transição de uma pergunta para outra.
Tarefa 1 – Criar a interface SPA usando AngularJS
Nesta tarefa, você usará AngularJS para implementar o lado do cliente do aplicativo Geek Quiz. O AngularJS é uma estrutura JavaScript de software livre que aumenta os aplicativos baseados em navegador com a funcionalidade MVC (Model-View-Controller ), facilitando o desenvolvimento e o teste.
Você começará instalando o AngularJS no Console do Gerenciador de Pacotes do Visual Studio. Em seguida, você criará o controlador para fornecer o comportamento do aplicativo Quiz Geek e a exibição para renderizar as perguntas e respostas do teste usando o mecanismo de modelo AngularJS.
Observação
Para obter mais informações sobre AngularJS, consulte [http://angularjs.org/](http://angularjs.org/).
Abra Visual Studio Express 2013 para Web e abra a solução GeekQuiz.sln localizada na pasta Source/Ex2-CreatingASPAInterface/Begin. Como alternativa, você pode continuar com a solução obtida no exercício anterior.
Abra o Console do Gerenciador de Pacotes do Gerenciador de Ferramentasdo Gerenciador de Pacotes> NuGet. Digite o comando a seguir para instalar o pacote NuGet AngularJS.Core .
Install-Package AngularJS.Core
Em Gerenciador de Soluções, clique com o botão direito do mouse na pasta Scripts do projeto GeekQuiz e selecione Adicionar | Nova Pasta. Nomeie o aplicativo de pasta e pressione Enter.
Clique com o botão direito do mouse na pasta do aplicativo que você acabou de criar e selecione Adicionar | Arquivo JavaScript.
Criando um novo arquivo JavaScript
Na caixa de diálogo Especificar Nome para Item, digitequiz-controller na caixa de texto Nome do item e clique em OK.
Nomeando o novo arquivo JavaScript
No arquivo quiz-controller.js , adicione o código a seguir para declarar e inicializar o controlador AngularJS QuizCtrl .
(Snippet de código - 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'; }; });
Observação
A função de construtor do controlador QuizCtrl espera um parâmetro injetável chamado $scope. O estado inicial do escopo deve ser configurado na função de construtor anexando propriedades ao objeto $scope . As propriedades contêm o modelo de exibição e estarão acessíveis ao modelo quando o controlador for registrado.
O controlador QuizCtrl é definido dentro de um módulo chamado QuizApp. Os módulos são unidades de trabalho que permitem dividir seu aplicativo em componentes separados. A main vantagens de usar módulos é que o código é mais fácil de entender e facilita o teste de unidade, a reutilização e a manutenção.
Agora você adicionará comportamento ao escopo para reagir a eventos disparados do modo de exibição. Adicione o código a seguir no final do controlador QuizCtrl para definir a função nextQuestion no objeto $scope .
(Snippet de código - 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; }); }; };
Observação
Essa função recupera a próxima pergunta da API Web trivia criada no exercício anterior e anexa os dados de pergunta ao objeto $scope .
Insira o código a seguir no final do controlador QuizCtrl para definir a função sendAnswer no objeto $scope .
(Snippet de código - 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; }); }; };
Observação
Essa função envia a resposta selecionada pelo usuário para a API Web do Trivia e armazena o resultado (ou seja, se a resposta estiver correta ou não) no objeto $scope .
As funções nextQuestion e sendAnswer acima usam o objeto AngularJS $http para abstrair a comunicação com a API Web por meio do objeto JavaScript XMLHttpRequest do navegador. O AngularJS dá suporte a outro serviço que traz um nível mais alto de abstração para executar operações CRUD em um recurso por meio de APIs RESTful. O objeto angularJS $resource tem métodos de ação que fornecem comportamentos de alto nível sem a necessidade de interagir com o objeto $http . Considere usar o objeto $resource em cenários que exigem o modelo CRUD (informações de fore, consulte a documentação $resource).
A próxima etapa é criar o modelo AngularJS que define a exibição do teste. Para fazer isso, abra o arquivo Index.cshtml dentro das Exibições | Pasta Inicial e substitua o conteúdo pelo código a seguir.
(Snippet de código – 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") }
Observação
O modelo AngularJS é uma especificação declarativa que usa informações do modelo e do controlador para transformar a marcação estática na exibição dinâmica que o usuário vê no navegador. Veja a seguir exemplos de elementos AngularJS e atributos de elemento que podem ser usados em um modelo:
- A diretiva ng-app informa ao AngularJS o elemento DOM que representa o elemento raiz do aplicativo.
- A diretiva ng-controller anexa um controlador ao DOM no ponto em que a diretiva é declarada.
- A notação de chaves {{ }} indica associações para as propriedades de escopo definidas no controlador.
- A diretiva ng-click é usada para invocar as funções definidas no escopo em resposta aos cliques do usuário.
Abra o arquivo Site.css dentro da pasta Conteúdo e adicione os seguintes estilos realçados no final do arquivo para fornecer uma aparência para a exibição do teste.
(Snippet de código - 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; }
Tarefa 2 – Executando a solução
Nesta tarefa, você executará a solução usando a nova interface do usuário criada com o AngularJS para responder a algumas das perguntas do teste.
Pressione F5 para executar a solução.
Registre uma nova conta de usuário. Para fazer isso, siga as etapas de registro descritas no Exercício 1, Tarefa 3.
Observação
Se você estiver usando a solução do exercício anterior, poderá fazer logon com a conta de usuário criada antes.
A Página Inicial deve aparecer, mostrando a primeira pergunta do teste. Responda à pergunta clicando em uma das opções. Isso disparará a função sendAnswer definida anteriormente, que envia a opção selecionada para a API Web trivia .
Respondendo a uma pergunta
Depois de clicar em um dos botões, a resposta deve aparecer. Clique em Próxima Pergunta para mostrar a pergunta a seguir. Isso disparará a função nextQuestion definida no controlador.
Solicitando a próxima pergunta
A próxima pergunta deve aparecer. Continue respondendo perguntas quantas vezes quiser. Depois de concluir todas as perguntas, você deve retornar à primeira pergunta.
Próxima pergunta
Voltar para o Visual Studio e pressione SHIFT + F5 para interromper a depuração.
Tarefa 3 – Criar uma animação de inversão usando CSS3
Nesta tarefa, você usará as propriedades CSS3 para executar animações avançadas adicionando um efeito de inversão quando uma pergunta for respondida e quando a próxima pergunta for recuperada.
Em Gerenciador de Soluções, clique com o botão direito do mouse na pasta Conteúdo do projeto GeekQuiz e selecione Adicionar | Item existente....
Adicionando um item existente à pasta Conteúdo
Na caixa de diálogo Adicionar Item Existente , navegue até a pasta Origem/Ativos e selecione Flip.css. Clique em Adicionar.
Adicionando o arquivo Flip.css de Ativos
Abra o arquivo Flip.css que você acabou de adicionar e inspecione seu conteúdo.
Localize o comentário de transformação de inversão . Os estilos abaixo desse comentário usam a perspectiva do CSS e as transformações rotateY para gerar um efeito "cartão inverter".
/* 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); }
Localize o ocultar parte de trás do painel durante o comentário invertido . O estilo abaixo desse comentário oculta o back-side dos rostos quando eles estão voltados para longe do visualizador definindo a propriedade CSS de visibilidade de backface como oculta.
/* hide back of pane during flip */ .front, .back { -moz-backface-visibility: hidden; -webkit-backface-visibility: hidden; backface-visibility: hidden; }
Abra o arquivo BundleConfig.cs dentro da pasta App_Start e adicione a referência ao arquivo Flip.css no pacote de estilo "~/Content/css"
bundles.Add(new StyleBundle("~/Content/css").Include( "~/Content/bootstrap.css", "~/Content/site.css", "~/Content/Flip.css"));
Pressione F5 para executar a solução e fazer logon com suas credenciais.
Responda a uma pergunta clicando em uma das opções. Observe o efeito de inversão ao fazer a transição entre exibições.
Respondendo a uma pergunta com o efeito de inversão
Clique em Próxima Pergunta para recuperar a pergunta a seguir. O efeito de inversão deve aparecer novamente.
Recuperando a pergunta a seguir com o efeito de inversão
Resumo
Ao concluir este laboratório prático, você aprendeu a:
- Criar um controlador de ASP.NET Web API usando o scaffolding ASP.NET
- Implementar uma ação Obter da API Web para recuperar a próxima pergunta do teste
- Implementar uma ação post da API Web para armazenar as respostas do teste
- Instalar o AngularJS do Console do Gerenciador de Pacotes do Visual Studio
- Implementar modelos e controladores AngularJS
- Usar transições CSS3 para executar efeitos de animação