ASP .NET MVC - Crud com Entity Framework usando Serviços AngularJS - II


 Neste artigo eu vou mostrar como realizar a integração entre o ASP .NET MVC e recursos do AngularJS como serviços para
 realizar as operações CRUD em um banco de dados SQL Server usando o Entity Framewor na abordagem Code-First.

Na primeira parte do artigo criamos a solução ASP .NET MVC e definimos o modelo de domínio (Livro) , o contexto (LivroContexto) e o controlador ASP .NET MVC HomeController.

Vamos agora definir a aplicação AngularJS em nosso projeto onde iremos criar o Module, o Controller e o Service.

Abaixo vemos a figura que representa de forma simplificada o papel do serviço Angular na arquitetura MVC:

AngularJS Conceito

O AngularJS é construído sob a ideologia de que programação declarativa deve ser usada para construção de Interfaces de Usuário e componentes de software, enquanto que a programação imperativa é excelente para escrever as regras de negócio. O framework adapta e estende o HTML tradicional para uma melhor experiência com conteúdo dinâmico, com a ligação direta e bidirecional dos dados (two-way data-binding) que permite sincronização automática de models e views. Como resultado, AngularJS abstrai a manipulação do DOM e melhora os testes.

A seguir vou relacionar algumas diretivas básicas do AngularJS para ilustrar e para que você tenha uma ideia do que são: (fonte wikipédia)

Um documento HTML usando AngularJS é composto basicamente das seguintes partes:

  1. Declaração das diretivas AngularJS

  2. Declaração da biblioteca AngularJS

  3. Utilização de código CSS

  4. Código JavaScript

Para alcançar nosso objetivo vamos realizar as seguintes tarefas neste artigo:

A seguir vou mostrar como fazer isso na prática.

Recursos usados:

Nota: Baixe e use a versão Community 2015 do VS ela é grátis e é equivalente a versão Professional.

Criando o Module e o Controlador AngularJS na pasta Scripts

Abra a solução Mvc_Crud_Angular_Service criada na primeira parte do artigo no VS 2015 Community.

Precisamos definir agora a nossa aplicação AngularJS pois já referenciamos a biblioteca do Angular em nosso projeto.

Para organizar melhor nossa aplicação vamos criar 3 arquivos que irão definir nossa aplicação Angular na pasta Scripts :

Nota: Se você quiser organizar melhor o código crie uma pasta app no projeto e a seguir crie os arquivos acima nesta pasta.

1- Modulejs.js

Agora clique com o botão direito do mouse sobre a pasta Scripts e a seguir em Add -> New Item;

Selecione o template JavaScript File e informe o nome Modulejs.js e clique no botão Add;

Digite o código abaixo neste arquivo:


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

Observe que eu criei um modulo chamado mvcCRUDApp.

Nota: poderia também ter usando a seguinte declaração : angular.module("mvcCRUDApp", []);

2- Controller.js

Agora precisamos criar o controller em nosso projeto.

Agora clique com o botão direito do mouse sobre a pasta Scripts e a seguir em Add -> New Item;

Selecione o template JavaScript File e informe o nome Controller.js e clique no botão Add;

Digite o código abaixo neste arquivo:

