Desenvolvimento - ASP. NET

Mini SPA com AngularJS e ASP.Net MVC

Esse artigo tem o intuito de mostrar como criar uma Mini Single Page Application utilizando AngularJS e ASP.Net MVC.

por Caio Saraiva de Aquino Barutti



Olá pessoal, tudo bem com vocês?

Hoje vamos falar um pouco sobre o Framework Javascript AngularJS, que na minha opinião é perfeito para criar páginas dinâmicas, ou seja, Single Page Applications(SPA).

Nesse exemplo, vou mostrar como fazer um Mini SPA com um cenário bem simples, somente para mostrar os benefícios de se trabalhar o ASP.Net MVC com o AngularJS.

Vamos lá! Primeiramente, criamos um novo projeto ASP.NET Web Application MVC vazio, com o nome ExampleAngularJs. Como nas Figuras 1 e 2 exibidas a seguir.

Figura 1 – Criando projeto ASP.NET Web Application.

Figura 2 – Criando projeto ASP.NET Web Application MVC Empty.

Para dar uma pequena aparência na nossa aplicação, vamos instalar o Bootstrap e em seguida criaremos nosso layout. A instalação do Bootstrap é feita a partir do Nuget, conforme a Figura 3.

Figura 3 – Tela do Nuget: Instalação do Bootstrap e do Json.NET, juntamente com a atualização do Jquery.

Feita a instalação do Bootstrap, aproveitamos para atualizar o Jquery e instalar também o pacote Json.NET, tudo a partir do Nuget.

Assim que concluído, criamos uma a pasta ‘Shared’ em ‘Views’, e uma nova View chamada _Layout.cshtml com o seguinte código:

  <html ng-app="app">
  <head>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular-route.min.js"></script>
      <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
      <script src="~/Scripts/jquery-2.1.1.min.js"></script>
      <script src="~/Scripts/bootstrap.js"></script>
      <script src="~/app/app.js"></script>
      <title>ExampleAngularJS</title>
      @RenderSection("JavascriptHeader", required: false)
  </head>
  <body>
      <div class="row">
          <div class="navbar navbar-default">
              <div class="navbar-header">
                  <ul class="navbar navbar-nav">
                      <li>
                          <span class="navbar navbar-brand">Registration</span>
                      </li>
                  </ul>
              </div>
              <div class="navbar-collapse colapse">
                  <ul class="nav navbar-nav">
                      <li><a href="/Registration/Courses">Courses</a></li>
                      <li><a href="/Registration/Students">Students</a></li>
                  </ul>
              </div>
          </div>
      </div>
      @RenderBody()
  </body>
  </html>
  


Pronto, o layout da nossa aplicação está feito. Note que já incluí a referência para a biblioteca do AngularJS no layout e já utilizei ela na tag Html do mesmo com o ‘ng-app’, que indica que tudo dentro daquela tag pode conter comandos AngularJS. Além disso, também separei uma seção javascript, que utilizaremos na nossa View.

Agora vamos modelar nossa aplicação. Vou fazer uma modelagem bem básica, sem uso de banco de dados, porque o intuito desse artigo é mostrar o comportamento do ASP.NET MVC com o AngularJS. Para modelagem, criaremos três objetos:

Primeiramente o Course.cs, dentro da pasta ‘Models/Courses’;

  namespace ExampleAngularJs.Models.Courses
  {
      public class Course
      {
          public string Code { get; set; }
          public string Name { get; set; }
          public string Instructor { get; set; }
      }
  }
  


Em seguida, criamos a classe Student.cs, na pasta ‘Models/Students’;

  namespace ExampleAngularJs.Models.Students
  {
      public class Student
      {
          public string Code { get; set; }
          public string Name { get; set; }
          public string Email { get; set; }
      }
  }
  


Posteriormente, criamos a classe Registration.cs, dentro de ‘Models/Registrations’.


  namespace ExampleAngularJs.Models.Registrations
  {
      public class Registration
      {
          public string Courses { get; set; }
          public string Students { get; set; }
      }
  }
  


