Você está na página 1de 467

.

NET Core - Atendendo múltiplos Frameworks


http://www.macoratti.net/19/07/netcore_mfrwk1.htm

 Neste artigo veremos como podemos atender múltiplos


frameworks em uma aplicação .NET Core.

A criação de uma aplicação .NET Core que atenda a vários


frameworks  é uma das abordagens para o compartilhamento de
código .(share code)

Podemos criar uma aplicação .NET Core e configurar vários


frameworks de destino para que ela possa ser executada com
todas os frameworks de destino configurados.

Para demonstrar isso, vamos criar o aplicativo console  .NET


Core 3.0 , que pode ser executado com o .NET Core, bem como
com o framework .NET tradicional no Visual Studio 2019.

Vamos começar criando um novo projeto no Visual Studio 2019


abrindo a janela Start Window (ou clique em File-> New
Project):
Clique em - Create a new project;

A seguir na próxima janela selecione :

 Language : C#
 Platform : All Platforms
 Project Type : Console
Selecione o tipo de projeto : Console App (.NET Core) e clique
em Next;

Informe o nome do projeto :  NetCore_MultiplosFrameworks

Selecione a localização em Location e marque a opção : Place


Solution and project in the same directory

Clique em Create para criar o projeto.


Veremos o projeto console criado. Vamos editar o arquivo de
projeto .csproj.

Clique com o botão direito sobre o projeto e selecione : Edit


NetCore_MultiplosFrameworks
Observando vemos que o nosso projeto Console foi criado
usando a versão 2.2 do .NET Core (eu ainda não instalei o .NET
Core 3.0 SDK preview):

Como você pode ver acima, o framework alvo


(<TargetFramework>) é netcoreapp2.2.
Isso significa que atualmente este aplicativo pode ser
executado no .NET Core 2.2. Podemos incluir vários frameworks
aqui, para atender vários frameworks.

Para atender várias frameworks, vamos


alterar  <TargetFramework> para o
plural <TargetFrameworks> e incluir informação para atingir
frameworks diferentes que desejamos atender separados por ; .

Nesta alteração, vamos dar suporte a mais dois frameworks :

 .NET Framework 4.5


 .NET Framework 4.6.

Na tabela abaixo temos uma lista de símbolos para alguns dos


frameworks do  .NET Core:

Frameworks Símbolos

.NET Framework NET20, NET35, NET40, NET45, NET451, NET452, NET46, NET461, NET462, NET4

NETSTANDARD1_0, NETSTANDARD1_1, NETSTANDARD1_2, NETSTANDARD1_3, NE


.NET Standard
NETSTANDARD1_5, NETSTANDARD1_6, NETSTANDARD2_0

.NET Core NETCOREAPP1_0, NETCOREAPP1_1, NETCOREAPP2_0, NETCOREAPP2_1, NETCOR

Portanto, inclua os identificadores:  net45 e net46,


respectivamente, conforme mostrado abaixo.

Assim que você salvar o arquivo .csproj acima, o Visual Studio


carregará e incluirá as referências para .NET 4.5 e .NET 4.6 na
seção Dependencies.
Você vai notar na base da janela a mensagem : Restoring
packages for...  , indicando que os pacotes estão sendo
restaurados:

Abriando a Solution Explorer e expiando a


seção Dependencies vemos as referências incluidas conforme
abaixo:

Agora, podemos abrir o arquivo Program.cs  e incluir um código


específico de framework usando as condições de pré-
processador #if e #elif como mostrado abaixo.
No código acima, definimos o código  uasndo as diretivas de
processamento condicionais, que fornecem uma maneira de
incluir ou excluir regiões de código a partir da
compilação, para realizar o processamento executando o
aplicativo para um framework específico: 4.5 , 4.6 ou .NET
Core 2.2.

Para executar o aplicativo para um framework específico,


clique na lista suspensa de execução e selecione um framework
de destino como mostrado abaixo.
Selecionando net46 e executando iremos obter:

Referenciando Frameworks Específicos


Às vezes, você pode precisar incluir referências específicas
para um framework específico.

Por exemplo, o pacote do .NET Core 2.2 já inclui as referências


para System.Net e System.Threading.Tasks, que não está
incluída no .NET 4.5. Portanto, precisamos incluí-lo no
arquivo .csproj usando a referência condicional, conforme
mostrado abaixo.
Agora, as referências System.Net e
System.Threading.Tasks serão adicionadas ao .NET 4.5 e o
código específico do dessas referências serão executados para
todas os frameworks.

E estamos conversados...

Palavra fiel é esta: que, se morrermos com ele, também com ele viveremos;
Se sofrermos, também com ele reinaremos; se o negarmos, também ele nos
negará;
Se formos infiéis, ele permanece fiel; não pode negar-se a si mesmo.

2 Timóteo 2:11-13
Palavra fiel é esta: que, se morrermos com ele, também com ele viveremos;
Se sofrermos, também com ele reinaremos; se o negarmos, também ele nos
negará;
Se formos infiéis, ele permanece fiel; não pode negar-se a si mesmo.

2 Timóteo 2:11-13
Palavra fiel é esta: que, se morrermos com ele, também com ele viveremos;
Se sofrermos, também com ele reinaremos; se o negarmos, também ele nos
negará;
Se formos infiéis, ele permanece fiel; não pode negar-se a si mesmo.
2 Timóteo 2:11-13

"Palavra fiel é esta: que, se morrermos com ele, também com


ele viveremos;
Se sofrermos, também com ele reinaremos; se o negarmos,
também ele nos negará;
Se formos infiéis, ele permanece fiel; não pode negar-se a si
mesmo."
2 Timóteo 2:11-13
Referências:

 Seção VB .NET do Site Macoratti.net


 Super DVD .NET - A sua porta de entrada na plataforma .NET
 Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
 Seção C# do site Macoratti.net
 Super DVD C#
 Super DVD Visual Basic
 Curso Básico VB .NET - Vídeo Aulas
 Curso C# Básico - Vídeo Aulas
 NET Core - Padrão Repositório - Macoratti
 Conceitos - .NET Framework versus .NET Core - Macoratti
 NET Core ou .NET Framework - Macoratti
 NET Core 3.0 e Visual Studio 2019 - Macoratti
 .NET Core - Database First e Scaffolding com MySql
 .NET Core - A classe HttpClient (C#) - I
 .NET Core 3.0 - O Suporte a Windows Forms e WPF
 Docker - Trabalhando com contêineres (revisitado)
ASP .NET Core 3.1 - Paginação de dados
http://www.macoratti.net/20/02/aspc_pagina1.htm

  Neste artigo veremos como realizar a paginação de


dados em uma aplicação ASP .NET Core MVC com   .NET
Core 3.1.

A paginação de dados é útil para mostrar uma quantidade N de


registros em uma página, permitindo a otimização da carga dos
dados conforme a demanda do usuário.

Eu já escrevi diversos artigos sobre como realizar a paginação


de dados com ASP.NET MVC e hoje vamos recordar os
procedimentos básicos adotando uma abordagem bem simples e
direta.

Veremos um exemplo de como realizar a paginação instalando a


biblioteca X.PagedList.Mvc.Core  via Nuget:

Install-Package X.PagedList.Mvc.Core -Version 7.9.1


Esta biblioteca é compatível com o .NET Standard 2.0.

Vamos usar uma abordagem DataBase First acessar os dados da


tabela Clientes do banco de dados ContatosDB do SQL Server
que possui a seguinte estrutura :
Para isso vamos criar uma entidade chamada Cliente em nosso
projeto com propriedades cujo nomes serão iguais aos da
coluna da tabela Clientes.

Atualmente temos os seguintes registros na tabela Clientes:

Obs:  Você pode criar o banco de dados e a tabela usando o


Code-First. Para isso basta aplicar o Migrations.

'Bora' pro código...

Recursos :

 Visual Studio 2019 Community


 .NET Core 3.1

Criando o projeto no VS 2019 Community


Abra o VS 2019 Community e crie uma solução em branco via
menu File-> New Project;

Selecione o template ASP .NET Core Web Application,


e, Informe o nome Aspnet_Paginacao1.

A seguir selecione .NET Core e ASP .NET Core 3.1 e marque o


template Web Application(MVC) e as configurações conforme
figura abaixo:

Clicando no botão Create teremos o projeto criado.


Vamos usar o EF Core para se comunicar com o banco de dados
e, precisamos incluir uma referência no projeto para poder
usar os recursos do EF Core. No menu Tools-> Nuget Package
Manager clique em Manage Nuget packages for Solution e
selecione o pacote Microsoft.EntityFrameworkCore.SqlServer na
versão 3.1.0 e clique em Install.

Ao instalar este pacote todas as dependências necessárias


serão instaladas inclusive o Entity Framework Core.

Se você for aplicar o Migrations vai ter que instalar também o


pacote Microsoft.EntityFrameworkCore.Tools no projeto. Caso
contrário não precisa instalar.

Já vamos instalar também o pacote X.PageList.Mvc.Core no


projeto via menu Tools em Manage Packages for Solution :

Definindo o modelo de domínio e o contexto


Vamos criar o nosso modelo de domínio que para o nosso
exemplo será a classe Cliente onde vamos definir as
propriedades para ClienteId, Nome, Endereco e Email.

Na pasta Models do projeto crie a classe Cliente.cs e defina o


código abaixo:

public class Cliente


{
public int ClienteId { get; set; }
public string Nome { get; set; }
public string Endereco { get; set; }
public string Email { get; set; }
}

A seguir vamos criar a classe AppDbContext onde vamos definir


o nosso contexto do EF Core que vai permitir acessar os dados
do banco de dados mapeados para a entidade Cliente.

Na pasta Models crie o arquivo AppDbContext.cs com o código


abaixo:

using Microsoft.EntityFrameworkCore;
namespace AspNet_Paginacao1.Models
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions options) : base(options)
{ }

public DbSet<Cliente> Clientes { get; set; }


}
}

Essa classe herda da classe DbContext e define a propriedade


do tipo DbSet<Cliente> que mapeia a entidade para a tabela
Clientes do banco de dados.

Precisamos agora registrar o contexto como um serviço no


arquivo Startup e definir a string de conexão do banco de dados
que iremos usar no arquivo appsettings.json.

Abrindo o arquivo Startup inclua o código abaixo no


método ConfigureServices:

public void ConfigureServices(IServiceCollection services)


{
services.AddDbContext<AppDbContext>(opts =>

opts.UseSqlServer(Configuration.GetConnectionString(" sqlConnection")));
services.AddControllersWithViews();
}

Aqui definimos o provedor para usar o SQL Server e o nome da


string de conexão como 'sqlconnection'.

No arquivo appsettings.json vamos incluir o código que define


a  string de conexão   com uma instância do SQL Server local:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"sqlConnection": "Data Source=Macoratti;Initial Catalog= ContatosDB;Integrated
Security=True"
},
"AllowedHosts": "*"
}

Criando o controller ClientesController


Agora vamos criar um controlador ClientesController na
pasta Controllers do projeto.

Clique com o botão direito do mouse sobre a pasta Controllers


e selecione : Add->Controller;

Selecione a opção MVC Controller with views using Entity


Framework da janela do Scaffold e clique em Add;

Informe o nome ClienteController e clique em Add;


A seguir informe as informações na janela Add API
Controller conforme acima e clique em Add.

Sera criado o controlador com os métodos Actions e todas as


views necessárias para gerenciar dos dados dos clientes na
pasta /Views/Clientes.

Vamos ajustar a view Index.cshtml da pasta Views/Home e o


arquivo _Layout.cshtml para exibir um link para acessar os
clientes.

...
 <ul class="navbar-nav flex-grow-1">
     <li class="nav-item">
        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-
action="Index">Home</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area=""  asp-controller="Clientes" asp-
action="Index">Clientes</a>
    </li>
</ul>
...

Executando o projeto teremos o resultado abaixo:


Temos aqui a exibição parcial das informações dos Clientes
obtidas da tabela Clientes.

Vamos agora implementar a paginação de dados.

Implementando a paginação de dados


Vamos começar abrindo o arquivo ClientesController e
incluindo uma referência ao pacote usado para realizar a
paginação.

using X.PagedList;

Vamos aplicar a paginação ao método Index do


controlador ClientesController pois é aqui que são retornadas
as informações dos clientes.

Assim altere o código Action Index conforme abaixo:

public async Task<IActionResult> Index(int? pagina)


{
const int itensPorPagina = 5;
int numeroPagina = (pagina ?? 1);
return View(await _context.Clientes.
ToPagedListAsync(numeroPagina, itensPorPagina));
}
Definimos no método o recebimento da pagina que pode ser
null e a seguir definimos o número de itens por página igual a 5
e o número da pagina que se não for informado será igual a 1.

Usamos então o método ToPagedListAsync() passando esses


valores para a view.

Agora a view Index.cshtml da pasta /Views/Clientes deve ter o


seu código alterado conforme abaixo:

@model
X.PagedList.IPagedList<AspNet_Paginacao1.Models.Cliente>
@using X.PagedList.Mvc.Core;
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Criar Novo</a>
</p>
<table class="table">
<thead>
<tr>
<th> Nome</th>
<th> Endereço</th>
<th> Email</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Nome)
</td>
<td>
@Html.DisplayFor(modelItem => item.Endereco)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
<a asp-action="Edit" asp-route-
id="@item.ClienteId">Edita</a> |
<a asp-action="Details" asp-route-
id="@item.ClienteId">Detalhe</a> |
<a asp-action="Delete" asp-route-
id="@item.ClienteId">Deleta</a>
</td>
</tr>
}
</tbody>
</table>
@Html.PagedListPager(Model, pagina => Url.Action("Index", new
{ pagina }))
 

Executando o projeto iremos obter o resultado abaixo onde


temos cada página exibindo 5 registros:

E temos os números que permitem navegar pelas


páginas (temos 3 páginas) neste exemplo.

Pegue o projeto (sem as referências) aqui :    


AspNet_Paginacao1.zip

Porque a lei foi dada por Moisés; a graça e a verdade vieram


por Jesus Cristo.
Deus nunca foi visto por alguém. O Filho unigênito, que está
no seio do Pai, esse o revelou.
João 1:17,18

Referências:

 Seção VB .NET do Site Macoratti.net


 Super DVD .NET - A sua porta de entrada na plataforma .NET
 Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
 Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
 Seção C# do site Macoratti.net
 Seção ASP .NET do site Macoratti .net
 Curso Básico VB .NET - Vídeo Aulas
 Curso C# Básico - Vídeo Aulas
 Curso Fundamentos da Programação Orientada a Objetos com VB .NET  
 Macoratti .net | Facebook
 macoratti - YouTube
 Jose C Macoratti (@macorati) | Twitter Seção Entity Framework -
Macoratti .NET
 Introdução ao Entity Framework - Macoratti.net
 C# - CRUD básico com Entity Framework - Macoratti.net
 C# - Paginando o DataGridView - Macoratti
 ADO .NET Entity Framework - Usando LINQ to Entties
 .NET - Entity Framework 5 - Operações CRUD (revisitado)
 NET - Melhorando o desempenho da Paginação ... - Macoratti

ASP .NET Core - Implementando a segurança com ... - Macoratti


ASP.NET Core MVC - Criando um Dashboard ... - Macoratti.net

 VB .NET - Paginação de dados no DataGridView ... - Macoratti



ASP .NET Core - Apresentando Razor Pages - Macoratti


ASP .NET Core MVC - CRUD básico com ADO .NET - Macoratti

 Entity Framework - O tratamento da concorrência - Curso  


 ASP .NET MVC - Catalogo de Clientes com foto e Paginação - III
 ASP .NET MVC - Realizando a paginação de dados - Macoratti
 ADO.NET - Paginação de dados - Macoratti
 Angular 6/7 - Paginação de dados - Macoratti
ASP.NET Core Web API - Apresentando API
Analyzers
http://www.macoratti.net/19/08/aspnc_anlyz1.htm

Neste artigo vamos apresentar o recurso API Analyzers introduzido


na versão 2.2 da ASP .NET Core.

Na ASP .NET Core 2.1 foi introduzido o atributo [ApiController]


para denotar convenções específicas de um Controller Web API
e realizar a validação do modelo com resposta automática de
erro 400.

A ASP .NET Core 2.2 vai além fornecendo os metadados para


a API Explorer, melhorando assim a experiência de
documentação da API. Para fazer isso a versão 2.2 introduziu o
recurso API Analyzers que ajudam a seguir um conjunto de
convenções para uma melhor documentação da API.

Nesta artigo vamos descobrir como usar os  API Analyzers ou


Analisadores de API.

Criando o projeto API no VS 2019 Community


Vamos criar uma aplicação ASP .NET Core Web
Application usando o template API no Visual Studio 2019
Community chamada Api_AnalyzersDemo;

Abra o VS 2019 Community e selecione : Create a new Project


Selecionando em Language : C#, Platform: All Platforms e
em Project Type: web podemos selecionar o template ASP .NET
Core Web Application:
A seguir vamos informar o nome do projeto, sua localização e
nome da solução conforme abaixo:
Finalmente seleciona a plataforma .NET Core e ASP .NET Core
2.2 e o template API.

Marque a opção para configurar HTTP e não vamos usar


Autenticação:
Ao final teremos um projeto Web API com a estrutura exibida
na janela Solution Explorer:
Incluinndo o Swagger para documentar a API
Depois que o projeto for criado, precisaremos ativar a
documentação do Swagger para a nossa API.

Vou mostrar bem resumidamente como fazer isso. Para


detalhes veja o meu vídeo: Gerando a documentação com
Swagger

Inclua uma referência no projeto ao


pacote Swashbuckle.AspNetCore:
A seguir no método ConfigureServices da
classe Startup adiciona o serviço Swagger ao middleware:

        public void ConfigureServices(IServiceCollection services)


        {
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info
                {
                    Version = "v1",
                    Title = "Api Analyzers",
                    Description = "API Demonstração - API Analyzers",
                    TermsOfService = "Nenhum",
                    Contact = new Contact() { Name = "Macoratti.net", Email =
"macoratti@yahoo.com", Url = "www.macoratti.net" }
                });
            });

           
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

A seguir vamos habilitar a UI Swagger no método Configure() :

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Mac API V1");
});
}

Pronto ! Isso é tudo que precisamos para configurar


o Swagger para documentar a API.

Criando um novo Controlador


Para mostrar a utilidade dos API Analyzers ou Analisadores de
API, precisamos de um exemplo de código real (basicamente,
um controlador com operações CRUD).

Vamos definir um modelo de domínio, criar um novo Controller


e definir as operações CRUD no controlador.

Primeiro vamos remover o controlador ValuesController da


pasta Controllers.

A seguir crie uma pasta Models no projeto e nesta pasta crie


um

public class Aluno


{
public int AlunoId { get; set; }
public string Nome { get; set; }
public int Idade { get; set; }
}

Vamos fazer a conexão com a tabela Alunos do banco de


dados EscolaDB no SQL Server usando o EF Core. Abaixo vemos
os dados existentes na tabela Alunos:
Para isso vamos criar a classe de contexto AppDbContext na
pasta Models para mapear a entidade Aluno para a
tabela Alunos existente.

Crie a classe AppDbContext na pasta Models com o código


abaixo:

using Microsoft.EntityFrameworkCore;
namespace Api_AnalyzersDemo.Models
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{}

public DbSet<Aluno> Alunos{ get; set; }


}
}

Note que esta classe herda de DbContext e define


um DbSet<Aluno> mapeando para a tabela Alunos.

Agora precisamos registrar o contexto como um serviço e


definir o provedor do banco de dados e a string de conexão no
método ConfigureServices da classe Startup incluindo a linha de
código abaixo:

...
services.AddDbContext<AppDbContext>(options =>

options.UseSqlServer(Configuration.GetConnectionString("DefaultConn
ection")));
...

Abra o arquivo appsettings.json e defina a string de


conexão DefaultConnection :

{
"ConnectionStrings": {
"DefaultConnection": "Data Source=Macoratti;Initial
Catalog=EscolaDB;Integrated Security=True"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

Agora temos tudo configurado e podemos criar o controlador.

Criando o controlador AlunosController


Vamos agora criar o controlador AlunosController usando
o Scaffold e definir os métodos CRUD com a integração do EF
Core.

Clique com o botão direito do mouse sobre a


pasta Controllers e selecione a opção Add Controller;

Na janela Add Scaffold escolha a opção API Controller with


actions using Entity Framework;

Na janela a seguir informe os dados conforme mostrado na


figura abaixo:

Após clicar no botão Add, nosso


controlador AlunosController será criado na pasta Controllers,
e, já poderemos testar nossa aplicação.

Executando o projeto e navegando para a


url : https://localhost:44326/swagger/

Iremos acessar a documentação da nossa API gerada pelo


Swagger conforme mostra a figura abaixo:
Clique no botão PUT para visualizar detalhes do método PUT e
sua implementação:
Observe que na documentação do Swagger nossa API PUT
esta retornando apenas o status code 200, mas se espiarmos o
código do método PutAluno no
controlador AlunosController veremos o seguinte:

...
// PUT: api/Alunos/5
[HttpPut("{id}")]
public async Task<IActionResult> PutAluno(int id, Aluno aluno)
{
if (id != aluno.AlunoId)
{
return BadRequest();
}
_context.Entry(aluno).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!AlunoExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
...

Note que no código temos 3 possíveis retornos:

 BadRequest - 400
 NotFound - 404
 NoContent - 204

Assim nossa documentação esta omissa quanto a esses tipos de


retornos esperados no método Http PUT.

Aqui entra o recurso API Analyzers, e, vamos ver como usá-lo


para corrigir esta falha.

Instalando e usando API Analyzers


Por padrão, a ASP.NET Core 2.2 é fornecida com um conjunto
de convenções padrão - DefaultApiConventions - baseadas no
controlador que o Scaffold da ASP.NET Core gera.

Se seus métodos Actions seguem o padrão que


o scaffolding produz, você deve ser bem sucedido usando as
convenções padrão. Estes analisadores trabalham com
controladores anotados com o
atributo ApiController introduzido na versão 2.1.

Para usar os analisadores de API, temos que instalar o pacote


nuget : Microsoft.AspNetCore.MVC.Api.Analyzers

Abra a janela - Package Manager Console - e digite


comando : Install-package <nome_pacote>
Após a instalação do pacote nuget, se você retornar aos
métodos Action do controlador AlunosController e observar o
método PutAluno vai notar que existem  alertas (warnings)  nas 3
linhas de return do código conforme mostra a figura abaixo:

O analizador reporta a falta da documentação para os códigos


de status e oferece uma opção para corrigir o problema.

Clicando em um dos alertas e selecionando a ferramenta para


fazer a correção veremos a sugestão que vai incluir os
atributos ProducesResponseType(StatusCode.<código_status_co
d> no método PutAluno, conforme mostra a figura abaixo:

Aceitando a sugestão para correção teremos o resultado


mostrado a seguir:
Com isso a geração da documentação vai incluir esses códigos
de status de response conforme vemos na figura abaixo para o
método HTTP Put:
Aplicando as convenções da Web API
O ASP.NET Core 2.2 e versões posteriores incluem uma maneira
de extrair documentação comum da API e aplicá-la a
várias Actions, controladores ou todos os controladores dentro
de um assembly.

As convenções da Web API são um substituto para decorar


ações individuais com [ProducesResponseType].

Uma convenção permite que você:


 Defina os tipos de retorno mais comuns e os códigos de
status retornados de um tipo específico de Action;
 Identifique Actions que se desviam do padrão definido;

As Convenções não compõem; cada Action pode estar associada


a exatamente uma convenção. Convenções mais específicas
têm precedência sobre convenções menos específicas. A
seleção  não é determinística quando duas ou mais convenções
da mesma prioridade se aplicam a uma ação.

As seguintes opções existem para aplicar uma convenção a


uma Action, do mais específico ao menos específico:

1- Microsoft.AspNetCore.Mvc.ApiConventionMethodAttribute

Aplicada às Actions individuais e especifica o tipo de convenção


e o método de convenção a que se aplica.

No exemplo, o tipo de convenção padrão do


método Microsoft.AspNetCore.Mvc.DefaultApiConventions.Put é
aplicado para Action Update:
 
[HttpPut("{id}")]
[ApiConventionMethod(typeof(DefaultApiConventions),
nameof(DefaultApiConventions.Put))]
public IActionResult Update(string id, Contato contato)
{
var contatoToUpdate = _contatos.Get(id);
if (contatoToUpdate == null)
{
return NotFound();
}
_contatos.Update(contato);
return NoContent();
}

Neste exemplo a
convenção Microsoft.AspNetCore.Mvc.DefaultApiConventions.Pu
t aplica os seguintes atributos ao método Action:

[ProducesDefaultResponseType]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
2- Microsoft.AspNetCore.Mvc.ApiConventionTypeAttribute aplic
ado ao Controller

Aplica o tipo de convenção especificado a todas as Actions no


controlador. Um método de convenção é decorado com dicas
que determinam as ações às quais o método de convenção se
aplica.

No exemplo a seguir um conjunto de convenções é aplicado


ao Controller Contatos:

[ApiController]
[ApiConventionType(typeof(DefaultApiConventions))]
[Route("api/[controller]")]
public class ContatosController : ControllerBase
{
}

3- Microsoft.AspNetCore.Mvc.ApiConventionTypeAttribute aplic
ado ao  assembly

Aplica o tipo de convenção especificado a todos os


controladores no assembly atual. Como uma recomendação,
aplique atributos de nível de assembly no arquivo  Startup.cs.

No exemplo a seguir o conjunto padrão de convenções é aplicado


a todos os controladores no assembly:

assembly: ApiConventionType(typeof(DefaultApiConventions))]
namespace ApiConventions
{
public class Startup
{}
...
}

Nota: A classe DefaultApiConventions é uma classe estática,


que define um conjunto de métodos como um padrão e os
metadados aplicáveis são aplicados ao método, se o padrão for
correspondido.

Pegue o projeto completo aqui:    Api_AnalyzersDemo.zip

"Dando graças ao Pai que nos fez idôneos para participar da


herança dos santos na luz;
O qual nos tirou da potestade das trevas, e nos transportou
para o reino do Filho do seu amor;
Em quem temos a redenção pelo seu sangue, a saber, a
remissão dos pecados;
O qual é imagem do Deus invisível, o primogênito de toda a
criação;"
Colossenses 1:12-15 Referências:

 Seção VB .NET do Site Macoratti.net


 Super DVD .NET - A sua porta de entrada na plataforma .NET
 Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
 Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
 Seção C# do site Macoratti.net
 Seção ASP .NET do site Macoratti .net
 ASP .NET Core 2 - MiniCurso Básico - Macoratti
 ASP .NET Core MVC - CRUD básico com ADO .NET - Macoratti
 ASP .NET Core - Implementando a segurança com ... - Macoratti
 ASP .NET Core - Iniciando com ASP .NET Core MVC e ... - Macoratti
 ASP .NET Core MVC - Criando um site com MySql e EF ... - Macoratti
 ASP .NET Core - Gerenciador de Despesas Pessoais com ... - Macoratti
 Minicurso ASP .NET Core 2.0 - Apresentando MVC - YouTube
 ASP .NET Core - Configurando o ambiente de ... - Macoratti
 ASP .NET Core e EF Core - Configurando o ambiente - Macoratti
 ASP .NET Core - Como configurar o AutoMapper - Macoratti
ASP .NET Core - Criando e atribuindo Roles – I
http://www.macoratti.net/18/02/aspcore_roles1.htm

 Neste artigo eu vou mostrar como criar e atribuir


roles a usuários em uma aplicação ASP .NET Core
MVC.

Quando você cria uma aplicação ASP .NET Core MVC usando o
template Web Application(Model-View-Controller) com
autenticação através da opção Individual User Accounts,  o
projeto criado possui toda a estrutura para realizar a
autenticação e o registro do usuário.

Você poderá registrar e autenticar usuários na aplicação mas


não poderá criar perfis de usuários (as roles) nem atribuir
perfis a usuários.

Neste artigo eu vou mostrar uma forma de criar e atribuir


perfis a usuários registrados e depois como fazer a
autenticação baseada em roles.

Recursos usados:

 Visual Studio 2017 Community

Criando o projeto no VS 2017


Abra o VS 2017 Community e crie um novo projeto ASP .NET
Core usando o template Empty.

 Create New Project;


 Visual C# -> Web -> ASP .NET Core Web Application;
 Informe o nome AspCore_Roles
 Selecione o template Web Application(Model-View-
Controller) , marque ASP .NET Core 2.0,  e clique
em Change Authentication, selecionando a seguir a
opção: Individual User Accounts:

Confirme as opções clicando em OK para criar o projeto.

Ao final teremos o projeto criado com a seguinte estrutura:


Controllers
 HomeController – Controladores
para Home, About, Contact
 AccountController – Controladores
para Login, Register,
ForgotPassword etc
 ManageController – Controladores
para Alterar Senha, gerenciar
perfil, para incluir two-factor
authentication etc

Data
 Classe ApplicationDBContext com
diferentes scripts de migração para
criar as tabelas do banco de dados

Extensions
 Classes para confirmação do email,
resetar passwaord, etc.

Models
 AccountViewModels(LoginViewMode
l, RegisterViewModel, etc)
 ManageViewModels(ChangePassword
ViewModel,
EnableAuthenticationViewModel,
etc)
 ApplicationUser
 ErrorViewModel

Services
 Serviço para Enviar Email

Views
 Views para Account, Manage,
Home, About, Contact etc

appsettings.json - arquivo de
configuração contendo a string de
conexão para o banco de dados

Program.cs - arquivo de entrada da


aplicação

Startup.cs - arquivo de inicialização


da aplicação

O recurso Identity está habilitado para o aplicativo


chamando app.UseAuthentication() no método Configure da
classe Startup.  Isso adiciona uma autenticação baseada em
cookie ao pipeline de solicitação.
Executando a aplicação iremos obter a página incial com os
links para Registrar um usuário e fazer a autenticação via
login.

Nota: Ao executar a aplicação pela primeira vez será acionado


o  Migrations  Inicial que irá criar o banco de dados e as
tabelas para armazenar as informações de usuários, roles, etc.

Antes de executar a aplicação eu vou alterar o nome do banco


de dados no arquivo appsettings.json dando um nome mais
simples:
 

{
  "ConnectionStrings": {
    "DefaultConnection":
"Server=(localdb)\\mssqllocaldb;Database=AspNet_RolesDB;Trusted_Connect
ion=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

Nota:  Você pode usar qualquer outro nome da sua escolha.

Agora aplique a migração inicial existente na aplicação, usando


o Package Manager Console e digitando o comando:  update-
database
Dessa forma teremos o banco de dados e todas as tabelas
criadas no SQL Server e prontas para serem usadas em nossa
aplicação.

Criando perfis de usuário


Agora veremos como criar perfis de usuários em nossa
aplicação. Vou criar três perfis de usuário iniciais  : Admin,
User e Operator.

Vamos criar um novo método chamado CreateRoles na


classe Startup da nossa aplicação usando o código a seguir:
 

        private async Task CreateRoles(IServiceProvider serviceProvider)


        {
           var roleManager =
serviceProvider.GetRequiredService< RoleManager<IdentityRole>>();
            var userManager =
serviceProvider.GetRequiredService< UserManager<ApplicationUser>>();
            string[] rolesNames = { "Admin", "User", "Operator" };
            IdentityResult result;
            foreach(var namesRole in rolesNames)
            {
                var roleExist = await roleManager.RoleExistsAsync(namesRole);
                if(!roleExist)
                {
                    result = await roleManager.CreateAsync(new
IdentityRole(namesRole));
                }
            }
        }

Vamos entender o código :

- O método CreateRoles recebe como parâmetro um objeto da


interface IServiceProvider;
- Criamos dois serviços :  roleManager e userManager;-  Criamos
um array de strings contendo os perfis que vamos criar e a
seguir atribuir aos usuários : "Admin", "User" e "Operator";
- Verificamos se os perfis já existem usando um laço foreach;
Se o perfil não existir criamos o perfil usando o
método CreateAsync da instância roleManager;

Após criar o método vamos invocá-lo a partir do


método Configure da classe Startup. Para isso inclua o código
em azul conforme mostrado abaixo:
 

       public void Configure(IApplicationBuilder app, IHostingEnvironment


env, IServiceProvider serviceProvider)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseAuthentication();

            app.UseMvc(routes =>


            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

            CreateRoles(serviceProvider).Wait();
        }

Agora quando executarmos a aplicação serão criados também


os perfis Admin, User e Operador.

Agora executando a aplicação novamente e examinando a


tabela AspNetRoles do banco de dados AspNet_RolesDB no SQL
Server Management, veremos que foram criados os
perfis: Operator, User e Admin:
Assim já estamos prontos para atribuir esses perfis ao registrar
um novo usuário e veremos como fazer isso na próxima parte
do artigo.

Aguardem...

"E Jesus, tendo ouvido isto, disse-lhes: Os sãos não necessitam


de médico, mas, sim, os que estão doentes; eu não vim chamar
os justos, mas, sim, os pecadores ao arrependimento. "
Marcos 2:17
ASP .NET Core - Criando e atribuindo Roles – II
http://www.macoratti.net/18/02/aspcore_roles2.htm

 Neste artigo eu vou mostrar como criar e atribuir roles


a usuários em uma aplicação ASP .NET Core MVC.

Continuando a primeira parte do artigo  vamos ajustar a nossa


aplicação para exibir os perfis criados na página de registro do
usuário.

Neste momento ainda não temos nenhum usuário registrado em


nossa aplicação e se espiarmos a tabela AspNetUsers no SQL
Server Management Studio veremos que ela esta vazia.

Para fazer a atribuição dos perfis ao usuário no momento que


um novo usuário for registrado, primeiro teremos que exibir os
perfis na página de registro do usuário e permitir que um perfil
seja selecionado e a seguir atribuirmos o perfil ao usuário.

A atribuição é feita na tabela AspNetUserRoles onde iremos


atribuir o id do perfil ao id do usuário.
Antes de prosseguir podemos desabilitar a chamada do
método CreateRoles na classe Startup pois já temos os perfis
criados.

Recursos usados:

 Visual Studio 2017 Community

Alterando a view Register para exibir os perfis


existentes
Para poder exibir os perfis na view Register primeiro temos
que alterar a classe RegisterViewModel com o código a seguir:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace AspCore_Roles.Models.AccountViewModels
{
    public class RegisterViewModel
    {
        [Required]
        [EmailAddress]
        [Display(Name = "Email")]
        public string Email { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max
{1} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation
password do not match.")]
        public string ConfirmPassword { get; set; }

        [DataType(DataType.Text)]
        [Display(Name = "Perfis de usuário : ")]
        [UIHint("List")]
        public List<SelectListItem> Roles { get; set; }

        public string Role { get; set; }

            public RegisterViewModel()
        {
            Roles = new List<SelectListItem>();
            Roles.Add(new SelectListItem(){Value = "1", Text = "Admin" });
            Roles.Add(new SelectListItem(){Value = "2", Text = "Operator" });
            Roles.Add(new SelectListItem(){Value = "3", Text = "User" });
        }
    }
}

Definimos duas propriedades : 

1- Roles do tipo List<SelectListItem> que irá exibir os perfis em


um dropdownlist na view Register.

Para isso estamos usando o atributo UIHint marcando em nosso


modelo que o campo Roles vai se comportar como
um DropDownList.

2- Role do tipo string que indica o perfil selecionado

No construtor da classe estamos criando uma lista de objetos


onde definimos os nomes dos perfis que foram criados em nossa
aplicação.

Nota:  Essa abordagem evita que tenhamos que acessar a


tabela  AspNetRoles  para obter os valores.  Ela simplifica nosso
código mas talvez não seja a melhor abordagem.

Agora teremos que alterar o método Register do


controlador AccountController.

Alterando o controlador AccountController

No controlador AccountController altere o
método Register conforme mostrado abaixo:
[HttpGet]
[AllowAnonymous]
public IActionResult Register(string returnUrl = null)
{
RegisterViewModel registerViewModel = new
RegisterViewModel();
ViewData["ReturnUrl"] = returnUrl;
return View(registerViewModel);
}

Aqui apenas criamos  uma instância de RegisterViewModel e


passamos a instância para a View.

Nosso próximo passo será alterar a view Register.

Alterando a view Register


Vamos agora alterar a view Register incluindo o código azul em
destaque onde usamos uma tag helper asp-for para exibir o
valor da propriedade Roles e um Html Helper dropdownlist
para exibir os perfis definidos na RegisterViewModel:

@model RegisterViewModel
@{
ViewData["Title"] = "Register";
}
<h2>@ViewData["Title"]</h2>
<div class="row">
<div class="col-md-4">
<form asp-route-returnUrl="@ViewData["ReturnUrl"]"
method="post">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-
danger"></span>
</div>
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-
danger"></span>
</div>
<div class="form-group">
<label asp-for="ConfirmPassword"></label>
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-
danger"></span>
</div>
<div class="form-group">
<label asp-for="Roles"></label>
@Html.DropDownList("Role", new
SelectList(Model.Roles, "Text", "Text"))
</div>
<div class="form-group">
<button type="submit" class="btn btn-
default">Register</button>
</div>
</form>
</div>
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
}

Executando a aplicação novamente e acionando o


link Register da página inicial teremos a
view Register.cshtml exibida conforme abaixo:
Agora podemos selecionar um perfil para poder atribuir ao
usuário.

Na próxima parte do artigo  veremos como fazer isso.

"Portanto, agora nenhuma condenação há para os que estão


em Cristo Jesus, que não andam segundo a carne, mas
segundo o Espírito."
Romanos 8:1
ASP .NET Core - Criando e atribuindo Roles – III
http://www.macoratti.net/18/02/aspcore_roles3.htm

 Neste artigo eu vou mostrar como criar e atribuir roles a


usuários em uma aplicação ASP .NET Core MVC.

Continuando a segunda   parte do artigo  vamos agora atribuir os


perfis criados aos usuários e aplicar a autenticação baseada em
Roles para testar se nossa implementação realmente funcionou.

A página de registro de um novo usuário agora exibe os perfis


criados. Para atribuir um perfil ao usuário basta selecionar o
perfil e clicar no botão Register.

Recursos usados:

 Visual Studio 2017 Community

Atribuindo um perfil de usuário


Para poder exibir atribuir um perfil selecionado ao usuário
temos que alterar o código da classe AccountController.

Vamos alterar o método Register (HttpPost) que será


acionando quando o usuário clicar no botão Register da página
de registro.

Inclua no método Register o código destacado em azul


mostrado abaixo:

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Register(RegisterViewModel model,
string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser { UserName = model.Email, Email
= model.Email };
                var result = await _userManager.CreateAsync(user,
model.Password);
                if (result.Succeeded)
                {
                    _logger.LogInformation("User created a new account with
password.");

                    var code = await


_userManager.GenerateEmailConfirmationTokenAsync(user);
                    var callbackUrl = Url.EmailConfirmationLink(user.Id,
code, Request.Scheme);
                    await
_emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl);

                    //-------------------atribuir role ao
user------------------------------
                    var applicationRole = await
_roleManager.FindByNameAsync(model.Role);
                    if (applicationRole != null)
                    {
                        IdentityResult roleResult = await
_userManager.AddToRoleAsync(user, applicationRole.Name);
                    }
                    //-------------------atribuir role ao
user------------------------------

                    await _signInManager.SignInAsync(user, isPersistent:


false);
                    _logger.LogInformation("User created a new account
with password.");
                    return RedirectToLocal(returnUrl);
                }
                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form


            return View(model);
        }

No código incluído estamos localizando o nome do perfil


selecionado usando o método FindByNameAsync e a seguir
verificando se ele não é nulo.

Depois estamos usando o método AddToRoleAsync() para


atribuir ao usuário o perfil selecionado.
Para que o código acima funcione temos que incluir no
construtor da classe AccountController uma instância da
classe RoleManager.

Abaixo vemos o código alterado:

    [Authorize]
    [Route("[controller]/[action]")]
    public class AccountController : Controller
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly IEmailSender _emailSender;
        private readonly ILogger _logger;
        private readonly RoleManager<IdentityRole> _roleManager;

        public AccountController(


            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager,
            IEmailSender emailSender,
            RoleManager<IdentityRole> roleManager,
            ILogger<AccountController> logger)
        {
            _userManager = userManager;
            _signInManager = signInManager;
            _emailSender = emailSender;
            _roleManager = roleManager;
            _logger = logger;
        }
        ....
}

Executando o projeto e registrando um novo usuário:


Podemos verificar na tabela AspNetUserRoles o Id do usuário e
o id do perfil atribuído:

Para fazer a prova dos nove vamos aplicar a autenticação


baseada em Roles usando o atributo Authorize.
Autenticação baseada em roles
Agora que temos usuários registrados e perfis atribuídos
podemos usar o atributo Authorize para permitir o acesso a um
recurso usando o perfil do usuário.

Para fazer isso basta definir em um controlador ou método


Action o atributo Authorize e especificar o perfil que terá
acesso usando Roles :  Authorize(Roles="Perfil1, Perfil2,...")

Como exemplo vamos definir o atributo Authorize no método


Action Contact do controlador HomeController definindo que
somente os usuários que tem o perfil  'Admin' terão acesso a
essa Action:

[Authorize(Roles = "Admin")]
public IActionResult Contact()
{
ViewData["Message"] = "Página de contato do Admin.";
return View();
}

Nossa aplicação possui dois usuários registrados:

1. admin@admin.com.br   com perfil Admin


2. teste@teste.com.br   com perfil User   

Agora se você executar a aplicação novamente e se logar como


usuário teste@teste.com.br  ao tentar acessar a
Action Contact irá obter o seguinte resultado:

Como o usuário não pertence ao perfil Admin ele não terá


acesso ao recurso.
Agora se logando como usuário admin@admin.com.br  e
acessando a Action Contact teremos o resultado abaixo:

Como o usuário possui o perfil Admin ele tem acesso ao


recurso.

Dessa forma a atribuição de perfis aos usuários esta


funcionando corretamente.

Pegue o projeto aqui :    AspCore_Roles.zip

(Disse Jesus)"Mas a hora vem, e agora é, em que os


verdadeiros adoradores adorarão o Pai em espírito e em
verdade; porque o Pai procura a tais que assim o adorem."
João 4:23
ASP .NET Core - Criando serviços backend para aplicações
móveis nativas – I
http://www.macoratti.net/17/04/aspcore_mobile1.htm

 Neste artigo eu vou mostrar como criar serviços


backend usando ASP .NET Core MVC com suporte a
aplicações móveis nativas.(Android, iOS e Windows
Phone)

Esta série de artigos se baseia no


original https://docs.microsoft.com/en-
us/aspnet/core/mobile/native-mobile-backend  com adaptações
e ajustes.

Para acompanhar este artigo você precisa ter instalado o  Visual


Studio Community 2017  com os seguintes workloads instalados:

O objetivo
Aplicações para dispositivos móveis podem se comunicar
facilmente com serviços backend ASP .NET Core e este artigo
vai demonstrar como criar serviços backend usando ASP .NET
Core MVC para suportar aplicações mobiles nativas.

Podemos dividir as etapas a serem cumpridas neste artigo da


seguinte forma:

1. Criar o serviço ASP .NET Core;


2. Criar a aplicação cliente Xamarin Forms;

Então vamos iniciar criando o serviço ASP .NET Core.

Criando o projeto ASP .NET Core


Vamos criar uma Web API que exponha serviços para gerenciar
tarefas. De forma que o serviço vai permitir acessar
informações e realizar operações de inclusão, exclusão e
atualização de dados via serviço web api a partir da aplicação
cliente que será a aplicação mobile.

Abra no VS 2017 e no menu File clique em New Project;

A seguir selecione o template Visual C# -> .NET Core e


marque ASP .NET Core Web Application (.NET Core);

Informe o nome TarefaAPI e clique no botão OK;

Na próxima janela escolha a versão ASP .NET Core 1.1 e


marque o template Web API sem autenticação e clique no
botão OK;
Será criado um projeto usando o template Web API com toda a
estrutura pronto para uso. Esse projeto será o nosso ponto de
partida.

Se você executar este projeto agora vai obter o seguinte


resultado:

Vamos iniciar alterando o arquivo Program.cs do projeto de


forma a fazer com que a aplicação atenda a todas as
requisições na porta 5000.

Para isso abra o arquivo Program.cs e e inclua a linha de


código .UseUrls("http://*:5000") no arquivo:

using Microsoft.AspNetCore.Hosting;
namespace TarefaAPI
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseUrls("http://*:5000")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
host.Run();
}
}
}

Vamos executar a aplicação diretamente e não via  II Express, o


qual ignora requisições não locais por padrão.

Dessa forma para rodar a aplicação vamos executar dotnet


run a partir da linha de comando ou escolher o perfil da
aplicação a partir da caixa de combinação Debug Target na
barra de ferramentas do Visual Studio.

Criando o nosso modelo de domínio: a classe


TarefaItem
Um modelo de domínio é um objeto que representa os dados
em seu aplicativo. Neste exemplo, o único modelo que teremos
é um item de tarefa.

Vamos criar uma pasta chamada "Models" no projeto para nesta


pasta definir o modelo.

Na janela Solution Explorer, clique com o botão direito do


mouse no projeto e selecione Add -> New Folder e informe o
nome Models.

Nota: Você pode colocar classes  do modelo  em qualquer lugar


em seu projeto, mas a pasta  Models  é usada por convenção.

Agora vamos criar uma classe TarefaItem. Clique com o botão


direito do mouse na pasta Models e selecione Add ->Class e
atribua o nome TarefaItem à classe e clique em Add.

Substitua o código gerado pelo código abaixo:

using System.ComponentModel.DataAnnotations;
namespace TarefaAPI.Models
{
public class TarefaItem
{
[Required]
public string ID { get; set; }
[Required]
public string Nome { get; set; }
[Required]
public string Notas { get; set; }
public bool Concluido { get; set; }
}
}

Definimos a classe TarefaItem contendo 4 propriedades onde


em cada propriedades usamos o atributo [Required] que indica
que o campo é obrigatório.

Adicionando uma classe Repositório


O padrão de projeto Repository acrescenta uma camada de
abstração no topo da camada de consultas e ajuda eliminar
lógica duplicada na implementação do código de suas consultas
ao modelo de entidades.

Foi Martin Fowler  definiu o padrão Repository no seu livro


-  Patterns of Enterprise Application Architecture  - da seguinte
forma:"Intermedeia entre o domínio e as camadas de
mapeamento de dados usando uma interface de coleção para
acessar objetos de domínio." (numa tradução livre by
Macoratti)

Assim, um repositório é essencialmente uma coleção de objetos


de domínio em memória, e, com base nisso o
padrão Repository permite realizar o isolamento entre a
camada de acesso a dados (DAL) de sua aplicação e sua camada
de apresentação (UI) e camada de negócios (BLL).

Ao utilizar o padrão Repository você pode realizar a


persistência e a separação de interesses em seu código de
acesso a dados visto que ele encapsula a lógica necessária para
persistir os objetos do seu domínio na sua fonte de
armazenamento de dados.

Vamos então implementar o padrão repositório, e, a abordagem


clássica para fazer isso é criar uma interface  contendo os
métodos que desejamos expor e a seguir implementar essa
interface na classe repositório.

Clique com o botão direito do mouse na pasta Models e


selecione Add -> New Item e selecione o template Interface e
informe o nome ITarefaRepositorio e clique no botão Add;

using System.Collections.Generic;
namespace TarefaAPI.Models
{
public interface ITarefaRepositorio
{
bool ItemExiste(string id);
IEnumerable<TarefaItem> All { get; }
TarefaItem Find(string id);
void Insert(TarefaItem item);
void Update(TarefaItem item);
void Delete(string id);
}
}

Nesta interface estamos definindo métodos para gerenciar as


informações sobre o nosso modelo de domínio: TarefaItem.
Vamos agora implementar essa interface.

Clique com o botão direito do mouse na pasta Models e


selecione Add -> Class e informe o nome TarefaRepositorio e
clique no botão Add;

A seguir define o código abaixo :

using System.Collections.Generic;
using System.Linq;
namespace TarefaAPI.Models
{
public class TarefaRepositorio : ITarefaRepositorio
{
private List<TarefaItem> _tarefaLista;
public TarefaRepositorio()
{
InitializeData();
}
private void InitializeData()
{
_tarefaLista = new List<TarefaItem>();
var tarefaItem1 = new TarefaItem
{
ID = "T100",
Nome = "Criando aplicações com Xamarin",
Notas = "Xamarin University",
Concluido = true
};
var tarefaItem2 = new TarefaItem
{
ID = "T200",
Nome = "Desenvolvimento de aplicação multiplataforma",
Notas = "Xamarin Studio/Visual Studio",
Concluido = false
};
var tarefaItem3 = new TarefaItem
{
ID = "T300",
Nome = "Publicando Aplicações",
Notas = "Azure Cloud",
Concluido = false,
};
_tarefaLista.Add(tarefaItem1);
_tarefaLista.Add(tarefaItem2);
_tarefaLista.Add(tarefaItem3);
}
public IEnumerable<TarefaItem> All
{
get { return _tarefaLista; }
}
public void Delete(string id)
{
_tarefaLista.Remove(this.Find(id));
}
public TarefaItem Find(string id)
{
return _tarefaLista.FirstOrDefault(item => item.ID == id);
}
public void Insert(TarefaItem item)
{
_tarefaLista.Add(item);
}
public bool ItemExiste(string id)
{
return _tarefaLista.Any(item => item.ID == id);
}
public void Update(TarefaItem item)
{
var tarefaItem = this.Find(item.ID);
var index = _tarefaLista.IndexOf(tarefaItem);
_tarefaLista.RemoveAt(index);
_tarefaLista.Insert(index, item);
}
}
}

No código acima temos a implementação dos métodos definidos


na interface ITarefaRepositorio.

Registrando o Repositório (usando o contâiner


DI)
Ao definir uma interface repositório, podemos desacoplar a
classe de repositório do controlador MVC que a utiliza. Ao invés
de instanciar uma classe TarefaRepositorio dentro do
controlador, injetaremos uma
interface ITarefaRepositorio usando o suporte interno no
ASP.NET Core para injeção de dependência.

Esta abordagem facilita os testes unitários dos controladores.


Os testes de unidade devem injetar uma versão simulada ou
stub de ITarefaRepositorio. Dessa forma, o teste segmenta de
forma restrita a lógica do controlador e não a camada de
acesso a dados.

Para injetar o repositório no controlador, precisamos registrá-


lo com o contâiner DI.

Abra o arquivo Startup.cs do projeto e no


método ConfigureServices(), adicione o código em azul em
destaque:

using AspnetCore_WebApi.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
...
public class Startup
{
...
// This method gets called by the runtime. Use this method to add
services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddSingleton<ITarefaRepositorio,
TarefaRepositorio>();
}
...
}

O método ConfigureServices() é responsável por definir os


serviços que a aplicação vai usar, incluindo recursos da
plataforma como ASP .NET Core MVC e Entity Framework.

Na implementação da Injeção de dependência do ASP.NET


Core, vemos o conceito de lifetimes ou "tempo de vidas".
Um lifetime ou tempo de vida especifica quando um objeto DI-
injetado é criado ou recriado. Existem três possibilidades:

1. - Transient : Criado a cada vez que são solicitados.


2. - Scoped: Criado uma vez por solicitação.
3. - Singleton: Criado na primeira vez que são solicitados.
Cada solicitação subseqüente usa a instância que foi
criada na primeira vez.

O parâmetro IServiceCollection permite configurar diferentes


tipos de serviços seja por criação de objeto ou correspondência
a uma interface específica e suporta os lifetimes mencionados.

No exemplo estamos adicionando um serviço Singleton.

Incluindo um Controller no projeto


Se você não sabe o que é um Controller então pode ler os
seguintes artigos  :

 Compreendendo Models, Views e Controllers - MVC - Macoratti


 ASP .NET - MVC - Introdução - Macoratti
 ASP .NET MVC 4 - Criando sua primeira aplicação MVC -
Macoratti

Os Controllers ou Controladores são os componentes que lidam


com a interação do usuário, trabalham com o modelo e,
finalmente, selecionam uma exibição de renderização que
mostra essa interface ao usuário. Por padrão os controladores
são colocados na pasta Controllers da solução.

Clique com o botão direito do mouse na pasta Controllers e


selecione Add -> New Item;

A seguir selecione o template Web API Controller Class e


informe o nome TarefaController e clique no botão Add;

A seguir inclua o seguinte código neste arquivo:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using TarefaAPI.Models;
namespace TarefaAPI.Controllers
{
[Route("api/[controller]")]
public class TarefaController : Controller
{
private readonly ITarefaRepositorio _tarefaRepositorio;
public TarefaController(ITarefaRepositorio tarefaRepositorio)
{
_tarefaRepositorio = tarefaRepositorio;
}
}
}

Entendendo o código:

- A classe deve herdar


de Microsoft.AspNetCore.Mvc.Controller;
- Adicionamos uma rota usando o atributo Rout para indicar
que o controlador irá tratar requisições feitas a partir da
url api/controller, onde  controller na rota será substituido
pelo prefixo do nome do controlador, ou seja: api/tarefa;
- Definimos uma variável _tarefaRepositorio do tipo da
interface ITarefaRepositorio;
- Requisitamos uma instância deste tipo no construtor que em
tempo de execução será fornecida pelo container de injeção de
dependência da ASP .NET Core;

Implementando os métodos CRUD


Para que esta API suporte as operações para gerenciar as
informações, ela tem que suportar 4 diferentes verbos HTTP
para realizar as operações CRUD na fonte de dados. Vamos
então implementar e testar cada um destas operações CRUD
com seus respectivos verbos HTTP.

Vamos usar uma enumeração para definir os códigos de estados


HTTP no código de forma mais amigável.

Abaixo vemos o código da enum que serão usados nos métodos


CRUD : Create, Edit e Delete.

        public enum ErrorCode


        {                          
TarefaItemNomeAndNotasRequired,
            TarefaItemIDInUse,
            RecordNotFound,
            CouldNotCreateItem,
            CouldNotUpdateItem,
            CouldNotDeleteItem
        }

1 - Lendo itens de tarefa

Para obter uma lista de itens de tarefa podemos aplicar o


método HTTP GET usando atributo [HttpGet] conforme mostra
o método List() a seguir:

[HttpGet]
public IActionResult List()
{
return Ok(_tarefaRepositorio.All);
}
A rota para esta Action é a rota especificada no controlador.
Você não é obrigato a usar o nome da Action como parte da
rota, mas tem que assegurar que cada Action possua uma única
rota.

Este método List retorna um código de resposta igual a 200


OK e todos os itens são serializados no formato JSON.

Para testar vamos usar o aplicativo Postman.

Para instalar o Postman acesse esse


link : https://www.getpostman.com/apps  ou abra o Google
Chrome e digite postam e a seguir clique no link:   Postman -
Chrome Web Store

Na janela que será aberta clique no botão - Usar no Chrome:

A seguir registre uma conta e faça o login.

Pronto ! Já podemos usar o Postman.

A primeira coisa a fazer é levantar aplicação ASP .NET Core


usando o comando : dotnet run.

Para isso abra uma  janela de prompt de comando  e se


posicione na pasta do projeto onde esta o
arquivo package.json e digite: dotnet run
Você verá a janela abaixo indicando que a aplicação esta
atendendo na porta 5000:

Obtenha o ip da sua máquina local usando o


comando ipconfig em uma janela de prompt de comando e a
seguir digite o comando abaixo no Postman:

Nota:  Para testar as requisições no Postam você também pode


executar a aplicação teclando F5 e usar o endereço e porta
informados na URL.(Ex: Localhost:XXXX/api/tarefa)

 Defina o método HTTP para GET


 Defina o endereço da URL
para :  http://192.168.1.18:5000/api/tarefa
 Clique no botão Send
Como vemos o envio da requisião GET usando a
url : http:192.168.1.18:5000/api/tarefa chama o
método List() que retorna todos os itens.

2 - Criando itens de tarefa

Por convenção a criação de um novo item de tarefa é mapeado


para um verbo HTTP POST. 

Vamos criar o método Create usando o atributo [HttpPost] e


aceitar um parâmetro ID e uma instância de TarefaItem.
[HttpPost("{id}")]
public IActionResult Create(string id, [FromBody]TarefaItem
item)
{
try
{
if (item == null || !ModelState.IsValid)
{
return
BadRequest(ErrorCode.TodoItemNameAndNotesRequired.ToString());
}
bool itemExists = _tarefaRepositorio.ItemExiste(item.ID);
if (itemExists)
{
return StatusCode(StatusCodes.Status409Conflict,
ErrorCode.TodoItemIDInUse.ToString());
}
_tarefaRepositorio.Insert(item);
}
catch (Exception)
{
return
BadRequest(ErrorCode.CouldNotCreateItem.ToString());
}
return Ok(item);
}

Entendendo o código:

Por convenção, a criação de novos itens de dados é mapeada


para o verbo HTTP POST.

O método Create tem um atributo [HttpPost] aplicado a ele e


aceita um parâmetro ID e uma instância TarefaItem.

Os atributos do verbo HTTP, como [HttpPost], aceitam


opcionalmente uma cadeia de modelo de rota ({id}  neste
exemplo). Isso tem o mesmo efeito que adicionar um atributo
[Route] para a Action.

Como o argumento item será passado no corpo do POST este


parâmetro é decorado com o atributo [FromBody].

Dentro do método, o item é verificado quanto à validade e


existência prévia no armazenamento de dados e, se nenhum
problema ocorrer, ele é adicionado usando o repositório.A
verificação de ModelState.IsValid executa a validação do
modelo, e deve ser feita em cada método de API que aceite a
entrada do usuário.

O exemplo usa um enum contendo códigos de erro que são


passados para o cliente móvel:

Para testar a adição de um novos item de tarefa usando o


Postman vamos fazer o seguinte:

1. Defina o método HTTP para POST


2. Defina o endereço da URL
para :  192.168.1.18:5000/api/tarefa/T400
3. Selecione a opção Body
4. Selecione a opção raw
5. Define o tipo para JSON
6. No editor chave-valor informe um item tarefa conforme
mostrado abaixo:
7. Clique no botão Send

{
   "ID": "T400",
   "Nome": "Incluindo um novo item",
   "Notas": "testando POST",
   "Concluido" : false
}
O novo item criado e retornado e exibido conforme a figura  
acima.

3 - Atualizando itens de tarefa

A atualização de um item existente de tarefa é mapeado para


um verbo HTTP PUT. 

[HttpPut("{id}")]
public IActionResult Edit(string id, [FromBody] TarefaItem item)
{
try
{
//Valida o modelo
if (item == null || !ModelState.IsValid)
{
//reproduz um Http Erro 400 - Requisição inválida
return
BadRequest(ErrorCode.TarefaItemNomeENotasRequired.ToString());
}
//localiza o item via método Find do repositório
var itemExistente = _tarefaRepositorio.Find(id);
if (itemExistente == null)
{
//reproduz um Http Erro 404 - Não Encontrado
return
NotFound(ErrorCode.RegistroNaoEncontrado.ToString());
}
//atualiza o item chamando o método do repositorio
_tarefaRepositorio.Update(item);
}
catch (Exception)
{
//reproduz um Http Erro 400 - Requisição inválida
return
BadRequest(ErrorCode.NaoPodeAtualizarItem.ToString());
}
return NoContent();
}

De acordo com a especificação HTTP, uma requisição PUT requer que o


cliente envie a entidade inteira atualizada.  (Para atualização parcial
usamos HTTP PATCH.)

Usamos o método Update definido no repositório, que esta sendo


injetado via DI no construtor, para atualizar o item da tarefa.

Vamos enviar uma requisição PUT para alterar os valores do


item de tarefa com id igual a 'T100' usando o Postman.

1. Defina o método HTTP para PUT


2. Defina o endereço da URL
para :  192.168.1.18:5000/api/tarefa/T100
3. Selecione a opção Body
4. Selecione a opção raw
5. Define o tipo para JSON
6. No editor chave-valor informe um item tarefa com a
chave que deseja alterar e informe os novos valores
conforme mostrado abaixo:
 

{
   "ID": "T100",
   "Nome": "alterando um item",
   "Notas": "testando PUT",
   "Concluido" : false
}
7. Clique no botão Send;

Para ver o resultado e confirmar se o item com id igual a 'T100'


foi alterado basta definir o método GET, digitar na
URL :  http://192.168.1.18:5000/api/tarefa  no Postman e
clicar em Send:
4 - Deletando itens de tarefa

A exclusão de item existente de tarefa é mapeado para um


verbo HTTP DELETE. 

[HttpDelete("{id}")]
public IActionResult Delete(string id)
{
try
{
//localiza o item via método Find do repositório
var item = _tarefaRepositorio. Find(id);
if (item == null)
{
//reproduz um Http Erro 404 - Não Encontrado
return
NotFound(ErrorCode.RegistroNaoEncontrado.ToString());
}
//deleta item chamando o método do repositorio
_tarefaRepositorio.Delete(id);
}
catch (Exception)
{
//reproduz um Http Erro 400 - Requisição inválida
return
BadRequest(ErrorCode.NaoPodeDeletarItem.ToString());
}
return NoContent();
}
 

O método Delete  usa HTTP DELETE. A resposta obtida é 204 (No


Content) .

Usamos o método Delete definido no repositório, que esta sendo


injetado via DI no construtor, para deletar o item de tarefa

Vamos enviar uma requisição DELETE para excluir um item de


tarefa com id igual a 'T100' usando o Postman.

1. Defina o método HTTP para DELETE


2. Defina o endereço da URL
para :  192.168.1.18:5000/api/tarefa/T100
3. Clique no botão Send;

Dessa forma o item de tarefa com id igual a 'T100' foi excluído.


O Retorno 204 No Content. Não exibe o resultado.

Para verificar defina o método GET , digite a


URL :  http://192.168.1.18:5000/api/tarefa  no Postman e
clique em Send :
Dessa forma temos os métodos All(), Create(), Update(), Edit()
e Delete() implementados em nosso controlador.

Conforme você desenvolve os serviços de back-end para o seu


aplicativo, você vai querer criar um conjunto consistente de
convenções ou políticas para lidar com responsabilidades
transversais. Por exemplo, no serviço mostrado acima,
solicitações de registros específicos que não foram encontrados
receberam uma resposta NotFound, em vez de uma
resposta BadRequest.

Da mesma forma, os comandos feitos para este serviço


passados em tipos vinculados ao modelo sempre
verificaram ModelState.IsValid e retornaram
um BadRequest para tipos de modelos inválidos.

Após identificar uma política comum para suas APIs,


normalmente é possível encapsulá-la usando um filtro.
Concluímos assim a primeira etapa criando um serviço Web API
que expõe métodos para acessar, incluir, excluir e atualizar
itens de tarefa.

No próximo artigo  vamos criar a aplicação cliente, a aplicação


Xamarin Forms, que vai consumir esse serviço.
ASP .NET Core - Criando serviços backend para aplicações
móveis nativas – II
http://www.macoratti.net/17/04/aspcore_mobile2.htm

 Neste artigo eu vou mostrar como criar serviços


backend usando ASP .NET Core MVC com suporte a
aplicações móveis nativas.(Android, iOS e Windows
Phone)

Continuando o artigo anterior  vamos criar neste artigo a


aplicação Xamarin Forms que vai consumir o serviço ASP .NET
Core Web API para gerenciar tarefas.

Recursos usados:

 Visual Studio Community 2017 ou Xamarin Studio


 Xamarin

Nota: Baixe e use a versão Community 2017 do VS ela é grátis e é


equivalente a versão Professional.

Criando o projeto Xamarin Forms no VS


Community 2017
Abra o Visual Studio Community 2017 e no menu File clique
em New Project;

Selecione Visual C#, o template Cross Plataform e a


seguir Cross Plataform App(Xamarin.Forms or Native);

Informe o nome XF_Tarefas e clique no botão OK;


Observe que a nova versão do Xamarin Forms disponbilizada
em Fevereiro/2017 trás novas opções de templates de projeto.

A seguir selecione Blank App e marque as opções


- Xamarin.Forms e Portable Class Library (PCL) e clique em
OK;

Será apresentada a janela abaixo, outra diferença da nova


versão, onde você pode escolhar os templates Blank
App e Master Detail e a seguir a tecnologia e o tipo de projeto.
Marque as opções Blank App, Xamarin.Forms e Portable Class
Library(PCL)  e clique em OK.

Será criado uma solução contendo no projeto Portable as


páginas App.xaml e MainPage.xaml. Essa é outra diferença que
a nova versão trouxe.

Incluindo as referências ao HttpClient e


NewtonSoft no projeto
Precisamos incluir duas referências em nosso projeto. Os
pacotes :

 HttpClient - fornece a classe base para enviar requisições


HTTP e receber respostas HTTP a partir de uma fonte
identificada por uma URI. Assim ela inclui recursos para
enviar requisições sobre HTTP bem como
usar HttpRequestMessage e HttpResponseMessage para
processar mensagens HTTP;
 Newtonsoft - Framework JSON que permite serializar e
deserializar objetos .NET para ou a partir do formato
JSON;

No menu Tools clique em Nuget Package Manager e a seguir


em Manage Nuget Packages for Solution;

Selecione a guia Browse e informe httpclient;


A seguir selecione o pacote Microsoft.Net.HttpClient e marque
a para instalar em todos os projetos e clique em Install;

Nota: Se houver erros durante a instalação, tente instalar


primeiro o pacote para microsoft.bcl.build.

Repita o procedimento para o pacote Newtonsoft.Json:

Definindo o modelo de domínio : a classe TarefaItem

Vamos criar a classe TarefaItem que será o nosso modelo de


domínio e que vamos usar para obter as informações da web
api.

Crie uma pasta chamada Models no projeto portable e a seguir


crie a classe TarefaItem.cs com o seguinte código:

namespace XF_Tarefas.Models
{
public class TarefaItem
{
public string ID { get; set; }
public string Nome { get; set; }
public string Notas { get; set; }
public bool Concluido { get; set; }
}
}

Essa classe possui exatamente as mesmas propriedades da


classe TarefaItem definida na web api criada na primeira parte
do artigo.

Definindo a camada de serviço:  a classe


Vamos criar uma nova pasta chamada Service no projeto
Portable e nesta pasta criar a classe DataService.

Essa classe contém o código que usa os recursos


do HttpClient e do Newtonsoft.Json para enviar requisições
HTTP e receber respostas HTTP a partir da url da nossa web api
e tratar os dados no formato JSON.

Abaixo temos o código da classe DataService:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using XF_Tarefas.Models;
namespace XF_Tarefas.Service
{
public class DataService
{
HttpClient client = new HttpClient();
public async Task<List<TarefaItem>> GetTarefasAsync()
{
try
{
string url = "http://192.168.1.18:5000/api/tarefa";
var response = await client. GetStringAsync(url);
var tarefas =
JsonConvert.DeserializeObject<List<TarefaItem>>(response);
return tarefas;
}
catch (Exception ex)
{
throw ex;
}
}
public async Task AddTarefaAsync(TarefaItem tarefa)
{
try
{
string url = "http://192.168.1.18:5000/api/tarefa/{0}";
var uri = new Uri(string.Format(url, tarefa.ID));
var data = JsonConvert.SerializeObject(tarefa);
var content = new StringContent(data, Encoding.UTF8,
"application/json");
HttpResponseMessage response = null;
response = await client.PostAsync(uri, content);
if (!response.IsSuccessStatusCode)
{
throw new Exception("Erro ao incluir tarefa");
}
}
catch (Exception ex)
{
throw ex;
}
}
public async Task UpdateTarefaAsync(TarefaItem tarefa)
{
string url = "http://192.168.1.18:5000/api/tarefa/{0}";
var uri = new Uri(string.Format(url, tarefa.ID));
var data = JsonConvert.SerializeObject(tarefa);
var content = new StringContent(data, Encoding.UTF8,
"application/json");
HttpResponseMessage response = null;
response = await client.PutAsync(uri, content);
if (!response.IsSuccessStatusCode)
{
throw new Exception("Erro ao atualizar tarefa");
}
}
public async Task DeletaTarefaAsync(TarefaItem tarefa)
{
try
{
string url = "http://192.168.1.18:5000/api/tarefa/{0}";
var uri = new Uri(string.Format(url, tarefa.ID));
await client.DeleteAsync(uri);
}
catch (Exception ex)
{
throw ex;
}
}
}
}

Nesta classe definimos métodos assíncronos para gerenciar os


produtos remotamente acessando a nossa web api definida no
endereço : http://192.168.1.18:5000/api/tarefa/

Assim temos os métodos :

 GetTarefasAsync() - Usa o método GetStringAsync(url) da


classe HttpClient para retornar todos os produtos;
 AddTarefaAsync(TarefaItem tarefa) - Usa o
método .PostAsync(uri, content) da classe HttpClient
para incluir um novo produto via web api;
 UpdateTarefaAsync(TarefaItem tarefa) - Usa o
método PutAsync(uri, content) da classe HttpCliente para
atualizar um produto selecionado;
 DeletaTarefaAsync(TarefaItem tarefa) - usa o
método  DeleteAsync(uri) da classe HttpCliente para
deletar um produto selecionado;

O código esta classe foi baseado na documentação do Xamarin


neste link: https://developer.xamarin.com/guides/xamarin-
forms/cloud-services/consuming/rest/

Criando a página para gerenciar tarefas : MainPage.xaml

Vamos criar a página da nossa aplicação Xamarin Forms no


arquivo MainPage.xaml usando uma view ListView onde iremos
usar os seguintes recursos:

 Ações de Contexto para Alterar e Remover produtos


 O evento ItemSelected para poder selecionar um produto
da lista
 View Button para incluir um novo produto

Vamos incluir no topo da ListView 2 views Entry e 1


view Label e uma view Swicth para exibir os dados do produto
selecionado que poderá assim ser alterado, e, uma
view Button onde poderemos incluir ou alterar um produto.

Abra o arquivo MainPage.xaml e altere o seu código conforme


mostrado a seguir: (Ao lado você vê o layout da página que
será exibida ao cliente)
<?xml version="1.0" encoding="utf-8" ?>  
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XF_Tarefas"
             x:Class="XF_Tarefas.MainPage">

    <StackLayout Orientation="Vertical">


        <StackLayout Padding="5,5,0,0">
            <Label Text="Adicionar uma Tarefa" TextColor="Green" />
        </StackLayout>
        <StackLayout Padding="10,0,10,0">
            <Entry x:Name="txtNome" Placeholder="Nome da Tarefa"
HorizontalOptions="Start"
                    VerticalOptions="StartAndExpand" HeightRequest="30"
WidthRequest="400" FontSize="Small"/>
            <Entry x:Name="txtNotas" Placeholder="Observações"
HorizontalOptions="Start"
                    VerticalOptions="StartAndExpand" HeightRequest="30"
WidthRequest="400" FontSize="Small" />
            <StackLayout Orientation="Horizontal">
                <Label Text="A Tarefa foi Concluida ?"
HorizontalOptions="Start"/>
                <Switch x:Name="opConcluido" HorizontalOptions="End"
VerticalOptions="StartAndExpand" IsToggled=" {Binding
Concluido}" />
            </StackLayout>
            <Button HorizontalOptions="FillAndExpand"
VerticalOptions="StartAndExpand" HeightRequest="40"
Text="Adicionar/Atualizar Tarefa"
                    Clicked="btnAdicionar_Clicked" FontSize="Small"/>
        </StackLayout>
        <StackLayout Orientation="Vertical" Padding="10,5,10,0">
            <ListView x:Name="listaTarefas"
ItemSelected="listaTarefas_ItemSelected"
                      BackgroundColor="Aqua" SeparatorColor="Blue"
HasUnevenRows="True">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.ContextActions>
                                <MenuItem Clicked="OnAtualizar"
CommandParameter="{Binding .}" Text="Atualizar" />
                                <MenuItem Clicked="OnDeletar"
CommandParameter="{Binding .}" Text="Deletar"
IsDestructive="True" />
                            </ViewCell.ContextActions>
                            <StackLayout Padding="5,5">
                                <Label Text="{Binding Nome}"
HorizontalOptions="StartAndExpand"/>
                                <Label Text="{Binding Notas}" TextColor="Blue"
HorizontalOptions="StartAndExpand"/>
                                <Label Text="{Binding Concluido}"
HorizontalOptions="StartAndExpand"/>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </StackLayout>

</ContentPage>

Na continuação do artigo  vamos definir ó código do


arquivo MainPage.xaml.cs para incluir, alterar, excluir e
acessar o serviço ASP .NET Core Web Api.

(Jesus) Veio para o que era seu, e os seus não o receberam.


Mas, a todos quantos o receberam, deu-lhes o poder de serem
feitos filhos de Deus, aos que crêem no seu nome;
Os quais não nasceram do sangue, nem da vontade da carne,
nem da vontade do homem, mas de Deus.
João 1:11-13

ASP .NET Core - Criando serviços backend para aplicações


móveis nativas – III
http://www.macoratti.net/17/04/aspcore_mobile3.htm
 Neste artigo eu vou mostrar como criar serviços
backend usando ASP .NET Core MVC com suporte a
aplicações móveis nativas.(Android, iOS e Windows
Phone)

Continuando o artigo anterior  vamos concluir o nosso projeto,


completando a segunda parte do artigo e definindo o código
para incluir, alterar, excluir e selecionar tarefas via acessando
o serviço ASP .NET Core Web API  que esta atendendo no
endereço:  http:// 192.168.1.18:5000/api/tarefa/

Para tornar mais simples o projeto não estou usando o


padrão MVVM e assim estou acessando diretamente a camada
de serviço a partir das Views. Em um projeto mais robusto isso
não é recomendado.

Também não estou implementando a


interface INotifyPropertyChanged nem usando a
coleção ObservableCollection que permitiria atualizar a view
automaticamente após qualquer alteração dos dados.

Para fazer a atualização estou chamando o


método AtualizaDados() que acessa a web api e retorna todos
os dados das tarefas. Essa abordagem simplifica o projeto mas
não é aconselhável ser usada em um projeto de produção.

Recursos usados:

 Visual Studio Community 2017 ou Xamarin Studio


 Xamarin

Nota: Baixe e use a versão Community 2017 do VS ela é grátis e é


equivalente a versão Professional.

Definindo o código dos métodos CRUD no arquivo code-behind


MainPage.xaml.cs

Abrindo o arquivo MainPage.axml.cs vamos começar definindo


os namespaces usados:
using System;
using System.Collections.Generic;
using System.Linq;
using Xamarin.Forms;
using XF_Tarefas.Models;
using XF_Tarefas.Service;

No início do arquivo vamos declarar duas variáveis:

 dataservice - que representa uma instância do nosso


serviço que iremos usar para acessar a web api;
 tarefas - que representa uma lista de tarefas

 que iremos usar e que precisam ser vísiveis em todo o arquivo:

DataService dataService;
List<TarefaItem> tarefas;

Código do construtor MainPage

No construtor da classe MainPage inclua o código abaixo onde


criamos uma nova instância da classe DataService() e
chamamos o método AtualizaDados();

public MainPage()
{
InitializeComponent();
dataService = new DataService();
AtualizaDados();
}

Método AtualizaDados()
A seguir temos o código do método AtualizaDados():

async void AtualizaDados()


{
tarefas = await dataService.GetTarefasAsync();
listaTarefas.ItemsSource = tarefas.OrderBy(item =>
item.Nome).ToList();
}

Estamos obtendo as tarefas a partir da nossa web api usando o


método GetTarefasAsync() e exibindo o resultado no
controle ListView usando sua propriedade ItemSource.
Assim quando a aplicação for iniciada ela vai exibir todas as
tarefas que definimos em nossa web api.

Código do evento Clicked do botão : Adicionar


Tarefa
Para incluir uma nova tarerfa basta digitar as informações
para Nome, Notas e marcar se a tarefa foi concluida ou não e
clicar no botão Adicionar Tarefa.

O evento Clicked possui o seguinte código:

private async void btnAdicionar_Clicked(object sender,


EventArgs e)
{
if (Valida())
{
TarefaItem novaTarefa = new TarefaItem
{
ID = "T" + DateTime.Now.Millisecond.ToString(),
Nome = txtNome.Text.Trim(),
Notas = txtNotas.Text.Trim(),
Concluido = opConcluido.IsToggled
};
try
{
await dataService.AddTarefaAsync(novaTarefa);
LimpaTarefa();
AtualizaDados();
}
catch (Exception ex)
{
await DisplayAlert("Erro", ex.Message, "OK");
}
}
else
{
await DisplayAlert("Erro", "Dados inválidos...", "OK");
}
}

Este código chama o método Valida() que irá verificar se as


informações da tarefa foram informadas e, em caso positivo,
retornar true.

A seguir criamos uma nova tarefa e atribuimos os valores


digitados.
Depois usamos o método AddTarefaAsync() da
classe DataService passando a nova tarefa para ser incluída e
atualizamos os dados do Listview.

Código do método Valida()


O código do método Valida() apenas retorna true se os dados
foram informados e false caso contrário:

private bool Valida()


{
if( string.IsNullOrEmpty(txtNome.Text) &&
string.IsNullOrEmpty(txtNotas.Text))
{
return false;
}
else
{
return true;
}
}

Código da ação de contexto do Listview para atualizar uma


tarefa: OnAtualizar

Se você não sabe o que uma ação de contexto do ListView veja


o meu artigo:   Xamarin.Forms - Trabalhando com ListView -
Macoratti

private async void OnAtualizar(object sender, EventArgs e)


{
if (Valida())
{
try
{
var mi = ((MenuItem)sender);
TarefaItem tarefaAtualizar =
(TarefaItem)mi.CommandParameter;

tarefaAtualizar.Nome = txtNome.Text;
tarefaAtualizar.Notas = txtNotas.Text;
tarefaAtualizar.Concluido = opConcluido.IsToggled;
await dataService.UpdateTarefaAsync(tarefaAtualizar);
LimpaTarefa();
AtualizaDados();
}
catch (Exception ex)
{
await DisplayAlert("Erro", ex.Message, "OK");
}
}
else
{
await DisplayAlert("Erro", "Dados inválidos...", "OK");
}
}

Para atualizar uma tarefa você tem que selecionar a tarefa que
deseja alterar no ListView para que os dados da tarefa sejam
exibidos nas views Entry/Switch acima do ListView.

Após isso altere os dados e depois, na tarefa selecionado no


ListView, mantenha o mouse pressionado por alguns segundos
para que as ações de contexto sejam exibidas.

Clique então em Alterar para acionar o evento OnAtualizar()


que vai usar o método UpdateTarefaAsync() para atualizar os
dados da tarefa.

Código do evento ItemSelected do ListView


No evento ItemSelected do ListView temos o código que vai
permitir obter os dados de um item selecionado e exibí-los nas
views Entry/Switch da página:

private void listaTarefas_ItemSelected(object sender,


SelectedItemChangedEventArgs e)
{
var tarefa = e.SelectedItem as TarefaItem;
txtNome.Text = tarefa.Nome;
txtNotas.Text = tarefa.Notas;
opConcluido.IsToggled = tarefa.Concluido;
}

Código da ação de contexto do Listview para remover uma


tarefa: OnDeletar

Na ação de contexto do ListView definida no


evento OnDeletar temos o código que irá remover a tarefa
selecionada:

private async void OnDeletar(object sender, EventArgs e)


{
try
{
var mi = ((MenuItem)sender);
TarefaItem tarefaDeletar =
(TarefaItem)mi.CommandParameter;

await dataService.DeletaTarefaAsync(tarefaDeletar);
LimpaTarefa();
AtualizaDados();
}
catch (Exception ex)
{
await DisplayAlert("Erro", ex.Message, "OK");
}
}

Este código chama o método DeletaTarefaAsync() da


classe DataService passando a tarefa selecionada para que ele
seja removido via web api.

Executando o projeto iremos obter o seguinte resultado:


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

Jesus dizia, pois, aos judeus que criam nele: Se vós


permanecerdes na minha palavra, verdadeiramente sereis
meus discípulos;
E conhecereis a verdade, e a verdade vos libertará.
João 8:31,32
ASP .NET Core - Criando uma aplicação com
Angular 2
http://www.macoratti.net/17/04/aspcore_ang21.htm

 Neste artigo eu vou mostrar como criar uma aplicação bem


simples usando Angular 2 e ASP .NET Core.

As aplicações SPA - Single Page Applications - são a vedete do


momento. Parece que muita gente esta desenvolvendo
aplicações SPA usando frameworks como o Angular ou React. E
isso tem um motivo: uma experiência final do usuário muito
boa.

Ocorre que a criação de aplicações SPA usando esses


frameworks parece ser um tanto complexa, particularmente
quando da integração do código do lado do cliente com o
código do lado do servidor.

Creio que atualmente, quando se fala tanto em produtividade,


ninguém quer ficar perdendo muito tempo com configurações e
gerações de código e outras tarefas que podem ser
automatizadas.

Pois é aqui que a ASP .NET Core vem atuando de forma a poder


oferecer ao desenvolvedor a oportunidade de criar aplicações
web modernas com pouco esforço. Nesse sentido a ASP .NET
Core, o server side,  traz mais recentente 3 novos pacotes
Nuget cujo objetivo é simplificar o desenvolvimento de
aplicações SPA e facilitar a integração com o lado do cliente.
São eles:

 Microsoft.AspNetCore.SpaTemplates -  Se conecta
ao dotnet new, fornecendo modelos de projeto para
aplicações Angular 2, Aurelia, Knockout, React e React +
Redux;
 Microsoft.AspNetCore.SpaServices - É como os projetos
produzidos pelo SpaTemplates funcionam internamente.
Ele fornece recursos úteis para aplicativos SPA, como
renderização do lado do servidor para aplicações Angular
e React, além de integração com o middleware de
construção Webpack;
 Microsoft.AspNetCore.NodeServices - É como
o SpaServices funciona internamente. É uma biblioteca
de baixo nível que fornece uma maneira rápida e robusta
para que os aplicativos ASP.NET Core executem código
JavaScript arbitrário no servidor.

Coletivamente, esses recursos são conhecidos pelo


nome JavaScriptServices.  (Você encontrará o código-fonte, o
rastreador de problemas e a documentação no
repositório  JavaScriptServices GitHub )

Então como eu posso usar esses recursos ?

Para trabalhar com essas tecnologias, primeiro certifique-se de


ter instalado o seguinte:

  .NET Core SDK 1.0 RC4 (ou posterior) para Windows,


Mac ou Linux  (Para Windows você pode instalar versão
final do  VS 2017  recém lançada, que já inclui o recurso.)
  Node.js, versão 6 ou posterior

Ao instalar o VS 2017  (Estou usando a versão Community) você


deverá instalar as seguintes workloads  para criar aplicações
ASP .NET Core:

Após ter o seu ambiente preparado com os recursos citados


vamos para a parte prática.

Criando uma aplicação SPA com Angular 2


Podemos iniciar a criação da nossa aplicação SPA com ASP .NET
Core usando o Visual Studio 2017 Community e criando uma
solução ou usando as ferramentas da interface de linha de
comando .NET Core (CLI).

Neste artigo vou optar pela interface de linha de comando


do .NET Core que é uma ferramenta multiplataforma onde as
ferramentas de nível superior como os IDEs , editores e
compiladores podem se apoiar.

Apenas como uma breve introdução vou apresentar os conceitos


básicos da CLI.

O comando dotnet é um driver genérico para a ferramenta de


interface de linha de comando (CLI). Quando invocada por si
própria, ela fornece breves instruções de uso.

Cada recurso específico é implementado como um comando.


Para usar o recurso, o comando é especificado após o dotnet,
como por exemplo :  dotnet build

Os comandos mais usados da CLI são:

Comando Ação

Cria um novo projeto, arquivo de configuração ou


dotnet new solução basedo em um template específico. (Inicia
um projeto .NET Core)

Usa o NuGet para restaurar dependências, bem


como ferramentas específicas do projeto que são
dotnet restore
especificadas no arquivo de
projeto.  (package.json)

Compila o projeto e suas dependências em um


conjunto de binários. Os binários incluem o código
do projeto em arquivos de linguagem
dotnet build
intermediária (IL) com uma extensão .dll e
arquivos de símbolo usados para depuração com
uma extensão  .pdb.

Permite executar sua aplicação a partir do código


dotnet run
fonte.  (depende do comando dotnet build)

dotnet clear Limpa a saida da compilação anterior.

Referências:  https://docs.microsoft.com/pt-
br/dotnet/articles/core/tools/dotnet
Agora vamos abrir uma janela de prompt de comando ou janela
de console. Se você estiver usando o Windows 10 como eu, uma
maneira de abrir essa janela é :

 Pressione Win+X para abrir o menu contextual e clique na


opção Prompt de Comando ou Prompt de Comando
(Admin).

Com a janela de comandos aberta vamos criar uma pasta onde


será criado o nosso projeto. Para isso execute os seguintes
comandos:

 cd\                                   - para posicionar-se  na pasta


raiz
 md aspncoreAngular2      - para criar a pasta
aspncoreAngular2
 cd aspncoreAngular2       - para posicionar-se na pasta
aspncoreAngular2

Nota: Se você quiser pode digitar o comando  dotnet  para


obter informações da versão instalada ou  dotnet info  para
obter informações sobre o ambiente.

Vamos iniciar instalando os


templates Microsoft.AspNetCore.SpaTemplates digitando na
linha de comando : dotnet new --install
Microsoft.AspNetCore.SpaTemplates::*

Após alguns minutos você deverá obter a seguinte exibição no


console :
Temos aqui exibidos os templates instalados e disponíveis para
criar aplicações com o React, Aurelia, Angular, etc.

Então, com os templates instalados, podemos realmente iniciar


o desenvolvimento da nossa aplicação, escolhendo o template
desejado.

Como já estamos na pasta onde iremos criar o projeto , vamos


escolher o template do Angular  e digitar na linha de
comando: dotnet new angular

Ao final você verá a mensagem indicando que o template "MVC


ASP .NET Core with Angular" foi criado com sucesso.
Digitando o comando dir na janela de comandos podemos ver as
pastas e arquivos criados no diretório do nosso projeto:

Observe as pastas Views, Controllers e a


pasta ClienteApp onde esta a aplicação Angular 2.

Para abrir o projeto no VSCode basta digitar: code . na linha


de comando :
Observe toda a estrutura e arquivos criados a partir do
template escolhido.

Agora para executar a aplicação primeiro vamos restaurar os


pacotes e dependências do projeto digitando na linha de
comando do console : dotnet restore

Ao final da execução você verá este resultado exibido no


console:
Agora basta digitar : dotnet run

Ao final da execução teremos a aplicação iniciada e escutando


na porta indicada : http://localhost:5000

Abrindo o navegador no endereço indicado iremos visualizar :


Dessa forma temos nossa aplicação front-end Angular
2 acessando um  backend  em um projeto ASP .NET Core.

Para abrir o projeto no Visual Studio 2017 Community basta


clicar no arquivo aspncoreAngular2.csproj conforme mostrado
abaixo:
Abaixo vemos o projeto aberto  no VS 2017 Community. Para
executar basta teclar F5 ou CTRL + F5.
E assim você acabou criando uma aplicação ASP .NET Core com
Angular 2 (e com Bootstrap) acessando uma Web API usando
templates fornecidos pelo Nuget sem digitar uma única linha
de código.

Um ponto importante a destacar é que se você estiver usando o


template Angular ou React+Redux, então você terá a pre-
renderização do lado do servidor. Isso faz com que a interface
de usuário inicial do aplicativo apareça muito mais
rapidamente, porque os usuários não precisam esperar que o
navegador baixe, avalie e execute grandes bibliotecas de
JavaScript antes que o aplicativo seja exibido.

Isso funciona executando componentes Angular/React/etc. no


servidor, bem como no cliente. De forma limitada, significa
que a aplicação SPA pode funcionar com JavaScript
desabilitado no navegador, o que é ótimo para garantir que seu
aplicativo seja acessível a todos os rastreadores de mecanismos
de pesquisa.

Outro detalhe importante é que o projeto usa o Webpack como


um sistema de compilação front-end, porque é o sistema
dominante usado pelos
desenvolvedores Angular/React/etc. Uma de suas
características poderosas é a capacidade, durante o
desenvolvimento, de continuar funcionando em segundo plano
e recompilar incrementalmente qualquer código modificado
extremamente rapidamente

E para encerrar temos atuando também o recurso Hot Module


Replacement(HMR) algo como uma substituição de módulo a
quente (HMR) que leva o recurso de middleware de
desenvolvimento um passo adiante. Ele configura um link
direto entre o serviço de middleware do Webpack dev e seu
aplicativo em execução no seu navegador local. Sempre que
seus arquivos de origem mudarem e o middleware do desenv
fornece uma atualização incremental, o HMR o empurra
imediatamente para o seu navegador local.

Ele faz isso sem causar uma recarga de página inteira  (porque
isso pode apagar o estado útil, como qualquer sessão de
depuração em andamento). Assim , ele atualiza diretamente os
módulos afetados no seu aplicativo em execução.
(Disse Jesus) :  Passará o céu e a terra, mas as minhas
palavras não hão de passar. Lucas 21:33  
Referências:
 Seção VB .NET do Site Macoratti.net
 Super DVD .NET - A sua porta de entrada na plataforma .NET
 Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
 Seção C# do site Macoratti.net
 Super DVD C#
 Super DVD Visual Basic
 Curso Básico VB .NET - Vídeo Aulas
 Curso C# Básico - Vídeo Aulas
 .NET - Apresentando o AngularJS - Macoratti.net
 ASP.NET MVC - Usando o AngularJS - I - Macoratti.net
 .NET - Criando um livro de contatos usando o AngularJS
 Compreendendo o Data Binding no AngularJS - Macoratti.net
.NET - Apresentando o AngularJS
http://www.macoratti.net/14/02/net_angjs1.htm

O que é o AngularJS ?

Segundo a Wikipédia "AngularJS é um framework JavaScript open-


source, mantido pelo Google, que auxilia na execução de single-page
applications. Seu objetivo é aumentar aplicativos que podem ser
acessados por um navegador web, sob o padrão model–view–
controller (MVC), em um esforço para facilitar tanto o
desenvolvimento quanto o teste dos aplicativos.

A biblioteca lê o HTML que contém tags especiais e então executa a


diretiva na qual esta tag pertence, e faz a ligação entre a
apresentação e seu modelo, representado por variáveis JavaScript
comuns. O valor dessas variáveis JavaScript podem ser setadas
manualmente, ou via um recurso JSON estático ou dinâmico.

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.

Objetivos:

 Abstrair a manipulação do DOM da lógica do aplicativo. Isto


melhora os testes do código.
 Considera os testes do aplicativo tão importantes quanto seu
desenvolvimento. A dificuldade do teste é diretamente afetada
pela maneira como o código é estruturado.
 Abstrai o acoplamento entre o lado cliente e o lado servidor da
aplicação. Isto permite que o desenvolvimento do aplicativo
evolua em ambos os lados, de forma paralela, e permite o
reuso de código.
 Guia os desenvolvedores através da construção de todo o
aplicativo: desde o design de Interface, passando pela escrita
das regras de negócio, até chegar aos testes da aplicação.

Seus recursos ainda incluem rotas, múltiplas views, AJAX e


serviços REST e a criação de componentes personalizados.

A AngularJS segue o padrão MVC da engenharia de Software e


encoraja o baixo acoplamento entre apresentação, dados e
componentes lógicos. Usando injeção de dependência, AngularJS trás
serviços comumente designados ao lado servidor da aplicação,
como controllers para os componentes visuais, para o lado cliente da
aplicação. Consequentemente, o peso do backend é radicalmente
reduzido, levando à aplicações muito mais leves."

Impressionante não é mesmo ?

Mas como isso funciona ou como faço isso funcionar ?

Se você já trabalhou com outras bibliotecas JavaScripts como o


jQuery vai pegar o logo o jeitão da coisa. (o AngularJS não substitui
o jQuery)

1. Primeiro você terá que indicar na sua página HTML, na seção


<head> a referência a biblioteca AngularJS.
2. Após isso você pode usar diretivas AngularJS, que nada mais são
do que elementos HTML, especificando tags HTML que possuem
um comportamento desejado
3. Ao realizar o parse do seu documento HTML no navegador, o
framework irá procurar tais diretivas transformando-as para
que tenham o comportamento desejado

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)

 ng-app - Declara um elemento como o elemento raiz da


aplicação, ocasionando a mudança do comportamento padrão
da tag;
 ng-bind - Muda o texto de um elemento HTML
automaticamente, de acordo com o seu resultado, vindo das
regras de negócio;
 ng-model - É similar ao ng-bind, mas permite ligação direta
bidirecional (two-way data binding ) entre a view e o escopo
do aplicativo;
 ng-class - Permite atributos de classe serem carregados
dinamicamente;
 ng-controller - Especifica um controller JavaScript para aquele
HTML em questão;
 ng-repeat - Instancia um elemento por item de um array;
 ng-show & ng-hide - Mostra ou esconde um elemento HTML de
acordo com o resultado de uma expressão booleana;
 ng-switch - Instancia um template, em uma lista de escolhas,
dependendo do valor obtido pela expressão;
 ng-view - A diretiva base para manipulação de rotas,
resolvendo um JSON antes de renderizar os modelos acionados
por controladores especificados;
 ng-if - Declaração básica de um 'if' que permite mostrar um
elemento se a condição for verdadeira;

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

O importante ressaltar que o foco do framework AngularJS esta no


HTML.

Onde conseguir o AngularJS ?

No site http://angularjs.org/ você pode baixar e obter mais


informações e exemplos sobre o AngularJS. (A versão atual é a 1.2.6)

Começando pelo começo


Vamos usar o exemplo do site oficial do AngularJS e começar criando
um documento básico que usa os recursos da biblioteca.

Abra o bloco de notas ou outro editor de textos de sua preferência e


digite ou copie código abaixo:

1.<!doctype html>
2.<html ng-app>
3. <head>
4. <script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></scrip
t>
5. </head>
6. <body>
7. <div>
8. <label>Nome:</label>
9. <input type="text" ng-model="SeuNome" placeholder="Informe o seu nome aqui">
10. <hr>
11. <h1>Feliz 2014, {{SeuNome}}!</h1>
12. </div>
13. </body>
14.</html>

Note que estou fazendo uma referência on-line a biblioteca do AngularJs.

Salve o arquivo com o nome: "AngularJS_Exemplo1.html"

A seguir abra o arquivo em um navegador como o IExplorer, FireFox,


Chrome, Opera, etc.

Veja o resultado:

Ao carregarmos esse exemplo no navegador e digitarmos qualquer


coisa no input, o parágrafo será atualizado de forma automática.

A diretiva ng-app declara o elemento raiz do documento indicando


que a partir dai o parse AngularJS irá atuar.

A diretiva ng-model funciona como uma ponte entre a nossa view e o


formulário podendo ser usada em inputs do tipo texto, selects,
textareas, checkboxes e radio buttons. (O model, seus dados e suas
validações ficam disponíveis no escopo da nossa aplicação)

A associação dos dados é feita através da instrução {{ }}, e o nome


definido no escopo (no nosso exemplo, o model SeuNome).

Vejamos agora outro exemplo onde mostramos o recurso data


binding retirado do manual do desenvolvedor no site oficial.
Abra o bloco de notas e digite ou copie o código abaixo:

.<!doctype html>
<html ng-app>
<head>
<script src="http://code.angularjs.org/1.2.6/angular.min.js"></script>
</head>
<body>
<div ng-init="qtde=1;custo=20">
<b>Pedido:</b>
<div>
Quantidade: <input type="number" ng-model="qtde" required >
</div>
<div>
Valor: <input type="number" ng-model="custo" required >
</div>
<div>
<b>Total:</b> {{qtde * custo | currency}}
</div>
</div>
</body>
</html

Salve o arquivo como "AngularJS_Exemplo_2.htm" e a seguir abra-o


em um navegador.

Veja o resultado abaixo:

Olhando o código HTML parece apenas um arquivo normal com umas


tags estranhas. No jargão do AngularJS este arquivo é chamado
de 'template'.

Quando o framework AngularJS inicia o processamento ele realiza


o parse e processa estas novas marcações a partir do template
usando o seu 'compilador'. O DOM carregado, transformado e
renderizado é chamado de 'view'.
As novas marcações que vemos no arquivo HTML são
chamadas diretivas. Elas aplicam um comportamento especial aos
atributos ou elementos no código HTML.

No exemplo estamos usando o atributo ng-app, o qual é vinculado a


um diretiva que inicia automaticamente nossa aplicação.

Temos também a diretiva para o elemento input que adiciona um


comportamento extra ao elemento.O atributo required permite
validar o texto entrado verificando valores vazios.

A diretiva ng-model armazena/atualiza o valor do campo input a


partir de uma variável e exibe o estado da validação do
campo input pela adição de classes css.

Abaixo vemos um esquema do fluxo de funcionamento do data-


binding no AngularJS:

O segundo tipo de marcação usada são as chaves duplas {{ expressão


| filtro }}.

Quando o compilador encontra esta marcação ele irá substituir o


conteúdo pelo valor avaliado da marcação. Uma expressão é um
template parecido com código javascript que permite ler e escrever
variáveis.

Essas variáveis não são globais, da mesma forma que as variáveis


possuem um escopo em uma função javascript, o AngularJS fornece
um 'scope' para as variáveis acessíveis para as expressões.

Os valores que são armazenados em variáveis no escopo são referidas


como o "model" no restante da documentação. No exemplo, a
marcação direciona o AngularJS a "tomar os dados que recebemos
dos inputs de entrada e multiplicá-los ."

O exemplo acima também contém um "filtro". Um filtro formata o


valor de uma expressão para exibição para o usuário. No exemplo
acima, ao filtro currency formata um número em uma saída para a
moeda.

O importante no exemplo é que o AngularJS fornece ligações


dinâmicas. Sempre que os valores de entrada se alterarem o valor
das expressões são automaticamente recalculados e o DOM é
atualizado com os seus valores. Esse conceito é conhecido como two-
way data binding .

Se você deseja se aprofundar no AngularJS sugiro que leia a


documentação do desenvolvedor no site oficial.

Em um outro artigo irei mostrar um CRUD básico para evidenciar os


recursos do data binding no AngularJS.

Um ótimo vídeo sobre o assunto pode ser visto neste


link: screencast.

Mat 7:15 Guardai-vos dos falsos profetas, que vêm a vós disfarçados em


ovelhas, mas interiormente são lobos devoradores.
Mat 7:16 Pelos seus frutos os conhecereis. Colhem-se, porventura, uvas dos
espinheiros, ou figos dos abrolhos?
Mat 7:17 Assim, toda árvore boa produz bons frutos; porém a árvore má
produz frutos maus.
Mat 7:18 Uma árvore boa não pode dar maus frutos; nem uma árvore má
dar frutos bons.
Mat 7:19 Toda árvore que não produz bom fruto é cortada e lançada no
fogo.
Mat 7:20 Portanto, pelos seus frutos os conhecereis.

Referências:

 http://docs.angularjs.org/guide/concepts
 http://docs.angularjs.org/guide/
 http://angularjs.org/
 ASP .NET - Apresentando JQuery - Macoratti.net
 jQuery- Usando jQuery com ASP .NET - Macoratti.net
 jQuery - Conceitos - Macoratti.net
 .NET - Usando BootStrap - pontapé inicial - Macoratti.net
 ASP .NET - BootStrap 3.0 com Web Forms - Macoratti.net
ASP .NET MVC  - Usando o AngularJS
http://www.macoratti.net/15/02/aspn_ajs1.htm

 Neste artigo eu vou mostrar como podemos usar os


recursos do AngularJS em uma aplicação ASP .NET MVC.

Se você não conhece o AngularJS, sugiro que leia o meu


artigo : .NET - Apresentando o AngularJS - Macoratti.net

De maneira bem sucinta, o Angular JS é um framework de


aplicações web de código aberto, mantido pelo Google e a
comunidade, que auxilia na criação de aplicativos de uma única
página(Single Page Application - SPA). Ele suporta o estilo MVC
de design de aplicativos e seu objetivo principal é o
desenvolvimento de aplicações SPA.

O AngularJS possui muitos recursos dentre eles o suporte


o two-way binding, que significa que o seu modelo de dados e
os dados do controle vão estar sincronizados.

Dessa forma a biblioteca AngularJS lê o HTML que contém tags


especiais e então executa a diretiva à qual esta tag pertence, e
faz a ligação entre a apresentação e seu modelo, representado
por variáveis JavaScript comuns.

O valor dessas variáveis JavaScript podem ser definidas


manualmente, ou via um recurso JSON estático ou dinâmico.

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.

Recursos usados:
 Microsoft VIsual Studio 2013 Express for web

 AngularJS

Criando o projeto no Visual Studio 2013 Express


for web
Abra o VS 2013 Express for web e clique em New Project;

Selecione a linguagem Visual Basic ou Visual C# e o template  ASP .NET


Web Application;

Informe o nome AspNet_ExibindoDados_AngularJS ou outro de


sua preferência e clique no botão OK;

A  seguir selecione o template MVC e clique no botão OK:


Vamos agora incluir uma referência ao AngularJS em nosso
projeto usando o Nuget.

Para isso clique no menu TOOLS -> Nuget Package Manager ->


Manage Nuget Package for Solution...

Informe o nome AngularJS na caixa de busca, e, após ser


encontrado selecione e clique no botão Install para o
pacote AngularJS;
Agora abra na janela Solution Explorer abra a
pasta App_Start e a seguir o arquivo BundleConfig.cs e inclua
as linhas de código abaixo neste arquivo:

...
bundles.Add(new ScriptBundle("~/bundles/angular").Include(
"~/Scripts/angular.js",
"~/Scripts/angular-route.js"));
...

Após isso abra o arquivo Layout.cshtml na


pasta Views/Shared e inclua as linhas de código em azul para
dar suporte ao AngularJS:
Observe que incluímos a tag ng-app="MacApp" na tag Body e
que fizemos a referência ao pacote do
angular : @Scripts.Render("~/bundles/angular")

Definimos também no script o arquivo MacApp.js que iremos


criar a seguir.

Clique com botão direito sobre a pasta Scripts e selecione  Add


-> New Item;

Selecione o template JavaScript File e informe o


nome MacApp.js e clique no botão Add;
Defina o seguinte código no arquivo MacApp.js:

(function () {
    //Cria um Module
    // será usado ['ng-Route'] quando implementarmos o roteamento
    var app = angular.module('MacApp', ['ngRoute']);  
    //Cria um Controller
    // aqui $scope é usado para compartilhar dados entre a view e o
controller
    app.controller('HomeController', function ($scope) {
        $scope.Mensagem = "Olá.  Esse é nosso primeiro contato com o
AgularJS no ASP .NEt MVC.";
    });
})();

Neste código eu criei um módulo angular e um controlador com


objeto $scope.

Vejamos o significado das tags do AngularJS usadas:

angular.module: Um módulo Angular é simplesmente uma


coleção de controladores, serviços, filtros, diretivas, etc., que
são inicializados quando o aplicativo é inicializado. Ele é
parecido com a função Main para outras linguagens.

angular.Controller: Contém o login de negócio por trás do


aplicativo como MVC controlador. Os Controladores são o ponto
de entrada em nossa lógica de negócios front-end, que contêm
todos os métodos e variáveis que nossa view usam. Os
Controladores também permitem inicializar o escopo, que vai
abrigar tanto os dados e as funções que nós vamos desejar
executar no modo de exibição.

$scope: Não nada mais que um objeto que permite vincular


a View com o Controller. O scope utiliza a ligação de dados de
duas vias do Angular para vincular os dados do modelo e de
view. Quando o AngularJS inicializar este controlador, ele
automaticamente cria e injeta o objeto $scope para esta
função usando a injeção de dependência.

Agora, como já temos um controlador


chamado HomeController criado na pasta Controllers basta
ajustar a view Index na pasta Views/Home com o código
abaixo:

@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div ng-controller="HomeController">
{{Mensagem}}
</div>
View Index.cshtml

A diretiva ng-controller define qual controlador será usado na


nossa view. Esta diretiva anexa a classe do controlador com a
view. Podemos anexar múltiplos controladores para uma única
view.

Aqui podemos ver que foi especificado a diretiva ng-


controller="HomeController" e isso especifica qual é o escopo
do objeto $scope da aplicação AngularJS.

Executando o projeto iremos obter o seguinte resultado:


Embora seja bem simples essa aplicação foi o nosso primeiro
contato com os recursos do AngularJS em uma aplicação ASP
.NET MVC.

Na continuação irei mostrar como podemos exibir dados obtidos


de um banco de dados relacional em uma aplicação MVC.

Pegue o projeto completo aqui:   AspNet_AngularJS.zip  (sem


as referências)

Disse-lhes, pois, Jesus: Quando levantardes o Filho do


homem, então conhecereis que EU SOU, e que nada faço por
mim mesmo; mas isto falo como meu Pai me ensinou.
E aquele que me enviou está comigo. O Pai não me tem
deixado só, porque eu faço sempre o que lhe agrada.
João 8:28-29
.NET - Criando uma agenda de contatos usando o
AngularJS
http://www.macoratti.net/14/02/ang_crud1.htm

No meu artigo - .NET - Apresentando o AngularJS - apresentei os conceitos


básicos sobre o AngularJS e neste artigo irei mostrar como usar os recursos
do data binding para criar uma agenda de contatos.

Recursos necessários:

1. Framework AngularJS - http://angularjs.org/


2. Navegador padrão - IExplorer, FireFox, Chrome, Opera, etc.

Objetivo:

Criar uma agenda de contatos com nome, email e telefone e realizar


as operações CRUD de manutenção da agenda.

Criando uma agenda de contatos


Crie uma pasta na sua máquina local chamada Agenda_AngularJS e
no seu interior uma subpasta js,

Baixe o arquivo minificado - angular.min - no site oficial e copie-o


para o interior da pasta js.

Vamos começar criando o arquivo HTML. Abra o bloco de notas ou o


seu editor de textos preferidos e digite o código abaixo salvando o
arquivo com o nome "contatos.html"

<!doctype html>
<html ng-app>
<head>
<script src="js/angular.min.js"></script>
<script src="js/func.js"></script>
</head>
<body>
<div ng-controller="ContatoController">
<form>
<table>
<tr>
<td>Nome</td>
<td><input type="text" name="nome" ng-model="novocontato.nome"/></td>
</tr>
<tr>
<td>Email</td>
<td><input type="text" name="email" ng-model="novocontato.email"/></td>
</tr>
<tr>
<td>Fone</td>
<td><input type="text" name="fone" ng-model="novocontato.fone"/></td>
</tr>
<tr>
<td><input type="hidden" ng-model="novocontato.id" /></td>
<td><input type="button" value="Salvar" ng-click="salvaContato()" /></td>
</tr>
</table>
</form>
<table border="1">
<tr>
<th>Nome</th>
<th>Email</th>
<th>Fone</th>
<th>Ação</th>
</tr>
<tr ng-repeat="contato in contatos">
<td>{{ contato.nome }}</td>
<td>{{ contato.email }}</td>
<td>{{ contato.fone }}</td>
<td>
<a href="#" ng-click="edita(contato.id)">edita</a> |
<a href="#" ng-click="deleta(contato.id)">deleta</a>
</td>
</tr>
</table>
</div>
</body>
</html>

Vamos explicar o código:

Declaramos a diretiva <html ng-app> para indicar a raiz a partir de


onde parse AngularJS irá atuar e iniciar a aplicação.

Entre as tags <head> declaramos o arquivo angular.min.js e o


arquivo func.js. O primeiro é a biblioteca javascript AngularJS e o
segundo o arquivo javascript contendo as funções que iremos criar
para realizar o CRUD.
<head>
<script src="js/angular.min.js"></script>
<script src="js/func.js"></script>
</head>
A seguir declaramos a tag ng-controller onde especificamos o
controlador "ContatoController" que será usado para este arquivo
HTML.
<div ng-controller="ContatoController">

Definimos um formulário onde criamos uma tabela contendo as


colunas Nome,Email e Fone.

Definimos 3 input types onde usamos a diretiva ng-model que


permite ligação direta bidirecional (two-way data binding ) entre
a view e o escopo do aplicativo;

Criamos também um campo oculto usando a diretiva ng-model para o


código do contato:

Definimos um button onde diretiva ng-click aciona a


função salvaContato();
<form>
<table>
<tr>
<td>Nome</td>
<td><input type="text" name="nome" ng-model="novocontato.nome"/></td>
</tr>
<tr>
<td>Email</td>
<td><input type="text" name="email" ng-model="novocontato.email"/></td>
</tr>
<tr>
<td>Fone</td>
<td><input type="text" name="fone" ng-model="novocontato.fone"/></td>
</tr>
<tr>
<td><input type="hidden" ng-model="novocontato.id" /></td>
<td><input type="button" value="Salvar" ng-click="salvaContato()" /></td>
</tr>
</table>
</form>

Criamos uma tabela onde iremos exibir os valores para nome, email e
contato e usamos a marcação {{ }} onde os valores serão exibidos
após o parse e a diretiva ng-click para tratar os eventos para editar e
deletar contatos:
<table border="1">
<tr>
<th>Nome</th>
<th>Email</th>
<th>Fone</th>
<th>Ação</th>
</tr>
<tr ng-repeat="contato in contatos">
<td>{{ contato.nome }}</td>
<td>{{ contato.email }}</td>
<td>{{ contato.fone }}</td>
<td>
<a href="#" ng-click="edita(contato.id)">edita</a> |
<a href="#" ng-click="deleta(contato.id)">deleta</a>
</td>
</tr>
</table>

Agora vamos criar o arquivo javascript chamado func.js onde iremos


definir as funções usando os recursos do AngularJS.

Abra o bloco de notas e digite o código abaixo:

var uid = 0;

function ContatoController($scope) {

$scope.contatos = [ ];

$scope.salvaContato = function() {

if($scope.novocontato.id == null) {
//novo contato
$scope.novocontato.id = uid++;
$scope.contatos.push($scope.novocontato);
}
//atualiza um contato existente
else {
for(i in $scope.contatos) {
if($scope.contatos[i].id == $scope.novocontato.id) {
$scope.contatos[i] = $scope.novocontato;
}
}
}
$scope.novocontato = {};//limpa o formulário
}

$scope.deleta = function(id) {

//procurar um contato com o id informado e deleta


for(i in $scope.contatos) {
if($scope.contatos[i].id == id) {
$scope.contatos.splice(i,1);
$scope.novocontato = {};
}
}
}
Abriando a página em um navegador como o Opera teremos o
seguinte resultado:

Vemos as funcionalidades de edição e exclusão implementadas


usando os recursos do data binding do AngularJs.

Pegue os exemplos aqui:   AngularJS_Exemplos.zip

João 3:31 Aquele que vem de cima é sobre todos; aquele que vem da
terra é da terra, e fala da terra. Aquele que vem do céu é sobre todos.
João 3:32 Aquilo que ele tem visto e ouvido, isso testifica; e ninguém
aceita o seu testemunho.
João 3:33 Mas o que aceitar o seu testemunho, esse confirma que Deus
é verdadeiro.
.NET - Compreendendo o Data Binding no
AngularJS
http://www.macoratti.net/15/02/angjs_3.htm

 Neste artigo vamos entender como funciona o data


binding no AngularJS.
   

O AngularJS é um framework de aplicações web de código


aberto. Ele foi originalmente desenvolvido em 2009 por  Misko
Hevery e Adam Abrons. Atualmente é mantido pelo Google.

Dentre os muitos recursos oferecidos pelo AngularJS o data


binding se destaca pela sua importância para o desenvolvedor.

Numa definição bem simplista temos que o Data-Binding é a


sincronização automática de dados entre os modelos e os
componentes da view.

O recurso da vinculação de dados ou data binding do AngularJS


é o recurso mais útil e facilita a vida do desenvolvedor
poupando-o de escrever muito código, e tirando dele a
responsabilidade de manipular manualmente os elementos DOM
e os atributos para refletir as mudanças do modelo.

O AngularJS fornece de duas vias de vinculação de dados para


lidar com a sincronização de dados entre o model e a view.

Assim em aplicativos AngularJS a vinculação de dados é a


sincronização automática de dados entre os componentes
do model e a view. A maneira que o Angular implementa a
vinculação de dados permite tratar o model como a única fonte
real na sua aplicação. A view é uma projeção do modelo em
todos os momentos. Quando o modelo for alterado, a view
reflete a mudança, e vice-versa.

O DataBinding no modelo clássico


A maioria dos sistemas de templates vinculam dados em apenas
uma direção: eles fundem o template e os componentes do
modelo em uma view. Após a fusão ocorrer, mudanças no
modelo ou seções relacionadas da visão NÃO são
automaticamente refletidas na view.

Pior ainda, as alterações que o usuário faz na view não são


refletidas no modelo. Isso significa que o desenvolvedor tem
que escrever código que constantemente sincroniza a view com
o model e o model com a view.

O DataBinding no AngularJS

Os templates do AngularJS funcionam de forma diferente.


Primeiro o modelo (que é o HTML não compilado juntamente
com qualquer marcação ou diretivas adicionais)  é compilado no
browser. A etapa de compilação produz uma view ao vivo.
Quaisquer alterações na view são imediatamente refletidas no
modelo, e quaisquer mudanças no modelo são propagadas para
a view.

O modelo é o a única fonte real para o estado do aplicativo,


simplificando enormemente o modelo de programação para o
desenvolvedor. Você pode pensar na view como simplesmente
uma projeção instantânea de seu modelo.

Como a view é apenas uma projeção do modelo, o controlador


é completamente separado da view e não sabe disso. Isso
facilita os testes unitários, porque é fácil testar o seu
controlador de forma isolada, sem a view e a dependência com
o DOM e o navegador.
(fonte-https://docs.angularjs.org/guide/databinding )

O mecanismo de tratamento da vinculação de dados no


AngularJS funciona com a ajuda de 3 recursos poderosos :

1. $watch - cria um observador para uma variável; Quando


você registra um observador você passa duas funções
como parâmetros para a função $watch() : uma função
e um ouvinte;
2. $digest - percorre todos os observadores em um objeto
$scope e seus objetos filhos;
3. $Apply - Toma uma função como parâmetro a qual é
executada depois que $scope.$digest é chamada
internamente;

Quando você cria uma vinculação de dados a partir de uma


fonte de dados em sua view para uma variável no
objeto $scope, o AngularJS cria um 'observador' internamente. 
Um 'observador' significa que o angularJS acompanha as
mudanças  na variável no objeto $scope. O Framework esta
observando a variável e  observadores são criados usando a
função $scope.$watch().

Em pontos chaves do seu aplicativo o AngularJS chama a


função $scope.$digest, e , esta função itera através de todos
os observadores e verifica se qualquer variável observada
sofreu alguma alteração. Se uma variável observada sofre
alguma mudança a função ouvinte(listener) correspondente é
chamada.
A função ouvinte faz todo o trabalho que precisa ser feito,
como por exemplo; alterar um texto HTML, para refletir o novo
valor da variável observada.

Dessa forma a função $digest() é quem desencadeia a


vinculação de atualizar os dados.

A maior parte do tempo o AngularJs irá chamar as


funções $scope.$watch() e $scope.$digest() para você, mas
em algumas situações você pode ter que chamar você mesmo
essas funções.

A função $scope.$apply é usada para executar um código, e


então chamar a função $scope.digest(), assim todos os
observadores são verificados e as correspondentes funções
ouvintes também são chamadas.

A função $apply é útil quando se integra uma aplicação


AngularJS com outro código.

Exemplo de databinding simples:

Digite o código abaixo em um editor de texto ou editor HTML e


salve com o nome angjs6.html :

<!DOCTYPE html>
<html>
<title>Angular DataBinding usando Diretivas - ng-int e ng-
repeat</title>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.
min.js"></script>
</head>
<body ng-app>
<div ng-init="jogadores = [{nome:'Rooney', pais:'Inglaterra'},
{nome:'Neymar', pais:'Brasil'},
{nome:'Messy', pais:'Argentina'}]">

<p>Nome : <input type="text" ng-model="nome"> {{nome}}</p>

<ul>
<li ng-repeat="jogador in jogadores">
[{{$index}}] {{jogador.nome}} : {{jogador.pais}}
</li>
</ul>
</div>
</body>
</html>

Abrindo o arquivo angjs6.html em um navegador iremos obter


o seguinte resultado:

Neste exemplo a diretiva ng-init é usada para inicializar um


array de objetos chamado jogadores.

A diretiva ng-repeat percorre esta coleção e para cada


instância a variável jogador e atribuída com o item atual da
coleção e este é exibido usando a expressão de
vinculação {{jogador.nome}} e {{jogador.pais}}.

Também esta sendo exibido o índice de cada item usando a


propriedade $index que é definida para o item atual.

Ao digitar um valor na caixa de texto o modelo   ng-


model="nome"  e a expressão de vinculação {{nome}} permitem exibir
o nome digitado.

Esse é o mecanismo do data binding no AngularJS.

Aguarde mais artigos sobre AngularJS em breve.

Porque também nós éramos noutro tempo insensatos,


desobedientes, extraviados, servindo a várias
concupiscências e deleites, vivendo em malícia e inveja,
odiosos, odiando-nos uns aos outros.
Mas quando apareceu a benignidade e amor de Deus, nosso
Salvador, para com os homens,
Não pelas obras de justiça que houvéssemos feito, mas
segundo a sua misericórdia, nos salvou pela lavagem da
regeneração e da renovação do Espírito Santo,
Que abundantemente ele derramou sobre nós por Jesus
Cristo nosso Salvador;
Para que, sendo justificados pela sua graça, sejamos feitos
herdeiros segundo a esperança da vida eterna.
Tito 3:3-7
ASP .NET MVC 5 - Criando uma aplicação com
AngularJS e Web API – I  

http://www.macoratti.net/16/03/mvc_angapi1.htm

  Neste
artigo eu
vou
mostrar
como criar
uma
aplicação
web
usando os
recursos
da ASP
.NET MVC
5, do
AngularJS
e da Web
API.

Neste artigo vou iniciar a construção de uma aplicação


web ASP .NET MVC 5 usando os recursos do AngularJS e
da Web API.

Vamos criar uma loja virtual onde teremos o login do usuário, o


catálogo de produtos, a manutenção dos produtos e as
operações básicas de seleção e compra de produtos.

Vou começar apresentando a arquitetura da aplicação e a seguir


apresentar os conceitos básicos sobre as
tecnologias AngularJS e Web API que iremos usar em nosso
projeto.

Apresentando a arquitetura do projeto web


O diagrama a seguir dá uma visão geral da arquitetura da nossa
aplicação web ASP .NET MVC 5
No lado do servidor vamos trabalhar com ASP .NET MVC e Web
API (Restfull) e do lado do cliente vamos trabalhar
com AngularJS.
 
AngularJS - Conceitos
O  "AngularJS é um framework JavaScript open-source, mantido
pelo Google, que auxilia na execução de Single Page
Applications. Seu objetivo é aumentar aplicativos que podem
ser acessados por um navegador web, sob o padrão model–
view–controller (MVC), em um esforço para facilitar tanto o
desenvolvimento quanto o teste dos aplicativos.

A biblioteca lê o HTML que contém tags especiais e então


executa a diretiva na qual esta tag pertence, e faz a ligação entre
a apresentação e seu modelo, representado por variáveis
JavaScript comuns. O valor dessas variáveis JavaScript podem ser
definidas manualmente, ou via um recurso JSON estático ou
dinâmico.

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.

Um dos recursos mais importantes do AngularJS é


o DataBindig que reflete a sincronização de dados entre a view
e o model; se a view mudar o model também muda e vice-versa.
Este processo é assegurado pela utilização do
objeto $scope conforme vemos no diagrama a seguir:

O AngularJS pode ser obtido do site https://angularjs.org/  . No


site você também vai encontrar recursos de aprendizagem,
cursos, a referência para a API e outros recursos.

Para usar o AngularJS podemos fazer a referência local em nosso


projeto via Nuget ou usar a distribuição CDN.

Web API - Conceitos


O protocolo HTTP não precisa ser usado apenas para servir
páginas. É também uma plataforma poderosa para a construção
de APIs que expõem serviços e dados. O HTTP é simples, flexível
e onipresente. Praticamente qualquer plataforma que você pode
pensar tem uma biblioteca HTTP, então os serviços HTTP podem
atingir uma ampla gama de clientes, incluindo navegadores,
dispositivos móveis e aplicações desktop tradicionais.

Uma Web API pode ser vista como um conjunto de serviços


expostos via web com o objetivo de integrar sua aplicação a
diversos tipos de clientes que queiram usar os serviços. Esses
serviços são usados como requisições HTTP e retornam uma
resposta em um formato específico como XML, REST, etc.

Essa resposta pode ser uma informação de  um repositório de


dados, o retorno de uma operação, etc. O cliente pode ser uma
página web, uma aplicação desktop, uma aplicação mobile, etc.
Como exemplos de Web API podemos citar as Web APIs do
Facebook e Twitter.

A ASP.NET Web API é um framework para a construção de web


APIs em cima do .NET Framework permitindo que sua aplicação
seja acessada por diversos clientes em diversas plataformas.

Para saber mais sobre AngularJS e Web API consulte as


referências no final do artigo.

Recursos usados:

 Visual Studio Community 2015

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


equivalente a versão Professional.

Criando o projeto no VS Community


Abra o VS Community 2015 e clique em New Project;

Selecione a linguagem Visual C# e o template ASP .NET Web


Application;

Informe o nome Mvc_LojaVirtual ou outro de sua preferência e


clique no botão OK;
A  seguir selecione o template MVC e marque a opção Web
API e clique no botão OK:
Para obter a AngularJS podemos usar o Nuget para incluir as
referências às biblioteca AngularJS.

Isso é feito no menu TOOLS e em Nuget Package Manager e


selecione Manage Nuget Package for Solutions.

Na janela do assistente selecione a guia Online e


informe AngularJS para localizar o pacote;

Selecione o pacote Angularjs e clique no botão Install para


instalar a biblioteca no projeto:
Podemos também usar usar a distribuição CDN que é
referenciada diretamente na página ASP .NET.

A url da distribuição CDN pode ser obtida no


site https://angularjs.org/  e é a
seguinte : https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0-
rc.0/angular.min.js

Dessa forma temos a estrutura do nosso projeto criado e pronto


para que possamos incluir os recursos que precisamos para
nossa loja Virtual.
A próxima parte do artigo  vamos definir o nosso modelo de
dados e criar o banco de dados, as tabelas, as stored procedures
que vamos usar.

E esta é a mensagem que dele (Jesus) ouvimos, e vos anunciamos:


que Deus é luz, e não há nele trevas nenhumas.
Se dissermos que temos comunhão com ele, e andarmos em
trevas, mentimos, e não praticamos a verdade.
1 João 1:5,6
ASP .NET MVC 5 - Criando uma aplicação com
AngularJS e Web API – II  

http://www.macoratti.net/16/03/mvc_angapi2.htm

  Neste
artigo eu
vou
mostrar
como
criar uma
aplicação
web
usando
os
recursos
da ASP .
NET
MVC 5,
do
AngularJ
S e da
Web
API.

Na primeira parte do artigo  apresentamos o nosso projeto,


alguns conceitos sobre AngularJS e Web API e criamos o projeto
referenciando o AngularJS via Nuget.

Neste artigo vamos definir o nosso modelo de dados e iniciar a


implementação usando o SQL Server e o Entity Framework.

Definindo o modelo de dados


Vamos adotar um modelo de dados bem simples para não
complicar muito o nosso projeto.
 
Supondo que nossa loja virtual também será um modelo
simplificado de uma loja virtual real podemos assumir que
teremos dois atores atuando em nossa aplicação :
 Consumidor : Após ser registrado, este ator poderá
acessar o catálogo de produtos, escolher produtos,
adicionar produtos no carrinho de compras, enviar
comandos e exibir o seu status;
 Administrador : Será o responsável por administrar as
tabelas de produtos e do movimento gerenciando os
produtos e o movimento;
Com base nessas afirmações podemos definir o seguinte modelo
de dados para o nosso projeto:
 

onde a estrutura de cada tabela pode ser vista a seguir:


 

Os campos MovimentoId e ProdutoId, além de chaves


primárias, são do tipo Identity e são gerenciados
pelo SGBD como campo autonumeração.

Criando um modelo de entidades com o Entity


Framework
Vamos agora criar um modelo de entidades usando o Entity
Framework.

Clique com o botão direito do mouse sobre a pasta Models e a


seguir em Add -> New Item;

Selecione a guia Data e clique em ADO .NET Entity Data


Model, informe o nome LojaVirtual e clique no botão Add;

A seguir selecione a opção EF Designer from database e clique


em Next>:

Para selecionar o banco de dados LojaVirtual.mdf que criamos


clique em New Connection;

Selecione o servidor SQL Server e o banco de dados e clique no


botão OK;
Confirme a conexão criada e salve a string de conexão no
arquivo web.config clicando em Next>:
Selecione as tabelas Movimento, Produtos e Usuarios e
marque as opções conforme a figura abaixo clicando em Finish:
Ao final teremos o nosso modelo de entidades mapeado para as
tabelas gerado conforme a figura a seguir:
A próxima parte do artigo vamos definir e iniciar a
implementação dos serviços que atuarão entre o Cliente e
o modelo de dados.

(Disse Jesus aos seus discípulos) : "Se vós fôsseis do mundo,


o mundo amaria o que era seu, mas porque não sois do
mundo, antes eu vos escolhi do mundo, por isso é que o
mundo vos odeia."
João 15:19
ASP.NET Core -  Inicialização da aplicação
(Startup)
http://www.macoratti.net/19/07/aspnc_start1.htm

Neste artigo veremos o processo de inicialização das aplicações


ASP .NET Core analisando os arquivos Startup.cs e Program.cs.

Todas as aplicações ASP .NET Core são aplicações console , e,


os outros tipos de aplicações como MVC, SPA, etc, são
construidas sobre a aplicação Console.

Examinando a classe Program


A aplicação console inicia com a execução do
arquivo Program.cs, que precisa conter o método
estático Main que é chamado sempre que a aplicação for
iniciada.

Vamos criar  uma aplicação ASP .NET Core Web


Application usando o template Empty e a seguir abrir o projeto
no VS 2017 Community 2017 exibindo o contéudo do
arquivo Program.cs.

Observe o código do método Main() : Este é o ponto de entrada


da nossa aplicação.

O método Main cria um Host, faz o Building e o executa, e, o


Host então passa a atender requisições HTTP.
O método estático CreateWebHostBuilder configura e cria o
Host, retornando uma referência ao Host.

A sintaxe usada neste método é chamada de 'expression bodied


function member'.

As tarefas realizadas por este método são:

 Configura o Kestrel como o servidor da web.


 Define a raiz do conteúdo como
Directory.GetCurrentDirectory.
 Carrega configuração opcional a partir de
o Appsettings.json.
o Appsettings.{Environment}.json.
o User Secrets quando o aplicativo é executado no
ambiente de desenvolvimento.
o Variáveis ambientais
o Argumentos da linha de comando.
 Ativa o log
 Integra a execução do Kestrel com o IIS

Você pode ver detalhes do código espiando o código fonte da


ASP .NET Core neste
link: https://github.com/aspnet/AspNetCore

Examinando a classe Startup


Analisando o código do arquivo Program notamos que no
método estático CreateaWebHostBuilder ele chama o
método Startup.

O método UseStartup informa ao host onde procurar pela classe


Startup. O host, então, espera que a classe de inicialização
defina o método de serviços Configure e ConfigureServices.

A classe Startup é uma classe simples que não herda de


ninguem e nem implementa nenhuma interface.

Ela tem duas funções principais.

1. Configurar o pipeline de requisições que lida com todas as


requisições feitas ao aplicativo;
2. Configurar os serviços para injeção de dependência;

Para realizar essas tarefas ela usa os


métodos ConfigureServices() e Configure().

O método ConfigureServices
O método ConfigureServices nos permite adicionar ou registrar
serviços no Aplicativo. As outras partes do nosso aplicativo
podem solicitar esses serviços via injeção de dependência.

A injeção de dependência é um dos novos recursos do ASP.NET


Core. O ASP.NET Core usa a injeção de dependência
extensivamente.
public void ConfigureServices (serviços IServiceCollection)
{
    
}

O método ConfigureServices espera a instância de serviços (do


tipo IServiceCollection) que é injetada no ConfigureServices via
Injeção de Dependência.

O método Configure
O método Configure nos permite configurar o pipeline de
requisição HTTP que especifica como o aplicativo deve
responder a solicitações HTTP.

Os componentes que compõem o pipeline de solicitação são


chamados de middleware.

public void Configure(IApplicationBuilder app, IHostingEnvironment


env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}

O método configure solicita uma instância


de IApplicationBuilder e HostingEnvironment. Estes são
injetados no Configure pelo Injector de Dependência nativo.

Nós, então, adicionamos nossos componentes de middleware à


instância da IApplicationBuilder(app).

A seguir verificamos se estamos em ambiente de


desenvolvimento, se sim, registramos o
Middleware DeveloperExceptionPage usando o método de
extensão UseDeveloperExceptionPage.

Em seguida, usamos o método Run do aplicativo para registrar


o segundo middleware. Este middleware escreve 'Hello
World' para o objeto Response.
Assim a ASP .NET Core é totalmente modular e inicia o pipeline
vazio, que você vai preenchendo conforme a necessidade de
serviços da sua aplicação. Isso faz com que as aplicações
ASP .NET Core tenham um ótimo desempenho.

Na próxima parte do artigo  vamos tratar do servidor Kestrel.

"Quão amáveis são os teus tabernáculos, SENHOR dos Exércitos!


A minha alma está desejosa, e desfalece pelos átrios do
Senhor; o meu coração e a minha carne clamam pelo Deus
vivo."
Salmos 84:1-2

ASP.NET Core -  O servidor web Kestrel


http://www.macoratti.net/19/07/aspnc_start2.htm
Neste artigo veremos o Web Server Kestrel e sua atuação na ASP
.NET Core.

A forma como hospedamos nosso aplicativo na ASP.NET Core


passou por algumas mudanças drásticas em comparação com a
versão anterior da ASP.NET. (Veja a primeira parte do artigo )

O Kestrel é a nova maneira de hospedar as aplicações


na ASP.NET Core Application. Ele é executado dentro do
processo do aplicativo, tornando-o completamente autocontido
(self-contained).

O que é o Kestrel
O Kestrel é um servidor HTTP baseado em E/S assíncrona, em
eventos, de código aberto e multiplataforma. Ele foi
desenvolvido para hospedar aplicações ASP.NET Core em
qualquer plataforma, e, está incluído por padrão nas aplicações
ASP.NET Core.

Ele é baseado no libuv  sendo de código aberto e esta diponível


no GitHub .

O Kestrel dá suporte aos seguintes cenários:

 HTTPS
 Atualização do Opaque usado para habilitar o WebSockets
 Soquetes do UNIX para alto desempenho protegidos pelo
Nginx
 HTTP/2 (exceto em macOS†)

Porque usar o Kestrel ?


Os aplicativos ASP.NET mais antigos são fortemente acoplados
ao IIS - Information Internet Service.

O IIS é um servidor da Web completo com todos os recursos que


você precisa de um servidor da Web. Ao longo do tempo ele se
tornou um servidor web maduro e estável, e, adicionou muitos
recurso o que o tornou pesado. Tornou-se um dos melhores
servidores da Web e, ao mesmo tempo, é um dos mais lentos.

Assim, as aplicações ASP.NET estavam fortemente acopladas


com o IIS e carregava o peso do IIS.

Com a ASP .NET Core isso mudou.

As aplicações ASP.NET Core agora estão completamente


desacopladas do IIS. Esse desacoplamento faz com que o
ASP.NET Core seja executado em qualquer
plataforma :  Windows, Mac ou Linux.

Ocorre que as aplicações ASP .NET Core ainda precisam ter a


capacidade de ouvir e atender solicitações HTTP e enviar a
resposta de volta para o cliente. É aí que entra Kestrel.

Usando o Kestrel
O servidor Kestrel é executado in-process no ASP .NET Core
Applications. Portanto, ele é executado independentemente do
ambiente no qual reside; ele esta disponível no
namespace Microsoft.AspNetCore.Server.Kestrel.

Vamos dar uma espiada nas classes Program e Startup de uma


aplicação ASP .NET Core criada com o template Empty, ou se
uma aplicação vazia. (veja o artigo anterior )

A classe Program contém o método Main estático, que é o


ponto de entrada para o nosso aplicativo.
O método Main chama CreateDefaultBuilder, responsável por
criar o host do aplicativo da web.

O CreateDefaultBuilder é um método auxiliar e chama o


método UseKestrel para registrar o Kestrel como o servidor que
será usado para hospedar nosso aplicativo.(veja o código
fonte: aqui  )

Existem duas maneiras de usar o Kestrel :

1. Self-Hosting (Autocontido)
2. Atrás de outro Web Server

1- Usando o Kestrel no modo Self-Hosting


No modo Self-Hosting as aplicações ASP.NET Core ouvem
diretamente as solicitações HTTP da Internet, conforme
mostrado na imagem abaixo:
2- Usando o Kestrel atrás de outro servidor
O Kestrel não é um servidor Web completo, e, por isso mesmo
ele é mais rápido.

Acontece que não é aconselhável executar o Kestrel como um


servidor da Web independente no ambiente de produção.
Recomenda-se executá-lo por trás de um servidor da Web
completo como IIS, Nginx, apache etc. Nesse cenário, o
servidor da Web atua como um servidor proxy reverso.

O servidor proxy reverso recebe a requisição HTTP da Internet


e a transmite para o servidor do Kestrel exatamente como é
recebido.

O IIS pode receber a requisição HTTP e executar algum


processamento útil, como registro em log, solicitação de
filtragem, reescrita de URL antes de passar a requisição para o
kestrel.

O diagrama a seguir mostra como é isso é implementado:


 

Existem muitas razões pelas quais você deve usar este


modelo  na produção:

1. Segurança
2. Poder limitar sua área de superfície exposta. Ele fornece
uma camada adicional opcional de configuração e defesa;
3. Simplificar o balanceamento de carga;
4. Configuração SSL;
5. Apenas seu servidor proxy reverso requer um certificado
SSL e esse servidor pode se comunicar com seus servidores
de aplicativos na rede interna usando HTTP simples;
6. Compartilhar IP Único com vários Endereços;
7. Solicitação de Filtragem, registro em log e URLs, etc.;
8. Poder garantir que o aplicativo seja reiniciado se houver
falhas;

O método CreateDefaultBuilder chama o UseIISIntegration, que


informa ao ASP.NET que o aplicativo usará o IIS como um proxy
reverso na frente do Kestrel.

Alternativas para Kestrel


O Kestrel não é a única maneira de hospedar aplicativos
ASP.NET Core. Há outra implementação de servidor Web
disponível no Windows conhecida como HTTP.SYS
O HTTP.sys é um servidor HTTP que roda somente do
Windows  com base no driver de kernel Http.Sys.

Quando usar o HTTP.sys ?

1 - Quando você precisar expor o servidor diretamente na


Internet sem usar o IIS;
2 - Uma implantação interna requer um recurso não disponível
no Kestrel, como a autenticação Windows.

O HTTP.sys é uma tecnologia madura que protege contra


muitos tipos de ataques e fornece a robustez, a segurança e a
escalabilidade de um servidor Web completo. O próprio IIS é
executado como um ouvinte HTTP em cima do HTTP.sys.

Temos assim um panorama da atuação do Kestrel e sua


importância na ASP .NET Core.

"Bom é louvar ao SENHOR, e cantar louvores ao teu nome, ó


Altíssimo;
Para de manhã anunciar a tua benignidade, e todas as noites a
tua fidelidade;"
Salmos 92:1,2
ASP .NET Core - Gerenciador de Despesas Pessoais com Gráfico (EF
Core) – I

http://www.macoratti.net/18/08/aspn_gfcg1.htm

 Hoje vamos criar uma aplicação ASP .NET Core para fazer o
gerenciamento de despesas pessoais e exibir um gráfico das
despesas usando os recursos do Entity Framework Core 2.0 .

    

Este é um artigo essencialmente prático onde vamos criar um


gerenciador de despesas pessoais usando o ASP.NET Core 2.1 e
a abordagem Code-First do Entity Framework Core. Criaremos
um gerenciador de despesas que rastreia suas despesas diárias e
fornece gráficos comparativos para mostrar um resumo de
despesas por período.

Vamos usar uma caixa de diálogo modal para manipular as


entradas do usuário e para mostrar o gráfico de resumo de
despesas mensal e semanal usando os recursos do Highcharts,
portanto, esse aplicativo será um Singe Page
Application ou Aplicativo de Página Única (SPA).

Veja abaixo a aplicação funcionando:


Os pré-requisitos necessários são:

 Instalar o   .NET Core 2.1 SDK


 Instalar a última versão do Visual Studio 2017 (15.7)
 SQL Server 2012 ou superior

Agora mãos à obra...

Criando o projeto ASP .NET Core no VS 2017


Após esse procedimento abra o VS 2017 Community e
selecione File ->New Project;

Selecione .NET Core e o template ASP .NET Core Web


Application e informe o nome MinhasFinancas e clique em OK;

Na próxima janela selecione ASP .NET Core 2.1 e o


template Web Application (Model-View-Controller) e clique
em OK:
 

Vamos agora incluir uma referência ao


pacote Microsoft.EntityFrameworkCore.Tools para poder ter
acesso aos recursos do Migrations para poder criar a tabela e o
banco de dados usados no projeto.

Como vamos usar a abordagem Code-First do EF Core vamos


precisar do Migrations.

No menu acesse Manage Nuget Packages for Solution e clique


na guia Browse;

A seguir selecione o pacote indicado , marque todos os projetos


e clique em Install:
Os pacotes para acessar o banco de dados SQL Server e o pacote
do Entity Framework Core já estão referenciados por padrão no
projeto.

Adicionando o modelo de domínio e a classe de contexto na


Aplicação

Clique com o botão direito do mouse sobre a pasta Models do


projeto e a seguir crie uma classe
chamada RelatorioDespesa com o código abaixo:
Esta classe contém as propriedades do nosso modelo de
domínio.

Observe que estou usando os recursos do Data Annotations


aplicando diversos atributos para configurar as propriedades
para gerar as colunas da tabela no banco de dados conforme
desejamos.

A seguir vamos criar a classe de contexto na pasta Models com


o nome de AppDbContext com o código abaixo:
A classe de contexto herda de DbContext e define uma
propriedade DbSet<> que mapeia a nossa entidade para a
tabela RelatorioDespesas e definimos uma instância
de DbContextOptions que vamos configurar no arquivo Startup
no método ConfigureServices onde vamos definir o provedor
do banco de dados e a string de conexão usada.

Abrindo a classe Startup definimos no
método ConfigureServices o código conforme mostrado abaixo
para registrar o nosso contexto como um serviço :

A string de conexão será obtida do arquivo appsettings.json cujo


código é visto a seguir:
Na string de conexão definimos o servidor SQL Server usado e o
nome do banco de dados: Financas

Criando o banco de dados e a tabela

Ja podemos usar os recursos do Migrations para criar o banco


de dados e a tabela.

Abra uma janela do Package Manager Console e digite o


comando : add-migration InicialDepesas

Esse comando irá criar o script de migração.

Para aplicar o script digite o comando : update-database

Esses comandos irão criar a pasta Migrations no projeto e os


arquivos de script e o
arquivo AppDbContextModelSnapshot.cs que armazena
informações sobre as migrações aplicadas.
Abrindo o SQL Server Management Studio podemos verificar a
criação do banco de dados Financas e da
tabela RelatorioDespesas com a estrutura desejada:

Criando a camada de acesso a dados da aplicação

Clique com o botão direito do mouse sobre o projeto e a seguir


selecione Add->New Folder e informe o nome DAL.
A seguir vamos incluir nesta classe a interface IFinancasDAL e a
sua implementação, a classe FinancasDAL que será a nossa
camada de acesso a dados. Poderiamos acessar os dados
diretamente do controlador via EF Core mas vamos criar uma
camada de acesso a dados para desacoplar nosso código do EF
Core.

Abaixo temos o código da interface IFinancasDAL contendo


todos os métodos que precisamos para gerenciar as despesas :

Agora crie a classe FinancasDAL que implementa a


interface IFinancasDAL com o código abaixo:

using Microsoft.EntityFrameworkCore;
using MinhasFinancas.Models;
using System;
using System.Collections.Generic;
using System.Linq;
namespace MinhasFinancas.DAL
{
public class FinancasDAL : IFinancasDAL
{
public FinancasDAL() { }
private readonly AppDbContext db;
public FinancasDAL(AppDbContext context)
{
db = context;
}
public IEnumerable<RelatorioDespesa> GetAllDespesas()
{
try
{
return db.RelatorioDespesas.ToList();
}
catch { throw; }
}
// Filtra os registros com base na string de busca
public IEnumerable<RelatorioDespesa> GetFiltraDespesa(string criterio)
{
List<RelatorioDespesa> desp = new List<RelatorioDespesa>();
try
{
desp = GetAllDespesas().ToList();
return desp.Where(x => x.ItemNome.IndexOf(criterio,
StringComparison.OrdinalIgnoreCase) != -1);
}
catch{ throw; }
}
//Adicionar uma nova despesas
public void AddDespesa(RelatorioDespesa despesa)
{
try
{
db.RelatorioDespesas.Add(despesa);
db.SaveChanges();
}
catch{ throw; }
}
//atualizar uma despesa
public int UpdateDespesa(RelatorioDespesa despesa)
{
try
{
db.Entry(despesa).State = EntityState.Modified;
db.SaveChanges();
return 1;
}
catch { throw; }
}
//Obter uma despesa pelo seu id
public RelatorioDespesa GetDespesa(int id)
{
try
{
RelatorioDespesa despesa = db.RelatorioDespesas.Find(id);
return despesa;
}
catch{ throw; }
}
//Deletar uma despesa
public void DeleteDespesa(int id)
{
try
{
RelatorioDespesa desp = db.RelatorioDespesas.Find(id);
db.RelatorioDespesas.Remove(desp);
db.SaveChanges();
}
catch{ throw; }
}
//Calcula despesa semestral
public Dictionary<string, decimal> CalculaDespesaPeriodo(int periodo)
{
Dictionary<string, decimal> SomaDespesasPeriodo = new Dictionary<string,
decimal>();
decimal despAlimentacao = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Alimentacao" && (cat.DataDespesa
>
DateTime.Now.AddMonths(-periodo)))
.Select(cat => cat.Valor)
.Sum();
decimal despCompras = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Compras" && (cat.DataDespesa >
DateTime.Now.AddMonths(-periodo)))
.Select(cat => cat.Valor)
.Sum();
decimal despTransporte = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Transporte" && (cat.DataDespesa >
DateTime.Now.AddMonths(-periodo)))
.Select(cat => cat.Valor)
.Sum();
decimal despSaude = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Saude" && (cat.DataDespesa >
DateTime.Now.AddMonths(-periodo)))
.Select(cat => cat.Valor)
.Sum();
decimal despMoradia = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Moradia" && (cat.DataDespesa >
DateTime.Now.AddMonths(-periodo)))
.Select(cat => cat.Valor)
.Sum();
decimal despLazer = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Lazer" && (cat.DataDespesa >
DateTime.Now.AddMonths(-periodo)))
.Select(cat => cat.Valor)
.Sum();
SomaDespesasPeriodo.Add("Alimentacao", despAlimentacao);
SomaDespesasPeriodo.Add("Compras", despCompras);
SomaDespesasPeriodo.Add("Transporte", despTransporte);
SomaDespesasPeriodo.Add("Saude", despSaude);
SomaDespesasPeriodo.Add("Moradia", despMoradia);
SomaDespesasPeriodo.Add("Lazer", despLazer);

return SomaDespesasPeriodo;
}
//Calcula despesa mensal
public Dictionary<string, decimal> CalculaDespesaPeriodoSemanal(int
periodo)
{
Dictionary<string, decimal> SomaDespesasPeriodoSemanal = new
Dictionary<string, decimal>();
decimal despAlimentacao = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Alimentacao" && (cat.DataDespesa
>
DateTime.Now.AddDays(-periodo)))
.Select(cat => cat.Valor)
.Sum();
decimal despCompras = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Compras" && (cat.DataDespesa >
DateTime.Now.AddDays(-periodo)))
.Select(cat => cat.Valor)
.Sum();
decimal despTransporte = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Transporte" && (cat.DataDespesa >
DateTime.Now.AddDays(-periodo)))
.Select(cat => cat.Valor)
.Sum();
decimal despSaude = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Saude" && (cat.DataDespesa >
DateTime.Now.AddDays(-periodo)))
.Select(cat => cat.Valor)
.Sum();
decimal despMoradia = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Moradia" && (cat.DataDespesa >
DateTime.Now.AddDays(-periodo)))
.Select(cat => cat.Valor)
.Sum();
decimal despLazer = db.RelatorioDespesas.Where
(cat => cat.Categoria == "Lazer" && (cat.DataDespesa >
DateTime.Now.AddDays(-periodo)))
.Select(cat => cat.Valor)
.Sum();
SomaDespesasPeriodoSemanal.Add("Alimentacao", despAlimentacao);
SomaDespesasPeriodoSemanal.Add("Compras", despCompras);
SomaDespesasPeriodoSemanal.Add("Transporte", despTransporte);
SomaDespesasPeriodoSemanal.Add("Saude", despSaude);
SomaDespesasPeriodoSemanal.Add("Moradia", despMoradia);
SomaDespesasPeriodoSemanal.Add("Lazer", despLazer);
return SomaDespesasPeriodoSemanal;
}
}
}
Nesta classe temos os métodos para realizar as operações CRUD
via Entity Framework Core onde usamos a injeção de
dependência para obter uma instância da classe de contexto.

Vamos a seguir criar o nosso controlador para acessar os


métodos da nossa camada de acesso a dados e gerenciar as
informações das despesas.

Usando a injeção de dependência nativa

A idéia da Injeção de Dependência é que, quando uma classe for


criada, ela deve ter suas classes dependentes injetadas ao invés
de criar essas classes. Isto proporciona uma situação na qual
obtemos um fraco acoplamento e uma alta coesão.

Vamos usar esse recurso registrando a nossa


interface IFinancasDAL e a classe concreta FinancasDAL como
um serviço no método ConfigureServices da classe Startup:

No nosso exemplo usamos o tempo de vida Transient e


informando que quando tivermos uma referência a uma
instância da interface queremos que seja injetado a instância da
classe concreta.

Criando a Web API : Incluindo o Controller


ClienteController
Clique com o botão direito sobre a pasta Controllers e
selecione Add -> New Item;
A seguir selecione o template Web-> API Controller Class e
informe o nome DespesaController:

Inclua o código abaixo no


controlador DespesaController gerado:

using Microsoft.AspNetCore.Mvc;
using MinhasFinancas.DAL;
using MinhasFinancas.Models;
using System;
using System.Collections.Generic;
using System.Linq;
namespace MinhasFinancas.Controllers
{
public class DespesaController : Controller
{
private readonly IFinancasDAL _dal;
public DespesaController(IFinancasDAL dal)
{
_dal = dal;
}
// GET: Despesas
public IActionResult Index(string criterio)
{
var lstDespesas = _dal.GetAllDespesas().ToList();
if (!String.IsNullOrEmpty(criterio))
{
lstDespesas = _dal.GetFiltraDespesa(criterio).ToList();
}
return View(lstDespesas);
}
public ActionResult AddEditDespesa(int itemId)
{
RelatorioDespesa model = new RelatorioDespesa();
if (itemId > 0)
{
model = _dal.GetDespesa(itemId);
}
return PartialView("_despesaForm", model);
}
[HttpPost]
public ActionResult Create(RelatorioDespesa novaDespesa)
{
if (ModelState.IsValid)
{
if (novaDespesa.ItemId > 0)
{
_dal.UpdateDespesa(novaDespesa);
}
else
{
_dal.AddDespesa(novaDespesa);
}
}
return RedirectToAction("Index");
}
[HttpPost]
public IActionResult Delete(int id)
{
_dal.DeleteDespesa(id);
return RedirectToAction("Index");
}
public ActionResult DespesaResumo()
{
return PartialView ("_despesaReport");
}
public JsonResult GetDepesaPorPeriodo()
{
Dictionary<string, decimal> despesaPeriodo =
_dal.CalculaDespesaPeriodo(7);
return new JsonResult(despesaPeriodo);
}
public JsonResult GetDepesaPorPeriodoSemanal()
{
Dictionary<string, decimal> despesaPeriodoSemanal =
_dal.CalculaDespesaPeriodoSemanal(7);
return new JsonResult(despesaPeriodoSemanal);
}
}
}

Neste código temos uma instância private readonly de nossa


interface IFinancasDAL, e, o construtor toma uma instância
de IFinancasDAL e define nossa instância particular para a
instância passada.  Esta é a injeção de dependência via
construtor em ação.

Neste momento a estrutura da nossa solução pode ser vista a


seguir:

A lógica do nosso backend esta pronta. Vamos agora definir o


código do lado do cliente.
Na próxima  parte do artigo  vamos definir as views que irão
exibir as informações e interagir com o usuário.

"Vinde a mim, todos os que estais cansados e oprimidos, e eu


vos aliviarei."(disse Jesus)
Mateus 11:28
ASP .NET Core - Gerenciador de Despesas Pessoais com Gráfico (EF
Core) – II

http://www.macoratti.net/18/08/aspn_gfcg2.htm

 Hoje vamos criar uma aplicação ASP .NET Core para fazer o
gerenciamento de despesas pessoais e exibir um gráfico das
despesas usando os recursos do Entity Framework Core 2.0 .    

Continuando a primeira parte do artigo  vamos definir a


interface com o usuário representada pelas Views que irão
exibir as informações e interagir com o usuário.

Vamos criar 3 Views em uma pasta Despesa da aplicação :

1. Index.cshtml
Esta view vai exibir todos os dados das despesas e contém
uma caixa de busca para um item particular e os botões
para Editar e Excluir uma despesa.

 
2. _despesaForm.cshtml
Esta é uma partial view que contém o formulário para
tratar a entrada do usuário. Ela será usasda para tratar as
funcionalidades de adicionar e editar e será exibida como
um diálogo modal.
 
3. _despesaReport.cshtml
É uma partial view que vai exibir um resumo das despesas
em um gráfico de barras usando os recursos
do HighCharts:

Então vamos ao trabalho...

Incluindo a view Index.cshtml

Clique com o botão direito do mouse no interior do método


Action Index do controlador DespesaController, e selecione
Add View;

Na janela Add MVC view aceite os valores padrão conforme


abaixo e clique no botão Add;
Será criada a view Index.cshtml dentro da
pasta Views/Despesa do projeto.

Inclua o código abaixo nesta view:

@model IEnumerable<MinhasFinancas.Models.RelatorioDespesa>
@{
ViewData["Title"] = "Gerenciandor de Finanças Pessoal";
}
<link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-
datepicker/1.8.0/js/bootstrap-datepicker.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-
datepicker/1.8.0/css/bootstrap-datepicker.css" rel="stylesheet">
<h2>Minhas Finanças</h2>
<br />
<div>
<div style="float:left">
<button class="btn btn-primary" onclick=" AddEditDespesa(0)">Adicionar
Despesa</button>
<button class="btn btn-success" onclick=" ReportDespesa()">Relatório
Despesas</button>
</div>
<div style="float:right; width:40%;">
<form asp-controller="Despesa" asp-action="Index" class="form-group">
<div class="col-sm-6">
<input class="form-control" type="text" name="criterio"
placeholder="Procurar">
</div>
<button type="submit" class="btn btn-default btn-info">Filtrar</button>
</form>
</div>
</div>
<br />
<br />
<table class="table">
<thead>
<tr>
<th>@Html.DisplayNameFor(model => model.ItemId)</th>
<th>@Html.DisplayNameFor(model => model.ItemNome)</th>
<th>@Html.DisplayNameFor(model => model.Valor)</th>
<th>@Html.DisplayNameFor(model => model.DataDespesa)</th>
<th>@Html.DisplayNameFor(model => model.Categoria)</th>
<th>Action Item</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(modelItem => item.ItemId)</td>
<td>@Html.DisplayFor(modelItem => item.ItemNome)</td>
<td>@Html.DisplayFor(modelItem => item.Valor)</td>
<td>@Html.DisplayFor(modelItem => item.DataDespesa)</td>
<td>@Html.DisplayFor(modelItem => item.Categoria)</td>
<td>
<button class="btn btn-default"
onclick="AddEditDespesa(@item.ItemId)">Editar</button>
<button class="btn btn-danger"
onclick="DeleteDespesa(@item.ItemId)">Deletar</button>
</td>
</tr>
}
</tbody>
</table>
<div class="modal fade" id="despesaFormModel" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a href="#" class="close" data-dismiss="modal">×</a>
<h3 id="title" class="modal-title">Adicionar Despesa</h3>
</div>
<div class="modal-body" id="despesaFormModelDiv">
</div>
</div>
</div>
</div>
<div class="modal fade" id="despesaReportModal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<a href="#" class="close" data-dismiss="modal">×</a>
<h3 class="modal-title">Relatório de Despesas</h3>
</div>
<div class="modal-body" id="despesaReportModalDiv">
</div>
</div>
</div>
</div>
<script>
var AddEditDespesa = function (itemId) {
var url = "/Despesa/AddEditDespesa?itemId=" + itemId;
if (itemId > 0)
$('#title').html("Edita Despesa");
$("#despesaFormModelDiv").load(url, function () {
$("#despesaFormModel").modal("show");
});
$('#despesaFormModel').on('shown.bs.modal', function () {
$('#calender-container .input-group.date').datepicker({
todayBtn: true,
calendarWeeks: true,
todayHighlight: true,
format: 'dd/mm/yyyy',
autoclose: true,
container: '#despesaFormModel modal-body'
});
});
}
var ReportDespesa = function () {
var url = "/Despesa/DespesaResumo";
$("#despesaReportModalDiv").load(url, function () {
$("#despesaReportModal").modal("show");
})
}
var DeleteDespesa = function (itemId) {
var resp = confirm("Deseja deletar a despesa : " + itemId);
if (resp) {
$.ajax({
type: "POST",
url: "/Despesa/Delete/" + itemId,
success: function () {
window.location.href = "/Despesa/Index";
}
})
}
}
</script>
<script>
$('body').on('click', "#btnSubmit", function () {
var myformdata = $("#despesaForm").serialize();
$.ajax({
type: "POST",
url: "/Despesa/Create",
data: myformdata,
success: function () {
$("#myModal").modal("hide");
window.location.href = " /Despesa/Index";
},
error: function (errormessage) {
alert(errormessage.responseText);
}
})
})
</script>

Vamos entender o código acima:

No início da view incluímos as referências bootstrap e jQuery.


Depois disso, adicionamos dois botões para adicionar uma nova
despesa e para criar o resumo de despesas. Incluímos também
um formulário contendo uma caixa de pesquisa para filtrar os
registros. Ao clicar no botão "Filtrar", o formulário é enviado e
ele invoca o método Index em nosso controlador, que retornará
os itens que correspondem aos critérios de pesquisa. A
funcionalidade de pesquisa é fornecida apenas no campo
do nome do item.

Estamos usando uma tabela para exibir todos os registros de


despesas em nosso banco de dados e cada registro tem dois
botões de ação correspondentes - Editar e Excluir.

Também criamos dois diálogos modais, um


para adicionar/editar os dados de despesas e outro para exibir
o relatório de resumo de despesas.

Na seção de script, definimos a função AddEditDespesa que


será invocada quando o botão “Adicionar Despesa” ou
“Editar” for clicado. Estamos passando o itemId como
parâmetro nesse método. Se o valor “ItemId” não for definido,
será considerado como uma operação para Adicionar e se o
“ItemId” estiver definido, é será considerado uma operação
para Editar.

Vamos invocar “AddEditDespesa” em nosso controlador que


retornará a  partial view  “_despesaForm” e vinculará ao
modelo RelatorioDespesa. O modal ficará vazio para a
chamada “Adicionar” e conterá os dados do item de despesa no
caso da chamada “Editar”. Estamos usando também o
bootstrap datepicker para selecionar a data da despesa,
portanto, definimos as propriedades do datepicker na carga de
diálogo modal.

A função ReportDespesa vai chamar o
método DespesaResumo em nosso controlador, que retornará a
partial view “_despesaReport” para ser exibida como um
diálogo modal. Essa view parcial vai exibir  o gráfico de resumo
de despesas mensal e semanal usando o Highcharts.

A função DeleteDespesa é usada para excluir o registro de uma


despesa específica. Ela vai o método "Excluir" em nosso
controlador para remover o registro de despesas do nosso
banco de dados.

Também estamos usando a vinculação dinâmica para vincular o


evento de envio do modal “despesaForm”. Este formulário é
definido na exibição “_despesaForm.cshtml”. Ao enviar o
formulário, estamos invocando uma chamada ajax para o
método "Create" em nossa classe controladora. Como estamos
usando o mesmo formato para a funcionalidade Editar e
Adicionar, precisamos distinguir entre os dois usando o
valor ItemId.

No método “Create” do controller, vamos verificar se


o ItemId está configurado, então vamos invocar o
método UpdateDespesa, caso contrário, vamos invocar o
método AddDespesa. Após o envio ser bem-sucedido,
fecharemos o modal e redirecionaremos para a view Index para
mostrar a lista atualizada de despesas.

Incluindo a partial view _despesaForm

Esta partial view exibe um diálogo model quando o botão


- Adicionar Despesa - da view Index, for clicado.

Clique com o botão direito do mouse sobre a


pasta Despesa dentro da pasta Views, e, a seguir clique
em Add -> View;

Na janela Add MVC View informe o nome _despesaForm e


marque - Create as partial view - conforme mostrado a seguir,
e clique em Add:
A seguir inclua o código abaixo nesta partial view:

@model MinhasFinancas.Models.RelatorioDespesa
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-
datepicker/1.3.0/js/bootstrap-datepicker.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-
datepicker/1.8.0/css/bootstrap-datepicker.css" rel="stylesheet">
<div>
<div class="row">
<div class="col-md-8">
<form id="despesaForm">
<input type="hidden" asp-for="ItemId" />
<div class="form-group">
<label asp-for=" ItemNome" class="control-label"></label>
<input asp-for=" ItemNome" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Categoria" class="control-label"></label>
<select asp-for="Categoria" class="form-control">
<option value="">-- Selecione a Categoria --</option>
<option value="Alimentacao">Alimentação</option>
<option value="Compras">Compras</option>
<option value="Transporte">Transporte</option>
<option value="Saude">Saúde</option>
<option value="Moradia">Moradia</option>
<option value="Lazer">Lazer</option>
</select>
</div>
<div class="form-group">
<label asp-for="Valor" class="control-label"></label>
<input asp-for="Valor" class="form-control" />
</div>
<div class="form-group" id="calender-container">
<label asp-for=" DataDespesa" class="control-label"></label>
<div class="input-group date">
<input asp-for="DataDespesa" type="text" class="form-
control"><span class="input-group-addon">
<i class="glyphicon glyphicon-calendar"></i></span>
</div>
</div>
<div class="form-group">
<button type="button" id="btnSubmit" class="btn btn-block btn-
info">Salvar</button>
</div>
</form>
</div>
</div>
</div>

No código desta partial view, no início estamos incluindo a


referência cdn para o bootstrap-datepicker, para que
possamos usá-lo em nossa caixa de diálogo modal. Então nós
temos um elemento de formulário, que se liga ao nosso modal.
Também temos um botão de envio que postará os dados do
formulário para o método Create em nosso controlador usando
a chamada ajax.
Incluindo a partial view _despesaReport

Vamos criar agora a partial view _despesaReport que exibirá a


caixa de diálogo model quando o botão - Relatório Despesas ,
da view Index, for clicado.

Clique com o botão direito do mouse sobre a


pasta Despesa dentro da pasta Views, e, a seguir clique
em Add -> View;

Na janela Add MVC View informe o nome _despesaReport e


marque - Create as partial view - conforme mostrado a seguir,
e clique em Add:

A seguir inclua o código abaixo nesta partial view:

<script src="https://code.highcharts.com/highcharts.js"></script>
<button id="btnReportMensal" class="btn btn-info">Relatório Mensal</button>
<button id="btnReportSemanal" class="btn btn-warning">Relatório
Semanal</button>
<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"></div>
<script>
$(document).ready(function () {
$("#btnReportSemanal").click(function () {
var titulomensagem = "Despesa semanal : ";
$.ajax({
type: "GET",
url: "/Despesa/GetDepesaPorPeriodoSemanal",
contentType: "application/json",
dataType: "json",
success: function (result) {
var keys = Object.keys(result);
var datasemanal = new Array();
var totalgasto = 0.0;
for (var i = 0; i < keys.length; i++) {
var arrL = new Array();
arrL.push(keys[i]);
arrL.push(result[keys[i]]);
totalgasto += result[keys[i]];
datasemanal .push(arrL);
}
createCharts(datasemanal , titulomensagem ,
totalgasto.toFixed(2));
}
})
})
$("#btnReportMensal").click(function () {
var titulomensagem = "Despesa semestral : ";
$.ajax({
type: "GET",
url: "/Despesa/GetDepesaPorPeriodo",
contentType: "application/json",
dataType: "json",
success: function (result) {
var keys = Object.keys(result);
var datamensal = new Array();
var totalgasto = 0.0;
for (var i = 0; i < keys.length; i++) {
var arrL = new Array();
arrL.push(keys[i]);
arrL.push(result[keys[i]]);
totalgasto += result[keys[i]];
datamensal .push(arrL);
}
createCharts(datamensal , titulomensagem ,
totalgasto.toFixed(2));
}
})
})
})
function createCharts(soma, tituloTexto, totalgasto) {
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: tituloTexto + ' ' + totalgasto
},
xAxis: {
type: 'category',
labels: {
rotation: -45,
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Valor Despesas'
}
},
legend: {
enabled: false
},
tooltip: {
pointFormat: 'Total despesas: <b>{point.y:.2f} </b>'
},
series: [{
type: 'column',
data: soma,
}]
});
}
</script>

No início do código incluímos a referência cdn para usar


o Highcharts. Também fornecemos dois botões para visualizar
os relatórios mensais dos últimos seis meses e os relatórios
semanais das últimas quatro semanas. O relatório será gerado
como um gráfico de barras para fornecer um estudo
comparativo dos resumos de despesas.

Ao clicar no botão de relatório semanal, invocaremos o


método GetDepesaPorPeriodoSemanal do nosso controlador
que retornará os dados no formato Json e passaremos isso para
a função createCharts para criar o gráfico de barras de
despesas semanais usando Highcharts.

Da mesma forma, invocaremos o


método GetDepesaPorPeriodo de nosso controlador ao clicar
no botão "Relatório mensal" e passaremos o resultado do Json
para a função createCharts para criar o gráfico de barras de
despesas mensal usando Highcharts.

Antes de executar a aplicação vamos alterar o roteamento


definido no arquivo Startup, no método Configure,  para
iniciar a execução chamando o método Index do
controlador DespesaController:

...

  app.UseMvc(routes =>
 {
     routes.MapRoute(
     name: "default",
    template: "{controller=Despesa}/{action=Index}/{id?}");
 });
...

Agora é só alegria...

Executando o projeto iremos obter o seguinte resultado:


O código do projeto completo esta no módulo Bônus do  Curso
de ASP .NET Core .
ASP .NET Core - Criando uma aplicação ASP .NET
Core MVC com o VS 2017
http://www.macoratti.net/17/04/aspcore_mvcfilme1.htm

  Neste
artigo eu
vou
mostrar
como criar
uma
aplicação
ASP .NET
Core MVC
usando o
VS 2017
recordand
o os
conceitos
da
implement
ação
ASP .NET
MVC.

Esta série de artigos se baseia no


original https://docs.microsoft.com/en-
us/aspnet/core/tutorials/first-mvc-app/  com adaptações e
ajustes.

Para acompanhar este artigo você precisa ter instalado o  Visual


Studio Community 2017  com os seguintes workloads instalados:
Se você não tem nenhuma noção sobre como funciona o padrão
MVC e sua implementação ASP .NET sugiro que leia esses artigos
:

 ASP .NET - MVC - Introdução - Macoratti


 Compreendendo Models, Views e Controllers - MVC -
Macoratti

Criando uma nova aplicação Web


Abra no VS 2017 e no menu File clique em New Project;

A seguir selecione o template Visual C# -> .NET Core e


marque ASP .NET Core Web Application (.NET Core);
Informe o nome MvcFilme e clique no botão OK;

Na próxima janela escolha a versão ASP .NET Core 1.1 e marque


o template Web Application sem autenticação e clique no
botão OK;
Você terá o seguinte projeto criado:

O Visual Studio utiliza um template padrão para o projeto MVC


que é criado e pode ser visto na figura acima.

Temos assim uma aplicação funcional, na verdade , um simples


projeto inicial, que é o nosso ponto de partida.

Pressione F5 para rodar a aplicação no


modo debug ou Ctrl+F5 para rodar no modo não debug.

Iremos obter a seguinte página :


O VS inicia o servidor IIS Express e executa a nossa aplicação.

Observe que o endereço na barra de navegação


exibe localhot:43470, isso é assim porque localhost é o nome
padrão para hospedagem no computador local.  Quando o VS
cria um projeto web uma porta aleatória é usada para o servidor
web.

Executando a aplicação no modo não debug(Ctrl+F5) podemos


fazer alterações no código, salvar o arquivo, atualizar o
navegador e visualizar as mudanças.

Podemos também usar o menu Debug para iniciar a aplicação:

Podemos também pressionar o botão II Express  no menu :

O template padrão usado para criar o projeto web MVC define


os links Home, About e Contact na página além de criar toda a
estrutura do projeto contendo arquivos e as pastas Controllers,
Views/Home e Views/Shared.

Incluindo um novo controlador no projeto


O modelo de arquitetura Model-View-Controller (MVC) separa
um aplicativo em três componentes principais: Modelo,
Visualização e Controlador. O padrão MVC ajuda você a criar
aplicativos que são mais testáveis e mais fáceis de atualizar do
que aplicativos monolíticos tradicionais.
Os Controladores são classes que processam requisições de um
navegador. Eles recuperam dados do modelo e invocam
templates Views que retornam uma resposta. Em um aplicativo
MVC, a View exibe apenas informações enquanto que o
controlador manipula e responde à entrada e interação do
usuário.

Dessa forma o controlador manipula dados de rota e valores de


string de consulta e passa esses valores para o modelo. O
modelo pode usar esses valores para consultar o banco de
dados.

Exemplos:
 - http://localhost:1234/Home/About tem dados de rota
de Home(o controlador) e About(o método Action para chamar o
controlador Home).
 - http://localhost:1234/Filme/Edit/5 é uma solicitação para
editar o filme com ID igual a 5 usando o controlador Filme.

Para incluir um novo controlador em nosso projeto vamos usar a


pasta Controllers que já foi criada.

Clique com o botão direito do mouse sobre a


pasta Controllers e a seguir clique em Add -> New Item;
Selecione o template MVC Controller Class e informe o
nome OlaMundoController.cs e clique em Add;

A seguir substitua o código que foi gerado para o


controlador OlaMundoController na pasta Controllers pelo
código abaixo:

using Microsoft.AspNetCore.Mvc;
namespace MvcFilme.Controllers
{
public class OlaMundoController : Controller
{
//
// GET: /OlaMundo/
public string Index()
{
return "Este é a Action padrão (Index)...";
}
//
// GET: /OlaMundo/BemVindo/
public string BemVindo()
{
return "Este é um método Action BemVindo...";
}
}
}

Cada método público em um controlador é pode ser chamado


como um endpoit HTTP.  No nosso exemplo, ambos os métodos
retornam uma string.

- O primeiro método, Index(),  é um método HTTP GET que é


invocado adicionando "/OlaMundo/" á URL base.
- O segundo método, BemVindo(),  é um método HTTP GET que
é invocado adicionando "/OlaMundo/BemVindo/" à URL.

Executando o projeto (CTRL+F5) e digitando "OlaMundo" no


caminho na barra de endereços do navegador.
Ex: http://localhost:XXXX/OlaMundo faz com que o método
Index retorne uma string. Você disse ao sistema para retornar
algum HTML, e ele obedeceu! 

Nota:  Temos que digitar  OlaMundo  (o prefixo do controlador)


pois este controlador não é o controlador padrão definido no
arquivo  Startup.cs. O controlador padrão é  HomeController.

O MVC invoca as classes controllers, e os métodos Action em


seu interior, dependendo de como a requisição vem na URL.

A lógica padrão para o roteamento da URL usada pelo MVC usa


o formato abaixo para detereminar qual código deve invocar:

/[Controller]/[ActionName]/[Parameters]
A definição desse formato esta definido no arquivo Startup.cs :

...
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template:
"{controller=Home}/{action=Index}/{id?}");
});
.....

Quando você executa o aplicativo e não fornece nenhum


segmento de URL, o padrão usado será o controlador "Home" e
o método "Index", especificado na linha template definida
acima.

O primeiro segmento de URL determina a classe do controlador


a ser executada. Então localhost:XXXX/OlaMundo mapeia para
a classe OlaMundoController.

A segunda parte do segmento de URL determina o


método Action na classe.
Assim, localhost:XXXX/OlaMundo/Index faz com que o
método Index da classe OlaMundoController seja executado.
(Por padrão o método Index já é invocado). Isso ocorre porque o
índice é o método padrão que será chamado em um controlador
se um nome de método não for explicitamente informado.

A terceira parte do segmento de URL (id) é para dados de rota.

Agora navegue até localhost:XXXX/OlaMundo/BemVindo

O método BemVindo será executado e retorna a string "Este é o


método Action BemVindo...". Para esta URL, o controlador
é OlaMundo e BemVindo é o método Action.

Vamos modificar um pouco o exemplo para que você possa


passar algumas informações de parâmetro na URL para o
controlador. Por exemplo: /OlaMundo/BemVindo?
Nome=Macoratti&numVezes=4.

Altere o código do método BemVindo para receber dois


parâmetros como mostrado abaixo. Observe que o código usa o
recurso do parâmetro opcional C# para indicar que o
parâmetro numVezes padrão é 1 se nenhum valor for passado
para esse parâmetro.

public string Welcome(string nome, int numVezes = 1)


{
return HtmlEncoder.Default.Encode($"Ola {nome},
NumVezes igual a : {numVezes}");
}

O código acima usa o


namespace HtmlEncoder.Default.Encode para proteger o
aplicativo de entrada maliciosa  (ou seja, JavaScript). Ele também
usa seqüências interpoladas.

No Visual Studio, no modo  sem depuração  (Ctrl + F5), não é


necessário criar o aplicativo depois de alterar o código. Basta
salvar o arquivo, atualizar o navegador e você pode ver as
alterações.

Execute seu aplicativo e navegue


até:  http://localhost:XXXX/OlaMundo/BemVindo?
nome=Macoratti&numVezes=5

No exemplo acima, o segmento de URL (Parameters) não esta


sendo usado, os parâmetros nome e numVezes são passados
como seqüências de consulta (query string).

O ? (Ponto de interrogação) na URL acima é um separador, e as


seqüências de caracteres de consulta vem a seguir. O
caractere & separa as seqüências de consulta.

Agora vamos alterar novamente o código do


método BemVindo conforme abaixo:

public string Welcome(string nome, int ID = 1)


{
return HtmlEncoder.Default.Encode($"Ola {nome}, ID =
{ID}");
}
Execute novamente informando a seguinte
URL: http://localhost:XXX/OlaMundo/BemVindo/3?
nome=Macoratti

Desta vez, o terceiro segmento de URL correspondeu ao ID do


parâmetro de rota. O método BemVindo contém um parâmetro
ID que corresponde ao modelo de URL no método MapRoute.

O ponto de interrogação em  id?,  Indica que o


parâmetro id é opcional conforme vemos no arquivo Startup:

...
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template:
"{controller=Home}/{action=Index}/ {id?}");
});
.....

Incluindo uma View


Até o momento o controlador estar retornando o HTML
diretamente e isso não é o seu papel, e, além disso ficaria muito
oneroso fazer a manutenção. Para resolver esse problema vamos
separar as responsabilidades e utilizar as Views para retornar o
código HTML.

Vamos então modificar a classe OlaMundoController para usar


os templates Views Razor e assim encapsular o processo de
geração de respostas HTML para um cliente.
Depois vamos criar um arquivo para a View usando Razor. Os
templates Views baseados em Razor têm uma extensão de
arquivo .cshtml. Eles fornecem uma maneira elegante de criar
saída HTML usando C#.

Atualmente, o método Index retorna uma string com uma


mensagem que esta fixada na classe controlador.

Altere o código da classe OlaMundoController para o


método Index conforme mostrado abaixo:

//
// GET: /OlaMundo/
public IActionResult Index()
{
return View();
}

O método Index acima agora retorna um objeto View(). Ele usa


um template para gerar uma resposta HTML para o navegador.

Geralmente os métodos de um Controlador (conhecidos como


métodos Actions) retornam um IActionResult (ou uma classe
derivada de ActionResult), e não tipos primitivos como uma
string.

Precisamos assim criar uma View para atender o retorno do


método Action Index. E vamos criar essa View na
pasta Views do projeto.

Clique com o botão direito do mouse sobre a pasta Views e a


seguir em Add -> New Folder e informe o nome OlaMundo.

Agora clique com o botão direito sobre a


pasta OlaMundo criada e a seguir em Add -> New Item;

Selecione o template MVC View Page; aceite o


nome Index.cshtml e clique no botão Add;
Substitua o conteúdo da View Razor Index.cshtml gerada pelo
código a seguir:

@{
ViewData["Title"] = "Index";
}
<h2>Macoratti .net - Index</h2>
<hr />
<p> Um alô da View Template !</p>

Agora vamos testar a nossa View.

Execute a aplicação e navegue


ate  http://localhost:XXXX/OlaMundo  e veja o resultado :
Que diferença !!!

O método Action Index() do
controlador OlaMundoController agora retornou uma View e
não uma string.

Como não foi informado o nome do arquivo da View, o MVC


usou o arquivo View - Index.cshtml na
pasta /Views/OlaMundo.

Notou que o MVC foi procurar a view Index.cshtml na


pasta OlaMundo, o mesmo nome do Controlador ?

Assim para todos os métodos Action que retornarem Views,


essas views devem ser criadas na pasta com nome do prefixo do
controlador. (Essas é uma das configurações padrão que o
framework MVC adota.)

No próximo artigo  vamos alterar as views e as páginas de


leaiute da aplicação.
ASP .NET Core - Criando uma aplicação ASP .NET
Core MVC com o VS 2017 – II
http://www.macoratti.net/17/04/aspcore_mvcfilme2.htm

  Neste
artigo
eu vou
mostra
r como
criar
uma
aplicaç
ão ASP
.NET
Core
MVC
usando
o VS
2017.

Continuando a primeira parte do artigo  vamos alterar as views e


as páginas de layout da nossa aplicação. As views geradas
utilizam a sintaxe Razor devido a sua simplicidade.

Nota:  Se você não conheçe o Razor e sua sintaxe sugiro que leia
este artigo :  ASP .NET - Apresentando a sintaxe Razor - Macoratti

Alterando Views e layouts


Abra a solução MvcFilme criada no VS 2017 via Start
Page usando a área Recent e selecionando o projeto criado ou a
área Open clicando na opção Open Project/Solution e
selecionando o projeto da aplicação:
Ao executar a aplicação e clicar nos links Home, About e
Contact que foram criados, cada página vai mostrar o mesmo
leiaut para o menu.

Nota:  Estamos usando o controlador


padrão  HomeController  definido em Startup.cs.
A implementação desse layout é feita pelo
arquivo _Layout.cshtml na pasta Views/Shared e vamos fazer
algumas alterações neste arquivo.

Um template Layout permite que você especifique o layout do


container HTML do seu site em um único local e então aplicar
esse leiaute a múltiplas páginas do seu site.

Abra o arquivo _Layout.cshtml da pasta Views/Shared e


localize a linha de código @RenderBody(),

RenderBody é um espaço reservado onde todas as páginas


específicas da visualização que você cria são exibidas, envolvidas
na página de layout. Quando selecionamos um link a respectiva
view desse link será renderizada dentro do método RenderBody.
Vamos alterar algumas partes do código no
arquivo _Layout.cshtml conforme destacadas abaixo:

@inject
Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet
JavaScriptSnippet
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,
initial-scale=1.0" />
<title>@ViewData["Title"] - Aplicação Filmes</title>
<environment names="Development">
<link rel="stylesheet"
href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet"
href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/boots
trap.min.css"
asp-fallback-
href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-
property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-
append-version="true" />
</environment>
@Html.Raw(JavaScriptSnippet.FullScript)
</head>
<body>
<nav 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="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@*<a asp-area="" asp-controller="Home" asp-
action="Index" class="navbar-brand">MvcFilme</a>*@
<a asp-area="" asp-controller="Filmes" asp-
action="Index" class="navbar-brand">Filmes do Macoratti</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="Home" asp-
action="Index">Home</a></li>
<li><a asp-area="" asp-controller="Home" asp-
action="About">Sobre</a></li>
<li><a asp-area="" asp-controller="Home" asp-
action="Contact">Contato</a></li>
</ul>
</div>
</div>
</nav>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>&copy; 2017 - Macoratti .net - MvcFilme</p>
</footer>
</div>
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-
2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-
K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH
+8Fk">
</script>
<script
src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn &&
window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha384-
Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNI
cPD7Txa">
</script>
<script src="~/js/site.min.js" asp-append-
version="true"></script>
</environment>
@RenderSection("Scripts", required: false)
</body>
</html>

Alterações feitas:

 Alteramos o conteúdo do elemento Title para Aplicação


Filmes;
 Alteramos o controlador de Home para Filmes;  (não
criamos ainda esse controlador , ok);
 Alteramos o link na barra de menu de MvcFilme
para Filmes do Macoratti;
 Traduzimos os links About para Sobre e Contact
para Contato;
 No rodapé alteramos o texto para : Macoratti .net -
MvcFilme

Salve as alterações e atualize a página para ver as alterações


feitas :

As alterações feitas irão se refletir em todas as páginas que


userem o leiaute definido no arquivo.

Mas como esse arquivo de leiaute é usado pelas views ?

Abrindo o arquivo _ViewStart.cshtml na pasta Views veremos o


código abaixo:

@{
Layout = "_Layout";
}
Esse arquivo é usado para definir a página padrão de leaiute
para a aplicação. Ele inclui o arquivo _Layout.cshtml em cada
view usando a propriedade Layout.

Você pode usar a propriedade Layout para definir um view de


leiaute diferente ou definir a propriedade para null de forma a
não usar nenhum leiaute.

Nota: Para saber mais sobre como funciona esse arquivo leia esse
artigo:  ASP .NET MVC - Diferentes maneiras de renderizar
layouts - Macoratti

Alterando o conteúdo das Views


Vamos alterar o conteúdo da view Index.cshtml que esta na
pasta Views/OlaMundo conforme mostrado abaixo:

@{
ViewData["Title"] = "Lista de Filmes";
}
<h1>Minha lista de Filmes</h1>
<hr />
<p> Um alô da View OlaMundo\Index.cshtml !</p>

Salve as alterações e execute o projeto digitando na barra de


navegação a url : http://localhost:XXXX/OlaMundo  e  veja o
resultado :
Observe como o conteúdo da view
template Index.cshtml contida em Views/OlaMundo foi
mesclado com o conteúdo da view de leiaute contida
em Views/Shared/_Layout.cshtml, e uma única resposta HTML
foi enviada para o navegador compondo o leiaute da página.

Assim os modelos de layout tornam muito fácil fazer alterações


que se aplicam a todas as páginas em seu aplicativo.

Na próxima parte do artigo  veremos como passar dados do


controlador para view.

(Jesus) Veio para o que era seu, e os seus não o receberam.


Mas, a todos quantos o receberam, deu-lhes o poder de
serem feitos filhos de Deus, aos que crêem no seu nome;
Os quais não nasceram do sangue, nem da vontade da carne,
nem da vontade do homem, mas de Deus.
João 1:11-13
ASP .NET Core - Criando uma aplicação ASP .NET
Core MVC com o VS 2017 – III
http://www.macoratti.net/17/04/aspcore_mvcfilme3.htm

  Neste
artigo
eu vou
mostra
r como
criar
uma
aplicaç
ão ASP
.NET
Core
MVC
usando
o VS
2017.

Continuando a segunda parte do artigo  vou mostrar como


podemos passar dados do  controlador para as views .

Nota:  Se você não conheçe o Razor e sua sintaxe sugiro que leia
este artigo :  ASP .NET - Apresentando a sintaxe Razor - Macoratti

Passando dados do Controller para a


View
Um Controller ou controlador é responsável por controlar a
maneira como um usuário interage com uma aplicação MVC e
possui o fluxo de controle lógico para uma aplicação ASP .NET
MVC.

É o controlador que determina que resposta será enviada de


volta ao usuário quando ele faz uma requisição via
navegador. Um controlador é uma classe que contém métodos
de ação ou Action.

As Actions (ações) do controlador são chamadas em resposta a


uma solicitação de URL de entrada. Uma classe de controlador é
onde você escreve o código que manipula as solicitações do
navegador de entrada. O controlador recupera dados de uma
fonte de dados e decide que tipo de resposta enviar para o
navegador. Os templates views (modelos de visualização) podem
ser usados a partir de um controlador para gerar e formatar uma
resposta HTML para o navegador.

Os controladores são responsáveis por fornecer os dados


necessários para que uma view produza uma resposta.

Recomenda-se que as views não devem executar lógica de


negócios ou interagir diretamente com um banco de dados. Em
vez disso, uma view deve funcionar apenas com os dados
fornecidos a ela pelo controlador. Manter esta "separação de
responsabilidades" ajuda a manter o seu código limpo, testável e
sustentável.

As ações do controlador são chamadas em resposta a uma


solicitação de URL de entrada. Uma classe de controlador é onde
você escreve o código que manipula as solicitações do
navegador de entrada. O controlador recupera dados de uma
fonte de dados e decide que tipo de resposta enviar para o
navegador. Os templates views (modelos de visualização) podem
ser usados a partir de um controlador para gerar e formatar uma
resposta HTML para o navegador.

Os controladores são responsáveis por fornecer os dados


necessários para que uma view produza uma resposta. Uma
prática recomendada: As views não devem executar lógica de
negócios ou interagir diretamente com um banco de dados. Em
vez disso, uma view deve funcionar apenas com os dados
fornecidos a ela pelo controlador. Manter esta "separação de
responsabilidades" ajuda a manter o seu código limpo, testável e
sustentável.

Atualmente, o método BemVindo na
classe OlaMundoController toma um  nome e um parâmetro
ID  e, em seguida, exibe diretamente os valores de saída para o
navegador.

Em vez do controlador processar essa resposta como uma


seqüência de caracteres, vamos alterar o controlador para usar
uma view para fazer isso como recomendado. A view irá gerar
uma resposta dinâmica, o que significa que você precisa passar
os bits de dados apropriados do controlador para a view, a fim
de gerar a resposta.

Você pode fazer isso fazendo com que o controlador coloque os


dados dinâmicos (parâmetros) que a view precisa em um
dicionário ViewData que a view pode acessar.

Abra o arquivo OlaMundoController.cs e altere o


método BemVindo para adicionar um
valor Mensagem e NumVezes ao dicionário ViewData.

O dicionário ViewData é um objeto dinâmico, o que significa


que você pode colocar o que quiser dentro dele; O
objeto ViewData não tem propriedades definidas até que você
coloque algo dentro dele. O sistema de vinculação do modelo
MVC mapeia automaticamente os parâmetros nomeados (nome
e numVezes)  da string de consulta na barra de endereços para
os parâmetros no seu método.

Nota: Para saber mais sobre ViewData leia o artigo:    ASP .NET


MVC - ViewBag, ViewData e TempData - Macoratti
Abaixo temos o código do arquivo OlaMundoController.cs
alterado:

using Microsoft.AspNetCore.Mvc;
namespace MvcFilme.Controllers
{
public class OlaMundoController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult BemVindo(string nome, int
NumVezes)
{
ViewData["Mensagem"] = "Olá " + nome;
ViewData["NumVezes"] = NumVezes;

return View();
}
}
}

Agora nosso controlador possui objetos


dictionary ViewData que contém dados que serão passados para
a view. Qual view ?

Bem, ainda não criamos a view. Mas sabemos que temos que
criar uma view na pasta Views/OlaMundo com o
nome BemVindo.cshtml porque esta é a convenção padrão que
o Framework MVC adota :

De forma geral, se você deseja retornar uma view para uma ação
do controlador, então você vai precisar criar uma subpasta na
pasta  Views  com o  mesmo nome do controlador ,   e, no interior
da subpasta você deverá criar uma View com o  mesmo nome da
ação do controlador.

Clique com o botão direito do mouse sobre a


pasta Views/OlaMundo e a seguir em Add-> New Item;
Selecione o template MVC View Page, informe o
nome BemVindo.cshtml e clique no botão Add;

A seguir inclua o código abaixo neste arquivo:

@{
ViewData["Title"] = "Bem-Vindo";
}
<h2>Macoratti .net - Seja Bem-Vindo</h2>
<ul>
@for (int i = 0; i < (int)ViewData["NumVezes"]; i++)
{
<li>@ViewData["Mensagem"]</li>
}
</ul>

Neste código estamos utilizando os dados, que serão passados


via URL via objeto ViewData, do controlador para a View e
usando um laço for iremos exibir a mensagem no número de
vezes informado.
Salve as alterações e altere a URL do navegador
para : http://localhost:XXXXX/Olamundo/BemVindo?
nome=Macoratti&numvezes=5  e veja o resultado :

Os dados são extraídos da URL e passados para o controlador


usando o MVC model binder . O controlador então empacota os
dados em um dicionário ViewData e passa esse objeto para a
view. A view então processa os dados como HTML para o
navegador. Foi o que aconteceu no exemplo acima: Exibimos a
mensagem 'Olá Macoratti' cinco vezes.

Nota: O Model Binding funciona assim   : Quando MVC recebe uma solicitação
HTTP, ele roteia a requisição para um método de Action específico de um
controlador. Ele determina qual método Action deve ser executado com base
no que está nos dados da rota, e então vincula valores da solicitação HTTP aos
parâmetros desse método Action.

Considere a seguinte URL:        Http://macoratti.com/filmes/edit/2

Como o modelo de rota esta definido assim,   {controller = Home}/{action


= Index}/{id?},  a url  Filmes/edit/2  roteia para o controlador
de  Filmes  e seu método Action  Edit. Ele também aceita um parâmetro
opcional chamado  id.

No exemplo acima, usamos o dicionário ViewData para passar


dados do controlador para uma view. Mais adiante usaremos
uma view model ou  modelo de visão  para passar dados de um
controlador para uma view. A abordagem em usar a view
model para passar dados é, em muitos casos, mais indicada em
relação à abordagem do dicionário ViewData.
Na próxima parte do artigo  vamos tratar dos dados da
aplicação criando um banco de dados chamado Filmes.

(Disse Jesus) Na verdade, na verdade vos digo que quem


ouve a minha palavra, e crê naquele que me enviou, tem a
vida eterna, e não entrará em condenação, mas passou da
morte para a vida.
João 5:24

ASP .NET Core - Criando uma aplicação ASP .NET


Core MVC com o VS 2017 – IV
http://www.macoratti.net/17/04/aspcore_mvcfilme4.htm
  Neste
artigo
eu vou
mostra
r como
criar
uma
aplicaç
ão ASP
.NET
Core
MVC
usando
o VS
2017.

Continuando a terceira parte do artigo  vamos definir um


modelo de domínio, o Model da nossa aplicação, criando
algumas classes para gerenciar filmes em um banco de dados.

Vamos utilizar a tecnologia de acesso a dados do .NET


Framework conhecida como Entity Framework Core para definir e
trabalhar com essas classes de modelo de dados. O Entity
Framework Core (EF Core para os íntimos) apresenta um
paradigma de desenvolvimento chamado Code First.

Esse paradigama funciona assim:    Você escreve o código e as


tabelas do banco de dados são criadas a partir desse código.

O Code First permite que você crie objetos de modelo de dados


escrevendo classes simples (conhecidas como classes POCO -
Plain Old CLR Objects) e, o  banco de dados será criado a partir
de suas classes.

Obs : Se você precisar criar primeiro o banco de dados, você


ainda pode seguir este tutorial para aprender sobre MVC e o
desenvolvimento app EF.
Nota:  Se você não conheçe nada sobre o Entity Framework
sugiro que leia este artigo : Introdução ao Entity Framework -
Macoratti

Criando as classes do modelo de


dados (Model)
Selecione o projeto MvcFilme na janela Solution Explorer e no
menu Project clique em Add ->New Folder e informe o
nome Models.

Clique com o botão direito sobre a pasta Models e a seguir


clique em Add -> Class e informe o nome Filme e clique no
botão Add;

A seguir inclua o código abaixo nesta classe definindo as


propriedades : ID, Titulo, Lancamento, Genero e Preco;

Além das propriedades inerentes ao filme, o campo ID é


requerido para identificar o filme e para mapear para a chave
primária do banco de dados que será criado a partir dessa
classe.

Compile o projeto antes de prosseguir.

Criando um controlador
Agora clique com o botão direito do mouse sobre a
pasta Controllers, e a seguir clique em Add -> Controller;

Na janela Add MVC Dependencies selecione a opção - Minimal


Dependencies e clique no botão Add;

O VS 2017 vai adicionar as dependências necessárias para


montar o controller. (Você pode deletar o
arquivo  ScaffoldingReadMe.txt  criado)

Após isso repita o procedimento e clique com o botão direito do


mouse sobre a pasta Controllers, e a seguir clique em Add ->
Controller;

Na janela Add Scaffold selecione a opção : MVC Controller


with views, using Entity Framework :
Clique no botão Add.

Agora na janela Add Controller vamos fazer as seguintes


definições :

Model Class :  Selecione Filme(MvcFilme.Models)

Data context class :  clique no botão + e


selecione MvcFilme.Models.MvcFilme.Context e clique no
botão Add;
Mantenha as demais opções com seus valores padrão conforme
abaixo e clique no botão Add:
O mecanismo de scaffolding do Visual Studio vai criar :

- Um controlador filmes (Controllers/FilmesController.cs)


- Os métodos Create, Delete, Details, Edit e Index  e as
respectivas View Razor (.cshtml) (Views/Filmes)

Assim, o VS criou automaticamente os métodos


Actions CRUD (criar, ler, atualizar e excluir) e as views para você.
Veja na figura abaixo:

A aplicação ainda não esta pronto para ser testada. Vamos


continuar...

Incluindo a referência ao Entity


Framework
Clique com o botão direito do mouse sobre o nome do
projeto MvcFilme e a seguir clique em Edit MvcFilme.csproj:

A seguir inclua as referências aos pacotes :

 "Microsoft.VisualStudio.web.CodeGeneration.Tools"
 "Microsoft.EntityFrameworkCore.Tools.DotNet"

em ItemGroup conforme mostra a figura abaixo:


Atualizando o banco de dados
Vamos agora abrir uma janela de prompt de comandos.  Existem
diversas formas de fazer isso.  (Estou usando o Windows 10)

No Windows 10, uma delas é usar o atalho Win+X :

  Pressione Win+X para abrir o menu contextual e clique na


opção Prompt de Comando ou Prompt de Comando
(Admin).

Com a janela de comandos aberta posicione-se no diretório


onde você criou o projeto da aplicação ASP .NET:

No meu exemplo a pasta do projeto esta localizada


em : C:\_aspncore\MvcFilme\MvcFilme
A seguir execute os seguintes comandos na sequência abaixo
esperando que cada um termine a sua execução :

 dotnet restore
 dotnet ef migrations add Initial
 dotnet ef database update

Vamos entender o que esses comandos fazem...

- dotnet (.NET Core) é uma implementação cross-platform da


plataforma .NET. (veja detalhes aqui)

- dotnet restore - faz download dos pacotes Nuget


especificados no arquivo .csproj do projeto;

- dotnet ef migrations add Initial  -  Executa o comando de


migração Entity Framework .NET Core CLI e cria uma migração
inicial. O parâmetro initial é arbitrário, mas usado para a
primeira migração do banco de dados . Esta operação cria o
arquivo Data/Migrations/<date-time>_Initial.cs contendo os
comandos de migração para adicionar(ou apagar) a
tabela Filme do banco de dados.

- dotnet ef database update - Atualiza o banco de dados com a


migração recém criada no item anterior:
Ao final da execução destes comandos já podemos testar a
nossa aplicação...

Testando a aplicação
Executando a aplicação e clicando no link - Filmes do
macoratti :
Será aberta a página de filmes vazia pois não temos nenhum
filme cadastrado ainda. Clique no link Create New:

Informe os dados do filme e clique no botão Create:


Pronto. Temos o filme exibido conforme abaixo:
Lembrando que você pode alterar os textos das páginas gerados
pelo scaffolding. Para isso basta abrir as respectivas views na
pasta Views/Filmes.

Dando uma espiada no código


gerado
Abra o arquivo Startup.cs e observe o código destacado abaixo
no método ConfigureServices() :

....
// This method gets called by the runtime. Use this method to
add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddDbContext<MvcFilmeContext>(options
=>

options.UseSqlServer(Configuration.GetConnectionString("M
vcFilmeContext")));
}
....

Este código mostra o contexto do banco de


dados Filme - MvcFilmeContext - sendo adicionado ao
contâiner de injeção de dependência nativa da ASP .NET Core.

Abra agora o arquivo FilmesController.cs na pasta Controllers:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using MvcFilme.Models;
using System.Linq;
using System.Threading.Tasks;
namespace MvcFilme.Controllers
{
public class FilmesController : Controller
{
private readonly MvcFilmeContext _context;
public FilmesController(MvcFilmeContext context)
{
_context = context;
}
.....
 

Neste código vemos que o construtor usa a Injeção de


dependência   para injetar o contexto do banco de dados no
controlador. Assim, o contexto do banco de dados é usado em
cada método CRUD no controller.

Model fortemente tipado e a palavra-


chave @model
Já falei sobre como passar dados ou objetos do controlador para
uma view usando o dicionário ViewData. O
dicionário ViewData é um objeto dinâmico que fornece uma
maneira convencional de transmitir informações a uma view.
O MVC também fornece a capacidade de passar
objetos model fortemente tipados para uma view. Esta
abordagem fortemente tipada permite uma melhor verificação
em tempo de compilação do seu código e um IntelliSense mais
rico no Visual Studio (VS). O mecanismo de scaffold no VS usou
essa abordagem (ou seja, passou um modelo fortemente tipado)
com a classe FilmesController e as respectivas views quando
criava os métodos e as views.

Vamos examinar o método Details do


controlador FilmesController gerado pelo scaffold :

// GET: Filmes/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var filme = await _context.Filme
.SingleOrDefaultAsync(m => m.ID == id);

if (filme == null)
{
return NotFound();
}
return View(filme);
}

Neste código estamos temos que :

O parâmetro id geralmente é passado como dados de rota, por


exemplo http:// localhost:1234/filmes/details/1 significa:

- filmes - O controlador para o FilmesController (o primeiro


segmento de URL).
- details - A Action para details (o segundo segmento de URL)
- O id para 1 (o último segmento de URL).
Você também pode passar o ID com uma string de consulta da
seguinte maneira:   http://localhost:1234/filmes/details?Id=1

Se for encontrado um filme com o id informado, uma instância


do modelo de Filme é passada para a view Details.

Abra então a view Details.cshtml na pasta Views/Filmes:

@model MvcFilme.Models.Filme

@{
ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
<h4>Filme</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Titulo)
</dt>
<dd>
@Html.DisplayFor(model => model.Titulo)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Lancamento)
</dt>
<dd>
@Html.DisplayFor(model => model.Lancamento)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Genero)
</dt>
<dd>
@Html.DisplayFor(model => model.Genero)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Preco)
</dt>
<dd>
@Html.DisplayFor(model => model.Preco)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.ID">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>

Ao incluir uma instrução @model na parte superior do arquivo


view, você pode especificar o tipo de objeto que a view espera.
Quando você criou o controlador FilmesController, o Visual
Studio automaticamente incluiu a seguinte instrução @model na
parte superior do arquivo Details.cshtml:  @model
MvcFilme.Models.Filme

Esta diretiva @model permite que você acesse o filme que o


controlador passou para a view usando um objeto Model que é
fortemente tipado.

Por exemplo, na view Details.cshtml, o código passa cada


campo do filme para os Html
Helpers DisplayNameFor e DisplayFor com o
objeto Modelo fortemente tipado. Os métodos Create e Edit e
as respectivas views também passam um objeto de modelo de
filme.

Examine agora o método Index() no


arquivo FilmesController.cs :

// GET: Filmes
public async Task<IActionResult> Index()
{
return View(await _context.Filme.ToListAsync());
}

 
Observe como o código cria um objeto List quando ele chama o
método View. O código passa esta lista de Filmes a partir do
método Action Index para a view Index.cshtml vista a seguir:

@model IEnumerable<MvcFilme.Models.Filme>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Titulo)
</th>
<th>
@Html.DisplayNameFor(model =>
model.Lancamento)
</th>
<th>
@Html.DisplayNameFor(model => model.Genero)
</th>
<th>
@Html.DisplayNameFor(model => model.Preco)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Titulo)
</td>
<td>
@Html.DisplayFor(modelItem => item.Lancamento)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genero)
</td>
<td>
@Html.DisplayFor(modelItem => item.Preco)
</td>
<td>
<a asp-action="Edit" asp-route-
id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-
id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-
id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Da mesma forma, a diretiva @model permite a você acessar a


lista de filmes que controlador passou para a view usando o
objeto Model fortemente tipado.

Observe que o código percorre os filmes usando um


instrução foreach sobre o objeto Model fortemente tipado.

Na próxima parte do artigo vamos trabalhar um pouco com o


banco de dados.

Jesus dizia, pois, aos judeus que criam nele: Se vós


permanecerdes na minha palavra, verdadeiramente sereis
meus discípulos;
E conhecereis a verdade, e a verdade vos libertará.
João 8:31,32
ASP .NET Core - Criando uma aplicação ASP .NET
Core MVC com o VS 2017 – V
http://www.macoratti.net/17/04/aspcore_mvcfilme5.htm

  Neste
artigo
eu vou
mostra
r como
criar
uma
aplicaç
ão ASP
.NET
Core
MVC
usando
o VS
2017.

Continuando a quarta parte do artigo  vamos entender como


funciona a configuração e o acesso ao banco de dados SQL
Server Local DB   usado no projeto.

Nós já vimos que o contexto do banco de


dados Filme - MvcFilmeContext - é adicionado ao contâiner
de  injeção de dependência   nativa da ASP .NET Core no
arquivo Startup.cs.

....
// This method gets
called by the runtime.
Use this method to
add services to the
container.
public void
ConfigureServices(IS
erviceCollection
services)
{
// Add
framework services.

services.AddMvc();

services.AddDbConte
xt<MvcFilmeContext
>(options =>

options.UseSqlServer
(Configuration.GetC
onnectionString("Mv
cFilmeContext")));
}
....

O objeto MvcFilmeContext manipula a tarefa de se conectar


com o banco de dados e mapear os objetos Filme para os
registros do banco de dados.

O sistema de configuração ASP.NET Core lê a ConnectionString,


sendo que , para desenvolvimento local, ele obtém a string de
conexão do arquivo appsettings.json:

{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
},
"ConnectionStrings": {
"MvcFilmeContext":
"Server=(localdb)\\mssqllocaldb;Database=MvcFilmeCo
ntext-af418162-dae9-452f-a5a1-
6d6e066cfacc;Trusted_Connection=True;MultipleActiveR
esultSets=true"
}
}

Quando você implanta o aplicativo em um servidor de teste ou


de produção, você pode usar uma variável de ambiente ou outra
abordagem para definir a string de conexão para um SQL Server
real.

Conhecendo o SQL Server Express


LocalDB
O SQL Server LocalDB é uma versão mais leve do SQL Server
Express Engine sendo iniciado sob demanda e executado em
modo user, dessa forma sua configuração não é complexa. Por
padrão o banco de dados LocalDB cria arquivos .mdf na
pasta C:/Users/<user>.

Vamos dar uma espiada no banco de dados MvcFilmeContext e


na tabela Filme criados para a nossa aplicação.

No menu View clique em SQL Server Object Explorer :

A seguir expanda o banco de dados MvcFilmeContext;


Clique com o botão direito do mouse sobre a tabela Filme e a
seguir clique em View Designer:

Abaixo vemos a estrutura da tabela Filme que foi criada


contendo os campos : ID, Genero, Lancamento, Preco e Titulo ,
que correspondem às propriedades que definimos na
classe Filme, o nosso modelo.
Observe que o campo ID foi definido como uma chave
primária e do tipo Identity, e assim, é um campo
autoincremental controlado pelo SGBD.

Para visualizar os dados da tabela basta clicar com o botão


direito do mouse sobre a tabela a seguir em View Data:

Vamos ver os dados do filme que cadastramos conforme a figura


abaixo:
Quando iniciamos nossa aplicação pela primeira vez vimos que o
banco de dados foi criado e a tabela foi criada vazia.

Podemos alterar esse comportamento e alimentar a nossa tabela


durante a sua criação via código.

Vamos então ver como podemos fazer isso...

Alimentando o banco de dados


Vamos criar uma classe chamada SeedData na pasta Models e
incluir o código abaixo nesta classe :

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
namespace MvcFilme.Models
{
public class SeedData
{
public static void Initialize(IServiceProvider
serviceProvider)
{
using (var context = new MvcFilmeContext(

serviceProvider.GetRequiredService<DbContextOptions<MvcFil
meContext>>()))
{
// porcura por filmes
if (context.Filme.Any())
{
return; //DB foi alimentado
}
context.Filme.AddRange(
new Filme
{
Titulo = "A Bela e a Fera",
Lancamento = DateTime.Parse("2017-3-16"),
Genero = "Fantasia/Romance",
Preco = 7.99M
},
new Filme
{
Titulo = "Caça-Fantasmas",
Lancamento = DateTime.Parse("1984-3-13"),
Genero = "Comedia",
Preco = 8.99M
},
new Filme
{
Titulo = "Kong - A ilha da Caveira",
Lancamento = DateTime.Parse("2017-3-09"),
Genero = "Ficção",
Preco = 9.99M
},
new Filme
{
Titulo = "Rio Bravo",
Lancamento = DateTime.Parse("1959-4-15"),
Genero = "Western",
Preco = 3.99M
}
);
context.SaveChanges();
}
}
}
}

Esta classe define o método Initialize() onde estamos incluindo


alguns filmes na tabela Filme do banco de
dados MvcFilmeContext.

Para usar esta classe vamos incluir a linha de código destacada


em azul no método Configure() do arquivo Startup.cs :

......
// This method gets called by the runtime. Use this method
to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app,
IHostingEnvironment env, ILoggerFactory loggerFactory)
{

loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template:
"{controller=Home}/{action=Index}/{id?}");
});

SeedData.Initialize(app.ApplicationServices);
}
......

Agora delete o registro que foi incluido na tabela Filme e


reinicie a aplicação novamente. (F5 ou CTRL+F5)

Após clicar no link Filmes do macoratti  você deverá ver a


relação de filmes exibida conforme a figura a seguir:
Vemos assim as informações dos filmes que definimos no
arquivo SeedData incluidos na tabela Filme.

Repetindo os procedimentos para visualizar os dados da


tabela Filme no SQL Server Object Explorer podemos verificar
o conteúdo da tabela Filme:
Na próxima parte do artigo  vamos ajustar o controller e as
views geradas da nossa aplicação.

Respondeu Jesus, e disse-lhes: Ainda que eu testifico de mim


mesmo, o meu testemunho é verdadeiro, porque sei de onde
vim, e para onde vou; mas vós não sabeis de onde venho,
nem para onde vou.
Vós julgais segundo a carne; eu a ninguém julgo.
E, se na verdade julgo, o meu juízo é verdadeiro, porque não
sou eu só, mas eu e o Pai que me enviou.
João 8:14-16
ASP .NET Core - Criando uma aplicação ASP .NET
Core MVC com o VS 2017 – VI
http://www.macoratti.net/17/04/aspcore_mvcfilme6.htm

  Neste
artigo
eu vou
mostra
r como
criar
uma
aplicaç
ão ASP
.NET
Core
MVC
usando
o VS
2017.

Continuando a quinta parte do artigo  vamos ajustar os métodos


do controller FilmesController e das respectivas Views geradas.

Vamos começar abrindo o arquivo Filme na pasta Models e


incluir as linhas de código destacas em azul conforme mostrado
a seguir:

using System;
using System.ComponentModel.DataAnnotations;
namespace MvcFilme.Models
{
public class Filme
{
public int ID { get; set; }
public string Titulo { get; set; }

[Display(Name = "Data de Lançamento")]


[DataType(DataType.Date)]
public DateTime Lancamento { get; set; }

[Display(Name = "Gênero")]
public string Genero { get; set; }

[Display(Name = "Preço")]
public decimal Preco { get; set; }
}
}

Incluimos alguns atributos que vão alterar a exibição e a


formatação das propriedades. Esses atributos são conhecidos
como atributos Data Annotations.

Os atributos Data Annotations foram introduzido no .NET 3.5


como uma forma de adicionar a validação para as classes usadas
por aplicações ASP.NET.

Para usar este recurso devemos incluir o


namespace System.ComponentModel.DataAnnotations, pois é
ele que provê atributos de classes (usados para definir
metadados) e métodos que podemos usar em nossas classes
para alterar as convenções padrão e definir um comportamento
personalizado que pode ser usado em vários cenários.

Incluimos os atributos Display nas propriedades Lancamento,


Genero e Preco e o atributo DataType no atributo Lancamento.
Esses atributos permitem validar e alterar a exibição do texto das
propriedades.

O atributo Display especifica oque exibir para o nome do


campo. No exemplo iremos exibir o nome Data de
Lançamento para o campo Lancamento e os nomes Gênero e
Preço para os respectivos campos.

O atributo DataType especifica o tipo de dados (Date), de forma


que a informação armazenada será a data e hora mas somente a
data será exibida na view.
Após essas alterações vamos executar a aplicação e clicar no link
para exibir os filmes. Iremos obter o seguinte resultado:

Observe que a View agora exibe os nomes  Data de Lançamento,


Gênero e Preço conforme a definição usada nos atributos na
classe Filme.

Veja também que cada filme exibe links para realizar a edição do
filme, exibir os detalhes do filme e deletar o filme no final da
linha de cada filme.

Podemos ver a definição desses links no


arquivo Index.cshtml da pasta Views/Filmes. Abaixo vemos o
trecho de código que mostra esta definição :

...
</td>
<td>
@Html.DisplayFor(modelItem => item.Genero)
</td>
<td>
@Html.DisplayFor(modelItem => item.Preco)
</td>
<td>
<a asp-action="Edit" asp-route-
id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-
id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-
id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>

Os links Edit, Details e Delete são gerados pela Tag Helper MVC


Core Anchor no arquivo /Filmes/Index.cshtml.

As Tag Helpers permitem que o código do lado do servidor


participe na criação e renderização de elementos HTML nos
arquivos Razor. No código acima, a tag helper Anchor gera
dinamicamente o valor do atributo HTML href a partir do
método Action do controlador e do id da rota.

Assim, esta tag helper foi usada para gerar


atributos href para vincular(link) para uma determinada ação
do controlador ou rota MVC. Ela é uma alternativa ao uso de
métodos @Html.ActionLink ou @Url.Action. Veja um exemplo
comparando as abordagens abaixo:

@Html.ActionLink("Registrar", "Registrar", "Conta")


<a href="@Url.Action("Registrra", "Conta")">Registrar</a>
<a asp-controller="Conta" asp-
action="Registrar">Registrar</a>

Abaixo vemos como o código acima é renderizado após a página


ser exibida no navegador:
....
<td>
<a href="/Filmes/Edit/5">Edit</a> |
<a href="/Filmes/Details/5">Details</a>     |
<a href="/Filmes/Delete/5">Delete</a>
</td>
.....

Mas qual a lógica é usada para renderizar o link nesse formato ?

Para saber isso devemos ver as configurações de roteamento no


arquivo Startup.cs :

....
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template:
"{controller=Home}/{action=Index}/{id?}");      
});
SeedData.Initialize(app.ApplicationServices);
}
}
}

Seguindo a lógica definida no roteamento a ASP.NET Core


converte a url http://localhost:1234/Filmes/Edit/4 em uma
requisição (request) para o método Action Edit do
controlador FilmesController com o parâmetro Id igual 4.

No controlador FilmesController temos dois métodos Edit.


Vamos examinar cada um deles. Abra o
arquivo FilmesController na pasta Controllers no primeiro
método Action Edit visto a seguir:

// GET: Filmes/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var filme = await _context.Filme.SingleOrDefaultAsync(m
=> m.ID == id);
if (filme == null)
{
return NotFound();
}
return View(filme);
}

Este código mostra o método HTTP GET Edit, que localiza o


filme com o id informado e preenche o formulário para edição
de dados gerado pelo arquivo Razor Edit.cshtml na
pasta Home/Filmes.

Agora a seguir temos o segundo método Edit:

// POST: Filmes/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id,
[Bind("ID,Titulo,Lancamento,Genero,Preco")] Filme filme)
{
if (id != filme.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(filme);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!FilmeExists(filme.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(filme);
}

Este código mostra o método HTTP POST Edit que processa os


valores dos filmes postados no formulário quando da edição dos
dados e quando o formulário for enviado(POST) ao servidor.

O atributo [Bind] é uma maneira de proteger contra a


sobreposição e evitar que dados sejam injetados na requisição
pois serão aceitas somente as propriedades informadas no Bind.
Você só deve incluir propriedades no atributo [Bind] que você
deseja alterar. (Usar ViewModels fornecer uma abordagem
alternativa para evitar a sobreposição.)

O atributo [HttPost] especifica que este método Edit só pode


ser invocado para requisições HTTP POST. (O atributo [HttpGet] é
o padrão e não precisa ser aplicado explicitamente)

O atributo ValidateAntiForgeryToken é usado para evitar a


falsificação de uma requisição POST e funciona em conjunto com
o token anti-falsificação gerada na respectiva view Edit.cshtml
que é gerado na view  pela tag helper Form :   <form asp-
action="Edit">
Assim, a tag helper Form gera um token anti-falsificação oculto
que deve corresponder ao token anti-falsificação
[ValidateAntiForgeryToken] gerado no método Edit do
controlador FilmesController.
Quando o sistema de scaffolding cria a View Edit, ele examinou
a classe Filme e criou o código para renderizar
elementos <label> e <input> para cada propriedade da classe.

Abaixo temos o código da View Edit gerada:

@model MvcFilme.Models.Filme
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<form asp-action="Edit">
<div class="form-horizontal">
<h4>Filme</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-
danger"></div>
<input type="hidden" asp-for="ID" />
<div class="form-group">
<label asp-for="Titulo" class="col-md-2 control-
label"></label>
<div class="col-md-10">
<input asp-for="Titulo" class="form-control" />
<span asp-validation-for="Titulo" class="text-
danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Lancamento" class="col-md-2 control-
label"></label>
<div class="col-md-10">
<input asp-for="Lancamento" class="form-
control" />
<span asp-validation-for="Lancamento" class="text-
danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Genero" class="col-md-2 control-
label"></label>
<div class="col-md-10">
<input asp-for="Genero" class="form-control" />
<span asp-validation-for="Genero" class="text-
danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Preco" class="col-md-2 control-
label"></label>
<div class="col-md-10">
<input asp-for="Preco" class="form-control" />
<span asp-validation-for="Preco" class="text-
danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-
default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

O código gerado pelo Scaffolding usa vários métodos Tag


Helper para simplificar a marcação HTML. A tag
helper Label exibe o nome do campo ("Titulo", "Data do
Lançamento", "Gênero" ou "Preço"). A tag
Helper Input renderiza o elemento HTML <input>. A Tag
Helper validation exibe todas as mensagens de validação
associadas a essa propriedade.
Os elementos <input> estão em um elemento HTML
<form> cujo atributo Action está definido para ser postado na
URL /Filmes/Edit/id.

Os dados do formulário serão postados para o servidor quando


o botão Salvar for clicado. A última linha antes do
elemento </form> de fechamento mostra o token XSRF oculto
gerado pelo tag helper do formulário.

Vejamos novamente o código do método Action Edit do


controlador FilmesController:

// POST: Filmes/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id,
[Bind("ID,Titulo,Lancamento,Genero,Preco")] Filme filme)
{
if (id != filme.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(filme);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!FilmeExists(filme.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(filme);
}

O Model Binding aceita os valores enviados do formulários e cria


um objeto Filme que é passado como o parâmetro de filme.

O método ModelState.IsValid verifica se os dados enviados no


formulário podem ser usados para modificar  (editar ou
atualizar) um objeto Filme. Se os dados estiverem válidos, serão
salvos.

Os dados de filme atualizados (editados) são salvos no banco de


dados chamando o método SaveChangesAsync do contexto do
banco de dados.

Depois de salvar os dados, o código redireciona o usuário para o


método Action Index da classe FilmesController, que exibe a
coleção de filmes, incluindo as alterações feitas.

Antes de o formulário ser postadso no servidor, a validação do


lado do cliente verifica as regras de validação nos campos. Se
houver algum erro de validação, uma mensagem de erro é
exibida e o formulário não é postado.

Se o JavaScript estiver desativado, você não terá a validação do


lado do cliente, mas o servidor detectará os valores postados
que não são válidos e os valores do formulário serão exibidos
novamente com mensagens de erro.

Todos os métodos HttpGet em FilmesController seguem um
padrão semelhante. Eles obtêm um objeto filme (ou lista de
objetos, no caso de Index) e passam o objeto (modelo) para a
view.

O método Create passa um objeto filme vazio para a


view Create. Todos os métodos que criam, editam, excluem ou
modificam dados fazem isso na sobrecarga [HttpPost] do
método.

A modificação de dados em um método HTTP GET é um risco de


segurança. A modificação de dados em um método HTTP GET
também viola as melhores práticas HTTP e o padrão REST, que
especifica que as solicitações GET não devem alterar o estado de
seu aplicativo. Em outras palavras, executar uma operação GET
deve ser uma operação segura que não tem efeitos colaterais e
não modifica os dados persistentes.

Para concluir vamos alterar todos os textos das views geradas


traduzindo-os para o português. Abaixo vemos o resultado na
view Index:

Na próxima parte do artigo  vamos incluir a funcionalidade


de  procurar dados  na nossa aplicação.

(Disse Jesus) "Quem ama a sua vida perdê-la-á, e quem neste


mundo odeia a sua vida, guardá-la-á para a vida eterna."
João 12:25

ASP .NET Core - Criando uma aplicação ASP .NET


Core MVC com o VS 2017 – VII
http://www.macoratti.net/17/04/aspcore_mvcfilme7.htm

  Neste
artigo
eu vou
mostra
r como
criar
uma
aplicaç
ão ASP
.NET
Core
MVC
usando
o VS
2017.

Continuando a sexta parte do artigo  vamos implementar a


funcionalidade de procurar informações em nossa aplicação.

Para isso vamos implementar a funcionalidade de buscar dados


no método Action Index e procurar filmes por titulo e por
gênero.

Filtrando os filmes pelo título


Abra o controlador FilmesController na pasta Controllers e
altere o método Index() conforme abaixo:

// GET: Filmes
public async Task<IActionResult> Index(string
criterioBusca)
{
var filmes = from m in _context.Filme
select m;
if (!String.IsNullOrEmpty(criterioBusca))
{
filmes = filmes.Where(f =>
f.Titulo.Contains(criterioBusca));
}
return View(await filmes.ToListAsync());
}

Na primeira linha do método temos uma consulta LINQ para


selecionar filmes :

   var filmes = from m in _context.Filme


                       select m;

Aqui a consulta foi apenas definida e não executada ainda.

Na sequência verificamos se o parâmetro criterioBusca não for


vazio nem nulo a consulta de filmes será modificada para filtrar
pelo critério informado o titulo dos filmes.

  if (!String.IsNullOrEmpty(searchString))
 {
     filmes = filmes.Where(s =>
s.Titulo.Contains(searchString));
 }

O código s => s.Titulo.Contains() é uma Expressão Lambda. As


lambdas são usadas em consultas LINQ baseadas em método
como argumentos para métodos de operador de consulta
padrão, como o método Where ou Contains (usado no código
acima).

As consultas LINQ não são executadas quando são definidas ou


quando são modificadas chamando um método, como Where,
Contains ou OrderBy. Em vez disso, a execução da consulta é
diferida. Isso significa que a avaliação de uma expressão é
atrasada até que seu valor realizado seja iterado  ou o
método ToListAsync seja chamado.

Nota:  O método  Contains  é executado no banco de dados, não


no código C# mostrado acima. A sensibilidade de maiúsculas e
minúsculas na consulta depende do banco de dados e do
collation. No SQL Server, o método Contains mapeia para a
instrução SQL LIKE, que é insensível a maiúsculas e minúsculas.
No SQLlite, com o collation padrão, ele é sensível a maiúsculas e
minúsculas.

Agora, com a aplicação em execução, abra o navegador e


navegue para /Filmes/Index :

A seguir anexe a seguinte string de consulta (criterioBusca) na


URL:  ?criterioBusca=ilha e tecle Enter:
Agora vamos alterar a assinatura do método Index do
controlador para usar um parâmetro chamado id ao invês
de criterioBusca.

Fazendo isso o parâmetro id irá corresponder ao marcador de


possível opcional  {id} usado para as rotas padrão que foram
definidas no arquivo Startup.cs :

....
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template:
"{controller=Home}/{action=Index}/{id?}");
});
....

Então a seguir vamos alterar o método Index do controlador


para usar id ao invês de criterioBusca:

// GET: Filmes
public async Task<IActionResult> Index(string id)
{
var filmes = from m in _context.Filme
select m;
if (!String.IsNullOrEmpty(id))
{
filmes = filmes.Where(f => f.Titulo.Contains(id));
}
return View(await filmes.ToListAsync());
}

Fazendo assim agora podemos passar o valor de busca como um


dado de rota (o segmento da URL) ao invês de um valor string
de consulta.

Podemos agora navegar para :  /Filmes/Index/ilha     (onde ilha


é o critério de busca que esta sendo passado como uma
informação de rota)

Fica muito mais elegante mas não seria viável ficar passando as
informações modificando a URL, então vamos adicionar na
view Index.cshtml uma caixa de busca para nos ajudar a filtrar
os filmes pelo critério.

Antes temos que retornar o método Index do controlador ao


seu código original :

// GET: Filmes
public async Task<IActionResult> Index(string
criterioBusca)
{
var filmes = from m in _context.Filme
select m;
if (!String.IsNullOrEmpty(criterioBusca))
{
filmes = filmes.Where(f =>
f.Titulo.Contains(criterioBusca));
}
return View(await filmes.ToListAsync());
}

Agora abra a view Index.cshtml na pasta /Views/Filme e vamos


alterar o seu código incluindo as linhas de código destacadas em
azul abaixo :

@model IEnumerable<MvcFilme.Models.Filme>
@{
ViewData["Title"] = "Index";
}
<h2>Filmes</h2>
<p>
<a asp-action="Create">Criar Novo</a>
</p>
<form asp-controller="Filmes" asp-action="Index">
<p>
Title: <input type="text" name="criterioBusca">
<input type="submit" value="Filtrar" />
</p>
</form>
...

A tag HTMl <form> usa a tag Helper Form de  maneira que


quando o formulário for submetido (Enviado) a
string criterioBusca será postada para a Action Index no
controlador Filmes realizando o filtro:
Filtrando os filmes pelo Gênero
Para incluir a funcionalidade de filtrar pelos gêneros dos filmes
teremos que criar uma View Model representada pela classe
chamada FilmeGeneroViewModel na pasta Models.

Nota:  Se você não conhece o padrão View Model leia este


artigo:  NET - O padrão MVVM (Model-View-ViewModel)
revisitado - Macoratti

Clique com o botão direito do mouse sobre a pasta Models e a


seguir clique em Add -> Class e informe o
nome FilmeGeneroViewModel;

A seguir inclua o código abaixo nesta classe:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace MvcFilme.Models
{
public class FilmeGeneroViewModel
{
public List<Filme> filmes;
public SelectList generos;
public string filmeGenero { get; set; }
}
}

A nossa View Model contém:

 Uma lista de Filmes - List<Filme> filmes;


 Um SelectList contendo a lista de gêneros. Isso permitirá
que o usuário selecione um gênero na lista -  SelectList
generos;
 O gênero selecionado - string filmeGenero;

Essa classe será usada como nosso Model para retornar a lista de
filmes e lista de gêneros para exibição na view Index.

Agora vamos alterar o método Index do


controlador FilmesController conforme o código a seguir:

// GET: Filmes
public async Task<IActionResult> Index(string
filmeGenero,string criterioBusca)
{
IQueryable<string> consultaGenero = from m in
_context.Filme
orderby m.Genero
select m.Genero;
var filmes = from m in _context.Filme
select m;
if (!String.IsNullOrEmpty(criterioBusca))
{
filmes = filmes.Where(s =>
s.Titulo.Contains(criterioBusca));
}
if (!String.IsNullOrEmpty(filmeGenero))
{
filmes = filmes.Where(x => x.Genero ==
filmeGenero);
}
var filmeGeneroVM = new FilmeGeneroViewModel();
filmeGeneroVM.generos = new SelectList(await
consultaGenero.Distinct().ToListAsync());
filmeGeneroVM.filmes = await filmes.ToListAsync();
return View(filmeGeneroVM);
}

Nosso método Index passou a receber dois


parâmetros : filmeGenero e criterioBusca.

No código estamos usando uma  consulta LINQ para retornar


todos os gêneros dos filmes:

IQueryable<string> consultaGenero = from m in


_context.Filme
orderby
m.Genero
select
m.Genero;

Depois verificamos se o parâmetro filmeGenero não é vazio


nem nulo, e neste caso, a consulta de generos será modificada
para filtrar pelo critério informado no gênero dos filmes.

            if (!String.IsNullOrEmpty(filmeGenero))
            {
                filmes = filmes.Where(x => x.Genero ==
filmeGenero);
            }

A seguir criamos uma instância da


classe FilmeGeneroViewModel() e usamos a
classe SelectList para projetar uma lista de gêneros distintas
para não haver gêneros duplicados.

Agora vamos exibir a lista de gêneros na página Index de forma


que o usuário possa escolher por qual gênero deseja filtrar.

Abra o arquivo Index.cshtml e altere o código conforme


mostrado a seguir:
@model MvcFilme.Models.FilmeGeneroViewModel
@{
ViewData["Title"] = "Index";
}
<h2>Filmes</h2>
<p>
<a asp-action="Create">Criar Novo</a>
</p>
<form asp-controller="Filmes" asp-action="Index">
<p>
<select asp-for="filmeGenero" asp-
items="Model.generos">
<option value="">Todos</option>
</select>
Titulo: <input type="text" name="criterioBusca">
<input type="submit" value="Filtrar" />
</p>
</form>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model =>
model.filmes[0].Titulo)
</th>
<th>
@Html.DisplayNameFor(model =>
model.filmes[0].Lancamento)
</th>
<th>
@Html.DisplayNameFor(model =>
model.filmes[0].Genero)
</th>
<th>
@Html.DisplayNameFor(model =>
model.filmes[0].Preco)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.filmes) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Titulo)
</td>
<td>
@Html.DisplayFor(modelItem => item.Lancamento)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genero)
</td>
<td>
@Html.DisplayFor(modelItem => item.Preco)
</td>
<td>
<a asp-action="Edit" asp-route-
id="@item.ID">Editar</a> |
<a asp-action="Details" asp-route-
id="@item.ID">Detalhes</a> |
<a asp-action="Delete" asp-route-
id="@item.ID">Deletar</a>
</td>
</tr>
}
</tbody>
</table>

Observe que agora o modelo usado é a


classe FilmeGeneroViewModel : @model
MvcFilme.Models.FilmeGeneroViewModel

Incluimos um dropdownlist para exibir todos os gêneros dos


filmes na página :
 <select asp-for="filmeGenero" asp-items="Model.generos">
            <option value="">Todos</option>
 </select>

Agora execute a aplicação novamente e abra na página de filmes


para visualizar as alterações que permitem filtrar por gênero e
por título do filme:

Na próxima parte do artigo  vamos mostrar como podemos


tratar com a alteração do modelo de dados com inclusão de
novos campos.

Pegue o projeto funcionando até aqui neste link:    


MvcFilme7.zip
Mas a hora vem, e agora é, em que os verdadeiros
adoradores adorarão o Pai em espírito e em verdade; porque
o Pai procura a tais que assim o adorem.
Deus é Espírito, e importa que os que o adoram o adorem em
espírito e em verdade.
João 4:23,24
ASP .NET Core - Criando uma aplicação ASP .NET
Core MVC com o VS 2017 – VIII
http://www.macoratti.net/17/04/aspcore_mvcfilme8.htm

  Neste
artigo
eu vou
mostra
r como
criar
uma
aplicaç
ão ASP
.NET
Core
MVC
usando
o VS
2017.

Continuando a sétima parte do artigo  vamos usar o Entity


Framework Code First Migrations para adicionar um novo
campo ao modelo e migrar essa alteração para o banco de
dados.

Quando você usa o EF Code First para criar automaticamente um


banco de dados, o Code First adiciona uma tabela ao banco de
dados para ajudar a rastrear se o esquema do banco de dados
está em sincronia com as classes do modelo de onde ele foi
gerado.

Se eles não estiverem sincronizados, o EF lançará uma exceção.


Isso torna mais fácil encontrar problemas inconsistentes de
banco de dados.
Adiciona a
propriedade Classificacao ao Model
Filme
Abra o arquivo Filme.cs na pasta Moldel e inclua a
propriedade Classificacao conforme mostrado o código :

public class Filme


{
public int ID { get; set; }
public string Titulo { get; set; }
[Display(Name = "Data de Lançamento")]
[DataType(DataType.Date)]
public DateTime Lancamento { get; set; }
[Display(Name = "Gênero")]
public string Genero { get; set; }
[Display(Name = "Preço")]
public decimal Preco { get; set; }
public string Classificacao { get; set; }
}

Dê um Build (CTRL+SHIFT+B) na Solution.

Como adicionamos um novo campo à classe Filme, vamos ter


que atualizar a lista de vinculação para que esta nova
propriedade seja incluída.

Abra o controlador FilmesController.cs, e atualize o atributo


[Bind] para os métodos de Action Create e Edit incluindo a
propriedade Classificacao:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult>
Create([Bind("ID,Titulo,Lancamento,Genero,Preco,Classificacao")
] Filme filme)
....
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id,
[Bind("ID,Titulo,Lancamento,Genero,Preco,Classificacao")] Filme
filme)
....

Precisamos também atualizar a respectivas Views a fim de exibir,


criar e editar a nova propriedade Classificacao.

Abra o arquivo /Views/Filmes/Index.cshtml e inclua o


campo Classificacao :

.....
</th>
<th>
@Html.DisplayNameFor(model =>
model.filmes[0].Classificacao)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.filmes) {
<tr>
....
<td>
@Html.DisplayFor(modelItem => item.Preco)
</td>
<td>
@Html.DisplayFor(modelItem =>
item.Classificacao)
</td>
....

A seguir atualize o arquivo /Views/Filmes/Create.cshtml com


um campo Classificacao. Você pode copiar e colar o "form
group" anterior e deixar o intelliSense ajudá-lo a atualizar os
campos. IntelliSense funciona com Tag Helpers.
...
<form asp-action="Create">
<div class="form-horizontal">
<h4>Filme</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-
danger"></div>
<div class="form-group">
<label asp-for="Titulo" class="col-md-2 control-
label"></label>
<div class="col-md-10">
<input asp-for="Titulo" class="form-control" />
<span asp-validation-for="Titulo" class="text-
danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Classificacao" class="col-md-2
control-label"></label>
<div class="col-md-10">
<input asp-for="Titulo" class="form-control" />
<span asp-validation-for="Classificacao"
class="text-danger"></span>
</div>
</div>
...

Após realizar esas alterações a aplicação não vai funcionar até


que atualizemos o banco de dados para incluir o novo campo.

Se você executar a aplicação vai receber a seguinte mensagem


de erro :  SqlException: Nome de coluna inválido
'Classificacao'.

Você está vendo esse erro porque a classe de


modelo Filme atualizada é diferente do esquema da tabela
Filmes do banco de dados existente. (Não existe ainda a coluna
Classificacao na tabela do banco de dados.)
Existem algumas abordagens para resolver o erro:

- Fazer com que o Entity Framework automaticamente elimine e


recrie o banco de dados com base no esquema da classe do
novo modelo. Esta abordagem é muito conveniente no início do
ciclo de desenvolvimento quando você está fazendo
desenvolvimento ativo em um banco de dados de teste; Ele
permite que você evolua rapidamente o modelo e o esquema de
banco de dados juntos. A desvantagem, porém, é que você
perde os dados existentes no banco de dados - então você não
quer usar essa abordagem em um banco de dados de produção!
Usar um inicializador para preencher automaticamente um banco
de dados com dados de teste é muitas vezes uma maneira
produtiva de desenvolver um aplicativo.

- Modificar explicitamente o esquema do banco de dados


existente para que ele corresponda às classes de modelo. A
vantagem dessa abordagem é que você mantém seus dados.
Você pode fazer essa alteração manualmente ou criando um
script de alteração de banco de dados.

- Usar o Code First Migrations para atualizar o esquema do


banco de dados.

Neste artigo vamos usar a opção - Code First Migrations.

Usando o Code First Migrations para


atualizar o banco de dados
Vamos atualizar a classe SeedData para que ela forneça um
valor para a nova coluna Classificacao.

Nota:

Classificação de filmes no Brasil:


L (verde) – Livre para todos os públicos.
10(azul)– Não recomendado para menores de 10 anos.
12(amarelo)– Não recomendado para menores de 12 anos.
14(laranja) – Não recomendado para menores de 14 anos.
16 (vermelho) – Não recomendado para menores de 16 anos. Por poder
conter nudez parcial ou violência.
18(preto) – Não recomendado para menores de 18 anos. Contém conteúdo
explícito apropriado somente para adultos.

A classificação indicativa vigente nos Estados Unidos adota a seguinte


classificação:

G – O filme não contém nada que os pais se ofenderiam caso


assistissem com seus filhos.
PG – Os pais devem verificar o que se passa no filme, pois pode conter
conteúdo não apropriado para os filhos mais novos.
PG13 – Os pais devem ficar atentos porque o filme pode conter
conteúdo não apropriado para pré-adolescentes.
R – O filme contém algum tipo de conteúdo adulto. Os pais devem
certificar-se sobre o filme antes de permitir que seus filhos
adolescentes assistam.
NC-17– Conteúdo apropriado somente para adultos. Não permitido
para jovens ou crianças.

Uma alteração de exemplo é mostrada abaixo, mas você


precisará fazer essa alteração para cada novo filme:

.....
context.Filme.AddRange(
new Filme
{
Titulo = "A Bela e a Fera",
Classificacao="L",
Lancamento = DateTime.Parse("2017-3-16"),
Genero = "Fantasia/Romance",
Preco = 7.99M
},
....

Após incluir a classificação em todos os filmes na


classe SeeData dê um Build na solução e abra uma janela de
prompt de comandos e posicione-se na pasta do projeto da sua
aplicação.
Nota: Para saber a localização da pasta do projeto clique com o
botão direito sobre o projeto e a seguir clique em  Open Folder in
File Explorer.

A seguir digite o seguinte comando no prompt de


comando:  dotnet ef migrations add Classificacao

Ao final da execução você verá a mensagem:

A seguir digite o comando :  dotnet ef database update

Se você receber a mensagem de erro :  No


executable
found matching command "dotnet-ef":

- Verifique se você está na pasta do projeto (que contém o


arquivo .csproj).
- Verifique se o arquivo .csproj contém o
pacote "Microsoft.EntityFrameworkCore.Tools.DotNet" NuGet
.

O comando migrations add diz à estrutura de migração para


examinar o Model Filme atual com o esquema atual do banco de
dados Filmes e criar o código necessário para migrar o BD para
o novo modelo.

O nome "Classificacao" é arbitrário e é usado para nomear o


arquivo de migração. É útil usar um nome significativo para a
etapa de migração.

Se você excluir todos os registros no Banco de dados , o


inicializador vai preencher novamente o Banco e vai incluir o
campo Classificacao.

Podemos verificar a estrutura do banco de dados acionando o


menu View -> SQL Server Object Explorer
Execute a aplicação e verifique se você pode criar, editar e exibir
filmes com o campo Classificacao.

Nota: Você também deve adicionar o campo  Classificacao  nas


views  Edit.cshtml, Details.cshtml e Delete.cshtml.
Na próxima parte do artigo  vamos tratar da lógica de validação
do Model Filme em nossa aplicação.

Pegue o projeto funcionando até aqui neste link:    


MvcFilme8.zip

(Disse Jesus) - 'Aquele que tem os meus mandamentos e os


guarda esse é o que me ama; e aquele que me ama será
amado de meu Pai, e eu o amarei, e me manifestarei a ele.'
João 14:21
ASP .NET Core - Criando uma aplicação ASP .NET
Core MVC com o VS 2017 – IX
http://www.macoratti.net/17/04/aspcore_mvcfilme9.htm

  Neste
artigo
eu vou
mostra
r como
criar
uma
aplicaç
ão ASP
.NET
Core
MVC
usando
o VS
2017.

Continuando a oitava   parte do artigo   vamos usar o Entity


Framework Code First Migrations para adicionar um novo
campo ao modelo e migrar essa alteração para o banco de
dados.

Neste artigo vamos adicionar a lógica de validação ao


Model Filme e verificar se as regras são aplicadas sempre que
um usuário cria ou edita um filme.

Mantendo as coisas Simples ( DRY-


Don´t repeat yourself )
Um dos princípios de design do MVC é conhecido pelo
acrônimo DRY ("Do not Repeat Yourself"). A ASP.NET MVC
incentiva você a especificar a funcionalidade ou o
comportamento apenas uma vez e, em seguida, fazer com que
ele seja refletido em toda parte da sua aplicação. Isso reduz a
quantidade de código que você precisa para escrever e torna o
código menos propenso ao erros, mais fácil de testar e mais fácil
de manter.

Nota:  O princípio  DRY, 'Não se Repita', é um importante


princípio que procura reduzir a duplicação de código e os
problemas oriundos dessa prática. A definição formal desse
princípio diz :   "Cada parte do conhecimento deve ter uma
representação única, não ambígua e definitiva dentro do
sistema."

O suporte de validação fornecido pelo MVC e pelo Entity


Framework Core Code First é um bom exemplo do princípio DRY
em ação. Você pode declarativamente especificar regras de
validação em um lugar (na classe do modelo) e as regras são
aplicadas em todos os lugares na aplicação

Adicionando regras de validação ao


Model Filme
Para aplicar as regras no Model Filme vamos usar o
recurso DataAnnotations.

A DataAnnotations fornece um conjunto embutido de atributos


de validação que você aplica declarativamente a qualquer classe
ou propriedade. Ela também contém atributos de formatação
como DataType que ajudam na formatação e não fornecem
qualquer validação. 

Para saber mais sobre esse assunto veja o artigo :   C# -


Validando dados com Data Annotations - Macoratti

Abra o arquivo Filme.cs da pasta Models e atualize o código da


classe usando os atributos de validação StringLength,
RegularExpression e Range :

using System;
using System.ComponentModel.DataAnnotations;
namespace MvcFilme.Models
{
public class Filme
{
public int ID { get; set; }
[StringLength(60, MinimumLength = 3)]
[Required]
public string Titulo { get; set; }
[Display(Name = "Data de Lançamento")]
[DataType(DataType.Date)]
public DateTime Lancamento { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
[Required]
[StringLength(30)]
[Display(Name = "Gênero")]
public string Genero { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
[Display(Name = "Preço")]
public decimal Preco { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
[StringLength(5)]
[Required]
public string Classificacao { get; set; }
}
}

Os atributos de validação especificam o comportamento que


você deseja aplicar nas propriedades do modelo ao qual são
aplicados.

Os atributos Required e MinimumLength indicam que uma


propriedade deve ter um valor; Mas nada impede que um
usuário entre com espaço em branco para satisfazer essa
validação.

O atributo RegularExpression é usado para limitar quais


caracteres podem ser inseridos. No código acima, Genero e
Classificacao devem usar apenas letras  (espaço em branco,
números e caracteres especiais não são permitidos).

O atributo Range restringe um valor dentro de um intervalo


especificado.

O atributo StringLength permite definir o comprimento máximo


de uma propriedade string e, opcionalmente, seu comprimento
mínimo.

Tipos de valor (como decimal, int, float, DateTime) são


inerentemente necessários e não é necessário o atributo
[Required].

Ter regras de validação automaticamente aplicadas pelo ASP.NET


ajuda a tornar o aplicativo mais robusto. Ele também garante
que você não se esqueça de validar algo e, inadvertidamente,
deixar dados sujos no banco de dados.

Validação de erros na Interface de


Usuário (UI)
Agora vamos executar a aplicação e criar um novo filme
informando dados inválidos. Você vai obter o seguinte resultado:
Observe como o formulário automaticamente  processou uma
mensagem de erro de validação apropriada em cada campo que
contém um valor inválido.

Os erros são aplicados tanto do lado do cliente (usando


JavaScript e jQuery) e do lado do servidor (no caso de um
usuário que tem o JavaScript desativado).

Um benefício significativo é que você não precisa alterar uma


única linha de código na classe FilmesController ou na
View Create.cshtml para habilitar essa validação da UI. O
controlador e as Views criadas anteriormente captaram
automaticamente as regras de validação que você especificou
utilizando atributos de validação nas propriedades da classe do
modelo Filme. Faça o teste de validação usando o método
Action Editar, e a mesma validação será aplicada.
Os dados do formulário não são enviados para o servidor até
que não haja erros de validação do lado do cliente.

Como a validação Funciona ?


Você pode estar perguntando como a validação da View foi
gerada sem nenhuma atualização do código do controlador nem
nas views Create nem Edit   ?

Vamos da um espiada nos dois métodos Create do


controlador FilmesController :

// GET: Filmes/Create
public IActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult>
Create([Bind("ID,Titulo,Lancamento,Genero,Preco,Classificacao")]
Filme filme)
{
if (ModelState.IsValid)
{
_context.Add(filme);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(filme);
}

O primeiro método Create(HTTP GET) exibe o


formulário Create inicial. A segunda versão de Create
([HttpPost]) processa a postagem (Post) do formulário e chama
o método ModelState.IsValid para verificar se o filme tem
qualquer erro de validação.

Chamar este método avalia quaisquer atributos de validação que


foram aplicados ao objeto. Se o objeto tiver erros de validação,
o método Create re-exibe o formulário. Se não houver erros, o
método salva o novo filme no banco de dados. Em nosso
exemplo de filme, o formulário não é enviado ao servidor
quando há erros de validação detectados no lado do cliente; O
segundo método Create nunca é chamado quando há erros de
validação do lado do cliente.

Se você desativar o JavaScript em seu navegador, a validação do


cliente será desabilitada e você poderá testar o método HTTP
POST Create onde teremos ModelState.IsValid detectando
quaisquer erros de validação.

Você pode definir um ponto de interrupção no


método [HttpPost] Create e verificar que o método nunca é
chamado, a validação do lado do cliente não irá enviar os dados
do formulário quando erros de validação são detectados.Tente
desabilitar o JavaScript em seu navegador, e envie o formulário
com erros, o ponto de interrupção será atingido. Assim você
ainda tem a validação completa mesmo sem JavaScript.

Se você abrir o arquivo Create.cshtml verá o código mostrado


abaixo que é usado pelo método Create para exibir o formulário
inicial e para re-exibir o form quando um error ocorrer:

...
<form asp-action="Create">
<div class="form-horizontal">
<h4>Filme</h4>
<hr />
<div asp-validation-summary="ModelOnly"
class="text-danger"></div>
<div class="form-group">
<label asp-for="Titulo" class="col-md-2 control-
label"></label>
<div class="col-md-10">
<input asp-for="Titulo" class="form-control" />
<span asp-validation-for="Titulo" class="text-
danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Classificacao" class="col-md-2 control-
label"></label>
<div class="col-md-10">
<input asp-for="Titulo" class="form-control" />
<span asp-validation-for="Classificacao"
class="text-danger"></span>
</div>
</div>
...

A Tag Helper input usa os atributos DataAnnotations e produz


atributos HTML necessários para a validação jQuery no lado do
cliente. O Validator Tag Helper exibe erros de validação.

O que é realmente agradável sobre essa abordagem é que nem


o controlador nem a view Create sabem nada sobre as regras de
validação reais sendo aplicadas ou sobre as mensagens de erro
específicas exibidas. As regras de validação e as strings de erro
são especificadas somente na classe Filme. Essas mesmas regras
de validação são aplicadas automaticamente à visualização Edit e
a quaisquer outros modelos de visualizações que você possa
criar que editam seu modelo.

Quando você precisa alterar a lógica de validação, pode fazê-lo


exatamente em um lugar, adicionando atributos de validação ao
modelo (neste exemplo, a classe Filme). Você não terá que se
preocupar com diferentes partes do aplicativo que não sejam
consistentes com a forma como as regras são aplicadas - toda a
lógica de validação será definida em um lugar e usado em todos
os lugares. Isso mantém o código muito limpo, e o torna fácil de
manter e evoluir. E isso significa que você estará honrando
totalmente o princípio DRY.

Usando atributos DataType


Abra o arquivo Filme.cs e examine a classe Filme.

O
namespace System.ComponentModel.DataAnnotations fornec
e atributos de formatação para além do conjunto incorporado de
atributos de validação.

Já aplicamos um valor de enumeração DataType para a data de


lançamento e para os campos de preço.

O trecho de código a seguir mostra as


propriedades DataLancamento e Preco com o
atributo DataType apropriado.

    public class Filme


    {
        public int ID { get; set; }

[StringLength(60, MinimumLength = 3)]


[Required]
public string Titulo { get; set; }
[Display(Name = "Data de Lançamento")]
[DataType(DataType.Date)]
public DateTime Lancamento { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
[Required]
[StringLength(30)]
[Display(Name = "Gênero")]
public string Genero { get; set; }
[Range(1, 100)]
[DataType(DataType.Currency)]
[Display(Name = "Preço")]
public decimal Preco { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
[StringLength(5)]
[Required]
public string Classificacao { get; set; }
}
Os atributos DataType fornecem somente sugestões para o
mecanismo de visualização para formatar os dados e fornecer
atributos como <a> para URLs e <a
href="mailto:EmailAddress.com"> para o email.

Você pode usar o atributo RegularExpression para validar o


formato dos dados. O atributo DataType é usado para
especificar um tipo de dados que é mais específico do que o
tipo intrínseco do banco de dados,  eles não são atributos de
validação.    Nesse caso, só queremos manter o controle da data,
e não da hora. A enumeração DataType fornece muitos tipos de
dados, como Date, TIme, PhoneNumber, Currency,
EmailAddress e etc.

O atributo DataType também pode permitir que o aplicativo


forneça automaticamente recursos específicos de tipo. Por
exemplo, um link mailto: pode ser criado
para DataType.EmailAddress e um seletor de data pode ser
fornecido para DataType.Date em navegadores que suportam
HTML 5. Os atributos DataType emitem atributos HTML 5-
data, que navegadores HTML 5 podem entender.  Assim os
atributos DataType não fornecem qualquer validação.

O atributo DataType.Date não especifica o formato da data que


é exibida. Por padrão, o campo de dados é exibido de acordo
com os formatos padrão com base no CultureInfo do servidor.
Para exibir especificamente o formatao da da Data usamos o
atributo DisplayFormat:

...
[Display(Name = "Data de Lançamento")]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}",
ApplyFormatInEditMode = true)]
[DataType(DataType.Date)]
public DateTime Lancamento { get; set; }
...

A configuração ApplyFormatInEditMode especifica que a
formatação também deve ser aplicada quando o valor é exibido
em uma caixa de texto para edição. (Talvez você não queira
aplicar isso para alguns campos - por exemplo, para valores de
moeda, você provavelmente não vai querer o símbolo de moeda
na caixa de texto para edição.)

Você pode usar o atributo DisplayFormat por si só, mas


geralmente é uma boa idéia usar o atributo DataType. O
atributo DataType transmite a semântica dos dados em vez de
como processá-lo em uma tela e fornece os seguintes benefícios
que você não obtém com DisplayFormat:

- O navegador pode ativar recursos HTML5  (por exemplo, para


mostrar um controle de calendário, o símbolo de moeda
apropriado à localidade, links de e-mail, etc.)
- Por padrão, o navegador renderizará dados usando o formato
correto com base em sua localidade
- O atributo DataType pode habilitar o MVC para escolher o
modelo de campo correto para processar os dados (o
DisplayFormat por si mesmo usa o modelo string).

Nota: A validação jQuery não funciona com o atributo  Range e


DateTime.

Para concluir podemos simplificar o código combinando os


atributos em uma única linha conforme mostrado a seguir:

public class Filme


{
public int ID { get; set; }
[StringLength(60, MinimumLength = 3)]
public string Titulo { get; set; }
[Display(Name = "Data de Lançamento"),
DataType(DataType.Date)]
public DateTime Lancamento { get; set; }
[Display(Name = "Gênero"), RegularExpression(@"^[A-Z]+
[a-zA-Z''-'\s]*$"), Required, StringLength(30)]
public string Genero { get; set; }
[Display(Name = "Preço"), Range(1, 100),
DataType(DataType.Currency)]
public decimal Preco { get; set; }
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$"),
StringLength(5)]
public string Classificacao { get; set; }
}

Na próxima parte do artigo, analisaremos o aplicativo e faremos


algumas melhorias nos métodos Details e Delete gerados
automaticamente.

"(Disse Jesus)Eu sou a porta; se alguém entrar por mim,


salvar-se-á, e entrará, e sairá, e achará pastagens.
O ladrão não vem senão a roubar, a matar, e a destruir; eu
vim para que tenham vida, e a tenham com abundância."
João 10:9,10
ASP .NET Core - Criando uma aplicação ASP .NET
Core MVC com o VS 2017 – X
http://www.macoratti.net/17/04/aspcore_mvcfilme10.htm

  Neste
artigo
eu vou
mostra
r como
criar
uma
aplicaç
ão ASP
.NET
Core
MVC
usando
o VS
2017.

Continuando a nona parte do artigo   vamos analisar o


aplicativo e fazer algumas melhorias nos métodos Details e
Delete gerados automaticamente.

Este artigo conclui esta introdução básica ao ASP .NET Core.

Examinando o método Details


Vamos abrir o arquivo FilmesController.cs na
pasta Controllers e examinar o método Details:

// GET: Filmes/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var filme = await _context.Filme
.SingleOrDefaultAsync(m => m.ID == id);

if (filme == null)
{
return NotFound();
}
return View(filme);
}

O mecanismo de Scaffolding MVC que criou este método Action


adicionou um comentário mostrando uma solicitação HTTP que
invoca o método. Neste caso, é uma solicitação GET com três
segmentos de URL, o controlador Filmes, o método Details e
um valor id. Lembre que esses segmentos são definidos em no
método Configure do arquivo Startup.cs:

...
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
...

O EF facilita a pesquisa dos dados usando o


método SingleOrDefaultAsync. Um recurso de segurança
importante deste método Details é que o código verifica se o
método de pesquisa encontrou um filme antes de tentar fazer
qualquer coisa com ele.

Por exemplo, um hacker pode introduzir erros no site alterando


a URL criada pelos links
de http://localhost:xxxx/Filmes/Details/1 para algo
como http://localhost:xxxx/Filmes/Details/12345 ( Ou algum
outro valor que não represente um filme real) com um objetivo
de provocar um erro.
Se você não fosse feita a verificação de filme nulo, o aplicativo
lançaria uma exceção.

Examinando o método Delete


Vejamos agora os métodos Delete e DeleteConfirm do
controlador FilmesController:

// GET: Filmes/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var filme = await _context.Filme
.SingleOrDefaultAsync(m => m.ID == id);

if (filme == null)
{
return NotFound();
}
return View(filme);
}
// POST: Filmes/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var filme = await _context.Filme.SingleOrDefaultAsync(m
=> m.ID == id);
_context.Filme.Remove(filme);

await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
Observe que o método HTTP GET Delete não exclui o filme
especificado, ele retorna uma view do filme onde você pode
submeter(HttpPost) a exclusão. Executar uma operação de
exclusão em resposta a uma solicitação GET (ou executar uma
operação de edição, ou criação ou qualquer outra operação que
altera dados) abre um buraco de segurança.

O método [HttpPost] que exclui os dados tem o


nome DeleteConfirmed para dar ao método HTTP POST uma
assinatura ou nome exclusivo. As assinaturas de dois métodos
são mostradas abaixo:

        // POST: Filmes/Delete/5


´      // GET:         [HttpPost,
Filmes/Delete/5 ActionName("Delete")]
        public async         [ValidateAntiForgeryToken]
Task<IActionResult> Delet         public async
e(int? id) Task<IActionResult> DeleteConfir
med(int id)

A Common Language Runtime (CLR) requer métodos


sobrecarregados para ter uma assinatura de parâmetro
exclusivo (mesmo nome de método mas lista diferente de
parâmetros). No entanto, aqui você precisa de dois
métodos Delete - um para GET e outro para POST - e ambos
têm a mesma assinatura de parâmetro. (Ambos precisam aceitar
um único inteiro como um parâmetro.)

Existem duas abordagens para este problema, uma delas é dar


aos métodos nomes diferentes. Isso é o que o mecanismo
Scaffolding fez no exemplo anterior. No entanto, isso introduz
um pequeno problema: a ASP.NET mapeia segmentos de um URL
para métodos Action por nome,    e, se você renomear um
método, o roteamento normalmente não seria capaz de
encontrar esse método.

A solução é o que você vê no exemplo, que é adicionar o


atributo ActionName ("Delete") para o
método DeleteConfirmed.

Esse atributo realiza o mapeamento para o sistema de


roteamento de modo que uma URL que inclui /Delete/ para uma
solicitação POST irá encontrar o método DeleteConfirmed.

Outra solução para contornar o problema de métodos que têm


nomes e assinaturas idênticas, é alterar artificialmente a
assinatura do método POST para incluir um parâmetro
extra  (não utilizado). Isso é o que fizemos em um post anterior
quando adicionamos o parâmetro notUsed. Você poderia fazer a
mesma coisa aqui para o método [HttpPost] Delete:

// POST: Movies/Delete/6
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id, bool notUsed)

E assim concluímos essa série de artigo apresentando os


conceitos básicos da ASP .NET MVC Core.

Na verdade se você já conhecia a ASP .NET MVC  percebeu que a


maioria dos conceitos sobre como a ASP .NET MVC funciona são
utilizados com ASP .NET MVC Core.

Se você não conhece os fundamenteos da tecnologia ASP .NET


MVC conheça o curso : CURSO ASP .NET MVC 5 Vídeo Aulas

Pegue o projeto aqui :   MvcFilme.zip

E, como Moisés levantou a serpente no deserto, assim


importa que o Filho do homem seja levantado;
Para que todo aquele que nele crê não pereça, mas tenha a
vida eterna.
João 3:14,15
ASP .NET Core - Configurando o ambiente de
desenvolvimento
http://www.macoratti.net/17/04/aspcore_ambi1.htm

  Neste
artigo eu
vou
mostrar
como
configurar
o seu
ambiente
para
desenvovl
er
aplicações
ASP .NET
Core.

Se você pretende desenvolver aplicações ASP .NET Core e esta


chegando agora ou já desenvolveu para web usando a ASP .NET
MVC 5 mas ficou um pouco afastado pode ficar um pouco
confuso com o cenário atual, primeiro pela profusão de artigos
sobre o tema, afinal você vai encontrar artigos para ASP .NET 5,
ASP .NET Core RC, ASP .NET Core 1.0, ASP .NET Core 1.1, e , o
que é pior, dependendo da versão que você usar, elas não serão
totalmente compatíveis.

Um pouco da culpa por essa confusão é da Microsoft, primeiro


por não adotar uma nomenclatura consistente segundo por ficar
fazendo alterações que afetam a compatibilidade entre as
versões.

Então vamos esclarecer algumas coisas:

- ASP .NET 5 - Não existe mais , foi um nome usado para
identificar o que hoje é conhecido como ASP .NET Core.
- ASP .NET Core 1.0 - É a versão estável da ASP .NET Core com
suporte da Microsoft e que deve ser usada para aplicações de
produção; (Nessa versão a solução usa o arquivo de projeto do
tipo project.json.)

- ASP .NET Core 1.1 - É a versão atual da ASP .NET Core e esta
em desenvolvimento. (Nessa versão a solução usa o arquivo de
projeto do tipo .csproj)

Então atualmente a última versão disponível é a ASP .NET Core


1.1; vejamos como configurar o ambiente de desenvolvimento
para criar projetos nesta versão.

Configurando o ambiente de
desenvolvimento para ASP NET Core
1.1
1- Vou desenvolver para o ambiente
Windows
Acesse o site oficial da .NET Core no
endereço :  http://www.microsoft.com/net/core

Se você for utilizar o ambiente Windows então basta instalar


o Visual Studio 2017 e você terá instalado todos os
componentes necessários para o desenvolvimento ASP .NET Core
1.1 :
Após instalar o VS 2017 você já pode criar projetos para ASP
.NET Core 1.1.

Nota:   Você pode usar o  Visual Studio 2015 Update 3   com


o    .NET Core 1.0.1 tools Preview 2   mas pode precisar ajustar
outros pacotes depedendo do seu ambiente. (Para mais detalhes e
instruções veja este
link:  https://www.microsoft.com/net/download/core   )

2- Não vou desenvolver para o


ambiente Windows ou não vou usar o
Visual Studio.
Se você não for usar o ambiente Windows mas vai desenvolver
no Linux ou Mac (ou não vai usar o Visual Studio) então clique
em : Command line / other

A seguir instale o pacote do .NET Core SDK no seu ambiente:


Instruções para instalar no Linux

Você pode instruções de instalação para o seu ambiente Linux


selecionando a sua distribuição Linux.

Instruções para instalar no Mac


 

Para instalação no MacOs veja as instruções de instalação e pré-


requisitos no respectivo link.

Instalando um Editor de Códigos


Para desenvolver aplicações ASP .NET Core  sem usar o Visual
Studio   você vai precisar de um editor de códigos e pode utilizar
o Visual Studio Code que é open source, multiplataforma e bem
leve. (Você pode usar outro editor de código como o Sublime,
Atom, etc.)

Para instalar o Visual Studio Code (VS Code) acesse o


link : https://code.visualstudio.com/
Faça o download e instale no seu ambiente.

Após instalar o Visual Studio Code no seu ambiente é


aconselhável (não é obrigatório) você instalar algumas extensões
para incrementar o seu ambiente de desenvolvimento no VS
Code.

Na figura a seguir temos algumas extensões que vão ajudar você


a ter uma experiência mais amigável para o desenvolvimento de
aplicações ASP .NET Core.
Dos
pacotes
apresentad
os na
figura os
únicos
realmente
essenciais
são :

 C# for
Visual
Studio Code
(powered
by
OmniSharp)
 C#
Extensions
 Auto
Import
 vscod
e-icons

Para mais
detalhes
sobre
o Visual
Studio
Code  (VS
Code) leia
o artigo : 
Visual
Studio
Code - O
Editor
multiplataf
orma da
Microsoft -
Macoratti

Ferramentas de Scaffolding para criar os seus


projetos usando um template
Embora você possa criar seus projetos sem usar nenhuma
ferramenta auxiliar isso é um pouco trabalhoso. Podemos
facilitar a etapa de criação do projeto e sua estrutura de pastas e
arquivos usando uma ferramenta de Scaffolding de linha de
comando que irá criar o esqueleto do projeto para você.

Atualmente temos duas opções mais usadas :

1. Usar Dotnet CLI

A interface de linha de comando (CLI) do .NET Core é uma nova


ferramenta multiplataforma para o desenvolvimento de
aplicativos .NET. A CLI é uma base sobre a qual as ferramentas
de nível superior, como Integrated Development Environments
(IDEs), editores e orquestradores de compilação, podem se
basear.

1. Usar o Yeoman

O Yeoman é um sistema para criação de templates genéricos


que permite a criação de qualquer tipo de aplicação. Assim ele
permite a rápida introdução de novos projetos e agiliza a
manutenção dos projetos existentes. O Yeoman é agnóstico de
linguagem e assim pode gerar projetos em qualquer
linguagem (Web, Java, Python, C#, etc.)

Para saber mais sobre o Yeoman veja este artigo :   NET -


Apresentando o Yeoman - Macoratti

Vamos então usar os recursos do Scaffolding do Yeoman.


Configurando o ambiente para usar o Yeoman
Como o Yeoman é distribuido como um pacote NPM você vai
precisar possuir os seguintes recursos instalados no seu
ambiente para instalar e usar o Yeoman.

 Node.js - Você pode baixar o Node.js neste link


- https://nodejs.org/en/download/current/
 NPM - é o gerenciado de pacotes do Node.js

Após instalar o Node.js o NPM será instalado por padrão. Então


ao final você deve ter as duas ferramentas instaladas.

Para verificar abra um terminal de comandos no seu ambiente e


digite os comandos:

 node -v
 npm -v

Agora para instalar o Yeoman digite o comando  :   sudo


npm install -g yo   (Esse comando irá instalar o Yeoman
globalmente.)

O Yeoman é apenas o engine precisamos dos templates para


gerar o esqueleto das nossas aplicações ASP .NET Core e para
isso vamos instalar o  aspnet generator  do Yeoman.
Para instalar o aspnet generator digite o seguinte
comando:  sudo npm install -g generator-aspnet
Pronto ! Agora o seu ambiente possui a ferramenta Yeoman e os
templates para gerar aplicações ASP .NET Core usando o Visual
Studio Code.

"Ora, o fim do mandamento é o amor de um coração puro, e


de uma boa consciência, e de uma fé não fingida."
1 Timóteo 1-5
.NET - Apresentando e usando o AutoMapper
http://www.macoratti.net/15/07/net_amap1.htm

 Neste artigo eu vou apresentar o AutoMapper , uma


biblioteca que realiza o mapeamento de propriedades de
um objeto para outro, evitando assim que o desenvolvedor
tenha o tedioso trabalho de realizar essa tarefa.
 
Já ouviu falar em um projeto simples e funcional ?

Pois o AutoMapper é exatamente isso : simples, funcional e


genial.

Mas o que ele faz exatamente ?

O AutoMapper é uma biblioteca pequena e simples, criada para


resolver um problema tedioso e complexo - evitar a codificação
quando mapeamos um objeto para outro. Esse tipo de trabalho
é bastante chato de fazer e sujeito a erros, então por que não
inventar uma ferramenta para fazer isso por
nós ?   (fonte:  http://automapper.org/ )

Você pode obter o AutoMapper neste


site : http://automapper.org/

Para consultar o guia de introdução que mostra como usar o


AutoMapper acesse esse
link: http://docs.automapper.org/en/stable/Getting-
started.html

No artigo de hoje eu vou mostrar como usar o AutoMapper para


facilitar a nossa vida de desenvolvedor.
Imagine o seguinte cenário:

Você tem um objeto Aluno que contém muitas propriedades e


deseja exibir as informações desse objeto em um controle de
formulário como um DataGridView, um ListBox, um TreeView,
etc.

O código da classe Aluno é :

 public class Aluno


    {
        public string Nome { get; set; }
        public string Email { get; set; }
        public Endereco Endereco { get; set; }
        public string Genero { get; set; }
        public int Idade { get; set; }
        public DateTime Nascimento { get; set; }
    }

O código da classe Endereco é :

public class Endereco


{
        public string Pais { get; set; }
        public string Cidade { get; set; }
        public string Rua { get; set; }
        public string Cep { get; set; }
}

Para facilitar a exibição dos dados no controle de formulário


você criou a classe AlunoViewItem com o seguinte código:

public class AlunoViewItem
{
   public string Nome { get; set; }
   public string Email { get; set; }
   public string Endereco { get; set; }
   public string Genero { get; set; }
   public int Idade { get; set; }
   public string Nascimento { get; set; }
}

Observe que na classe AlunoViewItem, as


propriedades Endereco, Genero e Nascimento são do tipo
string, justamente para facilitar a exibição das informações.
Com isso teremos que escrever código para mapear as
propriedades da classe Aluno e Endereco para a
classe AlunoViewItem. Seria algo assim :

AlunoViewItem viewItem = new AlunoViewItem();
viewItem.Nome = aluno.Nome;
viewItem.Email = aluno.Email;
viewItem.Endereco = aluno.Endereco.Cidade +
aluno.Endereco.Rua;
viewItem.Genero = aluno.Genero == true ? "Masculino" :
"Feminino";
viewItem.Idade = aluno.Idade;
viewItem.Nascimento = aluno.Nascimento.ToShortDateString();

É desse trabalho que o AutoMapper nos livra. (Imagine se a


classe possuísse 50 propriedades ????)

Vamos usá-lo para realizar esse mapeamento com pouco


código.

Então, ao trabalho...

 
Recursos usados :

 Visual Studio 2013 Community

Criando o projeto no VS 2013 Community


Abra o VS 2013 Community e clique em New Project;

A seguir clique em Other Project Types -> Visual Studio


Solutions e selecione o template Blank Solution;

Informe o nome Usando_AutoMapper e clique no botão OK;


Com isso criamos uma solução em branco
chamada Usando_AutoMapper. Vamos agora incluir um novo
projeto nesta solução.

Clique no menu FILE e a seguir em Add -> New Project;

Selecione Visual C# -> Windows Destkop e a seguir o


template Windows Forms Application;

Informe o nome CSharp_AutoMapper e clique no botão OK;


Vamos incluir neste projeto uma classe chamada Aluno.

Clique no menu PROJECT e a seguir em Add Class e informe o


nome Aluno.

A seguir digite o código abaixo nesta classe:

using System;
namespace CSharp_AutoMapper
{
public class Aluno
{
public string Nome { get; set; }
public string Email { get; set; }
public Endereco Endereco { get; set; }
public bool Genero { get; set; }
public int Idade { get; set; }
public DateTime Nascimento { get; set; }
}
}

Vamos criar também a classe Endereco para complementar a


informação da classe Aluno visto que a
propriedade Endereco da classe Aluno é do tipo Endereco:

O código da classe Endereco é visto a seguir:


public class Endereco
{
public string Pais { get; set; }
public string Cidade { get; set; }
public string Rua { get; set; }
public string Cep { get; set; }
}

Agora vamos criar a classe AlunoViewItem com seguinte código


:

public class AlunoViewItem


{
public string Nome { get; set; }
public string Email { get; set; }
public string Endereco { get; set; }
public string Genero { get; set; }
public int Idade { get; set; }
public string Nascimento { get; set; }
}

Agora é hora do AutoMapper entrar em ação para mapear as


propriedades das classe Aluno e Endereco para a
classe AlunoViewItem.

Usando o AutoMapper para mapear as


propriedades entre objetos
Para poder usar o AutoMapper temos que referenciá-lo em
nosso projeto. Agradeça ao Nuget que irá fazer isso para nós de
forma automática.

Você pode usar o Manager Console e digitar :   Install-Package


AutoMapper

Ou pode clicar no menu TOOLS -> Nuget Package Manager ->


Manage Nuget Packages for Solution...

E selecionar o AutoMapper na janela - Manage Nuget


Packages , clicando no botão Install para instalar a biblioteca
no seu projeto:
Concluída a instalação podemos incluir uma declaração ao
namespace AutoMapper:

using AutoMapper;

Para indicar ao AutoMapper o que mapear usamos a seguinte


linha de código:

Mapper.CreateMap<Aluno, AlunoViewItem>();

Para realizar o mapeamento bastaria digitar a seguinte linha de


código:

AlunoViewItem _alunoViewItem
= Mapper.Map<Aluno, Aluno>(aluno);

Mas como já sabemos a nossa classe AlunoViewItem possui


algumas inconsistências em relação à classe Aluno. Vejamos os
problemas:

 Endereco é um objeto complexo na classe Aluno mas


apenas uma string na classe AlunoViewItem;

 Nascimento é do tipo DateTime na classe Aluno mas é


uma string na classe AlunoViewItem
Portanto temos que realizar alguns ajustes no
método CreateMap no Mapper. Para o endereço podemos fazer
assim:

Mapper.CreateMap<Aluno, AlunoViewItem>()
   .ForMember(dest => dest.Endereco, m => m.MapFrom(a =>
a.Endereco.Cidade + ", " + a.Endereco.Rua));

Vejamos então como fica o mapeamento completo.

Criando a interface com o usuário


Vamos agora definir a interface com o usuário incluindo no
formulário form1.cs do projeto os seguintes controles a partir
da ToolBox:

 ListBox - name=lbDados

 Button - name=btnCriarMapeamento

Disponha os controles no formulário conforme o leiaute da


figura abaixo:

Vamos definir no início do formulários os


seguintes namespaces usados no projeto:

using System;
using System.Windows.Forms;
using AutoMapper;

Mapeando com AutoMapper


Agora vamos definir no evento Click do botão de comando
- Criar Mapeamento com AutoMapper - o código  a seguir:

private void btnCriarMapeamento_Click(object sender, EventArgs e)


{
Mapper.CreateMap<Aluno, AlunoViewItem>()
.ForMember(av => av.Endereco,
m => m.MapFrom(a => a.Endereco.Cidade + ", " +
a.Endereco.Rua)
)
.ForMember(av => av.Nascimento, m => m.ResolveUsing(src
=>
{
var dt = (DateTime)src.Nascimento;
return dt.ToShortDateString();
}));
Aluno aluno = new Aluno
{
Nome = "Macoratti",
Email = "macoratti@yahoo.com",
Endereco = new Endereco
{
Pais = "Brasil",
Cidade = "Brasilia",
Rua = "Rua Projetada 100",
Cep = "88900-520"
},
Genero = "Masculino",
Idade = 35,
Nascimento = new DateTime(1975, 10, 9)
};
AlunoViewItem _alunoViewItem = Mapper.Map<Aluno,
AlunoViewItem>(aluno);

lbDados.Items.Add(_alunoViewItem.Nome);
lbDados.Items.Add(_alunoViewItem.Email);
lbDados.Items.Add(_alunoViewItem.Endereco);
lbDados.Items.Add(_alunoViewItem.Genero);
lbDados.Items.Add(_alunoViewItem.Nascimento);
lbDados.Items.Add(_alunoViewItem.Idade);
}
C#

O código para a linguagem VB .NET ficaria assim:


   Imports AutoMapper

   Private Sub btnGerarMapeamento_Click(sender As Object, e As EventArgs)


Handles btnGerarMapeamento.Click

        Mapper.CreateMap(Of Aluno, AlunoViewItem)() _


       .ForMember(Function(av) av.Endereco, Sub(m) m.MapFrom(Function(a)
a.Endereco.Cidade + ", " + a.Endereco.Rua))

        Dim aluno As New Aluno() With


        { _
                    .Nome = "Macoratti", _
                   .Email = "macoratti@yahoo.com", _
                   .Endereco = New Endereco() With
                               { _
                               .Pais = "Brasil", _
                               .Cidade = "Brasilia", _
                               .Rua = "Rua Projetada 100", _
                               .Cep = "88900-520" _
                              }, _
                   .Genero = "Masculino", _
                   .Idade = 35, _
                   .Nascimento = New DateTime(1975, 10, 9) _
        }

        Dim _alunoViewItem As AlunoViewItem = Mapper.Map(Of Aluno,


AlunoViewItem)(aluno)

        lbDados.Items.Add(_alunoViewItem.Nome)
        lbDados.Items.Add(_alunoViewItem.Email)
        lbDados.Items.Add(_alunoViewItem.Endereco)
        lbDados.Items.Add(_alunoViewItem.Genero)
        lbDados.Items.Add(_alunoViewItem.Nascimento)
        lbDados.Items.Add(_alunoViewItem.Idade)

    End Sub

Agora podemos executar o projeto e verificar o resultado


conforme abaixo:
Colocando um ponto de interrupção podemos verificar o
objeto _alunoViewItem que contem o mapeamento gerado
conforme a figura abaixo:

O que vimos foi apenas uma introdução, o AutoMapper possui


muitos outros recursos que iremos abordar em outros artigos.

Pegue o projeto completo aqui:   


Usando_AutoMapper.zip  (projetos CSharp e VB .NET)

Jesus respondeu, e disse-lhe: Porque te disse: Vi-te debaixo da


figueira, crês ? Coisas maiores do que estas verás.
E disse-lhe: Na verdade, na verdade vos digo que daqui em
diante vereis o céu aberto, e os anjos de Deus subindo e
descendo sobre o Filho do homem.
João 1:50,51
ASP .NET Core - Como configurar o AutoMapper usando a DI
nativa

http://www.macoratti.net/19/04/aspc_autom1.htm

 Hoje veremos como configurar o AutoMapper em uma


aplicação ASP .NET Core usando a injeção de dependência
nativa da ASP .NET Core.
 
Eu já apresentei o AutoMapper neste artigo:  Apresentando e
usando o AutoMapper

Para consultar o guia de introdução que mostra como usar o


AutoMapper acesse esse
link: http://docs.automapper.org/en/stable/Getting-
started.html

O AutoMapper continua o mesmo, o que mudou foi a maneira


de configurar a sua utilização em aplicações ASP .NET Core.
Graças ao recurso da injeção de dependência(DI) nativa da
ASP .NET Core podemos agora usar a DI nativa para configurar o
AutoMapper.

Para ilustrar como configurar o AutoMapper usando a  DI nativa


da ASP .NET Core  vamos criar uma aplicação Web MVC usando a
ASP .NET Core 2.1 no VS 2017 selecionando a opção ASP.NET
Core Web Application e usando o template Web
Application(Model-View-Controller). Vou chamar a solução e o
projeto de AspCore_Automapper.

Nesta aplicação vamos configurar o AutoMapper para mapear


entre as classes Usuario e UsuarioViewModel.

  public class
    public class Usuario
UsuarioViewModel
    {
  {
        public string Nome { get; set; }
        public string
        public string Email { get; set; }
Nome { get; set; }
        public int Idade { get; set; }
        public string
        public DateTime Nascimento { get; set; }
Email { get; set; }
    }
  }

Essas classes devem ser criadas na pasta Models do projeto.


Então, ao trabalho...

 
Recursos usados :

 Visual Studio 2017 Community

Configurando o AutoMapper
Para poder usar o AutoMapper temos que incluir o pacote Nuget
em nosso projeto.

No menu Tools-> Nuget Package Manager clique em Manage


Nuget Packages for Solution;

Com a solução criada abra o arquivo Startup e no


método ConfigureServices inclua as linhas de código destacadas
em azul conforme mostra o código a seguir:

.....
public
void
ConfigureServ
ices(IServiceC
ollection
services)
{

services.Confi
gure<CookiePo
licyOptions>(o
ptions =>
{

options.Check
ConsentNeede
d = context =>
true;

options.Minim
umSameSitePo
licy =
SameSiteMode
.None;
});

services.AddM
vc().SetCompa
tibilityVersion
(Compatibility
Version.Versio
n_2_1);
var
config = new
AutoMapper.
MapperConfig
uration(cfg
=>
{

cfg.CreateMa
p<UsuarioVie
wModel,
Models.Usuari
o>();
});

IMapper
mapper =
config.Create
Mapper();

services.AddS
ingleton(map
per);
}
....

Vamos entender o código :


As primeiras linhas de código não são nenhuma novidade,
estamos criando uma instância do AutoMapper e definindo uma
mapeamento entre um modelo de domínio (Models.Usuario) e
um modelo de exibição (usuarioViewModel).

            var config = new AutoMapper.MapperConfiguration(cfg =>


            {
                cfg.CreateMap<UsuarioViewModel, Models.Usuario>();
            });

A seguir para usar a instância criada do AutoMapper precisamos


registrar o IMapper como um serviço usando o contêiner de
injeção de dependencia nativa da ASP .NET Core usando o
método services.AddSingleton():

IMapper mapper = config.CreateMapper();


services.AddSingleton(mapper);

Isso garante que, em vez de uma nova instância, a mesma


instância do IMapper será usada toda vez que uma instância
do IMapper for solicitada por um construtor no seu código.

Um exemplo de utilização para realizar o mapeamento pode ser


feito no controlador HomeController conforme mostra o código
a seguir:

using AspCore_AutoMapper.Models;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
namespace AspCore_AutoMapper.Controllers
{
public class HomeController : Controller
{
IMapper _mapper;
public HomeController(IMapper mapper)
{
_mapper = mapper;
}
public IActionResult Index()
{
var usuario = new Usuario
{
Nome = "Macoratti",
Email = "macoratti@yahoo.com"
};
var viewModel =
_mapper.Map<UsuarioViewModel>(usuario);
return View(viewModel);
}
public IActionResult About()
{}
public IActionResult Contact()
{}
...
...
}
}

Note que no construtor do


controlador HomeController injetamos uma instância
de IMapper usando a DI nativa da ASP .NET Core que
configuramos no arquivo Startup.

A partir disso você pode usar o AutoMapper conforme já esta


acostumado a usar.

Bem-aventurados os limpos de coração, porque eles verão a


Deus;
Bem-aventurados os pacificadores, porque eles serão chamados
filhos de Deus;
Mateus 5:8,9

ASP .NET Core - Criando uma app Básica com EF Core , Web API
e Angular 2
http://www.macoratti.net/17/06/aspncore_ang2.htm

 Neste artigo vou mostrar como criar uma aplicação ASP


.NET Core integrando o Angular 2 para criar uma aplicação
Básica que consome uma Web API e exibe um formulário
com controles dropdownlist, radiobutton, checkbox e
textbox.
O principal objetivo deste artigo é mostrar como integrar o
Angular 2 a uma aplicação ASP .NET Core e consumir o serviço
de uma Web API para uma aplicação básica.

Vamos criar uma aplicação básica que gerencia informações


sobre Veículos, e, para tornar o contexto o mais simples
possível, vamos tratar informações de Marcas, Modelos e
Acessórios.

Para criar o projeto ASP .NET Core com Angular 2 vamos usar
o Yeoman, depois vamos definir o nosso Modelo de domínio,
incluir o Entity Framework Core, criar o banco de dados usando
o Migrations, criar a Web API de serviços e ao final integrar
o Angular 2 para consumir o serviço e exibir as informações no
cliente em um formulário com recursos do Bootstrap.

Durante o desenvolvimento da aplicação iremos usar o terminal


de comandos, o Visual Studio 2017 Community e o VS Code para
editar o código do projeto.

São muitas etapas e vou procurar ser o mais objetivo possível


para não estender demais o artigo.

Recursos usados:

 VS 2017 Community update 3


 VS Code
 ASP .NET Core 1.1
 Yeoman
 Entity Framework Core 1.1
 Angular 2
 BootStrap
Criando o projeto ASP .NET Core usando o
Yeoman
Nota: Atualmente o projeto pode ser criado usando os
templates do Visual Studio.
Se você não não conhece o Yeoman leia este artigo : NET -
Apresentando o Yeoman - Macoratti

Como o Yeoman é distribuido como um pacote NPM vamos


precisar possuir os seguintes recursos instalados para usar o
Yeoman.

 Node.js - Você pode baixar o Node.js neste link


- https://nodejs.org/en/download/current/
 NPM - é o gerenciado de pacotes do Node.js

Abra um terminal de comandos e crie uma pasta para o


projeto.

Para o artigo eu vou criar uma pasta chamada Alfa :   md alfa

A seguir entre na pasta criada e digite o comando para criar o


projeto usando o Yeoman : yo aspnetcore-spa

Selecion a opção para usar o Angular como framework e


tecle Enter:
Informe No para incluir os  testes unitários  e tecle Enter para
confirmar o nome do projeto como alfa.

O projeto será criado e as dependências serão instaladas na


pasta node_modules.

Se desejar, você pode executar o projeto digitando no terminal


de comando: dotnet run  (a aplicação vai estar atendendo
em http://localhost:5000 )

Nota:  Você pode também abrir o projeto no VS Code, abrir


uma janela de terminal e digitar o mesmo comando para
executar a aplicação.

Espiando a estrutura do projeto criado

Vamos abrir o projeto criado no VS Code e examinar sua


estrutura.

Estando no terminal de comando digite : Code .

O projeto será aberto no VS Code e veremos a seguinte


estrutura:
Temos as seguintes
pastas no projeto:

- ClienteApp  - local
onde teremos o código
do lado do cliente
definido pelo Angular
2;

- Controllers - local
onde são criados os
controladores Asp
.Net Core. Aqui
iremos criar nossa
Web API;

- Views - local onde


são criadas as views
Asp .Net Core;

- node_modules -
contém das
dependências para o
Angular 2;

- wwwroot - pasta
onde são colocados os
arquivos públicos e
estáticos da aplicação
: ícones, imagens,
fontes, etc.;

Além disso temos os


seguintes arquivos
que foram gerados:

 Startup.cs -
classe que
processa o
pipeline de
requisições que
trata todas as
requisições
feitas para a
aplicação;
 Program.cs -
Contém o
ponto de
entrada
principal do
aplicativo;
 Alfa.csproj - O
arquivo de
projeto para a
ASP .NET Core
Web API;
 appsettings.js
on - Arquivo de
configuração
do aplicativo
de base do
ambiente;
 tsconfig.json -
configuração
para o
TypeScript;

Incluindo uma referência ao Entity Framework


Core
Vamos adicionar o suporte ao EF Core em nosso projeto e
instalar o provedor do banco de dados que vamos usar. No
exemplo deste artigo vamos instalar o provedor SQL
Server : Microsoft.EntityFrameworkCore.SqlServer .

Para instalar esse pacote abra uma janela do Package Manager


Console via menu Tools e digite o comando : Install-Package
Microsoft.EntityFrameworkCore.SqlServer

Este pacote e suas


dependências ( Microsoft.EntityFrameworkCore e
Microsoft.EntityFrameworkCore.Relational ) fornece o suporte
em tempo de execução ao EF.(Mais adiante iremos instalar
outro pacote para a migração)
Nota:  O EF para no .NET Core não possui todas as
funcionalidades do EF 6.  (lazy loading não esta suportado
ainda)

Vamos instalar também os seguintes pacotes usando o


comando Install-Package :

 Microsoft.EntityFrameworkCore.Tools no projeto para


ter acesso ao Migrations :
 Microsoft.EntityFrameworkCore.SqlServer.Design - para
poder executar os comandos dotnet no projeto;

Criando o modelo de domínio da aplicação


Abra o projeto no VS 2017 Community e crie uma pasta
chamada Models no projeto.

A seguir vamos definir 4 classes nesta pasta Models que irão


representar o nosso modelo de domínio e o arquivo de contexto
da aplicação.

 classe Marca - representa as Marcas dos veículos;


 classe Modelo - representa os modelos dos veículos;
 classe Acessorio - representa os acessórios dos veículos;
 AlfaDbContext - representa uma sessão com o banco de
dados;

Vamos usar o recurso Data Annotations alguns requisitos das


propriedades e validação das entidades.

A seguir inclua o código abaixo em cada um destes arquivos:

1- Classe Marca

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
namespace Alfa.Models
{
public class Marca
{
public int Id {get; set; }
[Required]
[StringLength(255)]
public string Nome {get;set;}
public ICollection<Modelo> Modelos {get;set;}
public Marca()
{
Modelos = new Collection<Modelo>();
}
}
}

Temos aqui a definição de um relacionamento um para


muitos,  onde uma Marca pode ter muitos Modelos. Isso é
representando pela definição da coleção Modelos.

O construtor da classe inicializa a coleção Modelos pois isso é


uma responsabilidade da classe Marca.

2- Classe Modelo

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Alfa.Models
{
[Table("Modelos")]
public class Modelo
{
public int Id { get; set; }

[Required]
[StringLength(255)]
public string Nome { get; set; }
public Marca Marca { get; set; }
public int MarcaId { get; set; }
}
}

O Data Annotations define que o nome da tabela gerada no


mapeamento será Modelos, e que o cmapo Nome é obrigatório
e tem o tamanho de 255 caracteres.

3- Classe Acessorio

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Alfa.Models
{
     [Table("Acessorios")]
    public class Acessorio
    {
         public int Id { get; set; }
         [Required]
         [StringLength(255)]
         public string Nome { get; set; }
    }
}

O Data Annotations define que o nome da tabela gerada no


mapeamento será Acessorios, e que o campo Nome é
obrigatório e tem o tamanho de 255 caracteres.

4- Classe AlfaDbContext

using Alfa.Models;
using Microsoft.EntityFrameworkCore;
namespace Alfa.Models
{
public class AlfaDbContext : DbContext
{
public AlfaDbContext(DbContextOptions<AlfaDbContext> options)
: base (options)
{}
public DbSet<Marca> Marcas { get; set; }
public DbSet<Acessorio> Acessorios { get; set; }
}
}

Esta classe deriva de DbContext e expõe as


propriedades DbSet que representam as coleções das entidades
especificadas no contexto.

Essa classe é chamada de classe de contexto  do banco de dados


e coordena a funcionalidade do Entity Framework para um dado
modelo de dados. No código dessa classe você especifica quais
entidades estão incluídas no modelo de dados.

Observe que não foi necessário definir um DbSet para Modelo


visto que ela esta relacionada com a entidade Marca.

Registrando o contexto com injeção de


dependência
A ASP.NET Core implementa a injeção de dependência por
padrão. Os serviços (como o contexto de banco de dados do
EF) são registrados com injeção de dependência durante a
inicialização do aplicativo. Componentes que requerem esses
serviços (como controladores MVC)  fornecem esses serviços
através de parâmetros do construtor. Mais adiante iremos
definir no construtor do controlador a instância do contexto.

Para registrar o nosso contexto AlfaDbContext como um


serviço, abra o arquivo Startup.cs e adicione as linhas
realçadas ao método ConfigureServices:

using Microsoft.EntityFrameworkCore;
using Alfa.Models;
...
....

       // This method gets called by the runtime. Use this method to add services to
the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<AlfaDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ConexaoAlfa")));

            // Add framework services.


            services.AddMvc();
        }
....

O nome da string de conexão é passada para o contexto pela


chamada do método no objeto DbContextOptionsBuilder. Para
o desenvolvimento local a ASP .NET Core obtém a string de
conexão do arquivo appsettings.json.

Vamos abrir o arquivo appsettings.json e adicionar a string de


conexão conforme mostrado a seguir:

{ "ConnectionStrings" : {
 "ConexaoAlfa" :
"Server=(localdb)\\mssqllocaldb;Database=Alfa;Trusted_Connection=True;Mu
ltipleActiveResultSets=true;"
},
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}
A string de conexão especifica um banco de dados identificado
pelo nome Alfa.

Gerando o banco de dados e as tabelas usando


Migrations
Agora  podemos usar o Migration do EF Core para criar o nosso
banco de dados.

Abra uma janela do Package Manager Console via


menu Tools e digite o comando : add-Migration ModeloInicial

Após a conclusão do comando verifique os arquivos criados na


pasta Migrations do projeto e veja se o mapeamento esta
correto.

A seguir na janela do Package Manager Console digite o


comando : update-database

Ao final desta etapa teremos o banco de dados Alfa.mdf e as


tabelas Marcas, Modelos e Acessorios criadas no banco de
dados.

Precisamos agora incluir algumas informações nestas tabelas


para podermos usá-las no projeto.

Para isso vamos criar uma migração vazia e depois vamos


definir os dados que vamos incluir.

Digite o comando na janela Package Manager Console : add-


migration SeedDatabase

Agora abra o arquivo SeedDatabase e você verá que temos a


classe SeedDatabase contendo os métodos Up e Down vazios.

Inclua o código abaixo nestes métodos para poder preencher as


tabelas com dados:

using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;

namespace Alfa.Migrations
{
    public partial class SeedDatabase : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            //Marcas
            migrationBuilder.Sql("INSERT INTO Marcas (Nome) VALUES ('Ford')");
            migrationBuilder.Sql("INSERT INTO Marcas (Nome) VALUES ('GM')");
            migrationBuilder.Sql("INSERT INTO Marcas (Nome) VALUES ('Honda')");
            //Modelos
            migrationBuilder.Sql("INSERT INTO Modelos (Nome, MarcaId) VALUES
('Fiesta', (SELECT Id FROM Marcas Where Nome= 'Ford'))");
            migrationBuilder.Sql("INSERT INTO Modelos (Nome, MarcaId) VALUES ('Ka',
(SELECT Id FROM Marcas Where Nome= 'Ford'))");
            migrationBuilder.Sql("INSERT INTO Modelos (Nome, MarcaId) VALUES ('Eco
Esport', (SELECT Id FROM Marcas Where Nome= 'Ford'))");
            //Modelos
            migrationBuilder.Sql("INSERT INTO Modelos (Nome, MarcaId) VALUES
('Prisma', (SELECT Id FROM Marcas Where Nome= 'GM'))");
            migrationBuilder.Sql("INSERT INTO Modelos (Nome, MarcaId) VALUES
('Onix', (SELECT Id FROM Marcas Where Nome= 'GM'))");
            migrationBuilder.Sql("INSERT INTO Modelos (Nome, MarcaId) VALUES
('Cruze', (SELECT Id FROM Marcas Where Nome= 'GM'))");
            //modelos
            migrationBuilder.Sql("INSERT INTO Modelos (Nome, MarcaId) VALUES
('Civic', (SELECT Id FROM Marcas Where Nome= 'Honda'))");
            migrationBuilder.Sql("INSERT INTO Modelos (Nome, MarcaId) VALUES ('Fit',
(SELECT Id FROM Marcas Where Nome= 'Honda'))");
            migrationBuilder.Sql("INSERT INTO Modelos (Nome, MarcaId) VALUES ('HRV
Suv', (SELECT Id FROM Marcas Where Nome= 'Honda'))");
            //acessórios
            migrationBuilder.Sql("INSERT INTO Acessorios (Nome) VALUES ('Ar
Condicionado')");
            migrationBuilder.Sql("INSERT INTO Acessorios (Nome) VALUES ('Bancos de
Couro')");
            migrationBuilder.Sql("INSERT INTO Acessorios (Nome) VALUES ('Câmera de
Ré')");

        }

        protected override void Down(MigrationBuilder migrationBuilder)


        {
            migrationBuilder.Sql("DELETE FROM Marcas WHERE Nome IN
('Ford','GM','Honda')");
            migrationBuilder.Sql("DELETE FROM Acessorios WHERE Nome IN ('Ar
Condicionado', 'Bancos de Couro', 'Câmera de Ré')");
        }
    }
}

O método Up permite fazer o upgrade para uma nova migração


alterando as tabelas e incluindo dados e o
método Down permite fazer o downgrade para a versão
anterior.

A seguir na janela do Package Manager Console digite o


comando : update-database
Se você verificar no SQL Server Management Studio ou no SQL
Server Object Explorer vai encontrar as tabelas criadas e com
os dados informados.

Assim já temos tudo pronto para poder iniciar a criação da


nossa Web API.

Na próxima parte do artigo  vamos criar a nossa ASP .NET Core


Web API.

Sabendo, amados irmãos, que a vossa eleição é de Deus;Porque


o nosso evangelho não foi a vós somente em palavras, mas
também em poder, e no Espírito Santo, e em muita certeza,
como bem sabeis quais fomos entre vós, por amor de vós.
1 Tessalonicenses 1:4,5
ASP .NET Core - Criando uma app Básica com EFCore, Web
API e Angular 2 – II
http://www.macoratti.net/17/06/aspncore_ang22.htm

 Neste artigo vou mostrar como criar uma aplicação ASP .NET
Core integrando o Angular 2 para criar uma aplicação Básica
que consome uma Web API e exibe um formulário com
controles dropdwon, radiobutton, checkbox e textbox.

Neste artigo vamos criar a nossa Web API ASP .NET Core e
utiilizar o AutoMapper para mapear as classes do domínio e
resolver o problema da referência circular entre as
entidades Modelo e Marca. (Veja o artigo anterior neste link )

O problema do relacionamento entre as entidades Modelo e


Marca : Usando o AutoMapper

Vamos recordar a definição das


entidades Modelo e Marca usadas no projeto:

public class Marca


{ public
public int Id {get; set; } class
public string Nome {get;set;} Modelo
{
public ICollection<Modelo> Modelos
{get;set;} public
public Marca() int Id
{ { get;
Modelos = new Collection<Modelo>(); set; }
}
public
}
string
Nome
{ get;
set; }
public
Marca
Marca {
get;
set; }

public
int
MarcaId
{ get;
set; }
}

 
Marca Modelo

Na definição da classe Modelo optamos por incluir uma


propriedade MarcaId como chave estrangeira de forma a
facilitar a atualização de um objeto Modelo no futuro, pois
para associar um Modelo com uma Marca basta usar a
propriedade MarcaId sem ter a necessidade de localizar uma
marca no banco de dados pelo seu id.

Ocorre que essa abordagem vai resultar em um problema


quando formos serializar os dados no formato JSON causando
um loop ou referência circular. Para resolver esse problema
teremos que criar classes que reflitam o nosso modelo de
domínio, sem usar o recurso da chave estrangeira, para evitar o
problema da referência circular, e, que possamos expor para o
cliente via serialização JSON.

Primeiro vamos criar classes que reflitam o nosso  modelo de


domínio e que podemos expor para o cliente via serialização.
Vamos criar uma pasta chamada Resources dentro da
pasta Controllers e a seguir vamos criar as
classes MarcaResource, ModeloResource e
AcessorioResource  conforme o código abaixo:

public class MarcaResource public class public class


{ ModeloResource AcessorioResource
public int Id {get; set; } { {
public string Nome public int Id public int Id { get;
{get;set;} { get; set; } set; }
public string public string Nome
public Nome { get; set; } { get; set; }
ICollection<Modelo> Modelos } }
{get;set;}
public Marca()    
{
Modelos = new
Collection<Modelo>();
}
}
MarcaResource ModeloResource AcessorioResource

Instalando e registrando o AutoMapper

O AutoMapper é uma biblioteca construída para resolver um


problema complexo :  livrar-se de um código que mapeou um
objeto para outro.

Para instalar o AutoMapper no projeto abra uma janela


do Package Manager Console, via menu Tools, e digite o
comando : Install-Package AutoMapper

Vamos instalar também o


pacote  AutoMapper.Extensions.Microsoft.DependencyInjecti
on via nuget.

A seguir vamos abrir o arquivo Startup.cs e registrar


o AutoMapper no método ConfigureServices:

 public void ConfigureServices(IServiceCollection services)


 {
      services.AddAutoMapper();

     services.AddDbContext<AlfaDbContext>(options =>


options.UseSqlServer(Configuration.GetConnectionString("ConexaoAlfa
")));
      // Add framework services.
      services.AddMvc();
}

Mapeando o modelo de entidades com o AutoMapper

Agora que já criamos as classes que representam o nosso


modelo de domínio e temos o AutoMapper instalado e
registrado vamos realizar o mapeamento entre as classes do
modelo de domínio e as classes criadas na pasta Resources que
representam o nosso domínio sem o relacionamento usando a
chave estrangeira.
Crie uma pasta chamada Mapping no projeto e defina uma
classe chamada MappingProfile contendo o seguinte código :

using Alfa.Controllers.Resources;
using Alfa.Models;
using AutoMapper;
namespace Alfa.Mapping
{
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Marca, MarcaResource>();
CreateMap<Modelo, ModeloResource>();
CreateMap<Acessorio, AcessorioResource>();
}
}
}

Neste código estamos mapeando as 3 classes que representam o


nosso modelo de entidades(Marca,Modelo e Acessorio) para as
classes que iremos expor via serialização JSON ao cliente.

Criando a Web API para expor marcas, modelos e acessórios

Agora vamos criar dois controladores na pasta Controllers onde


vamos expor as marcas, modelos e acessórios como um serviço
da nossa Web API.

1. MarcasControllers -  Retorna as marcas e respectivos


modelos;
2. AcessoriosControllers - Permite acessar e retornar os
acessórios dos veículos;

1 - MarcasControllers

using Alfa.Controllers.Resources;
using Alfa.Models;
using Alfa.Persistencia;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Alfa.Controllers
{
public class MarcasController : Controller
{
private readonly AlfaDbContext context;
private readonly IMapper mapper;
public MarcasController(AlfaDbContext context, IMapper mapper)
{
this.context = context;
this.mapper = mapper;
}
[HttpGet("/api/marcas")]
public async Task<IEnumerable<MarcaResource>> GetMarcas()
{
var marcas = await context.Marcas.Include(m =>
m.Modelos).ToListAsync();
return mapper.Map<List<Marca>,
List<MarcaResource>>(marcas);
}
}
}

2 - AcessoriosControllers

using Alfa.Controllers.Resources;
using Alfa.Models;
using Alfa.Persistencia;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace Alfa.Controllers
{
public class AcessoriosController : Controller
{
private readonly AlfaDbContext context;
private readonly IMapper mapper;
public AcessoriosController(AlfaDbContext context, IMapper
mapper)
{
this.context = context;
this.mapper = mapper;
}
[HttpGet("/api/acessorios")]
public async Task<IEnumerable<AcessorioResource>>
GetAcessorios()
{
var acessorios = await context.Acessorios.ToListAsync();
return mapper.Map<List<Acessorio>,
List<AcessorioResource>>(acessorios);
}
}
}
Dessa forma temos as seguintes rotas definidas em nossa Web
API:

 api/marcas - retorna as marcas e respectivos modelos;


 api/acessorios - retorna os acessórios;

Neste momento já temos o serviço da Web API pronto para ser


consumido e vamos definir um formulário que vai exibir essas
informações usando o Angular 2.

Na próxima parte do artigo  vamos criar iniciar a criação da


interface do usuário definindo componentes usando o Angular
CLI e o BootStrap.

O anjo do Senhor acampa-se ao redor dos que o temem, e os


livra.
Salmos 34:7
ASP .NET Core - Criando uma app Básica com EF Core, Web API
e Angular 2 – III
http://www.macoratti.net/17/06/aspncore_ang23.htm

 Neste artigo vou mostrar como criar uma aplicação ASP


.NET Core integrando o Angular 2 para criar uma aplicação
Básica que consome uma Web API e exibe um formulário com
controles dropdownlist, radiobutton, checkbox e textbox.

Neste artigo vamos definir a parte do cliente, ou seja, a


interface com o usuário usando Angular 2 e BootStrap. Vamos
aprender como criar dropdownlist em cascata e checkbox
dinâmicos. Para isso vamos criar componentes usando o Angular
CLI. (link para o artigo anterior )

Vamos iniciar preparando o ambiente e instalando o Angular CLI


e criando um novo componente e definindo uma rota para ele.

Incluindo um Novo Componente Angular usando Angular CLI

Vamos criar um novo componente Angular na


pasta ClienteApp/App/Components que é composto por um
arquivo Html um arquivo TypeScript usando o Angular CLI.

O Angular CLI  é o assistente oficial para criação e


gerenciamento de aplicações com o Angular e foi escrito em
Node.js. Para poder usar o Angular CLI temos que fazer a sua
instalação global.

Para isso abra uma janela de comando e digite o seguinte


comando :  npm install -g @angular/cli@latest
O comando acima instala a última versão (@latest) do Angular
CLI globalmente (-g).

Agora vamos criar um novo projeto usando o Angular CLI. Você


pode fazer isso em qualquer local. Eu vou criar o projeto na
pasta c:\teste .

Na janela de comandos digite o comando :


Será criado o projeto Angular na pasta c:\Teste\AloMundo .
Listando o conteúdo da pasta AloMundo podemos ver o
arquivo angular-cli.json criado no projeto.

Vamos copiar esse arquivo angular-cli.json para o nosso


projeto localizado em c:\alfa  usando o comando  :  copy
angular-cli.json ..\alfa
Agora vamos abrir o nosso projeto no VS Code (ou no V Studio),
abrir o arquivo angular-cli.json e alterar o seu conteúdo
conforme abaixo:

Altere o valor de "root": "src" para "root": "ClientApp":


Agora voltemos a janela de comando e vamos nos posicionar na
pasta do nosso projeto e vamos instalar o Angular CLI como
uma dependência do nosso projeto digitando o comando :

npm install @angular/cli@latest --save-dev

Com isso temos o Angular CLI pronto para criar o nosso


componente.
Vamos agora nos posicionar na pasta Components do nosso
projeto. Para isso abra uma janela de comandos e digite os
comandos conforme mostrado abaixo:

Observe que temos na pasta Components quatro componentes


criados nesta pasta : app, counter, fetchdata, home e
navemenu.

Vamos incluir um novo componente usando o Angular CLI


digitando o comando : ng g component veiculo-form
Após o processamento do comando será criado a pasta veiculo-
form na pasta components contendo 4 arquivos :

 veiculo-form.component.html
 veiculo-form.component.ts
 veiculo-form.component.css
 veiculo-form.component.spec.ts

Vamos excluir o arquivo veiculo-form.component.spec.ts que


é um arquivo typescript para testes unitários e usa o Jasmine
que não vou tratar neste artigo.

Após isso vamos abrir o arquivo app.module.ts do projeto e


verificar o registro do nosso componente e fazer o registro da
rota 'veiculos/novo' para o nosso componente:

Vamos incluir a seguir um link para a rota que acabamos de


criar no componente navemenu.component.html.
Abra o arquivo navemenu.component.html da pasta navmenu
e inclua o link para a nossa rota:

Executando o projeto iremos obter o seguinte resultado:

Vemos a opção no menu e a nossa rota veiculos/novo abrindo o


nosso componente veiculo-form.component.html.

Na próxima parte do artigo  vamos criar o formulário da


aplicação usando o Angular 2 e o BootStrap.
"Ora, o fim do mandamento é o amor de um coração puro, e
de uma boa consciência, e de uma fé não fingida."
1 Timóteo 1-5

ASP .NET Core - Criando uma app Básica com EF Core, Web API
e Angular 2 – IV
http://www.macoratti.net/17/06/aspncore_ang24.htm

 Neste artigo vou mostrar como criar uma aplicação ASP .NET
Core integrando o Angular 2 para criar uma aplicação Básica
que consome uma Web API e exibe um formulário com
controles dropdwon, radiobutton, checkbox e textbox.

Neste artigo vamos definir o conteúdo do nosso formulário do


nosso componente usando os recursos do Bootstrap e a seguir
criar um serviço para acessar os dados da nossa API.

Implementando um formulário com Bootstrap


Vamos usar os recursos do Bootstrap para criar formulário do
nosso componente. Para isso vamos nos basear no exemplo do
Bootstrap definido na documentação exemplo a seguir :
Vamos iniciar definindo dois controles dropdownlist onde em
um iremos exibir as marcas e conforme a marca selecionada no
outro iremos exibir o modelo referente a marca.

Teremos assim os controles dropdownlist em cascata.

Abra o arquivo veiculo-form.component.html e inclua o código


abaixo :

<h2>Novo Veiculo</h2>
<form>

<div class="form-group">
<label for="marca">Marca</label>
<select id="marca" class="form-control" >
<option value=""></option>
</select>
</div>

<div class="form-group">
<label for="model">Modelo</label>
<select id="model" class="form-control">
<option value=""></option>
</select>
</div>

<button class="btn btn-primary">Salvar</button>


</form>

Temos agora o esqueleto do nosso formulário pronto exibindo


os dois controles dropdownlist (select).

Executando o projeto iremos obter o seguinte resultado.


Precisamos agora criar um serviço para chamar a nossa API e
acessar os dados para exibir no formulário.

Criando um serviço para acessar aos dados da


nossa API
É uma boa prática encapsular as chamadas ao backend usando
serviços.  Vamos criar um service usando o Angular CLI.

Vamos criar  uma pasta chamada services dentro da


pasta ClienteApp/app.

Para isso digite os comandos conforme mostrado na figura


abaixo:
Após criar a pasta services vamos entrar nesta pasta e digitar o
comando para criar o serviço : ng g service veiculo

Serão criados na pasta services os arquivos:

 veiculo.service.ts
 veiculo.service.spec.ts

Vamos incluir o arquivo veiculo.service.spec.ts que é o


arquivo para testes unitários.

Abra o arquivo veiculo.service.ts e inclua o código abaixo :

import { Injectable } from '@angular/core';


import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class VeiculoService {
constructor(private http: Http)
{}
getMarcas() {
return this.http.get('api/marcas')
.map(res => res.json());
}
}

Neste código importamos o modulo Http e o


operador rxjs/add/operator/map e criamos o
método getMarcas() que faz a chamada à nossa API usando a
rota 'api/marcas' retornando um JSON.

Esse é o nosso serviço e para poder usá-lo temos que registrar o


serviço no arquivo app.module.ts do projeto.

Abra o arquivo app.module.ts e inclua as linhas de código em


azul :

import { FormsModule } from '@angular/forms';


import { VeiculoService } from './services/veiculo.service';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { UniversalModule } from 'angular2-universal';
import { AppComponent } from './components/app/app.component'
import { NavMenuComponent } from
'./components/navmenu/navmenu.component';
import { HomeComponent } from
'./components/home/home.component';
import { FetchDataComponent } from
'./components/fetchdata/fetchdata.component';
import { CounterComponent } from
'./components/counter/counter.component';
import { VeiculoFormComponent } from './components/veiculo-
form/veiculo-form.component';

@NgModule({
    bootstrap: [ AppComponent ],
    declarations: [
        AppComponent,
        NavMenuComponent,
        CounterComponent,
        FetchDataComponent,
        HomeComponent,
        VeiculoFormComponent
    ],
    imports: [
        UniversalModule, // Must be first import. This automatically
imports BrowserModule, HttpModule, and JsonpModule too.
        FormsModule,
        RouterModule.forRoot([
            { path: '', redirectTo: 'home', pathMatch: 'full' },
           
{ path: 'veiculos/novo', component: VeiculoFormComponent },
            { path: 'home', component: HomeComponent },
            { path: 'counter', component: CounterComponent },
            { path: 'fetch-data', component: FetchDataComponent },
            { path: '**', redirectTo: 'home' }
        ])
    ],
    providers: [
       VeiculoService
    ]
})
export class AppModule {
}

Agora podemos usar o nosso serviço. Vamos então definir o


código para chamar o serviço no nosso componente veiculo-
form.component.ts e depois o código para popular os
dropdownlists do formulário veiculo-form.component.html.

Abra o arquivo veiculo-form.component.ts e inclua o código


abaixo:

import { Component, OnInit } from '@angular/core';


import { VeiculoService } from "../../services/veiculo.service";
@Component({
selector: 'app-veiculo-form',
templateUrl: './veiculo-form.component.html',
styleUrls: ['./veiculo-form.component.css']
})
export class VeiculoFormComponent implements OnInit {
marcas: any[];

constructor(private veiculoService : VeiculoService) { }


ngOnInit() {
this.veiculoService.getMarcas().subscribe(marcas =>
this.marcas = marcas);
}
}

Agora vamos definir o código do formulário veiculo-


form.component.html para preencher o dropdownlist.

Abra o arquivo veiculo-form.component.html e inclua o código


em azul:

<h2>Novo Veiculo</h2>
<form>
<div class="form-group">
<label for="marca">Marca</label>
<select id="marca" class="form-control">
<option value=""></option>
<option *ngFor="let m of marcas"
value="{{m.id}}">{{m.nome}}</option>
</select>
</div>
<div class="form-group">
<label for="model">Modelo</label>
<select id="model" class="form-control">
<option value=""></option>
</select>
</div>
<button class="btn btn-primary">Salvar</button>
</form>

No código estamos usando a diretiva *ngFor para percorrer as


marcas retornadas e definindo o valor como sendo o id e
exibindo o nome da marca usando a interpolação {{}}.

Executando o projeto novamente teremos :

Para implementar outro dropdownlist para exibir os modelos


dos veículos conforme a marca selecionada no primeiro
dropdownlist basta seguir a mesma lógica.

Em outro artigo voltaremos ao assunto.


Visual Studio - Iniciando com Node.js - Criando um servidor
web

http://www.macoratti.net/16/03/vs_node2.html

 Neste artigo eu vou mostrar os conceitos básicos


para iniciar o desenvolvimento com Node.js usando o
ambiente do Visual Studio e o Visual Studio Code.

Não, não houve nenhum erro no título do artigo. Vou mostrar


como podemos usar o ambiente da plataforma .NET para
desenvolver para Node.js

Isso mesmo Node.js.

Se você esta chegando agora deve ler o meu artigo - Visual


Studio - Bem-Vindo Node.js : desenvolvendo para Node.js na
plataforma .NET  - que mostra como configurar o seu ambiente
do Visual Studio para usar o Node.js.

Após configurar o ambiente do Visual Studio você já pode e


verificar os templates de projeto Node.js que foram incluídos :
Dessa forma, já temos tudo pronto para desenvolver para
Node.js no Visual Studio 2015 (no meu caso estou usando a
versão Community)

Obs: Na primeira parte do artigo usamos o template Blank


Node.js Console Application.

Usando um terminal
O Node.js oferece o REPL que é uma janela interativa para que
você possa testar e experimentar JavaScript  e explorar soluções
para o problema que você está tentando resolver.

Para o usar o terminal basta abrir um prompt de comando (No


Windows 10 digite cmd.exe) e a seguir digitar : node e
teclar Enter:

Abaixo a figura que mostra o resultado após digitar :  .help para


ver opções de comandos disponíveis :

Você pode usar outros terminais como Git  que inclui o shell 'Git


bash' o qual fornece um terminal ao estilo Unix.

Se você desejar um terminal com mais recursos pode usar


o Console2  ou o ConEmu  que são melhores do que o CMD.exe.

Existe também uma alternativa on-line chamada Codio  que


oferece um serviço com um IDE e um terminal de linha de
comando com o Node já instalado.

Basta acessar o site https://codio.com/ , escolher a versão  trial


(por 15 dias), se registrar e criar um projeto:
Usando Editores
Você pode usar qualquer editor para escrever o seu código
Node.js. Até mesmo o bloco de notas.

É claro que existem editores que oferecem mais recursos que


aumentam a produtividade como NotePad++  e o TextPad .

Felizmente para o ambiente do Visual Studio você pode usar o


editor JavaScript ou também o Visual Studio Code .

Lembrando que o Visual Studio Code é executado nativamente


no sistema operacional da sua escolha e tem os seguintes
recursos:

 Mais de 30 linguagens e contagem, realce de sintaxe e


correspondência de parênteses
 Edição avançada rápida e centralizada no teclado com
vários cursores
 Localizar RegEx, estrutura de tópicos e definição de
inspeção
 IntelliSense, linting e refatoração
 Recursos de depuração :  Interrompa, observe, inspecione
 Controle de versão do Git - Confirme, compare, extraia e
envie por push
 ASP.NET 5 e Node.js - Suporte variado para tecnologias da
web atuais

Nota:  Linting  é o processo de análise de código que sinaliza


erros potenciais ou uso suspeito de código.

Gerenciador de pacotes npm


O npm é um gerenciador de pacotes universal para pacotes
Node. A palavra npm não é um acrônimo, mas uma abreviação
para 'npm is not an acronym.".

As duas principais responsabilidades de um gerenciador de


pacotes é a instalação de pacotes (óbvio) e o gerenciamento de
dependências.

O npm é rápido, capaz é fácil de usar, sendo um dos


responsáveis pelo rápido crescimento e diversidade do
ecossistema Node.

Quando você instala o Node.js o npm é instalado por padrão e


o primeiro comando que você vai usar com ele é :   install

Por exemplo para instalar o Grunt (um JavaScript task runner)


você digitaria no console do Node:

npm install -g grunt-cli

Onde -g indica que o pacote será instalado globalmente o que


significa que ele estará disponível de forma global no sistema.

O Grunt é uma aplicação de linha de comando que tem como objetivo


automatizar tarefas, principalmente tarefas em aplicações JavaScript.  
Você escreve as tarefas em JavaScript e roda no
Node.JS.  http://gruntjs.com/  (site oficial)

Criando um simples servidor web com Node


Se você já deve um contato com o desenvolvimento web, quer
seja usando apenas HTML estático, quer seja usando PHP, ASP,
ASP .NET, etc., você já usou um servidor web (Apache , TomCat,
IIS, etc.) para servir os arquivos de forma que um navegador
possa exibir o conteúdo das suas páginas.

O Node.js oferece um paradigma diferente do tradicional


servidor web. Ao desenvolver com Node, a aplicação que você
escreve é o servidor web. Assim, o Node oferece um framework
para você construir um servidor web.

Não se assuste, pois a tarefa é muito simples, e com poucas


linhas de código, e você tem um controle muito grande sobre a
aplicação.

Bem, então vamos a parte prática visto que já temos o Node.js


instalado.

Abra o Visual Studio Code, ou outro editor de comando de sua


escolha, e digite o código abaixo:
var http = require('http')
http.createServer(function(req,res) {
res.writeHead(200, { 'Content-Type' : 'text/plain' });
res.end(' Macoratti .net - Visual Studio e Node.js');
}).listen(3000);
console.log('Servidor iniciando em localhost:3000; pressione
Ctrl-C para encerrar')

Salve o arquivo com o nome aloMundo.js em uma pasta


adequada. No exemplo eu salvei na pasta c:\node .

Vamos entender o código:

A primeira coisa que vamos fazer em qualquer aplicação web que escrevemos
com Node é solicitar um módulo que permite-nos realmente servir um site.

As tarefas mais comuns do servidor são parte dos módulos http ou


https. No mínimo, qualquer aplicação web precisará importar um destes
módulos (ou outro módulo que tem um ou outro como uma
dependência) usando a função require. Ex: var http = require('http')

O gerenciamento de dependência interna do Node é semelhante


ao CommonJS e o comando require mascara a complexidade de
pesquisa para o módulo desejado e evitando a redundância.

Uma vez que o módulo http está disponível, podemos criar um servidor
e solicitar-lhe para começar escutar solicitações.

A função createServer() tem apenas um parâmetro: o retorno de


chamada que será executado sempre que uma solicitação é recebida.  

A função listen() que inicia o servidor pode ter vários argumentos, mas,


para um servidor simples, só precisamos fornecer a porta e,
opcionalmente, o IP do host.
 

A seguir abra um prompt de comando ou outro terminal de sua


escolha e posicione-se na pasta onde salvou o
arquivo aloMundo.js.
A seguir digite no terminal o comando : node aloMundo.js e
tecle enter:

Agora abra um navegador e digite : http://localhost:3000  e


voilá...

Seu primeiro servidor web criado no Node.js. Note que não


estamos servindo HTML mas apenas texto. Se quiser servir HTML
altere o Content-Type para 'text/html'.

Agora vamos fazer a mesma coisa usando o Visual Studio 2015


Community.

Abra o VS 2015 Community e no menu File clique em New ->


Project ;

Selecione JavaScript -> Node.js e o template Blank Node.js


Web Application e informe o nome VS_Node_Servidor e clique
em OK;
Será criado o projeto Node.js com a estrutura e código conforme
mostra a figura abaixo:

Observe que o código criado é muito parecido com o que


usamos para criar o nosso primeiro servidor web no Node.js via
código.
Executando o projeto iremos obter o seguinte resultado:

Vemos nosso servidor web atendendo na porta 1337.

Concluímos assim a criação de nosso primeiro servidor web com


Node.js usando código e também usando o Visual Studio 2015.

Na próxima parte do artigo  vamos mostrar outros recursos do


Node.js e incrementar a nossa aplicação.

Referências:
 Seção VB .NET do Site Macoratti.net
 Super DVD .NET - A sua porta de entrada na plataforma
.NET
 Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP
.NET e C#
 Seção C# do site Macoratti.net
 Super DVD C#
 Super DVD Visual Basic
 Curso Básico VB .NET - Vídeo Aulas
 Curso C# Básico - Vídeo Aulas
 ASP.NET - JavaScript - Macoratti.net
 Usando jQuery com ASP .NET - Macoratti.net
 Visual Studio - Bem-Vindo Node.js : desenvolvendo para
 Node - Criando uma API REST com Express acessando o ...
- Macoratti
 Visual Studio - Iniciando com Node.js - Criando um sevidor
... - Macoratti
 Node.js - Apresentando e usando o Sequelize (acesso
ao ... - Macoratti
Visual Studio - Iniciando com Node.js - Criando um servidor
web – II
http://www.macoratti.net/16/03/vs_node3.html

 Neste artigo eu vou  continuar a mostrar os conceitos


básicos para iniciar o desenvolvimento com Node.js
usando o ambiente do Visual Studio.

No artigo anterior  apresentei alguns fundamentos básicos para


poder usar o Node.js, e, neste artigo vou continuar
incrementando a aplicação que iniciamos.

Se você esta chegando agora deve ler o meu artigo - Visual


Studio - Bem-Vindo Node.js : desenvolvendo para Node.js na
plataforma .NET  - que mostra como configurar o seu ambiente
do Visual Studio para usar o Node.js.

Programação orientada a eventos


A principal filosofia por trás do Node é a programação orientada
a eventos. O que significa que você como desenvolvedor tem
que compreender quais eventos estão disponíveis para você e
como você pode responder a eles.

Se você esta chegando agora deve ler o meu artigo - Visual


Studio - Bem-Vindo Node.js : desenvolvendo para Node.js na
plataforma .NET  - que mostra como configurar o seu ambiente
do Visual Studio para usar o Node.js.

Programação orientada a eventos


A principal filosofia por trás do Node é a programação orientada
a eventos. O que significa que você como desenvolvedor tem
que compreender quais eventos estão disponíveis para você e
como você pode responder a eles.

Para os desenvolvedores Visual Basic e C# esse não é um


conceito novo, visto que quando criamos uma aplicação
Windows Forms, WPF ou mesmo ASP .NET Web Forms, temos
que tratar os eventos que são disparados pela interação com o
usuário. Assim sabemos que quando um usuário clica em um
botão temos que tratar o evento Click associado.

Com o Node existe uma pequena diferença : quanto trabalhamos


com o Node temos que lembrar que os eventos estão ocorrendo
do lado do servidor.

Em nosso servidor web criado no artigo anterior, cujo código


estou repetindo abaixo, o evento esta implícito:

var http = require('http')


http.createServer(function(req,res) {
res.writeHead(200, { 'Content-Type' : 'text/plain' });
res.end(' Macoratti .net - Visual Studio e Node.js');
}).listen(3000);
console.log('Servidor iniciando em localhost:3000; pressione
Ctrl-C para encerrar')

O evento que esta sendo tratado é uma requisição HTTP.

O método http.CreateServer usa uma função como um


argumento; essa função será invocada a cada vez que uma
requisição HTTP for realizada, e nosso programa apenas define o
tipo de conteúdo para texto plano e envia a string 'Macoratti .net
- Visual Studio e Node.js'

Roteamento
O roteamento é um mecanismo para servir o cliente com o
conteúdo que ele solicitou. Para aplicações web baseadas em
aplicações cliente/servidor, o cliente especifica o conteúdo
desejado na URL: path e a querystring.

Vamos então expandir nosso exemplo para fazer algo mais


interessante. Vamos servir um web site que consiste de uma
página Home, uma página Sobre e uma página Não
Encontrada.

Por enquanto vamos continuar servindo apenas texto plano ao


invés de HTML.

Abra o projeto VS_Node_Servidor, que foi criado no artigo


anterior, no Visual Studio 2015 Community e altere o código do
arquivo server.js conforme abaixo:

var http = require('http');


http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
// normalizar url removendo cadeia de consulta (querystring), a
barra final à direita e
// tornando tudo em caixa baixa
var path = req.url.replace(/\/?(?:\?.*)?$/, '').toLowerCase();
switch (path) {
case '':
res.writeHead(200, { 'content-type': 'text/plain' });
res.end('Home');
break;
case '/sobre':
res.writeHead(200, { 'content-type': 'text/plain' });
res.end('Sobre');
break;
default:
res.writeHead(404, { 'content-type': 'text/plain' });
res.end('Not found');
break;
}
}).listen(3000);
console.log('Servidor iniciado em : localhost:3000; tecle Ctrl+C para
terminar...')

Após salvar executando o  projeto iremos obter o seguinte


resultado:

1- Inicialmente teremos a janela do Console exibindo a


mensagem que o servidor esta atendendo e podemos abrir o
Navegador:
2- Digitando a URL : localhost:3000/ iremos obter:
3- Digitando a URL : localhost:3000/sobre,  teremos:

4- Digitando a URL : localhost:3000/macoratti ou qualquer outra


URL :
Obtivemos o comportamento esperado onde
qualquer querystring (localhost:3000/?teste=100) será ignorada,
e, qualquer outra URL irá servir a página Not Found.

Servindo recursos estáticos


Agora que temos o roteamento funcionando vamos servir HTML
e também uma imagem. Esses recursos são conhecidos como
recursos estáticos pois eles não se alteram.

Para realizar essa tarefa usando o Node temos que fazer o


trabalho de abrir o arquivo, ler o arquivo e então enviar o seu
conteúdo para o navegador.

Vamos então criar um diretório em nosso projeto


chamado public e nesta pasta criar os arquivos home.html,
sobre.html, 404.html.

Clique com o botão direito sobre o nome do projeto e a seguir


clique em Add-> New Folder e informe o nome public;
Selecione a pasta public e no menu Project clique em Add New
Item;

Selecione o template HTML file e informe o nome home.html:

Defina o conteúdo do
arquivo home.html , incluindo : <h1>Página
Home</h1> apenas para identificar a página:
Repita o procedimento acima e crie os arquivos sobre.html e
404.html.

Vamos criar também no interior da pasta public outra pasta


chamada img e vamos incluir nesta pasta um arquivo imagem
qualquer.No exemplo eu inclui a imagem maco.jpg.

Ao final nosso projeto terá a seguinte estrutura:

Finalmente vamos alterar o código do arquivo server.js criando


uma função para abrir e ler os arquivos que vamos servir pelo
nosso servidor.

Inclua o código abaixo no arquivo server.js :

var http = require('http');  


var fs = require('fs');
function serverStaticFile(res, path, contentType,
responseCode) {
if (!responseCode) responseCode = 200;
fs.readFile(__dirname + path, function (err, data){
if (err) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('500 - Internal Error');
} else {
res.writeHead(responseCode, { 'Content-Type':
contentType });
res.end(data);
}
});
}
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
var path = req.url.replace(/\/?(?:\?.*)?$/, '').toLowerCase();
switch (path) {
case '':
serverStaticFile(res, '/public/home.html', 'text/html');
break;
case '/sobre':
serverStaticFile(res, '/public/sobre.html', 'text/html');
break;
case '/img/maco.jpg':
serverStaticFile(res, '/public/img/maco.jpg',
'image/jpg');
break;
default:
serverStaticFile(res, '/public/404.html', 'text/html', 404);
break;
}
}).listen(3000);
console.log('Servidor iniciado em : localhost:3000; tecle Ctrl+C
para terminar...')
Entendendo o código :

- Criamos a função serverStaticFile para abrir e ler os arquivos


html.

- O método fs.readFile() faz a leitura de forma assíncrona dos


arquivos especificados

- Após a leitura do arquivo é executa o retorno de chamada da


função
- Se o arquivo não existe ou ocorrer qualquer outro erro a
variável err é definida e a é retornado o código 500 indicando o
erro.

- __dirname resolve o nome do diretório onde o script que


executa o código reside

Executando o projeto novamente veremos que as páginas HTML


serão servidas e exibidas no navegador.

1- Digitando a URL : localhost:3000 teremos:

Para exibir a imagem maco.jpg que esta na


pasta /public/img do projeto
digite : localhost:3000/img/maco.jpg
Digitando agora qualquer outra URL teremos:
Avançamos um pouco com nosso projeto, mas aposto que você
não esta muito animado com o que tem visto. Afinal, estamos
replicando o que um servidor Apache ou IIS faz
automaticamente para você.

Então aguarde a próxima parte do artigo onde vamos apresentar


mais recursos do Node e veremos como usar o Express, um
framework web rápido e minimalista para Node.js.

O Express é um framework para aplicativo da web do Node.js


mínimo e flexível que fornece um conjunto robusto de recursos
para aplicativos web e móvel.

Com uma miríade de métodos utilitários HTTP e middleware a


seu dispor, criar uma API robusta é rápido e fácil.

O Express fornece uma camada fina de recursos fundamentar


para aplicativos da web, sem obscurecer os recursos do Node.js
que você conhece e ama.

fonte: http://expressjs.com/pt-br/

Aguarde a  próxima parte do artigo ...


Visual Studio - Iniciando com Node.js - Criando um servidor
web – III  

http://www.macoratti.net/16/03/vs_node4.html

 Neste artigo eu vou continuar a mostrar os conceitos


básicos para iniciar o desenvolvimento
com Node.js usando o ambiente do Visual Studio.

No artigo anterior  incrementamos o nosso servidor web usando


os recursos de roteamento e servindo conteúdo estático.

Neste artigo vou apresentar o framework Express para o


Node.js.

Se você esta chegando agora deve ler o meu artigo - Visual


Studio - Bem-Vindo Node.js : desenvolvendo para Node.js na
plataforma .NET  - que mostra como configurar o seu ambiente
do Visual Studio para usar o Node.js.

Apresentando e usando o Express


Nos artigos anteriores criamos nosso servidor web usando um
módulo HTTP que é parte dos módulos principais do Node.js.

Antes de entrar no assunto Express é bom você conhecer o


conceito de Middleware usado no Node.js.

Mesmo com a ajuda dos módulos padrão do Node.js,


implementar todos os recursos de uma aplicação web atual seria
uma tarefa trabalhosa e tediosa. Você teria que escrever muita
coisa e isso acabaria impactando a sua produtividade. Uma
alternativa a isso é usar um middleware.

Podemos entender o conceito de Middleware como sendo são


funções que processam requisições em um estilo de linha de
montagem. (executam processos intermediários)
Assim um Middleware é todo o tipo de função que está entre
um pedido HTTP e a resposta final que o servidor envia de volta
para o cliente.

Neste cenário o framework Express é considerado um


Middleware e fornece um outro nível de abstração no topo do
HTTP, oferecendo diversos recursos que ajudam a acelerar o
desenvolvimento web.

Para iniciar o desenvolvimento com Express a primeira coisa a


fazer é instalá-lo, e a maneira mais fácil de fazer isso é através
do gerenciador de pacotes npm  do Node.js

Usando o ambiente do Windows 10 e possuindo uma conexão


coma internet ativa, abra uma janela de comando (digite CMD) e
a seguir digite a linha de comando abaixo para instalar o Express
:

npm install express

Com este comando estamos instalando o Express localmente no


contexto da nossa aplicação. 

A razão para isto é que aplicativos sempre olham no seu


contexto local para consultar as dependências. A instalação
global é feita apenas para configurar todo o sistema de binários
disponíveis.Instalando o Express globalmente você obtém um
binário do express que pode iniciar um aplicativo para você.
Nota  : Para instalar o Express globalmente use o parâmetro   -
g  :    npm install express -g
Após alguns segundos, se não houver nenhum erro, você irá
obter o resultado abaixo:

Agora nosso ambiente esta preparado para usar o Express.

Poderíamos iniciar usando um script executável pronto


do Express chamado express(1) que iria gerar o esqueleto da
aplicação Express, mas antes de fazer isso vamos criar uma
aplicação Express usando apenas JavaScript em um arquivo .js.
Abra um editor de texto qualquer e crie o
arquivo serverexpress.js em uma posta local do seu
computador.  (Eu estou usando uma pasta c:\node)

var express = require('express')


var appexp = express();
appexp.get('/', function(req, res) {
res.send('Benvindo Express');
});
appexp.listen(8084);
console.log('Servidor rodando na porta 8084');

Essa talvez seja a aplicação mais simples que você pode criar
com o Express.

Neste código a primeira coisa que eu fiz foi importar um


módulo express usando require('express') e depois criamos a
aplicação appexp como uma instância do servidor.

Com a aplicação criada definimos um manipulador


de response e definimos uma rota usando o método HTTP GET,
o caminho '/', que representa a nossa raiz e a função de callback
usando os objetos req e res que representam a  requisição e a
resposta.

Concluindo, informamos ao servidor para escutar na


porta 8084 usando o método listen do objeto appexp que cria
um servidor vinculado á porta 8084.

Agora  para rodar nossa aplicação basta digitar :   node


appexp.js 
O servidor indica que esta atendendo na porta 8084. Basta abrir
um navegador e digitar : http://localhost:8084/  para obter:

Podemos incluir a manipulação de múltiplas requisições em


nosso código. Pare o servidor, e altere o código do
arquivo appexp.js conforme abaixo:

var express = require('express');


var appexp = express();

appexp.get('/', function(req, res) {


    res.send('Bem-Vindo Express');
});

appexp.get('/admin', function(req, res) {


    res.send('Bem-Vindo Admin');
});

appexp.get('/macoratti', function(req, res) {


    res.send('Bem-Vindo Macoratti');
});
appexp.listen(8084);
console.log('Servidor iniciando na porta 8084,  pressione Ctrl-C
para encerrar')

Executando novamente e testando no navegador para a


rota /macoratti iremos obter:

Criando um projeto Node.js no Visual Studio


usando o Express
Vamos agora criar um projeto Node.js usando o Visual Studio e
mostrar que a utilização dos templates pode facilitar a nossa
vida.

Abra o Visual Studio 2015 Community e selecione o


template  JavaScript -> Node.js;

Você verá vários templates de projeto disponíveis.  Vamos


selecionar o projeto Starter Node.js Express 3 Application e
clique em OK;
Será criado o projeto na pasta indicada com a seguinte
estrutura:
Vemos aqui a
estrutura do
projeto Node
criado pelo Visual

- os pacotes
npm : express , jade
, stylus

- as fontes, imagens
e referencias
javascripts : bootstr
atp, jquery,

- as fontes de
estilos :  bootstrap

- o roteamento :
index.js

- as views usando o
engine Jade

O Jade é um
template engine
exclusivo para
Node.js, cuja
sintaxe é
totalmente
diferente do HTML
convencional.

- a aplicação
Node : app.js

- o pacote
json : package.json

Nota :  O destaque do Jade é que podemos trabalhar com


código server-side junto ao código client-side, ou seja, código
javascript server-side misturado com código html ou
javascript client-side;

Executando o projeto iremos ver a janela indicando a porta onde


o Debugger esta atendendo e a porta onde servidor esta
escutando(1337) :

A seguir veremos a página da aplicação Node exibida no


navegador:
Bem parecida com a página inicial de uma aplicação ASP .NET
gerada no Visual Studio.

O código gerado no arquivo app.js , que é o coração da


aplicação Express, é dado a seguir:

/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(require('stylus').middleware(path.join(__dirname,
'public')));
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/about', routes.about);
app.get('/contact', routes.contact);
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' +
app.get('port'));
});

Podemos também criar um template usando a versão


4 do Express escolhendo no Visual Studio o template Basic
Node.js Express 4 Application:
Neste executando o projeto teremos a aplicação Node exibida
no navegador :

Assim mostrei que com a utilização do Express podemos obter


um resultado mais elaborado em termos de interface com o
usuário.
A utilização do Visual Studio ajuda muito na criação de
aplicações Node pois possui templates prontos que podemos
usar e depois customizar.

Em outro artigo vou mostrar como criar uma aplicação Node


usando o script expression(1) do Express e explicar o esqueleto
gerado.
ASP .NET  - Usando JavaScript – I
http://www.macoratti.net/07/09/aspn_ujs.htm

 Neste
artigo
vou
apresent
ar os
conceitos
básicos
do
JavaScrip
t e como
usar os
seus
recursos
na
ASP
.NET.

Se você trabalha ou pretende trabalhar com desenvolvimento para


web usando ASP.NET e já ouviu a frase : "Não se preocupe, você não
precisa conhecer nada de JavaScript...", sinto informar-lhe que na
realidade isto não é verdade.

Embora a ASP.NET  tenha facilitado muito a vida do programador web


oferecendo recursos para tratamento tanto do lado do servidor como
do lado do cliente, conhecer JavaScript acaba sendo uma necessidade
que você vai sentir no seu dia a dia, e que sem ela você vai sentir falta
de alguns recursos que iriam lhe ajudar muito.

Nota: JavaScript não é a mesma coisa que Java. Java é uma


linguagem de programação orientada a objetos com muito mais
recursos que JavaScript que é um linguagem de scripts.
Você não vai precisar fazer um Phd em JavaScript mas precisa saber
como o JavaScript funciona para poder usar em suas páginas ASP.NET
recursos interessantes que a tornaram mais dinâmica e interativa.

Neste artigo eu não pretendo ir fundo no JavaScript , vou apresentar


os fundamentos e mostrar como você pode usar JavaScript para
melhorar a interação de suas páginas ASP.NET com o usuário. O
assunto JavaScript é vastíssimo e exigiria a publicação de dezenas de
artigos o que foge do escopo do site.

A primeira coisa que você deve ter em mente é que JavaScript(Js) é


usado para interação com o lado cliente efetuando validações, criando
janelas pop-ups , emitindo mensagens, etc., onde o navegador do
cliente é o encarregado de interpretar as instruções Javascript e
executá-las.

O código javascript geralmente é colocado no documento HTML e


deve estar entre as tags <script></script> para que possa funcionar.
Além disso podemos incluir código JavaScript em eventos da página e
de seus componentes.

Existem duas formas básicas de se executar JavaScript :

1- A execução direta - neste caso o código Js é colocado entre as


tags <SCRIPT> e o quando o navegador ler a página e encontrar o
script ele irá interpretar e executar o código

2- A resposta a um evento - Eventos são ações que são realizadas


pelo usuário. O JavaScript esta preparado para responder a
determinados eventos que ocorrem na página ou em seu controles e
realizar ações como resposta a estes eventos. Exemplo de eventos:
Clicar um botão (OnClick), receber o foco (Onfocus) , etc.

Nota: Tome o cuidado, o JavaScript é case sensitive , assim Alert()


não funciona , o correto é alert().

Abra o Visual Web Developer 2005 Express e crie um novo web site na
opção File->New Web Site com o nome js_Net. Selecione a
página Default.aspx criada por padrão e selecione o modo de
visualização Source e você verá o seguinte código:
<%@ Page Language="VB" AutoEventWireup="false"
CodeFile="Default.aspx.vb" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Usando JavaScript</title>

</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>

Código fonte da página Default.aspx

Vou incluir entre as tags Head (poderia ser entre as tags  Body) dois


codigos JavaScript bem simples, apenas para mostrar como funciona.

Abaixo temos o código da página já com o JavaScript incluído:

<%@ Page Language="VB" AutoEventWireup="false"


CodeFile="Default.aspx.vb" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Usando JavaScript</title>
<script>
       window.alert("Bem-vindo ao site: Macoratti.net.")
</script>
 <script> document.write(new Date()) </script>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>

Página Default.aspx com código JavaScript.

O código acima ilustra a forma de execução direta do código


javaScript.

Executando a página veremos o resultado como exibido nas duas


figuras abaixo:

1- Na primeira foi aberta uma janela com uma mensagem ao usuário


(1);

2- Na segunda foi obtida a data atual e exibido no formulário(2);


Com isso eu apenas mostrei que você pode usar JavaScript em páginas
ASP.NET da mesma forma que nas páginas HTML inclusive executando
diretamente o código. O código JavaScript usado será executado toda
a vez que a página for carregada o que não é muito adequado.

Agora vamos mostrar como usar JavaScript com ASP.NET de uma


forma mais efetiva. Se você não sabe nada de JavaScript sugiro que
procure no Google por tutoriais sobre o assunto, você vai encontrar
toneladas de material sobre o assunto.(Veja referência no fim do
artigo).

Usando JavaScript com ASP.NET

Embora você ainda possa continuar usando código JavaScript da forma


tradicional em páginas ASP.NET, a ASP.NET 2.0 apresenta muitas
funcionalidades, classes e métodos para facilitar o seu trabalho.

Vejamos a seguir como usar alguns destes recursos.

Vamos alterar o código incluído na página Default.aspx criando duas


funções conforme abaixo:

<%@ Page Language="VB" AutoEventWireup="false"


CodeFile="Default.aspx.vb" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Usando JavaScript</title>
<script language="javascript" type="text/javascript">
function mensagem()
{
    window.alert("Bem-vindo ao site: Macoratti.net.")
  }     
</script>
<script language="JavaScript" type="text/javascript">
 function data()
 {
  document.write(new Date())
 }
</script>
</head>
<body onload="javascript:document.forms[0]
['TextBox1'].value=Date();">
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
<asp:TextBox ID="TextBox1" runat="server"
Width="340px"></asp:TextBox>
</div>
</form>
</body>
</html>

Foram criadas duas funções JavaScript:

- mensagem() - exibe uma janela de mensagem no cliente;


- data() - exibe a data do cliente na página

Como podemos usar estas funções nas páginas ASP.NET ? Como


podemos chamá-las ?

1- Inclua dois botões de comando : Button1 e Button2 na página


2- Altere a propriedade do primeiro botão para : mensagem() e a do
segundo para data()
3- Selecione o primeiro botão e na janela de propriedades localize a
propriedade OnClientClick informe o nome da função
javascript mensagem() que criamos na página.
4- Repita o procedimento do item anterior para o
botão data() informando a função javascript data() na
propriedade OnClientClick.

Agora altere o modo de visualização para Source e veja o código para


os dois controles como foi alterado:

...
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server"
Text="mensagem()" OnClientClick="mensagem()" /><br />
<asp:Button ID="Button2" runat="server"
Text="data()" OnClientClick="data()" /></div>
</form>
</body>
...

Agora é só alegria. Execute a página e clique em cada um dos botões


para chamar as funções javascript e executar o código.

Incluindo JavaScript em páginas ASP.NET via


código
Vamos remover o código JavaScript da página Default.aspx, e incluir,
a partir da ToolBox , um controle Button conforme abaixo:

Vamos agora incluir no evento Load do formulário um código


JavaScript que deverá abrir uma janela de alerta quando o botão
Button1 for clicado . Clique duas vezes na área vazia do formulário
para abrir o evento Load do form. A seguir vamos digitar o seguinte
código:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As


System.EventArgs) Handles Me.Load
    Button1.Attributes.Add("OnClick", "alert('Macoratti.net')")
End Sub
Vamos entender:

Eu estou incluindo no botão Button1, na sua coleção de atributos, no


evento OnClick , o código JavaScript contendo a
função Alert('Macoratti.net') , através do método Add.

Execute a página e clique no controle Button; você verá uma janela


com a mensagem: "Macoratti.net"; em seguida dê uma olhada no
código fonte da página e perceba que foi incluido o código no
evento Onclick do botão:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>
Usando JavaScript
</title></head>
<body>
<form name="form1" method="post" action="Default.aspx"
id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwUKMTQ2OTkzNDMyMQ9kFgICAw9kFgICAQ8PZBYCHg
dPbkNsaWNrBRZBbGVydCgnTWFjb3JhdHRp_
Lm5ldCcpZGRjDfgHcg9zCSimwoo22dVpaG80lg==" />
</div>

<div>
<input type="submit" name="Button1"
value="Button" onclick="Alert('Macoratti.net');" id="Button1" />

<div>
<input type="hidden" name="__EVENTVALIDATION"
id="__EVENTVALIDATION"
value="/wEWAgKljZiPAgKM54rGBlkhKnble6ps0vQaKk4pc0+p6Xkx" />
</div></form>
</body>
</html>

O que fizemos no código acima foi registrar de forma automática o


código JavaScript em nossa página ASP.NET.  

Outro exemplo usando a mesma técnica seria colocar no


evento Click de um controle button a solicitação da confirmação ao
usuário:

Então a primeira etapa seria criar a função JavaScript em um arquivo


externo chamado funcoes.js contendo o seguinte código:

<script language="javascript">
<!--
function Confirmar()
{
    return(window.confirm("Confirma esta operação ?"))
}
//-->
</script>

O próximo passo e declarar a utilização do arquivo


javascript funcoes.js na página Default.aspx:
Perceba que o arquivo foi colocado  no projeto mas poderia ter sido
colocado em uma outra pasta.

Para encerrar no evento Load da página incluímos a função javascript


via código:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.E
ventArgs) Handles Me.Load

Button1.Attributes.Add("onclick", "return Confirmar()")

End Sub

Podemos também usar a seguinte alternativa para obter a hora da


máquina do cliente com javascript. Inclua abaixo do
controle Button um controle TextBox, e a seguir , no
evento Onload do elemento Body declare o código JavaScript:

javascript:document.forms[0]['TextBox1'].Value=Date();

O código deverá ficar assim:


<%@ Page Language="VB" AutoEventWireup="false"
CodeFile="Default.aspx.vb" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Usando JavaScript</title>
</head>
<body onload="javascript:document.forms[0]
['TextBox1'].value=Date();">
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</div>
</form>
</body>
</html>

Ao executar a página, quando o formulário for carregado , o resultado


será o seguinte:
A versão ASP.NET 2.0 apresenta a classe ClientScriptManager que
contém métodos que podem ser usados para incluir código JavaScript
no cliente.

Os métodos da classe Page são também disponibilizados por esta


nova classe e apresenta uma nova propriedade ClientScript que
permite usar a nova classe, ou seja , podemos acessar a
classe ClientScriptManager através de Page.ClientScript.

 RegisterClientScriptBlock - inclui um bloco de script no topo


da página. (Gera o script após a tag form). A sintaxe é:

               Public Sub RegisterClientScriptBlock ( _ type As Type, _


key As String, _ script As String _ )

 RegisterStartupScript - registra o bloco de script com o objeto


Page.(Gera o script antes do fechamento da tag </form>  ) A
sintaxe é:

   Public Sub RegisterStartupScript ( _ type As Type, _ key As


String, _ script As String _ )
   Public Sub RegisterStartupScript ( _ type As Type, _ key As
String, _ script As String _ , _boolean As Boolean)

 RegisterOnSubmitStatement - inclui um script que será


executado em reposta a um submit de um formulário;
 RegisterClientScriptInclude - Incluir um script em referência a
um arquivo javascript externo;

Vejamos um exemplo bem simples; Inclua um controle Button na


página e no seu evento Click digite o seguinte código:

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System
.EventArgs) Handles Button1.Click
Try
      'seu codigo para realizar qualque operação
    'se for bem sucedida então exibe uma mensagem ao usuário
   
Page.ClientScript.RegisterStartupScript(Me.GetType, "OK", "windo
w.alert('operação concluída com sucesso');", True)
Catch ex As Exception
    'se ocorreu um erro então exibe um aviso:
    Page.ClientScript.RegisterStartupScript(Me.GetType, "Erro", "wi
ndow.alert('Ocorreu um erro na aplicação');", True)
End Try
End Sub
 

Executando a página e clicando no botão iremos obter a janela  de


operação realizada com sucesso:

Dê uma espiada no código fonte e você verá que o código javascript


foi registrado no final da página:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>
Usando JavaScript
</title>
</head>
<body>
<form name="form1" method="post" action="Default.aspx"
id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwUKMTQ2OTkzNDMyMQ9kFgICAw9kFgICAQ8PZBYCHg
dvbmNsaWNrBRJyZXR1cm4gQ29uZmlybWFyKClkZHKMkRKI/pjwp5VA
hY5aNBpjSTAV" />
</div>

<input type="submit" name="Button1" value="Salvar" id="Button1"


style="height:36px;width:102px;" />

<div>

<input type="hidden" name="__EVENTVALIDATION"


id="__EVENTVALIDATION"
value="/wEWAgLNyre0DQKM54rGBlxnn59ZyjPgAZ/ukPSaxwF3sEl/" />
</div>

<script type="text/javascript">
<!--
window.alert('operação concluida com sucesso');// -->
</script>
</form>
</body>
</html>
 

Em meu artigo - ASP.NET - Messagebox - eu mostro mais detalhes


sobre esses métodos.

Eu poderia continuar a falar sobre utilização do javascript mas na


continuação deste artigo irei mostrar somente exemplos práticos de
utilização de código javascript em páginas ASP.NET.

Até lá...  :  Acompanhe a segunda parte aqui :   Usando JavaScript II  


ASP .NET - Usando JavaScript – II
http://www.macoratti.net/07/09/aspn_ujs2.htm

 Neste
artigo
vou
apresenta
r os
conceitos
básicos
do
JavaScrip
t e como
usar os
seus
recursos
na ASP
.NET.

Em continuação ao meu artigo, Usando JavaScript I onde apresentei


alguns conceitos básicos relacionados ao JavaScript, vou mostrar
alguns exemplos práticos que você pode usar para tornar as suas
aplicações ASP.NET mais interativas e funcionais.

1- Usando janelas pop-up estilo Lookup

Em aplicações desktop, é muito comum a utilização de consultas


lookup onde uma janela é aberta e apresenta as opções e o usuário
efetua a sua escolha. Talvez o exemplo clássico seja uma consulta de
clientes em um formulário de cadastro de pedidos. Vejamos como
implementar a mesma funcionalidade em ASP.NET usando JavaScript.

Abra o Visual Web Developer e crie um novo web site , menu File-


>New Web Site, com o nome de janelasPopUpJs.

A seguir você deve criar uma conexão com o banco de


dados Northwind.mdf no SQL Server 2005. Você pode usar o
DataBase Explorer e criar a conexão no seu projeto Local ou usar
o Management Studio (configura o meu artigo: .NET  2005 - Usando
o SQL Server Management Studio ).

Após ter a conexão criada vamos criar um DataSet tipado :

1- Clique com o botão direito do mouse sobre o nome do projeto na


janela Solution Explorer e acione a opção Add New Item;
2- Na janela Templates selecione DataSet e informe o
nome Northwind.xsd e clique no botão Add;
3- O VWD irá perguntar se você deseja colocar o DataSet na
pasta App_Code, clique em Yes e interrompa o processo neste ponto;
4- Abra a janela Database Explorer e expanda a
conexão Northwind criada de modo a exibir as tabelas;
5- Estando com o DataSet aberto a seguir arraste a
tabela Categorias do DataBase Explorer para  janela do DataSet;

Será criada o DataTable Categories e o


TableAdpater CategoriesTableAdapter

Agora selecione o arquivo Default.aspx e alterne para o


modo Design e vamos criar um formulário de cadastro de Produtos. A
partir do menu Layout selecione Insert Table e inclua uma tabela com
4 linhas e 2 colunas construindo o formulário de cadastro conforme a
figura abaixo:
Este formulário esta na página Default.aspx e será a página principal,
durante o cadastro o usuário poderá clicar no botão Busca e será
aberta uma nova janela exibindo as categorias cadastradas permitindo
a seleção da categoria desejada.

Configure as seguintes propriedades da célula Categoria do


formulário:

- ID do botão Busca igual btnBuscaCategoria


- ID txtCodigoProduto para o primeiro TextBox
- ID txtCodigoCategoria para o segundo primeiro TextBox
- ID txtNomeCategoria para o seguinte TextBox
- ID txtNomeProduto para o quarto TextBox

Vamos então incluir  um nova página chamada Categorias.aspx. No


menu WebSite selecione  Add New Item e marque o template Web
Form informando o nome da página e clicando no botão Add.

A partir da ToolBox, na guia Data, arraste o componente GriView para a


página Categorias.aspx e em Choose Data Source selecione <new
data source>
Na janela Choose a Data Source Type marque a opção Object e
altere o nome para oCategoriasDS e clique no botão Next>

Na próxima janela selecione o objeto de


negócio : NorthwindTableAdapters.CategoriasTableAdapter e
clique em Next> até encerrar o processo e termine clicando em Finish.

Você deverá ver o GridView exibindo os dados da tabela Categorias.


Clique no link Edit Columns e exclua o campo Description.

A seguir em Available fields localize e expanda CommandField e


inclua uma coluna do tipo Select definindo a sua
propriedade ButtonType como Button e defina sua
propriedade Text para Selecionar:
Aplique uma formatação e ative a paginação do GridView; o resultado
final pode ser visto na figura abaixo:
Temos portando duas páginas :  a página Default.aspx que é a página
de cadastro e a página Categorias.aspx que á página que será usada
para buscar e selecionar dados de uma categoria.

Volte a página Default.aspx e no evento Click do botão Busca vamos


incluir o código JavaScript:

Este código define um código javaScript que usa a


função window.open para abrir um janela pop-up. A
página Categorias.aspx será então aberta como uma janela pop-up
com as seguintes propriedades:

 resizable= no - não permite redimensionar a janela

 menubar=no  - não exibe a barra de menu

 scrollbars=no  - não exibe barras de rolagens

 width=350

 heigth=250

O RegisterClientScriptBlock da propriedade ClientScript do
objeto Page executa o javascript incluindo-o na página Default.aspx.

 Para abrir uma janela com Javascript podemos utilizar a


sentença window.open(). (cuidado JavaScript é case sensitive)

1. Sentença Javascript para abrir uma janela


A sentença é chamar a função window.open(). A função possui
muitos parâmetros. Vejamos os mais importantes:

A função window.open() usa três parâmetros:  window.open( URL , 


nome_da_janela,  forma_da_janela)
 
Exemplo:
<script language="javascript">
    window.open("pagina_a_ser_aberta" , "nome_da_página" );
</script>
 
Abrindo pop-up (macoratti.html):
<script language="javascript">
     window.open("macoratti.html" , "macoratti");
</script>
 
Pela função window.open podemos controlar o tamanho da janela:
<script language="javascript">
   window.open("macoratti.html", "Macoratti" , "height = 350 ,
width = 350");
   //Height = Altura, Width = largura.
   //Abre uma Nova Janela de 350 x 350 com o título "Macoratti"
</script>
 
Esta função permite escolher entre exibir ou não: a barra de rolagem, a
barra de status, a barra de menu,
barra de ferramentas, barra de endereços, barra de títulos, exibir em
tela cheia... Exemplo para exibir a barra de rolagem:
 
<script language="javascript">
window.open("macoratti.html", "Macoratti" ,"scrollbars =
yes");
</script>
As demais opções são: Barra de status: status=yes/no, Barra de
menu: menubar=yes/no , Barra de ferramentas: toolbar=yes/no ,
Barra de título: titlebar=yes/no, Barra de
endereços:location=yes/no , Tela cheia:fullscreen=yes/no ,
Barra de diretórios:directories=yes/no
Se executarmos a página Default.aspx e clicarmos no botão Busca
iremos obter:

Precisamos agora obter os dados da seleção do usuário na janela pop-


up (o código da categoria e o seu nome) e preencher as caixas de texto
no formulário principal.

Como fazer isso ?

Usando JavaScript , ora bolas...

Selecione a página Categorias.aspx e no
evento SelectedIndexChanged do controle GridView vamos incluir o
código abaixo:

Protected Sub gdvCategorias_SelectedIndexC
hanged(ByVal sender As Object, ByVal e As Sy
stem.EventArgs) Handles gdvCategorias.Select
edIndexChanged
 
Dim jscript As String = ""
Dim codigo As String =
gdvCategorias.SelectedRow.Cells(1).Text
Dim nome As String =
gdvCategorias.SelectedRow.Cells(2).Text

jscript += "<script language='JavaScript'>"


jscript
+= ";window.opener.document.forms[0].txtCo
digoCategoria.value= '"
jscript += codigo
jscript
+= "';window.opener.document.forms[0].txtN
omeCategoria.value= '"
jscript += nome
jscript += "';window.close();"
jscript += "</script>"

Page.ClientScript.RegisterClientScriptBlock(Me
.GetType(), "Categorias", jscript)
 
End Sub

Executando a página Default.aspx e clicando agora no botão Busca. A


página Categorias.aspx é aberta e quando selecionamos uma
categoria o valor do código da categoria e do nome da mesma são
retornados para os controles TextBox da janela que a chamou ,
a opener:

Nota:  Quando se trabalha com janelas popups às vezes


precisamos manipular a janela "pai", aquela janela gerou a janela
popup. Neste caso podemos usar a propriedade opener do objeto
window.  Quando uma janela é aberta a partir de outra janela , ela
mantêm uma referência para a primeira janela através de 
window.opener.
2- Efetuando a formatação do formulário com estilos

Vamos agora melhorar o visual do formulário efetuando a formatação


do mesmo usando um arquivo de estilo.

Clique com o botão direito do mouse sobre o nome do projeto e


selecione a opção Add ASP.NET Folder->Theme , e em seguida
informe o nome da sub-pasta como Tema.
A seguir
clique
com o
botão
direito
sobre a
pasta Tem
a e
selecione 
Add New
Item

Na janela
Templates
selecione
Style
Sheet e
aceite o
nome
padrão: St
yleSheet.
css

Agora vamos definir alguns estilos para o


arquivo StyleSheet.css usando o editor de estilos do VWD, conforme
figura abaixo:
Neste arquivo de estilos eu estou definindo 4 classes de formatação
que serão ativadas via JavaScript usando os seguintes eventos:

 onFocus - Quando a caixa de texto receber o foco iremos


atribuir a classe .CaixaTextoDestaque que irá alterar a cor de
fundo da caixa para azul claro e o tamanho da fonte para
medium;

 onBlur -  Quando a caixa de texto perder o foco iremos atribuir


a classe .CaixaTextoNormal que irá alterar a cor de fundo da
caixa para branco;

Para ativar o estilo vamos definir no arquivo web.config a


propriedade page Theme="Tema" conforme figura a seguir:
Finalmente vamos usar atribuir os estilos no evento Load da
página Default.aspx :

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.Ev
entArgs) Handles Me.Load

If Not Page.IsPostBack Then
   txtCodigoProduto.Focus()
  
txtCodigoProduto.Attributes.Add("onFocus", "this.className='CaixaTex
toDestaque';")
  
txtCodigoProduto.Attributes.Add("onBlur", "this.className='CaixaText
oNormal';")
  
txtCodigoCategoria.Attributes.Add("onFocus", "this.className='CaixaT
extoDestaque';")
  
txtCodigoCategoria.Attributes.Add("onBlur", "this.className='CaixaTex
toNormal';")
  
txtNomeCategoria.Attributes.Add("onFocus", "this.className='CaixaTe
xtoDestaque';")
  
txtNomeCategoria.Attributes.Add("onBlur", "this.className='CaixaText
oNormal';")
  
txtNomeProduto.Attributes.Add("onFocus", "this.className='CaixaText
oDestaque';")
  
txtNomeProduto.Attributes.Add("onBlur", "this.className='CaixaTexto
Normal';")
  
txtPrecoProduto.Attributes.Add("onFocus", "this.className='CaixaText
oDestaque';")
  
txtPrecoProduto.Attributes.Add("onBlur", "this.className='CaixaTexto
Normal';")
End If
End Sub

Executando a página Default.aspx ao navegar pelas caixas de texto


veremos a aplicação do estilo definido :
Eu poderia também definir mensagens ao usuário , texto de ajuda , etc.
usando a mesma técnica , mas vou deixar isso para um próximo artigo.

Pegue o projeto completo aqui:    janelasPopUpJs.zip (sem a base de


dados)

Visual Studio - Desenvolvendo para Node.js na plataforma


.NET

http://www.macoratti.net/16/03/vs_node1.html

 Neste artigo eu vou mostrar como configurar o


ambiente do Visual Studio para poder desenvolver
para Node.js.

Não, não houve nenhum erro no título do artigo. Vou mostrar


como podemos usar o ambiente da plataforma .NET para
desenvolver para Node.js

Isso mesmo Node.js.

Node.js é um interpretador de código JavaScript que


funciona  do lado do servidor . Seu objetivo é ajudar
programadores na criação de aplicações de alta
escalabilidade (como um servidor web),  com códigos capazes de
manipular dezenas de milhares de conexões simultâneas, numa
única máquina física.(Wkipédia ).

O Node.js utiliza um modelo de I/O direcionada a evento não


bloqueante que o torna leve e eficiente, ideal para aplicações em
tempo real com troca intensa de dados através de dispositivos
distribuídos.
Com Node.js você pode desenvolver para Windows, para Linux
para Mac OS. O site oficial pode ser visitado neste
link: https://nodejs.org/en/

Você pode então baixar o Node.js para o seu ambiente de forma


bem simples e rápida.

Nota: No Visual Studio 2015 (incluindo a versão Community)


o Node.js já vem instalado.

Após instalar, para verificar se o Node.js esta instalado na sua


máquina, basta abrir um prompt de comando e digitar :

node -v   ou   node --version


No prompt deverá aparecer a versão do Node. No meu caso é a
versão v.0.12.2.

O Node.js oferece o REPL que é uma janela interativa para que


você possa testar e experimentar JavaScript  e explorar soluções
para o problema que você está tentando resolver.

Apenas para testar e brincar um pouco, digitamos Node para


acessar o Node.js e criamos um array chamado carros com dois
carros: Golf e Corsa:
A seguir estamos executando um arquivo de script no Node.js:

O arquivo de script foi criado em um editor de texto com o


nome de AloMundo.js e que possui o seguinte
código:  console.log("Alo Mundo Node.js.");

Finalmente digite node para entrar no REPL e seguir


digite .help para ver opções de comandos disponíveis :
Para integrar o desenvolvimento do Node.js podemos qualquer
editor de texto ou IDE (WebStorm, Sublime, Visual Studio Code,
etc.).

Nota: Lembre-se que Node.js usa JavaScript do lado do servidor e


JavaScript é interpretado e não compilado.

Para preparar o ambiente no Visual Studio, basta baixar o Visual


Studio Tools for Node.js neste
link: https://www.visualstudio.com/pt-br/features/node-js-
vs.aspx
Clicando no link - Obtenha Ferramentas para Node.js para
VS você vai baixar um pacote  de 6.0 MB que deverá ser
instalado:

Após concluir a instalação abra o Visual Studio e verifique os


templates de projeto Node.js que foram incluídos :
Dessa forma, já temos tudo pronto para desenvolver para
Node.js no Visual Studio 2015 (no meu caso estou usando a
versão Community)

Além dos templates de projetos para Node.js, você tem


disponível os seguintes
recursos :  (fonte :  https://www.visualstudio.com/pt-
br/features/node-js-vs.aspx   )
 Intellisense - Experimente o preenchimento útil e
sintaticamente correto feito pelo potente
mecanismo IntelliSense, que analisa estaticamente o
código Node.js e os pacotes que você utiliza.
 
 Integração com npm - Você prefere interagir
com npm por uma avançada interface de usuário, por linha
de comando ou ambos? Você é quem escolhe.
 
 Janela Interativa - Digite código Node.js e visualize os
resultados imediatamente na Janela interativa de Node.js
(também conhecida como janela REPL)
 
 Depurador Avançado - Mova-se pelo seu código com
pontos de interrupção e notificações automáticas de
exceção com o depurador interativo do Visual Studio.
 
 Criação de Perfil - Os relatórios de criação de perfil
fornecem visualizações em diferentes níveis para a
estrutura do seu aplicativo, das linhas de código-fonte a
processos, e dados de execução de programas a partir da
chamada e funções chamadas de uma função específica até
a árvore de chamadas do aplicativo inteiro.
 
 Teste de Unidade - As Ferramentas Node.js para Visual
Studio possuem suporte para descoberta e execução de
testes de unidade.
 
 Integração com TypeScript - O TypeScript  é um
superconjunto de JavaScript que compila e limpa o
JavaScript gerado.
 
 Controle do código fonte - Gerencie seus
projetos Git/TFS, alterações pendentes e ramificações
facilmente utilizando o Team Explorer.
 
 Integração com a nuvem -  Crie, teste e implante sites da
Web escritos com Node.js e depure-os da sua área de
trabalho enquanto eles são executados no seu servidor
com base em Linux ou Windows.
 
 Personalize suas ferramentas - Complemente a sua
experiência com as muitas extensões para JavaScript e
Node.js disponíveis na Galeria do Visual Studio.
 
 Grátis com código fonte aberto - As Ferramentas Node.js
para Visual Studio são uma extensão gratuita e com
código-fonte aberto para o Visual Studio suportada pela
Microsoft e pela comunidade

Sua primeira aplicação Node.js no Visual Studio


E já que estamos embalados vamos criar uma pequena aplicação
Node.js usando o Visual Studio.

Abra o VS e clique em New Project;

Selecione o template JavaScript -> Node.js;

Clique em Blank Node.js Console Application e aceite o nome


padrão ou altere o nome a seu gosto:
Será criado um projeto com a estrutura mostrada na figura
abaixo.

Altere o código do arquivo app.js conforme mostrado a seguir:

Não se preocupe com o arquivo package.json nem com


o npm neste momento iremos abordá-los em outro artigo.
Vamos executar este aplicativo console no Visual Studio
colocando um breakpoint na linha - console.log('Macoratti
.net') e pressionando F5.

Veremos a janela de comando exibindo o resultado abaixo:

Todas as ferramentas de depuração do Visual Studio, como a


pilha de chamadas, variáveis locais e relógio, funcionam bem
com node. js.

Você pode até ver o código-fonte "dentro" do node.js. Por


exemplo, o module.js mostrado na pilha de chamadas da figura
abaixo é uma parte do node.js e não nossa aplicação.
Pressionando F5 novamente veremos o resultado final esperado:

Para concluir, podemos visualizar a janela de propriedades da


aplicação clicando com o botão direito sobre o nome da
aplicação e a seguir em Properties;

Abaixo vemos a janela de propriedades onde você pode


modificar a maneira como o Visual Studio interage com
o node.exe :
Aguarde em breve, artigos mostrando como desenvolver para
Node.js com exemplos práticos.
Node.js - Apresentando e usando o Sequelize (acesso ao
Mysql)
http://www.macoratti.net/17/01/node_sequelize1.html

 Neste artigo eu vou apresentar o Sequelize e mostrar


como usar esse ORM para acessar um banco de
dados MySql.

Se você esta chegando agora sugiro que leia os seguintes


artigos onde apresento os conceitos sobre o Node js:

 Visual Studio - Iniciando com Node.js - Macoratti


 Visual Studio - Bem-Vindo Node.js : desenvolvendo para Node.js
na plataforma .NET

Os pré-requisitos para acompanhar o artigo são:

 Possuir o Node.js instalado;


 Possuir o NPM(o gerenciador de pacotes do Node) instalado;
 Possuir o MySQL instalado;
 Possuir um editor como o VSCode , ou Atom, ou
Sublime; (Eu vou usar o VS Code)

Para saber mais sobre o editor VS Code leia os seguintes


artigos :

 Visual Studio Code - O Editor multiplataforma da Microsoft -


Macoratti

Apresentando o Sequelize

O Sequelize é um ORM(Object/Relational Mapper) baseado


em Promise  para Node.js e io.js, e suporta os
dialetos PostgreSQL, MySQL, MariaDB, SQLite e MSSQL e
recursos a transação, relacionamentos, replicação de leitura e
muito mais.

Ele possui um mecanismo de migração muito poderoso que


pode transformar um esquema existente de banco de dados em
uma nova versão e também fornece mecanismos de
sincronização de banco de dados que podem criar estrutura de
banco de dados especificando a estrutura do modelo.

O Sequelize esta disponível via NPM e sua instalação pode ser


feita executando o comando no Node.js:   npm install --save
sequelize

A seguir você deve instalar instalar o conector para o banco de


dados que você deseja acessar usando o Sequelize, e, isso pode
ser feito executando os comandos abaixo:

$ npm install --save pg pg-hstore


$ npm install --save mysql // para os dialetos mysql e
mariadb
$ npm install --save sqlite3
$ npm install --save tedious // para o SQL Server

Criando o schema MySql

Vamos agora mostrar na prática como usar o Sequelize para


acessar um banco de dados MySQL.

Para isso eu vou criar um novo schema no MySQL usando


o MySQL Workbench conforme os passos a seguir:

Passo 1

- Abra o MySQL WorkBench e clique no ícone   para criar um


novo schema: (ou clique com o botão direito do mouse sobre a
área  Schemas  e a seguir em  Create Schema)

Passo 2
-  A seguir informe o nome do schema, eu usei o
nome mac_demo, e clique no botão Apply;

Passo 3

-  Na próxima janela clique em Apply e a seguir em Finish;

Ao final você deverá ver na área SCHEMAS do MySql WorkBench


o schema mac_demo criado e pronto para ser usado:
Criando a aplicação Node e instalando o Sequelize

Neste momento você já deve ter o Node.js e o NPM instalados


para poder continuar.

Crie uma pasta na sua máquina local onde será criada a nossa
aplicação Node e onde vamos instalar o Sequelize e os pacotes
necessários.

Para isso abra uma janela de prompt de comando clicando no


ícone do Windows e a seguir em Prompt de
Comando digitando cmd ou command na barra de tarefas.  (Eu
estou usando o Windows 10)

Com a janela de comandos aberta digite os comandos:

 cd\                              - para posicionar-se  na pasta raiz


 md sequelize_demo     - para criar a pasta
sequelize_demo
 cd sequelize_demo      - para posicionar-se na pasta
sequelize-demo
Vamos iniciar nossa aplicação criando o
arquivo package.json que será usado para definir os pacotes
que iremos usar em nossa aplicação.

Digite no prompt e comando :  npm init -y   (se você não usar


o  -y  terá que responder algumas perguntas relacionadas ao
projeto)
Será criado o arquivo package.json e seu conteúdo será exibido
a seguir conforme mostra a figura.

Vamos agora instalar o Sequelize digitando o seguinte comando


: npm install --save sequelize   (o --save  salva no arquivo
package.json a dependência ao sequelize.)

Agora vamos instalar o Connector para o MySql digitando o


seguinte comando :  npm install --save mysql   (o --save  salva
no arquivo package.json a dependência ao conector MySql.)

Abrindo o arquivo package.json podemos ver as dependências


do mysql e do sequelize informadas. Isso é importante pois com
base apenas na informação deste arquivo podemos gerar todas
as dependências usando o NPM através do comando : npm
install

Pronto ! Já temos o Sequelize e o conector para o MySQL


instalados em nossa aplicação agora vamos primeiro estabelecer
uma conexão e testar se estamos conseguindo acessar o
schema mac_demo criado.

Usando o VS Code e criando a arquivo app.js da aplicação

Vamos agora usar o editor VS Code para poder criar o


arquivo app.js na pasta sequelize_demo da nossa aplicação.

Abra o VS Code e no menu File clique na opção Open Folder


Selecione a pasta sequelize_demo que criamos para o nosso
projeto.

Você deve visualizar apenas a pasta node_modules que foi criada


no projeto e que contém todos os arquivos de dependências
necessários para a execução da nossa aplicação.

Deverá ver também o arquivo package.json.

Clique no ícone New File para criar um novo arquivo no projeto


e informe o nome app.js:
A seguir digite o código abaixo no arquivo app.js :

Vamos entender o código :

Neste código a primeira coisa que eu fiz foi importar um


módulo sequelize usando require('sequelize').  Assim Sequelize
representa uma variável de referência ao Sequelize.

Não precisamos importar nada referente ao conector com o


banco de dados usado pois o Sequelize cuida disso.
A seguir criamos uma nova instância do Sequelize usando o seu
construtor que possui a seguinte sintaxe:

new Sequelize(database, [username=null], [password=null], [options={}])

onde :

1. database é o nome do schema do banco de dados que


vamos acessar. No nosso exemplo usamos o
schema mac_demo criado no MySQL;
2. username é o nome do usuário de acesso ao MySQL, no
exemplo estou usando o usuário root;
3. password é senha do usuário root. Para o exemplo estou
usando a senha do usuário root;

Para mais detalhes veja a documentação


em : http://sequelize.readthedocs.io/en/latest/api/sequelize/

A seguir estou usando o parâmetro authenticate que retorna


uma Promise para verificar a conexão com o banco de dados
mac_demo do MysQL:

Nota:  Promise é um objeto usado para processamento


assíncrono. Um Promise (de "promessa") representa
um  valor que pode estar disponível agora, no futuro ou
nunca.

    var conexao = connection.authenticate()


    .then(function(){
       console.log('Conexão com o MySQL foi estabelecida com sucesso');
    })
    .catch(function (err) {
      console.log('Não foi possível se conectar com o banco de dados MySql');
    })
    .done();

Agora  vamos rodar a nossa aplicação,  digitando ::  node


app.js 
Observe a mensagem indicando que a conexão foi estabelecida
com sucesso.

Muito bem...

Agora vamos criar uma tabela chamada Artigos neste schema e


definir dois campos : titulo e assunto

Depois vamos incluir um registro na tabela e para concluir


vamos exibir o registro incluido.

Para isso vamos alterar o código do arquivo app.js conforme


mostrado a seguir:

Entendendo o código:
Usamos o método define para definir mapeamentos entre um
modelo e uma tabela.

Com esse método o Sequelize irá automaticamente adicionar os


atributos createdAt e updatedAt e assim, você será capaz de
saber quando foi a entrada no banco de dados e quando ele foi
atualizado a última vez. (Em outro artigo vou mostrar como inibir
esse recurso)

var Artigos = connection.define('artigos', {


        titulo: Sequelize.STRING,
        assunto : Sequelize.TEXT
});

Assim o método define irá criar a tabela Artigos contendo os


campos :

 titulo - tipo de dados STRING


 assunto - tipo de dados TEXT
 createdAd
 updatedAt

Para saber mais detalhes sobre  os tipos de dados consulte


aqui http://docs.sequelizejs.com/en/latest/api/datatypes/

Depois disso estamos usando o método sync() para sincronizar


os modelos para o banco de dados com a tabela e usando o
método create() para incluir um registro nos campos titulo e
assunto.  (sync() retorna uma  Promise)

connection.sync().then(function () {
    Artigos.create({
       titulo: 'Usando Sequelize',
       assunto: 'Neste artigo vamos abordar como usar os recursos do Sequelize'
    })
});

Finalmente estamos usando o método findAll() para listar todos


os registros da tabela artigos.

connection.sync().then(function () {
       Artigos.findAll().then(function(artigos) {
         console.log(artigos.dataValues)
     });
});

Para testar basta digitar o comando : node app.js

Você também pode executar o comando no VS Code. Para isso


pressione  CTRL+SHIFT+'  para abrir a janela de comandos e
digite : node app
Como vemos temos o registro incluído e exibido no console.
Para constatar vamos abrir o MySQL WorkBench e verificar a
tabela e os seus dados:

Observe que por padrão os campos createdAt e


updateAt foram criados e atualizados.
O registro esta duplicado porque eu executei duas vezes o
comando :  node app.js

E assim, nesse primeiro contato com o Sequelize, já acessamos


um banco de dados MySQL , criamos uma tabela e inserimos um
registro.

Nada mal...

Aguarde mais novidades sobre o Sequelize.

Você também pode gostar