app.controller("mvcCRUDCtrl", function ($scope, crudAJService) {
    $scope.divLivro = false;
    GetTodosLivros();
    //Obtem todos os registros de livros
    function GetTodosLivros() {
        debugger;
        var getDadosLivro = crudAJService.getLivros();
        getDadosLivro.then(function (livro) {
            $scope.livros = livro.data;
        }, function () {
            alert('Erro ao tentar obter os registros dos livros');
        });
    }
    //edita livro
    $scope.editarLivro = function (livro) {
        var getDadosLivro = crudAJService.getLivro(livro.Id);
        getDadosLivro.then(function (_livro) {
            $scope.livro = _livro.data;
            $scope.livroId = livro.Id;
            $scope.LivroTitulo = livro.Titulo;
            $scope.LivroAutor = livro.Autor;
            $scope.LivroEditor = livro.Editor;
            $scope.livroIsbn = livro.Isbn;
            $scope.Action = "Atualizar";
            $scope.divLivro = true;
        }, function () {
            alert('Erro ao tentar obter os registros dos livros');
        });
    }
    //atualiza/inclui livro
    $scope.AdicionarAtualizarLivro =function () {
        var Livro = {
            Titulo: $scope.LivroTitulo,
            Autor: $scope.LivroAutor,
            Editor: $scope.LivroEditor,
            Isbn: $scope.livroIsbn
        };
        var getLivroAction = $scope.Action;
        if (getLivroAction == "Atualizar") {
            Livro.Id = $scope.livroId;
            var getDadosLivro = crudAJService.AtualizarLivro(Book);
            getDadosLivro.then(function (msg) {
                GetTodosLivros();
                alert(msg.data);
                $scope.divLivro = false;
            }, function () {
                alert('Erro ao tentar atualizar os registros do livro');
            });
        } else {
            var getDadosLivro = crudAJService.AdicionarLivro(Book);
            getDadosLivro.then(function (msg) {
                GetTodosLivros();
                alert(msg.data);
                $scope.divLivro = false;
            }, function () {
                alert('Erro ao adicionar o livro');
            });
        }
    }
    // define div
    $scope.AdicionarLivroDiv = function () {
        LimpaCampos();
        $scope.Action = "Adicionar";
        $scope.divLivro = true;
    }
    //deleta livro
    $scope.deletarLivro = function (livro) {
        var getDadosLivro = crudAJService.DeletarLivro(livro.Id);
        getDadosLivro.then(function (msg) {
            alert(msg.data);
            GetTodosLivros();
        }, function () {
            alert('Erro ao tentar excluir o livro');
        });
    }
    //limpa campos
    function LimpaCampos() {
        $scope.livroId = "";
        $scope.LivroTitulo = "";
        $scope.LivroAutor = "";
        $scope.LivroEditor = "";
        $scope.livroIsbn = "";
    }
    $scope.Cancel = function () {
        $scope.divLivro = false;
    };
});

Neste código registramos o controller mvcCRUDCtrl e injetamos o serviço  crudAJService no controlador.

O controller irá obter os dados acessando o serviço angular e torná-los disponíveis para a view via objeto $scope.

No código javascript acima estamos usando a função alerta para exibir mensagens de aviso que se você quiser pode remover ou comentar e assim tornar o código mais enxuto. Estamos definindo também algumas variáveis no escopo que iremos tratar na view.

3- Service.js

Agora clique com o botão direito do mouse sobre a pasta Scripts e a seguir em Add -> New Item;

Selecione o template JavaScript File e informe o nome Service.js e clique no botão Add;

Digite o código abaixo neste arquivo:

app.service("crudAJService", function ($http) {
    //otem todos os livros
    this.getLivros = function () {
        return $http.get("Home/GetTodosLivros");
    };
    //obtem livro por id
    this.getLivro = function (livroId) {
        var response = $http({
            method: "post",
            url: "Home/GetLivroPorId",
            params: {
                id: JSON.stringify(livroId)
            }
        });
        return response;
    }
    // Atualiza livro
    this.AtualizarLivro = function (livro) {
        var response = $http({
            method: "post",
            url: "Home/AtualizarLivro",
            data: JSON.stringify(livro),
            dataType: "json"
        });
        return response;
    }
    // Adiciona Livro
    this.AdicionarLivro = function (livro) {
        var response = $http({
            method: "post",
            url: "Home/AdicionarLivro",
            data: JSON.stringify(livro),
            dataType: "json"
        });
        return response;
    }
    //Deleta livro
    this.DeletarLivro = function (livroId) {
        var response = $http({
            method: "post",
            url: "Home/DeletarLivro",
            params: {
                livroId: JSON.stringify(livroId)
            }
        });
        return response;
    }
});

 

