Neste artigo, eu vou mostrar como criar uma aplicação ASP .NET Single Page Application usando os recursos do AngularJS com Web API: Criando um serviço.
Na quarta parte do artigo, definimos o roteamento em nossa aplicação Angular, criamos o controller detalhesController e agora estamos navegando para a página que exibe os filmes e também os detalhes de um filme.
Neste artigo, vamos criar um serviço customizado de forma a encapsular a lógica de acesso às informações dos filmes em um service do Angular.
Os services do AngularJS são objetos substituíveis que estão ligados entre si usando a injeção de dependência (DI). Você pode usar serviços do Angular para organizar e compartilhar código (reuso) em seu aplicativo.
Os serviços do Angular são:
- Instanciados tardiamente (Lazy Load) – O Angular somente instancia um serviço quando um componente da aplicação depende disso.
- Singletons – Cada componente dependente de um serviço obtém uma referência a uma única instância gerada pela fábrica de serviço.
O Angular oferece vários serviços úteis (como $http, $log, $route, $location, $window etc.), mas podemos criar serviços de acordo com a necessidade da nossa aplicação.
Para usar um serviço Angular, basta adicioná-lo como uma dependência para o componente (controlador, serviço, filtro ou diretiva) que depende do serviço. O subsistema de injeção de dependência do Angular cuida do resto.
Vamos, então, criar um serviço customizado para a nossa aplicação que encapsula as capacidades da Web API FilmeController, de forma que nossos controladores não precisem usar o serviço $http diretamente.
Existem três maneiras principais de criar registros e serviços:
- Service: Quando você estiver usando um Service, ele é instanciado com a palavra-chave “new”. Por causa disso, você vai adicionar propriedades a “this” e o serviço retornará “this”. Quando você passar o serviço ao seu controlador, essas propriedades em “this” estarão disponíveis no controlador por meio de seu serviço.
- Factory (a forma mais popular de criar services): Ao usar um Factory, você cria um objeto, adiciona propriedades a ele e então retorna o mesmo objeto. Quando você passar esse serviço ao seu controlador, as propriedades do objeto estarão disponíveis no controlador por meio de sua factory.
- Provider: Os provedores são o único serviço que você pode passar para a função config(). Use um Provider quando você desejar fornecer configuração ao módulo para o objeto de serviço antes de torná-lo disponível.
Recursos usados:
- Visual Studio 2015 Community
- AngularJS
- Web API
- Entity Framework
Nota: Baixe e use a versão Community 2015 do VS; ela é grátis e é equivalente à versão Professional.
Criando um serviço AngularJS
Abra a solução Filmoteca criada no artigo anterior no VS Community 2015 (Open Project).
Clique então com o botão direito do mouse sobre a pasta js e, a seguir, em Add-> New Item.
Selecione o template JavaScript file e informe o nome filmeService.js.
Defina o código abaixo nesse arquivo:
(function (app) { var filmeService = function ($http, filmeApiUrl) { var getFilmes = function() { return $http.get(filmeApiUrl); }; var getFilmePorId = function (id) { return $http.get(filmeApiUrl + id); }; var atualizar = function (filme) { return $http.put(filmeApiUrl + filme.Id, filme); }; var criar = function (filme) { return $http.post(filmeApiUrl, filme); }; var deletar = function (filme) { return $http.delete(filmeApiUrl + filme.Id); }; return { getFilmes: getFilmes, getFilmePorId: getFilmePorId, atualizar: atualizar, criar: criar, deletar: deletar }; }; app.factory("filmeService", filmeService); }(angular.module("filmoteca")))
No arquivo filmeService.js, criamos um serviço e estamos encapsulando os recursos da Web API FilmeController, de forma que agora o nossos controllers AngularJS não vão precisar usar o serviço $http diretamente.
Observe que o serviço está imitando a API FilmeController do lado do servidor fornecendo métodos para retornar todos os filmes, obter um filme pelo seu Id, atualizar, criar e deletar um filme. Cada um desses métodos encaminha uma chamada para o serviço $http, o qual é uma dependência de filmeService.
Note que em filmeService temos também uma dependência de filmeApiUrl, o que demonstra como passar a informação da configuração de uma aplicação para os serviços e outro componente dentro da aplicação pelo registro de valores constantes durante a configuração da aplicação.
Voltemos então para o arquivo filmoteca.js, no qual as rotas estão definidas e vamos registrar o valor constante usando o método constant. Esses valores usam uma chave como primeiro parâmetro e o valor associado com a chave como segundo parâmetro. Nosso arquivo filmoteca.js deve ficar com o seguinte código:
(function () { var app = angular.module("filmoteca", ["ngRoute"]); var config = function ($routeProvider) { $routeProvider .when("/", { templateUrl: "/cliente/html/lista.html"}) .when("/detalhes/:id", { templateUrl: "/cliente/html/detalhes.html"}) .otherwise( { redirecTo: "/"}); }; app.config(config); //inclusão app.constant("filmeApiUrl", "/api/filme/"); }());
Qualquer componente que precisar chamar FilmeController pode agora requisitar a dependência filmeApiUrl, mas somente filmeService vai precisar desse valor. Para usar o serviço, vamos incluir o script na view Index.html:
<div class="well"> <h4>Macoratti .net</h4> </div> <div ng-app="filmoteca"> <ng-view></ng-view> </div> @section scripts { <script src="~/Scripts/angular.js"></script> <script src="~/Scripts/angular-route.js"></script> <script src="~/AngularApp/js/filmoteca.js"></script> <script src="~/AngularApp/js/listaController.js"></script> <script src="~/AngularApp/js/detalhesController.js"></script> <script src="~/AngularApp/js/filmeService.js"></script> }
Podemos agora alterar o controller listaController para usar o serviço criado em vez de usar o $http:
(function (app) { var listaController = function ($scope, filmeService) { filmeService .getFilmes() .success(function (data) { $scope.filmes = data; }); }; app.controller("listaController", listaController) }(angular.module("filmoteca")));
Vamos fazer a mesma coisa com o controller detalhesController:
(function (app) { var detalhesController = function ($scope, $routeParams, filmeService) { var id = $routeParams.id; filmeService .getFilmePorId(id) .success(function (data) { $scope.filme = data; }); }; app.controller("detalhesController", detalhesController) }(angular.module("filmoteca")));
Aqui usamos o serviço $routeParams, que permite retornar o conjunto atual de parâmetros à rota – no nosso exemplo, o Id do filme.
Se executarmos o projeto novamente, iremos obter o mesmo resultado, mas agora estamos usando um serviço criado para encapsular as funcionalidades da Web API e, assim, poderemos reusar o serviço caso precisemos:
Acima, vemos a apresentação dos filmes e a exibição dos detalhes de um filme.
Na próxima parte do artigo, vamos implementar as funcionalidades para deletar, editar e criar filmes em nossa aplicação SPA.