Repare que a Registration.cs possui uma ‘lista’ de courses e students, coloquei esses atributos do tipo string, pois estou considerando que já vamos preencher esses atributos com o objeto respectivamente serializado. Portanto, vamos criar a classe RegistrationFactory.cs, dentro de ‘Models/Registrations’, para preencher e serializar esses objetos.


  using System.Web.UI;
  using ExampleAngularJs.Models.Courses;
  using ExampleAngularJs.Models.Students;
  using Newtonsoft.Json;
  using Newtonsoft.Json.Serialization;
   
  namespace ExampleAngularJs.Models.Registrations
  {
      public class RegistrationFactory
      {
          public Registration BuildRegistration()
          {
              var registration = new Registration
              {
                  Courses = GetSerializedCourses(),
                  Students = GetSerializedStudents(),
              };
              return registration;
          }
   
          public string GetSerializedCourses()
          {
              var courses = new[]
              {
                  new Course {Code = "1A", Name = "Ensinando .Net", Instructor = "Geeglo"},
                  new Course {Code = "2B", Name = "Ensinando Azure", Instructor = "Amozan"},
                  new Course {Code = "3C", Name = "Ensinando Angular", Instructor = "Mocrisoft"},
              };
   
              JsonSerializerSettings settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
   
              return JsonConvert.SerializeObject(courses, Formatting.None, settings);
          }
   
          public string GetSerializedStudents()
          {
              var students = new[]
              {
                  new Student {Code = "1", Name = "Algum Nome", Email = "algumnome@email.com"},
                  new Student {Code = "2", Name = "Outro Nome", Email = "outronome@email.com"},
                  new Student {Code = "3", Name = "Mais Um Nome", Email = "maisumnome@email.com"},
              };
   
              JsonSerializerSettings settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
   
              return JsonConvert.SerializeObject(students, Formatting.None, settings);
          }
      }
  }
  

A imagem a seguir exibe como ficou a pasta ‘Models’ da aplicação.

Figura 4 – Estrutura da pasta ‘Models’ da aplicação.

O próximo passo para a construção do nosso Mini SPA é criar a nossa Controller.

Então dentro de ‘Controllers’, criamos a HomeController.

  using ExampleAngularJs.Models.Registrations;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web;
  using System.Web.Mvc;
   
  namespace ExampleAngularJs.Controllers
  {
      public class HomeController : Controller
      {
          private RegistrationFactory registrationFactory = new RegistrationFactory();
          public ActionResult Index()
          {
              return View("Index", "", registrationFactory.BuildRegistration());
          }
                    }
  }
  

Note que estou fazendo uso da RegistrationFactory e na Index.cshtml passo o objeto Registration.cs preenchido e com os atributos courses e students serializado.

Mas no momento não vamos criar a nossa Index.cshtml, temos que preparar o AngularJS, criando nosso Module, nossas Controllers e nossos Templates. Não confundir as controllers do Angular, com as controllers do ASP.Net MVC.

Portanto, crie uma nova pasta no projeto chamada ‘app’, e crie um novo JavaScript File com o nome app.js, esse será o nosso Module. No primeiro momento ele somente irá iniciar o module ‘app’.


  var app = angular.module("app", []);
  


Em seguida, vamos criar nossa Controller de Courses, faremos isso com um novo JavaScript File dentro de ‘app/Courses’ e com o nome de courses-controller.js.

  'use strict';
   
  app.controller("CoursesController", function ($scope, bootstrappedData) {
      $scope.courses = bootstrappedData.courses;
  });
  

Essa courses-controller faz uso do nosso Module e também faz o ‘bootstrapped’ do dado, atribuindo ele para a variável courses do escopo do AngularJS Module. Também teremos que criar uma students-controller com o mesmo intuito. Dentro de ‘app/Students’ criamos então a students-controller.js.

  'use strict';
   
  app.controller("StudentsController", function ($scope, bootstrappedData) {
      $scope.students = bootstrappedData.students;
  });
  

Agora sim podemos criar nossa view da HomeController/Index. Sendo assim, dentro de ‘Views/Home’, criamos a Index.cshtml


  @model ExampleAngularJs.Models.Registrations.Registration
  @{
      Layout = "~/Views/Shared/_Layout.cshtml";
  }
   
  @section JavascriptHeader
  {
      <script src="~/Scripts/Courses/courses-controller.js"></script>
      <script src="~/Scripts/Students/students-controller.js"></script>
      <script type="text/javascript">
          app.factory('bootstrappedData', function() {
              return {
                  courses: @Html.Raw(Model.Courses),
                  students: @Html.Raw(Model.Students)
              };
          });
      </script>
  }
   
  <div class="container" >
      <div ng-view></div>
  </div>
  


Feito isso, vamos precisar criar nossas views para courses e students. Mas em vez de criar arquivos cshtml, vamos criar arquivos html, porque as páginas requisitadas pelo Mini SPA serão exibidas nesse formato. Portanto criamos a pasta ‘templates’ no projeto e adicionamos as seguintes páginas html:

courses.html dentro de ‘templates/Courses’;

  <div class="row">
      <div class="span10">
          <h2>Courses</h2>
      </div>
  </div>
  <div class="row">
      <div class="span10">
          <table class="table table-bordered table-hover">
              <tr>
                  <th>Code</th>
                  <th>Course</th>
                  <th>Instructor</th>
              </tr>
              <tr ng-repeat="course in courses">
                  <td>{{course.code}}</td>
                  <td>{{course.name}}</td>
                  <td>{{course.instructor}}</td>
              </tr>
          </table>
      </div>
  </div>
  


E por fim, a students.html dentro de ‘templates/Students’.


  <div class="row">
      <div class="span10">
          <h2>Students</h2>
      </div>
  </div>
  <div class="row">
      <div class="span10">
          <table class="table table-bordered table-hover">
              <tr>
                  <th>Code</th>
                  <th>Name</th>
                  <th>Email</th>
              </tr>
              <tr ng-repeat="student in students">
                  <td>{{student.code}}</td>
                  <td>{{student.name}}</td>
                  <td>{{student.email}}</td>
              </tr>
          </table>
      </div>
  </div>
  


Pronto! Está quase completo nosso Mini SPA, falta somente configurar as rotas do Module do Angular (‘app.js’), mas isso também é bem simples, vamos editar então o Module adicionando as configurações de rotas.


  var app = angular.module("app", ['ngRoute'])
   .config(function ($routeProvider, $locationProvider) {
   $routeProvider.when('/Registration/Courses', { templateUrl: '/templates/Courses/courses.html', controller: 'CoursesController' });
   $routeProvider.when('/Registration/Students', { templateUrl: '/templates/Students/students.html', controller: 'StudentsController' });
   $locationProvider.html5Mode(true);
   });
  


Com isso, ao carregar nossa Home/Index.cshtml, temos o carregamento completo da página, como pode ser observado na Figura 5.


Figura 5 – Página Home/Index.

E ao solicitarmos os courses ou os students, notamos que só é feita a requisição do courses.html e do students.html.


Figura 6 – Requisição à courses.html.

Figura 7 – Requisição à students.html.

Ou seja, o angular identifica e trata essas requisições sem passar pelo Server do ASP.Net MVC, agilizando assim o carregamento da página para o cliente.

Bom pessoal, finalizamos por aqui essa brincadeira com a construção desse Mini SPA com AngularJS, espero que vocês tenham compreendido o conceito e a grande vantagem que esse Framework Javascript pode nos proporcionar. Em seguida deixo o link desse projeto no GitHub, juntamente com o link da aplicação, publicada no AppHarbor e a documentação do AngularJS.

Link projeto GitHub: https://github.com/caiobarutti/ExampleAngularJs

Link aplicação no AppHarbor: http://exampleangularjsminispa.apphb.com/

Link documentação AngularJs: https://docs.angularjs.org/api

Abraço.

Caio Saraiva de Aquino Barutti

Caio Saraiva de Aquino Barutti - Formado em Engenharia de Computação pela UCDB, tem muito orgulho de trabalhar a pouco mais de um ano com ASP.NET. Atualmente é analista desenvolvedor na empresa Portal Educação onde trabalha com plataforma Microsoft.