Definimos um serviço chamado crudAJService que vai usar o serviço $http do Angular para chamar os métodos do back-end definidos no controlador HomeController. Observe que na chamada dos métodos, por convenção usamos o nome do controlador (sem o sufixo Controller) : Ex: Home/GetTodosLivros

O serviço $http é um serviço Angularjs para leitura de dados a partir de servidores remotos.  Esse suporte permite realizar requisições a um ou mais servidores o que é essencial para um aplicativo do lado do cliente como o nosso que precisa obter e definir dados.

O serviço $http ajuda a facilitar a comunicação com servidores remotos via HTTP o objeto XMLHttpRequest ou através de JSONP.

A sintaxe do objeto de configuração usada na requisição é a seguinte :

$http({
  method
: 'GET',
  url
: '/Url'
}).then(function successCallback(response) {
   
// este callback será chamado assincronamente
   
// quando o response estiver disponível

 
}, function errorCallback(response) {
  
 // chamado assincronamento se um erro ocorrer
   
// ou o servidor retornar um response com status de erro
 
});
 // Atualiza livro
    this.AtualizarLivro = function (livro) {
        var response = $http({
            method: "post",
            url: "Home/AtualizarLivro",
            data: JSON.stringify(livro),
            dataType: "json"
        });
        return response;
    }

O retorno do serviço $http é uma promessa (promise) que deve ser tratada, e isso esta sendo feito no Controller.

Assim os serviços servem então para abstrair e encapsular regras de negócio e para realizar o acesso aos dados e também compartilhar dados com os controllers.

Criando a View Index a partir do controlador HomeController e definindo o controlador e as diretivas Angular

Abra o arquivo HomeController.cs na pasta Controllers e a seguir clique com o botão direito do mouse no interior da Action Index e a seguir clique em Add View;

Selecione o Template Empty e clique em Add;

Digite o código a seguir para a view Index.cshtml criada na pasta Home:

@{
    ViewBag.Title = "Home Page";
}
<div ng-controller="mvcCRUDCtrl">
    <div class="divList">
        <p><b><i>Lista de Livros</i></b></p>
        <table class="table table-hover">
            <tr>
                <td><b>ID</b></td>
                <td><b>Titulo</b></td>
                <td><b>Autor</b></td>
                <td><b>Editor</b></td>
                <td><b>Isbn</b></td>
                <td><b>Ação</b></td>
            </tr>
            <tr ng-repeat="livro in livros">
                <td>{{livro.Id}}</td>
                <td>{{livro.Titulo}}</td>
                <td>{{livro.Autor}}</td>
                <td>{{livro.Editor}}</td>
                <td>{{livro.Isbn}}</td>
                <td>
                    <span ng-click="editarLivro(livro)" class="btn btn-primary">Editar</span>
                    <span ng-click="deletarLivro(livro)" class="btn btn-danger">Deletar</span>
                </td>
            </tr>
        </table>
    </div>
    <span ng-click="AdicionarLivroDiv()" class="btn btn-success">
        Adicionar Livro
    </span>
    <div ng-show="divLivro">
        <p class="divHead"></p>
        <table class="table">
            <tr>
                <td><b><i>{{Action}} Livro</i></b></td>
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td><b>Id</b></td>
                <td>
                    <input type="text" disabled="disabled" ng-model="livroId" />
                </td>
                <td><b>Titulo</b></td>
                <td>
                    <input type="text" ng-model="LivroTitulo" />
                </td>
            </tr>
            <tr>
                <td><b>Autor</b></td>
                <td>
                    <input type="text" ng-model="LivroAutor" />
                </td>
                <td><b>Editor</b></td>
                <td>
                    <input type="text" ng-model="LivroEditor" />
                </td>
            </tr>
            <tr>
                <td><b>Isbn</b></td>
                <td>
                    <input type="text" ng-model="livroIsbn" />
                </td>
                <td></td>
                <td>
                    <input type="button" class="btn btn-default" value="Salvar" ng-click="AdicionarAtualizarLivro()" />
                    <input type="button" class="btn btn-danger" value="Cancelar" ng-click="Cancelar()" />
                </td>
            </tr>
        </table>
    </div>
</div>

No código da view acima estamos usando as seguintes diretivas do AngularJS:

1- <div ng-controller="mvcCRUDCtrl" >   - Define o controlador mvcCRUDCtrl que será responsável pelo escopo definido no interior da div;

2- <tr ng-repeat="livro in livros">  - Percorre as informações definida no objeto livros exibindo-as em uma tabela

3- ng-click="editarLivro(livro)"  - chama a função editarLivro() quando o usuário clicar no botão
   
ng-click="deletarLivro(livro)" - chama a função deletarLivro() quando o usuário clicar no botão
    ng-click
="AdicionarLivroDiv()" - chama a função AdicionarLivroDiv() quando o usuário clicar no botão
    ng-click="AdicionarAtualizarLivro()" - chama a função AdicionarAtualizarLivro() quando o usuário clicar no botão
    ng-click="Cancelar()" - chama a função Cancelar() quando o usuário clicar no botão

4- <div ng-show="divLivro"> Exibe/Oculta a tag div - divLivro

5- ng-model  - Faz a vinculação dos controles input definidos na view a uma propriedade do escopo . No exemplo estamos definindo propriedades para o Livro.

Configurando o AngularJS no projeto

Para poder usar o AngularJS temos que referenciar a library Javascript em nosso projeto e existem duas maneiras de fazer isso:

  1. Usar o MVC minification e o bundling - Nesta abordagem o AngularJS ficará disponível em todo o projeto;
  1. Adicionar a referência ao AngularJS na seção Script de uma view individual ou no código HTML da view :
@section scripts{
    <script src="~/Scripts/angular.js">script>
}

A seguir basta aplicar a diretiva ng-app ou qualquer outra diretiva no elemento HTML para usar os recursos do AngularJS.

Vamos agora configurar o nosso ambiente para poder usar o AngularJS. 

Abra o arquivo _Layout.cshtml na pasta \Views\Shared e inclua as referências conforme mostradas a seguir:

<!DOCTYPE html>
<html ng-app="mvcCRUDApp">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Livraria</title>
    <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="~/Scripts/angular.js"></script>>
    <script src="~/Scripts/Modulejs.js"></script>
    <script src="~/Scripts/Controller.js"></script>
    <script src="~/Scripts/Service.js"></script>
    <script src="~/Scripts/modernizr-2.6.2.js"></script>
</head>
<body>
    <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("Macoratti .net", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
        .....
        .....  

A diretiva ng-app foi definida na tag html do arquivo e indica o módulo mvcCRUDApp que será carregado quando do início da aplicação.

Neste exemplo eu referenciei a biblioteca do Angular e os arquivos de scripts diretamente na tag head mas uma abordagem mais robusta seria usar os arquivos de bundling da aplicação.

Agora é só alegria...

Executando o projeto iremos obter o seguinte resultado:

1- Na primeira execução a tabela será criada mas como não temos nenhuma informação nada será exibido:

2- Clicando no botão Adicionar Livro veremos o formulário para registrar um livro. Após informar os dados e clicar no botão Salvar veremos a mensagem de alerta javascript informando que os dados foram incluídos com sucesso:

3- Abaixo vemos os dados informados agora sendo exibidos na view:

4- Clicando no botão Editar podemos alterar informações do livro:

5- Clicando no botão Deletar podemos excluir um livro cadastrado:

Nesta implementação veremos a mensagem de alerta javascsript informando que livro foi deletado. Você pode incrementar o projeto implementando a confirmação da exclusão.

Pegue o projeto completo aqui :   Mvc_Crud_Angular_Service.zip (sem as referências)

Tornou, pois, Jesus a dizer-lhes: Em verdade, em verdade vos digo que eu sou a porta das ovelhas.
Todos quantos vieram antes de mim são ladrões e salteadores; mas as ovelhas não os ouviram.
Eu sou a porta; se alguém entrar por mim, salvar-se-á, e entrará, e sairá, e achará pastagens.

João 10:7-9

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti