Quantcast
Channel: José Carlos Macoratti
Viewing all 293 articles
Browse latest View live

Xamarin.Forms – Criando uma aplicação com acesso a dados (SQLite) para Android usando o VS 2015 e C# – Parte 02

$
0
0

No artigo de hoje, vou mostrar como criar uma aplicação multiplataforma que pode ser usada no Windows Phone, Android e iOS, usando o Xamarin.Forms com acesso ao banco de dados SQLite usando o Visual Studio e a linguagem C#.

Vamos continuar a primeira parte deste artigo, definindo agora a nossa camada de acesso a dados que será responsável por acessar e gerenciar as informações do nosso banco de dados SQLite.

Estamos usando o Xamarin.Forms, no qual podemos compartilhar o código da UI com as plataformas iOS, Android e Windows Phone:

xam_1

Definindo a camada de acesso a dados no projeto Portable

A camada de acesso de dados de aplicativos móveis é um pouco diferente das dos projetos web e assemelha-se mais à dos aplicativos para desktop. Geralmente usamos uma abordagem adotando os padrões MVVM, MVC para realizar operações CRUD básicas.

Lembre-se de que, em um dispositivo móvel, as páginas com dados vinculados tipicamente alimentam um banco de dados local no dispositivo, que sincroniza com um servidor de dados remoto usando serviços da web.

Dessa forma, vamos criar uma classe bem simples para realizar as operações CRUD em nossa aplicação. Na verdade, nesse exemplo iremos ver apenas a inclusão de dados.

Selecione o projeto compartilhado – Cadastro – e no menu Tools clique em Add Class.

Informe o nome AcessoBD.cs e inclua o código abaixo nesse arquivo:

using System;
using SQLite.Net;
using System.IO;
using Xamarin.Forms;
using System.Linq;
using System.Collections.Generic;

namespace Cadastro
{
    public class AcessoDB : IDisposable
    {
        private SQLiteConnection conexaoSQLite;

        public AcessoDB()
        {
            var config = DependencyService.Get<IConfig>();
            conexaoSQLite = new SQLiteConnection(config.Plataforma, Path.Combine(config.DiretorioSQLite, "Cadastro.db3"));
            conexaoSQLite.CreateTable<Cliente>();
        }

        public void InserirCliente(Cliente cliente)
        {
            conexaoSQLite.Insert(cliente);
        }

        public void AtualizarCliente(Cliente cliente)
        {
            conexaoSQLite.Update(cliente);
        }

        public void DeletarCliente(Cliente cliente)
        {
            conexaoSQLite.Delete(cliente);
        }

        public Cliente GetCliente(int codigo)
        {
            return conexaoSQLite.Table<Cliente>().FirstOrDefault(c => c.Id == codigo);
        }

        public List<Cliente> GetClientes()
        {
            return conexaoSQLite.Table<Cliente>().OrderBy(c => c.Nome).ToList();
        }

        public void Dispose()
        {
            conexaoSQLite.Dispose();
        }
    }
}

Nesse código, definimos os seguintes métodos:

  • InserirCliente – Inclui um objeto Cliente no banco de dados;
  • AtualizarCliente – Atualiza um objeto Cliente;
  • DeletarCliente – Exclui um objeto Cliente do banco de dados;
  • GetCliente – Obtém um cliente pelo seu código;
  • GetClientes -Retorna todos os clientes ordenados pelo nome;
  • Dispose – Libera os recursos usados.

No construtor da classe, usamos o DependencyService para encontrar a implementação da plataforma correta, permitindo que o código compartilhado acesse a funcionalidade nativa que nosso exemplo é o caminho do banco de dados na plataforma Android.

xam_2

A seguir, criamos o banco de dados Cadastro.db3 e depois criamos a tabela Clientes.

Nos métodos implementados na classe AcessoDB(), usamos os métodos Insert, Update, Delete e table<Cliente> para realizar as operações CRUD.

Na próxima parte do artigo, vamos criar a nossa interface com o usuário usando código XAML e C#.


O padrão repositório revisitado – Parte 03

$
0
0

Neste artigo, vamos rever os conceitos relacionados ao padrão repositório com um exemplo prático em uma aplicação ASP .NET MVC 5 usando a linguagem C#.

Na segunda parte do artigo, implementamos a camada de negócios (BLL), definimos a string de conexão no arquivo web.Config e criamos o controlador UsuarioController usando o Scaffold, de forma a ter os métodos Actions e as views criadas automaticamente.

Vamos concluir o nosso projeto fazendo os ajustes no controlador UsuarioController, utilizando a nossa camada de negócios e o nosso repositório.

Recursos usados:

Ajustando o controlador para usar a camada de negócios e o repositório

Abra o projeto Mvc_Repositorio criado na versão do VS 2013 Express for web do artigo anterior.

Em seguida, abra o arquivo UsuarioController.cs da pasta Controllers.

Altere o código desse controlador conforme mostrado a seguir:

using System.Net;
using System.Web.Mvc;
using Mvc_Repositorio.Dominio.Entidades;
using Mvc_Repositorio.Negocio;

namespace Mvc_Repositorio.Controllers
{
    public class UsuarioController : Controller
    {
        private UsuarioBLL _usuarioBll;

        public UsuarioController()
        {
            _usuarioBll = new UsuarioBLL();
        }

        public ActionResult Index()
        {
            return View(_usuarioBll.Get_UsuarioInfo());
        }

        // GET: Usuario/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Usuario usuario = _usuarioBll.Localizar(id);//db.Usuarios.Find(id);
            if (usuario == null)
            {
                return HttpNotFound();
            }
            return View(usuario);
        }

        // GET: Usuario/Create
        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "UsuarioId,Nome,Senha,Email")] Usuario usuario)
        {
            if (ModelState.IsValid)
            {
                _usuarioBll.AdicionarUsuario(usuario);//db.Usuarios.Add(usuario);
                //_usuarioBll.db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(usuario);
        }

        // GET: Usuario/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Usuario usuario = _usuarioBll.Localizar(id);//db.Usuarios.Find(id);
            if (usuario == null)
            {
                return HttpNotFound();
            }
            return View(usuario);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "UsuarioId,Nome,Senha,Email")] Usuario usuario)
        {
            if (ModelState.IsValid)
            {
                _usuarioBll.AlterarUsuario(usuario);
                //db.Entry(usuario).State = EntityState.Modified;
                //db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(usuario);
        }

        // GET: Usuario/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Usuario usuario = _usuarioBll.Localizar(id);//db.Usuarios.Find(id);
            if (usuario == null)
            {
                return HttpNotFound();
            }
            return View(usuario);
        }

        // POST: Usuario/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Usuario usuario = _usuarioBll.Localizar(id);//db.Usuarios.Find(id);
            _usuarioBll.ExcluirUsuario(usuario);//db.Usuarios.Remove(usuario);
            //db.SaveChanges();
            return RedirectToAction("Index");
        }
    }
 }
}

No código acima, eu criei uma instância da nossa camada de negócio no construtor do controlador UsuarioController:

        private UsuarioBLL _usuarioBll;

        public UsuarioController()
        {
            _usuarioBll = new UsuarioBLL();
        }

Dessa forma, agora basta substituir o código que usava a instância do contexto pela instância da nossa camada de negócio.

O código em azul foi incluído e o código anterior foi comentado e colorido na cor verde.

Note que estamos usando a instância _usuarioBll para acessar os métodos da camada de negócio e que agora a implementação da camada de acesso a dados é transparente para nossa interface.

Feito isso, não precisamos alterar nenhuma view gerada pelo Scaffold (apenas fazer as traduções para o português, se você desejar).

Vou alterar o arquivo _Layout.cshtml da pasta \Views\Shared incluindo uma imagem em todas as views:

net_1

Note que a imagem Cadastro.png que eu usei está na pasta Imagens criada no projeto.

Executando o projeto, iremos obter o seguinte resultado:

net_2

Com isso, fizemos uma revisão de conceitos sobre o padrão repositório usando uma abordagem bem simples para mostrar a sua importância.

Em outro artigo, vou abordar a injeção de dependência que pode ser usada para desacoplar ainda mais os nossos projetos e que poderia ser aplicada a esse exemplo.

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

Xamarin.Forms – Criando uma aplicação com acesso a dados (SQLite) para Android usando o VS 2015 e C# – Parte 03

$
0
0

No artigo de hoje, vou mostrar como criar uma aplicação multiplataforma que pode ser usada no Windows Phone, Android e iOS, usando o Xamarin.Forms com acesso ao banco de dados SQLite utilizando o Visual Studio e a linguagem C#.

Vamos continuar a segunda parte deste artigo, definindo agora a nossa camada de Interface (UI) e, para isso vamos criar uma página XAML no projeto compartilhado Cadastro.Droid.

A linguagem de marcação XAML – eXtensible Markup Language –  faz parte do Xamarin.Forms, e permite aos desenvolvedores definir interfaces de usuário em aplicações mobile usando marcações em vez de código.

Você não é obrigado a usar XAML em um programa Xamarin.Forms, pode usar o código C# no arquivo code-behind, mas muitas vezes o código XAML é mais sucinto e visualmente mais coerente.

Usando XAML, o desenvolvedor Xamarin.Forms pode definir interfaces de usuário utilizando todas as views, layouts e páginas Xamarin.Forms, bem como classes personalizadas. O arquivo XAML é analisado em tempo de compilação para localizar objetos nomeados, e novamente em tempo de execução para criar uma instância e inicializar objetos, e estabelecer ligações entre esses objetos e código de programação.

A XAML é particularmente adequada para uso com a arquitetura MVVM (Model-View-ViewModel): o XAML define a View que está ligada ao código ViewModel por meio de ligações de dados baseados em XAML.

Definindo a Interface de Usuário compartilhada (UI) no projeto Portable

Selecione o projeto compartilhado – Cadastro – e, no menu Tools, clique em Add New Item.

A seguir, selecione Visual C# -> Cross Plataform -> Forms Xaml Page.

Informe o nome ClientesPage e clique no botão Add.

xam_1

Vamos definir uma interface com usuário usando uma ContentPage que representa uma única view, e um StackLayout para empilhar os controles verticalmente em um leiaute bem simples:

xam_2

No arquivo ClientesPage.xaml, inclua o código XAML abaixo:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Cadastro.ClientesPage">

       <ContentPage.Content>

        <StackLayout Padding="20" Spacing="20">

             <Entry x:Name="NomeCliente" Placeholder="Nome" TextColor="White"/>

             <Entry x:Name="EmailCliente" Placeholder="Email" Keyboard="Email" TextColor="White"/>

             <Button x:Name="Salvar" Text="Salvar Dados" Clicked="SalvarClicked"/>

             <ListView x:Name="ListaCliente" BackgroundColor="White" />

        </StackLayout>

    </ContentPage.Content>  

</ContentPage>

Iniciamos com a definição do layout ContentPage que exibe uma única View.

A seguir, definimos um StackLayout que posiciona elementos filhos em uma única linha e que podem ser orientados horizontal e verticalmente.

Na sequência, definimos 2 entradas para Nome, Email usando o controle Entry e definindo as propriedades PlaceHolder, que exibe o texto definido no controle, e Keyboard, que define o tipo de teclado usado.

Concluímos definindo um controle Button com o texto – Salvar Dados com o evento SalvarClicked associado ao evento Click do botão, e a seguir definimos o controle ListView – ListaCliente com uma cor de fundo para destacá-lo.

Abaixo, temos a UI apresentando em um emulador Android:

xam_3

Para poder exibir os itens no controle ListView, que serão os clientes cadastrados, temos que obter os clientes e atribuir os valores à propriedade ItemsSource do controle ListView.

Fazemos isso no arquivo code-behind ClientesPage.xaml.cs, definindo o código a seguir:

using System;
using Xamarin.Forms;

namespace Cadastro
{
    public partial class ClientesPage : ContentPage
    {
        public ClientesPage()
        {
            InitializeComponent();

            using (var dados = new AcessoDB())
            {
                this.ListaCliente.ItemsSource = dados.GetClientes();
            }
        }
    }
}

E, para concluir, precisamos implementar no arquivo code-behind  ClientesPage.xaml.cs o código relacionado com o evento click do botão que definimos como SalvarClicked:

using System;
using Xamarin.Forms;

namespace Cadastro
{
    public partial class ClientesPage : ContentPage
    {
        public ClientesPage()
        {
            InitializeComponent();

            using (var dados = new AcessoDB())
            {
                this.ListaCliente.ItemsSource = dados.GetClientes();
            }
        }

        protected void SalvarClicked(object sender, EventArgs e)
        {
            var cliente = new Cliente
            {
                Nome = this.NomeCliente.Text,
                Email = this.EmailCliente.Text,
            };

            using (var dados = new AcessoDB())
            {
                dados.InserirCliente(cliente);
                this.ListaCliente.ItemsSource = dados.GetClientes();
            }
        }
    }
}

O código associado ao tratamento do evento Click – SalvarClicked – cria uma instância do objeto Cliente e atribui às propriedades Nome e Email os valores que estão definidos na interface do usuário, ou seja, nos controles Entry : NomeCliente e EmailCliente.

Depois criamos uma instância da classe AcessoBD e usamos o método inserirCliente(), passando os dados do cliente atual, e exibimos os dados no ListView usando o método GetClientes().

Na próxima parte do artigo, vamos concluir a nossa aplicação fazendo o deploy e testando em  um emulador Android.

ASP .NET MVC 5 – a misteriosa classe ModelState

$
0
0

Neste artigo vou desmistificar a misteriosa classe ModelState, mostrando o seu significado, recursos e como devemos tratá-la em aplicações ASP .NET MVC.

O que é o ModelState?

O ModelSate é uma propriedade do Controller e pode ser acessado a partir das classes que herdam de System.Web.Mvc.Controller. Ele é um dicionário disponível na classe base do controlador que armazena as informações adicionais e de estado sobre o modelo.

O ModeState representa uma coleção de pares de nome e valor que são submetidos ao servidor durante o POST. Ele também contém uma coleção de mensagens de erros para cada valor submetido.

Apesar de usar o nome ModelState, ele não conhece nada sobre qualquer classe de modelo. Ele apenas contém nomes, valores e erros.

Então, para que serve o ModelState? Ele tem dois propósitos:

  1. Armazenar o valor submetido ao servidor;
  2. Armazenar os erros de validação associados com esses valores.

Assim, quando um post acontece, você pode realizar suas verificações; e se algo der errado, você pode adicionar um item ao dicionário ModelState e esta informação estará disponível para ser utilizada pela View para exibir um resumo das incoerências.

O ModelStateDictionary tem vários métodos para adicionar entradas:

void Add (KeyValuePair <string, ModelState> item);
void Add (string chave, valor ModelState);
AddModelError void (string chave, exceção Exception);
AddModelError void (chave string, string errorMessage);

Simples assim.

Vamos, então, mostrar isso na prática.

Recursos usados: Visual Studio 2013 Express for Web

Desmistificando o ModelState

Abra o VS 2013 Express for web e clique em New Project. A seguir, selecione Visual C# -> ASP .NET Web Application e informe o nome Mvc_ModelState. Clique no botão OK.

mvc_mdlst11

A seguir, selecione o template Empty, marque MVC  e clique no botão OK.

mvc_mdlst12

Será criado um projeto contendo toda a estrutura de pastas criadas pelo framework ASP .NET MVC.

Definindo o Model

Vamos definir um view model na pasta Models para representar um usuário. Não sabe que é um View Model? Então, dê uma olhada nos modelos de domínio do seu projeto, e veja se há códigos que são utilizados exclusivamente pelas Views, não tendo nenhuma relação com o domínio do negócio em questão.

Se isto estiver ocorrendo, então, seu modelo de domínio está assumindo muitas responsabilidades. O padrão View Model veio justamente para resolver isso.

O ViewModel deve conter a lógica da interface do usuário e permitir modelar entidades a partir de um ou mais modelos em um único objeto, representando um conjunto de um ou mais Models e outros dados que serão representados em uma View.

Assim, um View Model tem as seguintes características:

  • Contém toda lógica de interface e a referência ao modelo e assim atua como modelo para a View;
  • Separar as responsabilidades do Model usando Informações que somente serão exibidas nas Views;
  • A View direciona a construção da ViewModel;
  • O ViewModel contém somente dados e comportamento relacionados com a view;
  • Cada ViewModel possui uma View Tipada.

Clique com o botão direito do mouse na pasta Models e a seguir Add Class. Depois informe o nome UsuarioViewModel e defina o código abaixo para esta classe:

public class UsuarioViewModel
{
        public string Nome { get; set; }
        public string Sobrenome { get; set; }
        public string Email { get; set; }
}

Definindo o Controller

Vamos agora definir o controlador do nosso projeto: clique com o botão do mouse sobre a pasta Controllers e, a seguir, clique em Add -> Controller. Selecione o Scaffold – MVC 5 Controller Empty – e clique em Add. Depois informe o nome HomeController e, a seguir, defina dois métodos Actions (o get e o post) neste controlador para incluir um usuário usando o nomeIncluirUsuario():

using System.Web.Mvc;
using Mvc_ModelState.Models;
namespace Mvc_ModelState.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult IncluirUsuario()
        {
            UsuarioViewModel model = new UsuarioViewModel();
            return View(model);
        }
        [HttpPost]
        public ActionResult IncluirUsuario(UsuarioViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }
            return RedirectToAction("Index");
        }
        public ActionResult Index()
        {
            return View();
        }     
    }
}

O código referencia o namespace  Mvc_ModelState.Models para ter acesso ao modelo definido na pasta Models.

Temos o método IncluirUsuario(), que apresenta o formulário ao usuário com base no modelo UsuarioViewModel e, a seguir, trata o POST deste formulário no mesmo método onde recebe os dados enviados da view para o controlador via ModelBinding.

O método Action Index() irá definir uma view Index bem simples.

Criando as Views

Vamos criar a view Index(). Para isso, clique com o botão direito do mouse sobre o método Index() e a seguir em Add View. Depois, defina o template como Empty(without model) e clique no botão Add.

Informe apenas um texto para identificar a view, pois talvez ela nem será usada.

Vamos agora criar a view IncluirUsuario: clique com o botão direito do mouse sobre o método IncluirUsuario() e, a seguir, em Add View. Defina o template como Empty e o Model Class igual a UsuarioViewModel e clique no botão Add.

mvc_mdlst13

A seguir, vamos definir código da view onde temos um formulário para o usuário informar o nome, o sobrenome e o e-mail:

@model Mvc_ModelState.Models.UsuarioViewModel
<h2>Incluir Usuário</h2>
@using (Html.BeginForm())
{
    <div>
        <div>
           Nome : @Html.TextBoxFor(x => x.Nome)
        </div>
        <div>
           Sobrenome: @Html.TextBoxFor(x => x.Sobrenome)
        </div>
        <div>
          Email:  @Html.TextBoxFor(x => x.Email)
        </div>
        <div>
            <input type="submit" value="Salvar Usuário" />
        </div>
    </div>
}

Executando o projeto e preenchendo o formulário, ao clicar no botão – Salvar Usuário – veremos que todos os valores entrados serão exibidos na instância de UsuarioViewModel (model) no controlador.

Nota: Marque um breakpoint no método Action IncluirUsuario(Post) e verifique os valores de model.

Como esses valores foram parar aí?

mvc_mdlst14

Vamos dar uma espiada no código HTML da view IncluirUsuario.cshtml que foi renderizada:

mvc_mdlst15

No momento do POST, todos os valores nas tags <input> são submetidos para o servidor como pares chave-valor.

Quando o MVC recebe o POST, ele recebe todos os parâmetros do POST e os inclui em uma instância ModelStateDictionary.

Quando debugamos o método Action POST do Controlador, podemos usar a janela Local para investigar os valores neste dicionário:

mvc_mdlst16

Espiando o ModelState no Debug, vemos o seguinte:

mvc_mdlst17

Cada uma das propriedade tem uma instância de ValueProviderResult que contém os valores atuais submetidos ao servidor.

O MVC cria todas essas instâncias automaticamente quando submetemos os dados, e o método Action POST tem os inputs que mapeia os valores submetidos.

Essencialmente, o MVC está encapsulando os inputs do usuário em classes no servidor (ModelState).

E os erros, onde estão?

Vamos aplicar atributos Data Annotations em nosso UsuarioViewModel para realizar a validação e espiar os erros. Altere a classe UsuarioViewModel incluindo os atributos abaixo no código da classe:

using System.ComponentModel.DataAnnotations;
namespace Mvc_ModelState.Models
{
    public class UsuarioViewModel
    {
        [Required(ErrorMessage = "Informe o nome do usuário.")]
        [StringLength(20, ErrorMessage = "O nome deve ser menor que {1} caracteres.")]
        [Display(Name = "Nome do Usuário:")]
        public string Nome { get; set; }
        [Required(ErrorMessage = "Informe o sobrenome do usuário.")]
        [StringLength(20, ErrorMessage = "O sobrenome não pode ter mais que {1} caracteres.")]
        [Display(Name = "Sobrenome do Usuário:")]
        public string Sobrenome { get; set; }
        [EmailAddress(ErrorMessage = "Email inválido")]
        [Required(ErrorMessage = "Informe o endereço de Email.")]
        [Display(Name = "Endereço de Email:")]
        public string Email { get; set; }
    }
}

Feito isso, vamos alterar a nossa view IncluirUsuario.cshtml incluindo o ValidationSummary() e o ValidationMessageFor() para exibir mensagens de erros se eles ocorrerem.

  • ValidationSummary() – realiza a validação do modelo e lê os erros do estado do modelo e exibe em uma lista;
  • ValidationMessageFor() – Exibe os erros para a propriedade específica.

Veja como deve ficar o código da view:

@model Mvc_ModelState.Models.UsuarioViewModel
<h2>Incluir Usuário</h2>
@using (Html.BeginForm())
{
    <div>
        @Html.ValidationSummary()
        <div>
            Nome : @Html.TextBoxFor(x => x.Nome)
            @Html.ValidationMessageFor(x => x.Nome)
        </div>
        <div>
            Sobrenome: @Html.TextBoxFor(x => x.Sobrenome)
            @Html.ValidationMessageFor(x => x.Sobrenome)
        </div>
        <div>
            Email:  @Html.TextBoxFor(x => x.Email)
            @Html.ValidationMessageFor(x => x.Email)
        </div>
        <div>
            <input type="submit" value="Salvar Usuário" />
        </div>
    </div>
}

Agora, vamos executar novamente e simular um erro (não informar o nome do usuário) e fazer o Debug espiando o ModelState:

mvc_mdlst18

Conforme era esperado, a instância de ModelState para o nome agora possui um erro na coleção Errors.

Quando o MVC cria o model state para as propriedade submetidas, ele vai até cada propriedade no ViewModel e valida a propriedade usando os atributos associados a ela.

Se houver algum erro, ele é adicionado na coleção Errors na propriedade do ModelState. Note também que IsValid agora é false, indicando que existe um erro.

Dessa forma, definindo a validação como fizemos, permitimos ao MVC trabalhar da forma esperada: o ModelState armazena os valores submetidos e permite que eles sejam mapeados para propriedades de classe, mantendo uma coleção de erros para cada propriedade.

É tudo que precisamos e tudo isso ocorre de forma transparente e não precisa de nenhuma configuração extra.

Pegue o projeto completo aqui: Mvc_ModelState.zip

Xamarin.Forms – Criando uma aplicação com acesso a dados (SQLite) para Android usando o VS 2015 e C# – Parte 04

$
0
0

No artigo de hoje vou mostrar como criar uma aplicação multiplataforma que pode ser usada no Windows Phone, Android e iOS, usando o Xamarin.Forms com acesso ao banco de dados SQLite usando o Visual Studio e a linguagem C#.

Vamos continuar a terceira parte deste artigo, fazendo os ajustes finais em nossa aplicação e realizando o deploy para um emulador Android.

Neste momento, já temos o projeto Android e o projeto compartilhado definidos e prontos para serem utilizados. Falta o último detalhe que é definir no projeto compartilhado, no arquivo App.cs a criação da instância da nossa interface de usuário.

Selecione o projeto compartilhado – Cadastro – e selecione o arquivo App.cs. A seguir, inclua o código abaixo neste arquivo:

xam_forms100

O código é muito simples e basta criar uma instância da classe ClientesPage() que representa a nossa interface com o usuário.

Para fazer o deploy, selecione o projeto Android e um emulador adequado e clique para iniciar o Deploy, que terá início com a inicialização do emulador (isso pode demorar um pouco) e, após alguns minutos, você deverá ver a aplicação disponível no dispositivo:

xam_forms101

Executando a aplicação, teremos a nossa  interface apresentando o Nome e E-mail , o botão Salvar Dados e o controle ListView:

xam_forms10a

Acionando a entrada de dados para Nome ,teremos o teclado exibido conforme abaixo:

xam_forms102

Acionando a entrada para o E-mail, vemos que o teclado apresentado mostra o símbolo @ e o ponto (definimos isso na propriedade Keyboard):

xam_forms103

Clicando no botão Salvar Dados, vemos o nome e e-mail exibidos no controle ListView:

xam_forms104

Você pode parar e abrir novamente a aplicação e vai verificar que os dados realmente forma persistidos.

Dessa forma, criamos uma aplicação com acesso a dados multiplataforma (no meu caso, para Android apenas) usando os recursos do Visual Studio, da linguagem C# e da plataforma Xamarin, especificamente o Xamarin.Forms.

Aguarde em breve mais artigos sobre esse importante assunto.

ASP .NET MVC 5 – DropdownList com seleção múltipla

$
0
0

Neste artigo vou mostrar como usar o controle dropdownlist em aplicações ASP .NET MVC 5.

O Helper Html.DropDownList é renderizado no navegador como um elemento HTML <select>. Ele é geralmente usado para fornecer ao usuário um meio de selecionar uma de um número de opções. Você também pode permitir que o usuário selecione mais de uma opção quando não deseja usar checkboxes.

Existem duas formas de habilitar a seleção múltipla:

  1. Adicionar o atributo multiple ao Helper Html.DropDownList usando os parâmetros htmlAttributes
  2. Usar o Helper Html.ListBox

As opções podem ser passadas para o helper de diversas formas:

  • Como um Enumerable<SelectListItem>
  • Como um objeto SelectList
  • Como um objeto MultiSelectList

Vamos ver como implementar isso usando o ASP .NET MVC 5.

Recursos Usados: Visual Studio 2013 Express for web.

Criando o projeto no VS 2013

Abra o Visual Studio 2013 Express for web e crie um novo projeto ASP .NET MVC usando a linguagem C#. Informe o nome Mvc_DropDownList_Multiplo e use o template Empty; não utilize autenticação, marque a opção MVC e clique em OK.

mvc_ddl11

mvc_chlp12 (2)

Vamos incluir um Entity Data Model (EDM) definindo o nosso modelo de domínio  na pasta Models. Clique com o botão direito do mouse sobre a pasta Models e, a seguir, em Add New Item. Depois selecione a guia Data e a seguir ADO .NET Entity Data Model e informe o nome NorthwindModel e clique em Add.

Selecione a opção EF Designer from database e clique em Next>. Selecione a conexão com o banco de dados Northwind.mdf e clique em Next>.

mvc_ddl12

Selecione a tabela Categories e marque as opções conforme mostra a figura abaixo:

mvc_ddl13

Ao final, teremos a nossa entidade Category mapeada para a tabela Categories do banco de dados Northwin.mdf e o contexto com nosso modelo de domínio gerado na pasta Models:

mvc_ddl14

Agora clique com o botão direito sobre a pasta Controllers e, a seguir, em Add Controller. Depois selecione o Scaffold – MVC5 Controller Empty – e informe o nome HomeController.

A seguir, defina o código abaixo sobrescrevendo o método Action Index:

using System.Linq;
using System.Web.Mvc;
using Mvc_DropDownList_Multiplo.Models;
namespace Mvc_DropDownList_Multiplo.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            using (var db = new NorthwindEntities())
            {
                var categorias = db.Categories.Select(c => new
                {
                    CategoryID = c.CategoryID,
                    CategoryName = c.CategoryName
                }).ToList();

                ViewBag.Categorias = new MultiSelectList(categorias, "CategoryID", "CategoryName");
                return View();
            }
        }
    }
}

O código retorna uma lista de categorias armazenando o resultado no ViewBag.Categorias.

Clique com o botão direito do mouse no interior do método Action Index e, a seguir, em Add View. Depois informe o template Empty e selecione o Model Category e o Data Context conforme abaixo:

mvc_ddl15

A seguir, inclua o código abaixo na view Tipada:

@model Mvc_DropDownList_Multiplo.Models.Category
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <h2>Macoratti .net  - DropDownList com seleção múltipla </h2>
    <hr />
    <div> 
        DropDownList - multiple
        <br />
        @Html.DropDownList("CategoryId", (MultiSelectList)ViewBag.Categorias, new { multiple = "multiple" })
        <br />
        ListBox
        <br />
        @Html.ListBox("CategoryId", (MultiSelectList)ViewBag.Categorias)
    </div>
</body>
</html>

Executando o projeto teremos o resultado abaixo:

mvc_ddl16

Se você espiar o código fonte da página, irá notar que a renderização é a mesma para os dois componentes:

mvc_ddl18

Podemos alterar a quantidade de itens exibidos (o padrão é 4) usando definindo um valor para o atributo size no helper da view Index:

@Html.ListBox("CategoryId", (MultiSelectList)ViewBag.Categorias, new { size = 8 } )

Agora obtemos:

mvc_ddl17

Tudo bem. Mas como a seleção múltipla do usuário é processada em um post? Quando um controle com seleção múltipla é postado para o servidor, a coleção dos valores selecionados são processados por uma lista separada por vírgulas; O Model Binding entra em ação e vê essa coleção como um array.

Se os valores selecionados podem ser representados por inteiros, você pode usar um array de inteiros para representar os valores postados.

Como exemplo, vamos alterar o código da view Index incluindo um formulário através do helper Html.BeginForm para postar a seleção para a Action Selecao:

@model Mvc_DropDownList_Multiplo.Models.Category
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <h2>Macoratti .net  - DropDownList com seleção múltipla </h2>
    <hr />
    <div> 
        @using (Html.BeginForm("Selecao", "Home", FormMethod.Post, new { id = "TheForm" }))
        {
            <text>DropDownList - multiple</text>
            <br />
            @Html.DropDownList("CategoryId", (MultiSelectList)ViewBag.Categorias, new { multiple = "multiple" })
            <br />
            <text>ListBox</text>
            <br />
            @Html.ListBox("CategoryId", (MultiSelectList)ViewBag.Categorias, new { size = 8 })
            <input type="submit" value="Enviar" />
        }
    </div>
</body>
</html>

E vamos criar a Action Selecao no controlador HomeController:

[HttpPost]
 public ActionResult Selecao(int[] categoryId)
 {
        return View();
 }

Executando o projeto e fazendo mais de uma seleção ao postar, teremos o seguinte resultado:

mvc_ddl19
Para concluir, se você desejar exibir a lista com alguns itens pré-selecionados, basta alterar o código da Action Index conforme mostra a linha azul em destaque no código abaixo:

 public ActionResult Index()
        {
            using (var db = new NorthwindEntities())
            {
                var categorias = db.Categories.Select(c => new
                {
                    CategoryID = c.CategoryID,
                    CategoryName = c.CategoryName
                }).ToList();
                //ViewBag.Categorias = new MultiSelectList(categorias, "CategoryID", "CategoryName");
                ViewBag.Categorias = new MultiSelectList(categorias, "CategoryID", "CategoryName", new[] { 1, 3, 7 });
                return View();
            }
        }

Agora, ao executar, teremos os itens 1, 3 e 7 pré selecionados na caixa de listagem:

mvc_ddl1a

Pegue o projeto completo aqui: Mvc_DropDownList_Multiplo.zip

ASP .NET – Enviando e-mails via SMTP a partir de um banco de dados

$
0
0

Neste artigo vou mostrar como criar uma pequena aplicação ASP .NET Web Forms que permite enviar e-mails coletados a partir de um banco de dados e via SMTP.

Vamos supor que você tenha uma relação de e-mails armazenado em um banco de dados e que precisa criar uma aplicação web para enviar esses e-mails.

O banco de dados pode ser qualquer um, mas vamos usar um banco de dados Microsoft Access chamado Clientes.accdb contendo a tabela e-mails com a seguinte estrutura:

webf_email16

A tabela possui somente um campo Código e um campo E-mail onde temos os e-mails que vamos usar.

Você deseja também poder selecionar os e-mails que deseja enviar.

Muito bem vamos partir desse cenário e criar uma aplicação ASP .NET Web Forms que faça exatamente isso que você deseja.

Recursos usados: Visual Studio 2013 Express for Web.

Criando o projeto no Visual Studio

Abra o Visual Studio 2013 Express for web e crie um novo projeto ASP .NET Web Forms usando o template Empty com o nome Envia_EmailVBNET.

webf_email11

webf_email12

A seguir, no menu PROJECT clique em Add New Item.

Selecione o template Web Form e informe o nome Default.aspx e clique em OK.

webf_email13

Agora vamos incluir no projeto uma referência ao BootStrap.

No menu TOOLS clique em Nuget Package Manager -> Manage Nuget Packages for Solution. Depois digite bootstrap e localize o pacote.

A seguir, clique no botão Install para instalar o pacote no projeto:

webf_email14

Vamos incluir um novo WebForm em nosso projeto que será usado como página de erros.

No menu PROJECT, clique em Add New Item. Selecione o template Web Form e informe o nome PaginaErro.aspx e clique em OK.

A seguir, defina o seguinte código nesta página Web form:

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="PaginaErro.aspx.vb" 
Inherits="Envia_Email_VBNET.PaginaErro" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="Content/bootstrap.css" rel="stylesheet" />
    <style type="text/css">
        .auto-style1 {
            font-family: "Arial Rounded MT";
        }
        .auto-style2 {
            color: #CC0000;
        }
        .auto-style3 {
            font-family: "Arial Rounded MT";
            color: #CC0000;
        }
    </style>
</head>
<body>
    <h3> Macoratti .net</h3>
    <hr />
    <div class="well">
    <form id="form1" runat="server">
       <h3 class="auto-style3">Ocorreu um erro durante o processamento.</h3>
       <h3 class="auto-style1"><span class="auto-style2">Contate o Suporte</span>.</h3>
        <br />
       <hr />
       <strong><a href="Default.aspx">Retornar</a></strong>
    </form>
   </div>
</body>
</html>

webf_email17

Na figura acima vemos o leiaute da nossa página de erro que será exibida quando algum erro ocorrer.

Agora vamos criar uma interface na página Default.aspx para apresentar um formulário onde iremos realizar as operações para enviar os e-mails.

Vamos usar os controles TextBox, Button, CheckBoxList para criar a interface, conforme mostra o leiaute abaixo:

webf_email15

O código referente a este leiaute visualizado na guia Source é o seguinte:

%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="Envia_Email_VBNET._Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Enviar Email</title>
    <link href="Content/bootstrap.min.css" rel="stylesheet" />
    <style type="text/css">
        #form1 {
            width: 652px;
            background-color: #97EAFF;
        }
        .auto-style1 {
            color: #0033CC;
        }
    </style>
</head>
<body>
    <h2 class="auto-style1">Macoratti .net - Enviando Emails </h2>
    <div class="well">
        <form id="form1" runat="server">
            Recipiente(s):<br />
            <asp:TextBox ID="txtRecipiente" runat="server" Height="50px" Width="525px" TextMode="MultiLine"></asp:TextBox>
            <br />
            <asp:Button ID="btnRecipienteDB" runat="server"
                onclick="btnRecipienteDB_Click" Text="Recipiente a partir do Banco de dados" />
            <br />
            <asp:CheckBoxList ID="chklstRecipientesDB" runat="server" Visible="False"></asp:CheckBoxList>
             <asp:Button ID="btnIncluirSelecionado" runat="server"
                        Text="Adicionar Seleção" onclick="btnIncluirSelecionado_Click" Visible="False" />
            <br /> 
            Assunto:<br />
            <asp:TextBox ID="txtAssunto" runat="server" Height="18px" Width="522px"></asp:TextBox>
            <br />
            <br />
            Corpo do Email:<br />
            <asp:TextBox ID="txtEmailBody" runat="server" Height="290px" Width="520px" TextMode="MultiLine"></asp:TextBox>
            <br />
            <asp:Button ID="btnEnviar" runat="server" onclick="btnEnviar_Click" Text="Envia Email" />
         </form>
   </div>
</body>
</html>

O código usado é bem simples.

  • Referenciamos o bootstrap e estamos usando a classe Well no formulário;
  • Definimos os controles com seus nomes e propriedades e eventos.

A seguir, vamos definir o code-behind nos eventos dos controles.

Quando o formulário for apresentado, o usuário deverá obter a lista de e-mails a partir do banco de dados clicando no botão – Recipiente a partir do banco de dados.

O código do evento Click deste botão é dado a seguir:

  Protected Sub btnRecipienteDB_Click(sender As Object, e As EventArgs) Handles btnRecipienteDB.Click
        Try
            Dim dsClientes As DataSet = GetDataSetCliente()
            chklstRecipientesDB.DataSource = dsClientes.Tables(0)
            chklstRecipientesDB.DataTextField = "Email"
            chklstRecipientesDB.DataValueField = "Email"
            chklstRecipientesDB.DataBind()
            chklstRecipientesDB.Visible = True
            btnIncluirSelecionado.Visible = True
        Catch ex As Exception
            Server.Transfer("PaginaErro.aspx", True)
        End Try
    End Sub

Neste código, estamos criando um DataSet – dsClientes – a partir da chamada do método GetDataSetCliente().

A seguir, estamos vinculando o campo E-mail da tabela E-mails ao controle CheckBoxList e tornando visível os CheckListBox e o botão para incluir a seleção dos e-mails.

O código do método GetDataSetCliente() é visto abaixo:

Private Function GetDataSetCliente() As System.Data.DataSet
        Try
            'retornar a string de conexao da chave ConnectionString no Web.Config descomente o código abaixo e comente o código usado
            'Dim connectionString as String = ConfigurationManager.ConnectionStrings("conexaoEmails").ConnectionString
            Dim connectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Dados\Clientes.accdb;Persist Security Info=False;"
            'cria um novo OleDB connection
            Dim conn As New System.Data.OleDb.OleDbConnection(connectionString)
            'passa o comando Select e a informação da conexão para o construtor 
            Dim da As New System.Data.OleDb.OleDbDataAdapter("SELECT Email FROM Emails", conn)
            'Cria um novo datas com a tabela : CLIENTES
            Dim ds As New System.Data.DataSet("Clientes")
            'Preenche o dataset e tabela com os dados retornados
            da.Fill(ds, "Clientes")
            'retorna o novo dataset
            Return ds
        Catch ex As Exception
            Server.Transfer("PaginaErro.aspx", True)
        End Try
    End Function

Com isso, teremos os e-mails exibidos na página e agora o usuário poderá selecionar os e-mails e clicar no botão: Adicionar Seleção.

O código do evento Click deste botão é dado a seguir:

Protected Sub btnIncluirSelecionado_Click(sender As Object, e As EventArgs) Handles btnIncluirSelecionado.Click
        Try
            Dim strRecipienteEmails As New StringBuilder()
            For Each chk As ListItem In chklstRecipientesDB.Items
                If chk.Selected Then
                    strRecipienteEmails.Append(chk.Value)
                    strRecipienteEmails.Append(";")
                End If
            Next
            txtRecipiente.Text = strRecipienteEmails.ToString()
            chklstRecipientesDB.Visible = False
            btnIncluirSelecionado.Visible = False

        Catch ex As Exception
            Throw ex
        End Try
End Sub

Este código verifica os e-mails marcados e copia o e-mail correspondente para o TextBox exibindo os e-mails que serão enviados.

Finalmente basta clicar no botão Enviar E-mail que tem o seguinte código no seu evento Click:

Protected Sub btnEnviar_Click(sender As Object, e As EventArgs) Handles btnEnviar.Click
        Try
            ' se voce quiser enviar emails diretametne do banco de dados
            ' descomente o codigo abaixo e ajuste para enviar 
            '----------------------------------------------------------
            ''Dim dsClientes As DataSet = GetDataSetCliente()
            ''If dsClientes.Tables("Clientes").Rows.Count > 0 Then
            ''    For Each dr As DataRow In dsClientes.Tables("Clientes").Rows
            ''        EnviaEmail(dr("Email").ToString())
            ''    Next
            ''End If
            '---------------------------------------------------------------
            Dim separador As Char() = {";"c}
            For Each _email As String In txtRecipiente.Text.Split(separador)
                 EnviaEmail(_email)
            Next
        Catch ex As Exception
            Server.Transfer("PaginaErro.aspx", True)
        End Try
    End Sub

Este código obtém os e-mails da caixa de texto e percorre cada um deles chamando o método EnviaEmail() para enviar o e-mail.

O código do método EnviaEmail() é dado a seguir:

Private Sub EnviaEmail(EmailAddress As String)
        Try
            'Cria uma instância da classe MailMessage
            Dim mail As New MailMessage()
            'destino
            mail.[To].Add(EmailAddress)
            'origem
            mail.From = New MailAddress("macoratti@yahoo.com")
            'assunto
            mail.Subject = txtAssunto.Text
            'corpo do email (texto)
            mail.Body = txtEmailBody.Text
            'é html ?
            mail.IsBodyHtml = True
            'cria instãncia STMP
            Dim smtp As New SmtpClient()
            'define o servidor SMTP
            smtp.Host = "smtp.gmail.com"
            'Dados do seu servidor SMTP
            smtp.Credentials = New System.Net.NetworkCredential("SeuNomeUsuario@gmail.com", "SuaSenha_gmail")
            'Suas credenciais SMTP
            'habilita o envio via SSL
            smtp.EnableSsl = True
            'envia o email
            smtp.Send(mail)
        Catch ex As Exception
            Server.Transfer("PaginaErro.aspx", True)
        End Try
    End Sub

Aqui você deve informar os dados do seu servidor SMTP ou usar outra forma de enviar os emails. (Veja artigo para enviar email usando o SendGrid).

Executando o projeto, iremos obter o seguinte resultado:

webf_email18

Após selecionar os e-mails, basta clicar no botão Envia E-mail.

Esse exemplo não deve ser considerado para enviar grandes quantidades de e-mail, mesmo porque esse tipo de atividade pode ser considerada prática de SPAM e dependendo da política do seu servidor SMTP isso pode te trazer problemas.

Para melhorar o desempenho, você pode considerar usar o método Parallel.ForEach para executar a operação de envio de e-mail de forma assíncrona.

A seguir, um exemplo onde estamos enviando diretamente do banco de dados onde criamos um DataTable – dtClientes:

Parallel.ForEach(dtClientes.AsEnumerable(),Function(linha)
             Return EnviaEmail(linha("Email").ToString()
   End Function)

Pegue o projeto completo aqui: Envia_Email_VBNET.zip

ASP .NET – Single Page Application(SPA) usando AngularJS com Web API – Parte 04

$
0
0

Neste artigo vou mostrar como criar uma aplicação ASP .NET Single Page Application usando os recursos do AngularJS com Web API: definindo o routing.

Na terceira parte do artigo, criamos a nossa aplicação Angular definindo o module, o controller e usando o serviço $http para obter informações do nosso banco de dados, exibindo-os na view Index.cshtml.

Um recurso muito poderoso do angular é o roteamento de páginas. O módulo ngRoute do Angular fornece serviços para realizar o roteamento de páginas para alguma rota pré-definida. Este recurso está disponível como um arquivo chamado angular-route.js, separado do pacote angular.js.

Para usar o recurso, basta referenciar o arquivo angular-route.js e registrar o ngRoute no módulo da aplicação Angular.

Nota: Você pode baixar o arquivo angular-route.js neste link (podemos instalar o pacote via Nuget).

   angular.module(“nomeModulo”,[“ngRoute”]);

Depois, basta configurar a rota específica usando o serviço $routeProvider e uma rota padrão, caso nenhuma rota seja encontrada.

O serviço $routeProvider possui dois métodos para fazer isso:

  • when(path, rota)  – define uma rota específica

  • otherwise(path) – define rota padrão

O método when recebe dois parâmetros (path e route):

  • O primeiro parâmetro é o path da rota
  • O segundo parâmetro é o objeto de configuração da rota. É neste momento que definimos qual template e controlador serão injetados.

O método otherwise é utilizado para definir uma rota padrão.

Quando nenhuma rota for encontrada, o AngularJS redirecionará a aplicação para essa rota padrão.

Exemplo:

$routeProvider
        .when('/', { templateUrl: '/views/home.html' })
        .when('/artigos', { templateUrl: 'views/artigos.html', controller: 'ArtigosController'})
        .when('/sobre', { templateUrl: 'views/sobre.html', controller: 'SobreController'})
        .otherwise({redirectTo: "/"})

Após isso, para exibir o resultado da renderização das páginas, basta usar a diretiva ng-view na página principal (master page).

<div ng-view> </div>

A figura abaixo mostra um esquema de funcionamento do roteamento no AngularJS:

asp_spaaj41

Para navegar entre as rotas podemos usar links : <a href=”#/produtos”>Produtos</a>

Para redirecionar ou retornar para uma determinada rota, podemos usar:

  • redirectTo : “/produtos”
  • $location.path(“/produtos”)

Onde o serviço $location analisa a URL na barra de endereços do navegador (baseado em window.location) e torna essa URL disponível para a sua aplicação. Alterações na URL na barra de endereços são refletidas no serviço $location e essas mudanças são refletidas na barra de endereços do navegador. ( https://docs.angularjs.org/guide/$location)

Recursos usados:

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

Definindo o roteamento na aplicação Angular

Abra a solução Filmoteca criada no artigo anterior no VS Community 2015 (Open Project). No menu Tools-> Nuget Package Manager, clique em Manage Nuget Packages for Solution. Depois informe o nome angular route e selecione o pacote AngularJS.Route, selecionando o projeto e clicando no botão Install:

asp_spaa41

O pacote javascript angular-route.js será instalado na pasta Scripts do projeto.

Agora temos que incluir a referência a esse pacote em nosso arquivo Index.cshtml na seção scripts:

...
@section scripts
{
    <script src="~/Scripts/angular.js"></script>
    <script src="~/Scripts/angular-route.js"></script>
    <script src="~/AngularApp/js/filmoteca.js"></script>
    <script src="~/AngularApp/js/listaController.js"></script>
}

Vamos também incluir uma dependência ao roteamento em nosso módulo Angular, incluindo no arquivo filmoteca.js da pasta js o código conforme mostrado abaixo:

(function () {
    var app = angular.module('filmoteca', ["ngRoute"]);
}());

Lembre-se que as dependências são informadas como o segundo parâmetro para o método module; onde o parâmetro é um array de strings contendo os nomes dos módulos requeridos.

Para o roteamento o nome é ngRoute.

Agora estamos prontos para definir o roteamento em nossa aplicação Angular usando um método config e o serviço $routeprovider, onde$routeProvider é o provider do serviço $route.

Por se tratar de um provider, ele só pode ser injetado dentro da função config (não podemos utilizar $routeProvider dentro de um controlador).

Abra o arquivo filmoteca.js e inclua o código abaixo neste arquivo:

(function () {
    var app = angular.module("filmoteca", ["ngRoute"]);
    var config = function ($routeProvider) {
        $routeProvider
        .when("/",
               { templateUrl: "/cliente/html/lista.html", controller: "listaController" })
        .when("/detalhes/:id",
               { templateUrl: "/cliente/html/detalhes.html", controller: "detalhesController" })
        .otherwise(
               { redirecTo: "/"});
    };
    app.config(config);
}());

No código acima definimos duas rotas:

  1. para a raiz do projeto (“/”) a rota é : /cliente/html/lista.html
  2. para a url /detalhes/id a rota é : /cliente/html/detalhes.html

Onde estamos acessando os arquivos lista.html e detalhes.html na pasta html dentro da pasta cliente. Vamos, agora, criar a pasta Cliente e dentro dela uma outra pasta html; a seguir, criaremos os arquivos html lista.html e detalhes.html.

Criando os arquivos HTML do roteamento na pasta html e o controller detalhesController

Selecione o projeto e no menu Project clique em New Folder e informe o nome Cliente. A seguir, clique com o botão direito sobre a pasta Cliente e no menu Project clique em New Folder e informe html. Agora clique com o botão direito do mouse sobre a pasta html e a seguir em Add -> New Item. Em seguida selecione o template HTML page e informe o nome lista.html. Inclua o código abaixo neste arquivo:

<div ng-app="filmoteca" ng-controller="listaController">
    <table class="table">
        <tr>
            <th>Título</th>
        </tr>
        <tr ng-repeat="filme in filmes">
            <td>{{filme.Titulo}}</td>
            <td>
                <a href="#/html/detalhes/{{filme.Id}}">Detalhes</a>
            </td>
        </tr>
    </table>
</div>

O código acima usa uma tabela HTML e a diretiva ng-repeat para percorrer o array de filmes que será obtido do banco de dados via WebApi.

A seguir, definimos um link usando a rota detalhes/id de forma que quando o usuário clicar no link será montada a URL: detalhes/id onde id é o código do filme que será passado como um parâmetro.

Repita o procedimento e crie o arquivo detalhes.html com o código a seguir na mesma pasta:

<div ng-controller="detalhesController">
    <h2>
       Filme :  {{filme.Titulo}}
    </h2>
    <div>
       <h3> Lançamento em : {{filme.AnoLancamento}} </h3>
    </div>
    <div>
       <h3>{{filme.Duracao}} minutos de duração.</h3>
    </div>
    <hr />
    <a href="#/">Lista</a>
</div>

Perceba que o controller usado na página html é o controle detalhesController que teremos que definir na pasta js.

Clique, então, com o botão direito do mouse sobre a pasta js e a seguir em Add-> New Item.

Selecione o template JavaScript file e informe o nome detalhesController.js, incluindo, a seguir, o código abaixo neste arquivo:

(function (app) {
    var detalhesController = function ($scope, $http, $routeParams)
    {
        var id = $routeParams.id;
        $http.get("/api/filme/" + id)
        .success(function (data) {
            $scope.filme = data;
        });
    };
    app.controller("detalhesController", detalhesController)
}(angular.module("filmoteca")));

Este controlador utiliza dois serviços: o serviço $routeParams e o serviço $http.

O serviço $routeParams contém os parâmetros adquiridos a partir da URL, como o valor para o Id do filme. Obtendo o Id e combinando-o com a URL, permite-se que o serviço $http retorne os detalhes atualizados para o filme específico e coloque os dados no objeto $scope para posterior apresentação na view.

Vamos ajustar agora a view Index.cshtml na pasta Views/Home substituindo o código existente pelo código abaixo:

<div class="well">
    <h4>Macoratti .net</h4>
</div>
<div data-ng-app="filmoteca">
    <ng-view></ng-view>
</div>

@section scripts
{
    <script src="~/Scripts/angular.js"></script>
    <script src="~/Scripts/angular-route.js"></script>
    <script src="~/AngularApp/js/filmoteca.js"></script>
    <script src="~/AngularApp/js/listaController.js"></script>
    <script src="~/AngularApp/js/detalhesController.js"></script>
}

No código acima incluímos a diretiva ng-view para renderizar as páginas html definidas no roteamento e a referência ao controllerdetalhesController.js criado.

Executando o projeto, iremos obter o seguinte resultado:

asp_spaa42

Note que o link Detalhes monta a url : #/detalhes/id. Clicando em qualquer um dos links iremos obter os detalhes do filme especificado pelo id:

asp_spaa43

Poderíamos implementar aqui a edição dos dados, mas antes de prosseguir com essa tarefa vamos incrementar o nosso projeto acrescentando uma abstração ao serviço $http para tornar a interação com a Web API mais fácil.

Na próxima parte do artigo vamos criar um serviço customizado para encapsular os recursos da Web API FilmeController de forma a não termos que usar o serviço $http diretamente dos controllers.

Pegue o projeto até esta etapa aqui: Filmoteca4.zip (sem as referências)


ASP .NET MVC – CRUD com Repositório Genérico e Unit of Work

$
0
0

Neste artigo, volto a falar sobre o padrão repositório e o padrão Unit of Work aplicando na prática os conceitos no desenvolvimento de uma aplicação que realiza um CRUD básico nas informações de livros.

Nosso modelo de domínio, portanto, será a entidade chamada de Livro que iremos detalhar no decorrer do artigo.

A aplicação desenvolvida vai usar os recursos do BootStrap e do JavaScript para melhorar a experiência do usuário.

Para tornar o entendimento mais simples, irei trabalhar com uma única entidade Livro.

Vou definir um repositório genérico para todas as entidades e uma classe UnitOfWork, que vai criar uma instância do nosso repositório para cada entidade, sendo que o repositório será usado para realizar as operações CRUD – Create, Read, Update e Delete.

O padrão Repository separa a lógica de acesso a dados e mapeia essa lógica para entidades na lógica de negócio. Ele trabalha com as entidades de domínio e realiza a lógica de acesso a dados.

No padrão Repository, as entidades de domínio e a lógica de acesso a dados se comunicam usando interfaces, e isso esconde os detalhes do acesso a dados da camada de negócios.

Martin Fowler afirma: “O padrão  Repository faz a mediação entre o domínio e as camadas de mapeamento de dados, agindo como uma coleção de objetos de domínio em memória…
Conceitualmente, um repositório encapsula o conjunto de objetos persistidos em um armazenamento de dados e as operações realizadas sobre eles, fornecendo uma visão mais orientada a objetos da camada de persistência… e também dá suporte ao objetivo de alcançar uma separação limpa e uma forma de dependência entre o domínio e as camadas de mapeamento de dados”.

Vamos criar uma instância da classe UnitOfWork no controlador da aplicação ASP .NET MVC e, então, criar uma instância do repositório dependendo da entidade e, posteriormente, usar os métodos do repositório conforme as operações CRUD.

No diagrama abaixo, temos o relacionamento entre o repositório e o contexto do Entity Framework; os controladores MVC interagem com o repositório por meio da Unit of Work em vez de acessarem diretamente o Entity Framework.

asp-1

Vamos definir a classe UnitOfWork e criar uma instância dessa classe de forma que a Unit Of Work irá instanciar o nosso DbContext e, a seguir, cada instância do repositório usa o mesmo DbContext para realizar as operações no banco de dados. Dessa forma, a Unit of Work é o padrão que garante que todos os repositórios irão usar o mesmo contexto do banco de dados.

Vamos utilizar o Entity Framework em uma abordagem Code First.

Nossa aplicação está baseada em uma arquitetura em camadas na qual teremos os seguintes projetos:

  1. Livraria.Core – Contém as entidades e o nosso domínio
  2. Livraria.Dados – Contém o DataContext, o mapeamento da entidade, o repositório e a Unit of Work
  3. Livraria.Web – Contém a interface com usuário representada pela aplicação ASP .NET MVC

Recursos usados:

  • Visual Studio Community 2015

Criando a solução e os projetos da aplicação

Abra o VS 2015 Community e clique em New Project.

A seguir, selecione Other Project Types -> Visual Studio Solutions.

Informe o nome Livraria e clique no botão OK.

asp-2

No menu File, clique em Add -> New Project e selecione o template Class Library.

Informe o nome Livraria.Core e clique em OK.

Repita o processo acima e crie o projeto Livraria.Dados.

Por último, clique no menu File e em Add -> New Project.

Selecione Web -> ASP .NET Web Applications e informe o nome Livraria.Web e clique no botão OK.

A seguir, selecione o template MVC conforme mostra a figura abaixo:

asp-3

Será criada uma solução contendo os projetos e a aplicação MVC contendo toda a estrutura de pastas criadas pelo framework ASP .NET MVC:

asp-4

Vamos incluir um novo projeto do tipo Class Library em nossa solução.

No menu File, clique em Add -> Project, selecione o template Class Library e informe o nome Mvc_Repositorio.Dominio.

Vamos incluir uma referência ao Entity Framework neste projeto via Nuget.

No menu TOOLS, clique em Nuget Package Manager e a seguir em Manage Nuget Packages for Solution.

asp-5

Selecione o Entity Framework e clique no botão Install escolhendo para ser instalado somente no projeto Mvc_Repositorio.Dominio.

Apague o arquivo Class1.cs criado por padrão e, a seguir, crie uma pasta chamada Repositorio no projeto Mvc_Repositorio.Dominio. Nessa pasta, vamos criar a nossa interface do Repositorio.

No menu PROJECT, clique em Add New Item.

Selecione o template Interface e informe o nome IRepositorio.cs

Agora vamos definir os métodos na nossa interface que deverão ser implementados para realizar o acesso e a persistência dos dados na camada de acesso a dados.

Lembre-se de que uma interface é um contrato que define como uma classe deve ser implementada, assim vamos definir assinaturas de métodos que deverão implementados por qualquer classe que desejar usar a nossa interface.

Abaixo, vemos os métodos definidos na nossa interface IRepositorio:

namespace Mvc_Repositorio.Dominio.Repositorio
{
    public interface IRepositorio<T> where T : class
    {
        IQueryable<T> GetTodos();
        IQueryable<T> Get(Expression<Func<T, bool>> predicate);
        T Procurar(params object[] key);
        T Primeiro(Expression<Func<T, bool>> predicate);
        void Adicionar(T entity);
        void Atualizar(T entity);
        void Deletar(Func<T, bool> predicate);
        void Commit();
        void Dispose();
    }
}

Vamos entender o código acima:

1 – Note que estamos usamos o namespace using System.Linq.Expressions, que contém classes e enumerações que permitem representar expressões de código no nível da linguagem como objetos na forma de árvores de expressões;
2 – Na assinatura da classe, estamos declarando public interface IRepositorio<T> where T : class; aqui, T é uma classe;
3 – IQueryable<T> GetTodos() – esse método retorna todos os dados como IQueryable; dessa forma, podemos retornar a lista e aplicar expressões lambdas para filtrar e classificar os dados;
4 – IQueryable<T> Get(Expression<Func<T, bool>> predicate) – retorna os dados que atendem ao critério informado em tempo de execução via expressão lambda. Estamos usando o delegate Func, e aplicando o predicate para verificar se o dado atende ao critério (retorna true ou false);
5 – T Find(params object[] key) – recebe um array de objetos e efetua a pesquisa pela chave primária;
6 – T First(Expression<Func<T, bool>> predicate) – retorna o primeiro dado que atende ao critério informado via expressão lambda. Usamos novamente o delegate Func e aplicamos o predicate para verificar se o dado atende ao critério;
7 – void Adicionar(T entity) – recebe o objeto T para realizar a inclusão no banco de dados;
8 – void Atualizar(T entity) – recebe o objeto T para realizar a atualização no banco de dados;
9 – void Deletar(<Func<T, bool>> predicate) – excluir registros usando uma condição definida na expressão lambda (via delegate Func) e aplicando o predicate (retorna true ou false) para verificar o critério;
10 – void Commit() – chama o método ChaveChanges() do contexto para efetivar todas as alterações realizadas no contexto. Ao final de cada operação, você deve sempre chamar este método para efetivar as operações que foram feitas na memória no banco de dados. Se não fizer isso, irá perder todas as operações realizadas;
11 – void Dispose() – executa a limpeza dos objetos.

Observe que não temos nenhum comando SQL, nenhuma declaração de objetos ADO .NET como connection, command, dataset, datareader etc.

Já temos o contrato definido e agora vamos definir a classe que irá implementar esse contrato.

Antes de implementar a interface IRepositorio, vamos definir o nosso domínio.

Definindo o domínio

Vamos criar uma pasta chamada Entidades no projeto Mvc_Repositorio.Dominio.

Selecione o projeto e, no menu PROJECT, clique em New Folder e informe o nome Entidades. Nessa pasta, vamos definir as entidades do nosso domínio.

Para tornar as coisas bem simples, eu vou definir apenas uma entidade chamada Usuario e vou mapear essa entidade para uma tabela Usuarios existente em um banco SQL Server chamado Cadastro.mdf.

Abaixo vemos a estrutura da tabela Usuarios:

asp-6

Selecione a pasta criada e, no menu PROJECT, clique em Add Class e informe o nome Usuario.

Defina o código baixo nessa classe:

namespace Mvc_Repositorio.Dominio.Entidades
{
    [Table("Usuarios")]
    public class Usuario
    {
        [Key]
        public int UsuarioId { get; set; }
        [Required(ErrorMessage = "Informe o login do usuário.")]
        [Display(Name = "Usuário")]
        public string Nome { get; set; }
        [Required(ErrorMessage = "Informe a senha do usuário.")]
        [DataType(DataType.Password)]
        public string Senha { get; set; }
        [Required(ErrorMessage = "Informe o email do usuário.")]
        public string Email { get; set; }
    }
}

O código acima usa os atributos do Data Annotations para definir o mapeamento para a tabela Usuarios e restrições de validações que deverão ser aplicadas na renderização das views que iremos criar.

Agora, para realizar o mapeamento ORM, vamos definir uma classe onde iremos usar os recursos do Entity Framework por meio do DbSet.

Selecione a pasta criada e, no menu PROJECT, clique em Add Class e informe o nome Usuario.

Defina o código baixo nessa classe:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

using System.Data.Entity;

namespace Mvc_Repositorio.Dominio.Entidades
{
    public class UsuarioContexto : DbContext
    {
         public UsuarioContexto()
            : base("name=ConexaoUsuarios")
        { }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            Database.SetInitializer<UsuarioContexto>(new CreateDatabaseIfNotExists<UsuarioContexto>());
        }

        public DbSet<Usuario> Usuarios { get; set; }
    }
}

Nessa classe, usamos o DbContext e realizamos o mapeamento da entidade Usuario com a tabela Usuarios.

O último detalhe que não podemos esquecer é definir no arquivo web.config da aplicação web a string de conexão  ConexaoUsuarios do banco de dados Cadastro.mdf.

Implementando a interface IRepositorio na classe Repositorio

Selecione a pasta Repositorio do projeto de Dominio e selecione o menu PROJECT – clique em Add New Item.

Selecione o template Class, informe o nome Repositorio.cs e clique no botão Add.

Vamos definir a assinatura da classe Repositorio conforme abaixo:

using Mvc_Repositorio.Dominio.Entidades;
using System;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;

namespace Mvc_Repositorio.Dominio.Repositorio
{
    public class Repositorio<T> : IRepositorio<T> ,  IDisposable where T : class
    {
        private UsuarioContexto Context;

        protected Repositorio()
        {
            Context = new UsuarioContexto();
        }

        public IQueryable<T> GetTodos()
        {
            return Context.Set<T>();
        }

        public IQueryable<T> Get(Expression<Func<T, bool>> predicate)
        {
            return Context.Set<T>().Where(predicate);
        }

        public T Procurar(params object[] key)
        {
            return Context.Set<T>().Find(key);
        }

        public T Primeiro(Expression<Func<T, bool>> predicate)
        {
            return Context.Set<T>().Where(predicate).FirstOrDefault();
        }

        public void Adicionar(T entity)
        {
            Context.Set<T>().Add(entity);
        }

        public void Atualizar(T entity)
        {
            Context.Entry(entity).State = EntityState.Modified;
        }

        public void Deletar(Func<T, bool> predicate)
        {
            Context.Set<T>()
           .Where(predicate).ToList()
           .ForEach(del => Context.Set<T>().Remove(del));
        }

        public void Commit()
        {
            Context.SaveChanges();
        }

        public void Dispose()
        {
            if (Context != null)
            {
                Context.Dispose();
            }
                GC.SuppressFinalize(this);
            }
        }
   }

Dessa forma, como já temos o nosso repositório criado, vamos definir agora as interfaces para representarem o repositório específico para a entidade Usuario.

Então, selecione a pasta Repositorio e, no menu PROJECT, clique em Add New Item.

Selecione o template Interface, informe o nome IUsuarioRepositorio.cs e clique no botão Add.

A seguir, defina o código abaixo para a interface IUsuarioRepositorio:

using Mvc_Repositorio.Dominio.Entidades;

namespace Mvc_Repositorio.Dominio.Repositorio
{
    public interface IUsuarioRepositorio : IRepositorio<Usuario>
    {
    }
}

Deveremos criar também a classe que implementa a interface IUsuarioRepositorio.

Então, selecione a pasta Repositorio e, no menu PROJECT, clique em Add New Item.

Selecione o template Class, informe o nome UsuarioRepositorio.cs e clique no botão Add.

A seguir, defina o código abaixo para a classe UsuarioRepositorio:

using Mvc_Repositorio.Dominio.Entidades;

namespace Mvc_Repositorio.Dominio.Repositorio
{
    public class UsuarioRepositorio :  Repositorio<Usuario>, IUsuarioRepositorio
    {
    }
}

Observe que não precisamos definir nenhum código nas interfaces e classes acima, pois estamos usando o mecanismo da herança e da implementação da interface e, assim, estamos usando os métodos definidos na interface IRepositorio e na classe Repositorio. Note também que estamos usando as entidades que foram separadas no projeto de Dominio.

Neste momento, nossa solução tem a seguinte estrutura:

asp-7

Na próxima parte do artigo, iremos criar a camada de negócios da nossa aplicação.

Mensagem do anunciante:

Conheça a Umbler, startup de Cloud Hosting por demanda feita para agências e desenvolvedores. Experimente grátis!

ASP .NET – Single Page Application (SPA) usando AngularJS com Web API – Parte 05

$
0
0

Neste artigo, eu vou mostrar como criar uma aplicação ASP .NET Single Page Application usando os recursos do AngularJS com Web API: Criando um serviço.

Na quarta parte do artigo, definimos o roteamento em nossa aplicação Angular, criamos o controller detalhesController e agora estamos navegando para a página que exibe os filmes e também os detalhes de um filme.

Neste artigo, vamos criar um serviço customizado de forma a encapsular a lógica de acesso às informações dos filmes em um service do Angular.

Os services do AngularJS são objetos substituíveis que estão ligados entre si usando a injeção de dependência (DI). Você pode usar serviços do Angular para organizar e compartilhar código (reuso) em seu aplicativo.

Os serviços do Angular são:

  1. Instanciados tardiamente (Lazy Load) – O Angular somente instancia um serviço quando um componente da aplicação depende disso.
  2. Singletons – Cada componente dependente de um serviço obtém uma referência a uma única instância gerada pela fábrica de serviço.

O Angular oferece vários serviços úteis (como $http, $log, $route, $location, $window etc.), mas podemos criar serviços de acordo com a necessidade da nossa aplicação.

Para usar um serviço Angular, basta adicioná-lo como uma dependência para o componente (controlador, serviço, filtro ou diretiva) que depende do serviço. O subsistema de injeção de dependência do Angular cuida do resto.

Vamos, então, criar um serviço customizado para a nossa aplicação que encapsula as capacidades da Web API FilmeController, de forma que nossos controladores não precisem usar o serviço $http diretamente.

Existem três maneiras principais de criar registros e serviços:

  1. Service: Quando você estiver usando um Service, ele é instanciado com a palavra-chave “new”. Por causa disso, você vai adicionar propriedades a “this” e o serviço retornará “this”. Quando você passar o serviço ao seu controlador, essas propriedades em “this” estarão disponíveis no controlador por meio de seu serviço.
  2. Factory (a forma mais popular de criar services):  Ao usar um Factory, você cria um objeto, adiciona propriedades a ele e então retorna o mesmo objeto. Quando você passar esse serviço ao seu controlador, as propriedades do objeto estarão disponíveis no controlador por meio de sua factory.
  3. Provider: Os provedores são o único serviço que você pode passar para a função config(). Use um Provider quando você desejar fornecer configuração ao módulo para o objeto de serviço antes de torná-lo disponível.

Recursos usados:

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

Criando um serviço AngularJS

Abra a solução Filmoteca criada no artigo anterior no VS Community 2015 (Open Project).

Clique então com o botão direito do mouse sobre a pasta js e, a seguir, em Add-> New Item.

Selecione o template JavaScript file e informe o nome filmeService.js.

Defina o código abaixo nesse arquivo:

(function (app) {    

    var filmeService = function ($http, filmeApiUrl) {

        var getFilmes = function() {
            return $http.get(filmeApiUrl);
        };

        var getFilmePorId = function (id) {
            return $http.get(filmeApiUrl + id);
        };

        var atualizar = function (filme) {
            return $http.put(filmeApiUrl + filme.Id, filme);
        };

        var criar = function (filme) {
            return $http.post(filmeApiUrl, filme);
        };

        var deletar = function (filme) {
            return $http.delete(filmeApiUrl + filme.Id);
        };

        return {
            getFilmes: getFilmes,
            getFilmePorId: getFilmePorId,
            atualizar: atualizar,
            criar: criar,
            deletar: deletar
        };
    };

    app.factory("filmeService", filmeService);

}(angular.module("filmoteca")))

No arquivo filmeService.js, criamos um serviço e estamos encapsulando os recursos da Web API FilmeController, de forma que agora o nossos controllers AngularJS não vão precisar usar o serviço $http diretamente.

Observe que o serviço está imitando a API FilmeController do lado do servidor fornecendo métodos para retornar todos os filmes, obter um filme pelo seu Id, atualizar, criar e deletar um filme. Cada um desses métodos encaminha uma chamada para o serviço $http, o qual é uma dependência de filmeService.

Note que em filmeService temos também uma dependência de filmeApiUrl, o que demonstra como passar a informação da configuração de uma aplicação para os serviços e outro componente dentro da aplicação pelo registro de valores constantes durante a configuração da aplicação.

Voltemos então para o arquivo filmoteca.js, no qual as rotas estão definidas e vamos registrar o valor constante usando o método constant. Esses valores usam uma chave como primeiro parâmetro e o valor associado com a chave como segundo parâmetro. Nosso arquivo filmoteca.js deve ficar com o seguinte código:

(function () {

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

    var config = function ($routeProvider) {

        $routeProvider
        .when("/",
               { templateUrl: "/cliente/html/lista.html"})
        .when("/detalhes/:id",
               { templateUrl: "/cliente/html/detalhes.html"})
        .otherwise(
               { redirecTo: "/"});
    };
    app.config(config);
    //inclusão
    app.constant("filmeApiUrl", "/api/filme/");
}());

Qualquer componente que precisar chamar FilmeController pode agora requisitar a dependência filmeApiUrl, mas somente filmeService vai precisar desse valor. Para usar o serviço, vamos incluir o script na view Index.html:

<div class="well">
    <h4>Macoratti .net</h4>
</div>

<div ng-app="filmoteca">
    <ng-view></ng-view>
</div>

@section scripts
{
    <script src="~/Scripts/angular.js"></script>
    <script src="~/Scripts/angular-route.js"></script>
    <script src="~/AngularApp/js/filmoteca.js"></script>
    <script src="~/AngularApp/js/listaController.js"></script>
    <script src="~/AngularApp/js/detalhesController.js"></script>
    <script src="~/AngularApp/js/filmeService.js"></script>
}

Podemos agora alterar o controller listaController para usar o serviço criado em vez de usar o $http:

(function (app) {

    var listaController = function ($scope, filmeService)
    {
        filmeService
            .getFilmes()
            .success(function (data) {
            $scope.filmes = data;
            });
    };

    app.controller("listaController", listaController)

}(angular.module("filmoteca")));

Vamos fazer a mesma coisa com o controller detalhesController:

(function (app) {

    var detalhesController = function ($scope, $routeParams, filmeService)
    {
        var id = $routeParams.id;
        filmeService
            .getFilmePorId(id)
            .success(function (data) {
            $scope.filme = data;
        });
    };

    app.controller("detalhesController", detalhesController)

}(angular.module("filmoteca")));

Aqui  usamos o serviço $routeParams, que permite retornar o conjunto atual de parâmetros à rota – no nosso exemplo, o Id do filme.

Se executarmos o projeto novamente, iremos obter o mesmo resultado, mas agora estamos usando um serviço criado para encapsular as funcionalidades da Web API e, assim, poderemos reusar o serviço caso precisemos:

macoratti

Acima, vemos a apresentação dos filmes e a exibição dos detalhes de um filme.

Na próxima parte do artigo, vamos implementar as funcionalidades para deletar, editar e criar filmes em nossa aplicação SPA.

.NET – O padrão MVVM (Model-View-ViewModel) revisitado

$
0
0

Neste artigo vou apresentar os conceitos relacionados como padrão de projeto Model-View-ViewModel (MVVM).

O padrão MVVM é basedo no padrão MVC – Model-View-Controller e eles possuem em comum o Model-View e são separados pelo ViewModel.

O padrão MVVM foi projetado para implementar a vinculação de dados entre o seu ViewModel e a sua View conforme mostra a figura abaixo:

net_mvvm11

Estruturalmente, uma aplicação que usa o padrão MVVM consiste basicamente em três componentes principais: o Modelo, a Visão (View) e a ViewModel.

Essa tarefa (a vinculação de dados) pode ser feita usando o Knockout e atualmente com o AngularJS que faz isso muito bem usando o recurso do two-way databinding.

Nota: O AngularJS é considerado um framework Model-View-Whatever.(MVW) onde Whatever significa ‘Tudo oque funciona para você”.

A KnockoutJS é uma library JavaScript Open Source que usa o padrão MVVM (Model-View-ViewModel) para criar interfaces de usuário através de ligações declarativas de dados, interface de atualização automática, rastreamento de dependência e modelagem do lado cliente.

O conceito de MVVM deve ser muito intuitivo e familiar, especialmente para pessoas com experiência em WPF.

Você pode obter mais informações, bem como baixar a library JavaScript no site oficial do KnockoutJS.

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.

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.

A coisa mais importante para se lembrar quando você for criar o seu ViewModel é que eles devem ser organizados de forma a tornar mais fácil a representação de como as suas Views vão usar os dados.

Esta é uma diferença importante pois os Models no padrão MVC são uma representação de como os dados estão armazenados no banco de dados.

net_mvvm13

No padrão MVC, o controlador de MVC aceita solicitações HTTP, obtém dados a partir do modelo, e encaminha o modelo para a view renderizando a saída. Já os ViewModels são a peça que realiza essa mesma tarefa, pois o ViewModel assume a responsabilidade de realizar, ou expor o comando que abriga toda a lógica de interface do usuário, além de buscar os dados e a ligação de dados.

Neste contexto, a ViewModel tem a responsabilidade de disponibilizar para a View uma lógica de representação.

Em uma aplicação ASP .NET MVC, podemos ter um ViewModel representando um conjunto de um ou mais Models e outras informações que desejamos exibir em uma View.

net_mvvm12

Na figura cima vemos que o ViewModel – AlteraSenha – é composto por informações do Model Usuario e de informações que precisamos exibir somente na View para confirmar a senha.

Uma maneira de saber se você precisa usar o padrão ViewModel é observar como foi definido o seu Model e verificar se nele existem definições que somente são utilizadas pelas Views e não têm nada a ver com seu modelo de domínio.

Se isso for encontrado no seu modelo, então talvez fosse o caso de você usar o ViewModel para separar essa responsabilidade a mais que está no seuModel.

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 e clique em New Project. A seguir, selecione a linguagem Visual C# e o template ASP .NET Web Application, depois informe o nome Mvc_MVVM e clique no botão OK.

A seguir, selecione o template Empty, marque o folder MVC e clique no botão OK.

net_mvvm14

Definindo o Model

Vamos supor que temos uma classe Usuario no nosso modelo de domínio.

Vamos definir na pasta Models o nosso modelo de domínio representando pela classe Usuario que tem o seguinte código:

using System;
using System.ComponentModel.DataAnnotations;
namespace Mvc_MVVM.Models
{
    public class Usuario
    {
       public int Id { get; set; }
       [Required]
       public string Nome { get; set; }
       [Required]
       public string Email { get; set; }
       [Required]
       public string Senha { get; set; }
       public DateTime DataCriacao { get; set; }
    }
}

Esse é nosso modelo de negócio que representa um usuário com id, nome, e-mail, senha e data de inclusão no cadastro.

Definindo o ViewModel

Agora vamos supor que desejamos criar um formulário para alterar a senha do usuário e que vamos precisar exibir neste formulário as seguintes informações:

  • Nome

  • Senha

  • NovaSenha

  • ConfirmarSenha

Observe que temos informações que precisamos exibir que não constam no nosso modelo de domínio. Essas informações somente serão exibidas na view.

Com base nisso, vamos criar uma pasta ViewModel em nosso projeto e nesta pasta criar o nosso ViewModel representado pela classeUsuarioViewModel com o seguinte código:

using System.ComponentModel.DataAnnotations;
namespace Mvc_MVVM.ViewModel
{
    public class UsuarioViewModel
    {
        [Required]
        public string Nome { get; set; }
        [Required]
        public string Senha { get; set; }
        [Required]
        public string NovaSenha { get; set; }
        public string ConfirmarSenha { get; set; }
    }
}

Como você pode ver a nossa View Model contém as propriedades Nome e Senha do modelo de domínio e as propriedades NovaSenha e ConfirmarSenha que iremos somente exibir na view.

As propriedades Id, E-mail e DataInclusao não são necessárias em nosso ViewModel.

Definindo o Controlador

Vamos definir um controlador HomeController na pasta Controllers bem simples apenas para gerar a view para o nosso ViewModel.

O código do controlador HomeController é dado a seguir:

using Mvc_MVVM.ViewModel;
using System.Web.Mvc;
namespace Mvc_MVVM.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            UsuarioViewModel usuario = new UsuarioViewModel();
            return View(usuario);
        }
        [HttpPost]
        public ActionResult Index(UsuarioViewModel usuario)
        {
            //logica para alterar senha do usuároi
            return View();
        }
    }
}

Gerando a view Index para o método Action Index e usando as seguintes configurações:

net_mvvm16

Teremos o seguinte código:

@model Mvc_MVVM.ViewModel.UsuarioViewModel
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    @using (Html.BeginForm()) 
    {
        @Html.AntiForgeryToken()
        <div class="form-horizontal">
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.Nome, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Nome, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Nome, "", new { @class = "text-danger" })
                </div>
            </div>
           <div class="form-group">
                @Html.LabelFor(model => model.Senha, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Senha, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Senha, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.LabelFor(model => model.NovaSenha, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.NovaSenha, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.NovaSenha, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.LabelFor(model => model.ConfirmarSenha, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.ConfirmarSenha, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.ConfirmarSenha, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Alterar Senha" class="btn btn-default" />
                </div>
            </div>
        </div>
       }
</body>

Temos uma view fortemente tipada onde o tipo é nosso ViewModel: UsuarioViewModel.

Executando o projeto teremos o resultado abaixo:

net_mvvm15

O ponto chave a lembrar aqui é que o ViewModel somente representa os dados que você deseja usar na sua view e nada mais (um ViewModel pode combinar dados de mais de um Model).

Creio que você entendeu o conceito básico do que é um ViewModel e quando usá-lo.

Pegue o projeto completo aqui: Mvc_MVVM.zip.

VB .NET – Tratando strings e coleções de strings com LINQ

$
0
0

Neste artigo vou mostrar como podemos usar os recursos da LINQ – Language Integrated Query – para tratar strings e coleções de strings.

A LINQ pode ser usada para consultar e transformar strings e coleções de strings e este recurso pode ser muito útil, especialmente com dados estruturados em arquivos textos.

Podemos combinar as consultas LINQ com as funções strings tradicionais e com expressões regulares, aumentando, assim, o seu potencial de recursos. Dessa forma podemos:

  • Usar o método Split() para criar um array de strings que podemos consultar e modificar usando LINQ e também podemos usar usar o métodoIsMatch() na cláusula Where da consulta LINQ;
  • Usar a LINQ para consultar ou modificar o resultado MatchCollection retornado por uma expressão regular.

Assim podemos separar um texto fonte em palavras, sentenças, parágrafos, páginas e qualquer outro critério e, então, realizar consulta adicional.

Muitos tipos de arquivos textos consistem em uma série de linhas, com uma formatação padrão que usa vírgula, tab, arquivos delimitados, arquivos fixo etc. Após você ler esses arquivos, você pode usar a LINQ para consultar e modificar as linhas.

Esse artigo será útil para recordar os recursos da LINQ no tratamento de strings.

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 2015 Community e clique em New Project. Selecione a linguagem Visual Basic e o template Windows Forms Application.

Informe o nome da solução como LINQ_Strings e clique no botão OK.

net_strlnq11

1. Contando as ocorrências de uma palavra em uma string

Como a classe string implementa a interface genérica IEnumerable(Of T), qualquer string pode ser consultada como uma sequência de caracteres (para operações mais complexas é aconselhável usar Regex).

Este exemplo mostra como podemos usar uma consulta LINQ para contar as ocorrências de uma palavra especificada em uma string.

Para realizar a tarefa, primeiro usamos o método Split para criar um array de palavras e isso tem um impacto no desempenho da aplicação; portanto, se a única tarefa é contar palavras, poderíamos usar os métodos Matches ou IndexOf.

Defina no formulário form1.vb os controles:

  • 1 Button – btnLerTexto

  • 1 TextBox – txtText, Multiline=True

  • 1 Button – btnContarOcorrencias

  • 1 Textbox – txtPalavra

  • 1 Button – btnLimpar

  • 1 ListBox – lbResultado

Disponha os controles no formulário conforme o leiaute da figura abaixo:

net_strlnq12

No evento Click do botão – btnLerTexto inclua o código que permite escolher um arquivo texto e exibir no formulário:

Private Sub btnLerTexto_Click(sender As Object, e As EventArgs) Handles btnLerTexto.Click
        Dim ofd1 As New OpenFileDialog
        ofd1.Title = "Selecionar Arquivo"
        ofd1.InitialDirectory = "C:\Dados\"
        'filtra para exibir somente arquivos textos
        ofd1.Filter = "Arquivos Texto (*.Txt)|*.Txt|" & "Todos Arquivos (*.*)|*.*"
        ofd1.CheckFileExists = True
        ofd1.CheckPathExists = True
        ofd1.FilterIndex = 1
        ofd1.RestoreDirectory = True
        ofd1.ReadOnlyChecked = True
        Dim dr As DialogResult = ofd1.ShowDialog()
        If dr = System.Windows.Forms.DialogResult.OK Then
            ' abre o arquivo e le o seu conteudo
            txtTexto.Text = My.Computer.FileSystem.ReadAllText(ofd1.FileName)
        End If
    End Sub

No evento Click do botão – btnContarOcorrencias – inclua o código que irá contar o número de ocorrências da palavra informada:

 Private Sub btnContarOcorrencias_Click(sender As Object, e As EventArgs) Handles btnContarOcorrencias.Click
        Dim palavraAlvo As String = txtPalavra.Text.Trim()
        If String.IsNullOrWhiteSpace(palavraAlvo) Then
            MessageBox.Show("Informe a palavra a ser contada na string")
            Exit Sub
        End If
        Dim fonteDados As String() = txtTexto.Text.Split(New Char() {" ", ",", ".", ";", ":", "-", ", ", "(", ")"}, StringSplitOptions.RemoveEmptyEntries)
        ' Cria e executa a consulta
        ' Ela é executada imediatamente porque um único valor é produzido
        ' Usamos ToLower para encontrar "xxx" e "XXX" 
        Dim resultado = From palavra In fonteDados
                                    Where palavra.ToLowerInvariant() = palavraAlvo.ToLowerInvariant()
                                    Select palavra
        'conta as ocorrências
        Dim valor As Integer = resultado.Count()
        'exibe o resultlado o listbox
        lbResultado.Items.Add(valor & " ocorrência da palavra """ & palavraAlvo & """ foram encontradas.")
    End Sub

Executando o projeto e fazendo alguns testes teremos o resultado abaixo:

net_strlnq14

2. Combinando Consultas LINQ com expressões regulares

Vamos realizar agora uma consulta mais complexa usando LINQ e expressões regulares. Vamos supor que desejamos verificar a ocorrência de uma palavra em arquivos HTML (.htm).

Depois, vamos incluir um novo formulário no projeto atual e definir uma interface simples e intuitiva usando os seguintes controles:

  • 1 TextBox – txtLocal

  • 1 Button – btnLocalBusca

  • 1 TextBox – txtPalavra

  • 1 Button – btnOcorrencias

  • 1 ListBox – lbResultado

No evento Click do botão btnLocalBusca, inclua o código que permite selecionar uma pasta a partir de onde serão lidos os arquivos para realizar a busca:

Private Sub btnLocalBusca_Click(sender As Object, e As EventArgs) Handles btnLocalBusca.Click
        Dim fbd1 As New FolderBrowserDialog
        fbd1.Description = "Selecione uma pasta para busca"
        fbd1.RootFolder = Environment.SpecialFolder.MyComputer
        fbd1.ShowNewFolderButton = True

        'Exibe a caixa de diálogo
        If fbd1.ShowDialog = DialogResult.OK Then
            'Exibe o nome da pasta no textbox
            txtLocal.Text = fbd1.SelectedPath.ToString()
        End If
End Sub

A seguir, no evento Click do botão – btnOcorrencias -, temos o código que percorre todos os arquivos com extensão .htm da pasta e faz a busca por ocorrências nos arquivos da palavra definida para critério de busca:

Private Sub btnOcorrencias_Click(sender As Object, e As EventArgs) Handles btnOcorrencias.Click
        Dim pastaBusca As String = txtLocal.Text.Trim
        Dim listaArquivos As IEnumerable(Of FileInfo) = ObtemArquivos(txtLocal.Text.Trim)
        ' Cria uma expressão regular para encontrar as ocorrências do texto indicado
        Dim termoBusca As System.Text.RegularExpressions.Regex =
                                                  New System.Text.RegularExpressions.Regex(txtPalavra.Text.Trim)
        'define a consulta nos arquivos .htm do texto indicado
        Dim consultaArquivos = From _arquivo In listaArquivos
                                                  Where _arquivo.Extension = ".htm"
                                                  Let arquivoTexto = File.ReadAllText(_arquivo.FullName)
                                                  Let correspondencia = termoBusca.Matches(arquivoTexto)
                                                Where (correspondencia.Count > 0)
                                                 Select Name = _arquivo.FullName,
                                                        Matches = From match As System.Text.RegularExpressions.Match In correspondencia
                                                        Select match.Value
        ' Executa a consulta
        lbResultado.Items.Add("O termo " & termoBusca.ToString() & " foi encontrado em :")
        For Each arquivosCoincidentes In consultaArquivos
            Dim s = arquivosCoincidentes.Name.Substring(pastaBusca.Length - 1)
            lbResultado.Items.Add(s)
            For Each encontrado In arquivosCoincidentes.Matches
                lbResultado.Items.Add("  " + encontrado)
            Next
        Next
    End Sub

Abaixo temos o código do método ObtemArquivos que recebe a pasta de destino e obtém os arquivos contidos nesta pasta:

  Shared Function ObtemArquivos(ByVal raiz As String) As IEnumerable(Of System.IO.FileInfo)
        Return From arquivo In My.Computer.FileSystem.GetFiles(
                   raiz, FileIO.SearchOption.SearchAllSubDirectories, "*.*")

               Select New FileInfo(arquivo)

    End Function

Executando o projeto e fazendo alguns testes teremos o resultado abaixo:

net_strlnq13

Dessa forma, vimos como usar os recursos do LINQ para tratar strings e coleções.

Pegue o projeto completo aqui: LINQ_Strings.zip

ASP .NET MVC 5 – Usando o StructureMap para injeção de dependência

$
0
0

Neste artigo vou mostrar como usar a ferramenta StructureMap para realizar a injeção de dependência em uma aplicação ASP .NET MVC 5. O StructureMap é a ferramenta mais antiga para realizar a injeção de dependência para a plataforma .NET.

Antes de começar, vamos recordar alguns conceitos:

Dependency Inversion Principle (DIP)

  • Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstraçõe;
  • Abstrações não devem depender de detalhes. Detalhes devem depender de abstrações.

O DIP nos ajuda a desenvolver um código com baixo acoplamento fazendo com que módulos de alto nível dependam de abstrações e não de implementações concretas de módulos de baixo nível.

Indo direto ao ponto: dependa de interfaces e não de classe concretas.

O padrão Inversion of Control é uma implementação deste princípio.

Inversion of Control (IoC)

O termo Inversion of Control (Ioc) se refere a um estilo de programação onde um framework controla o fluxo do programa alterando o controle na sua forma normal.

Dependency Injection (DI)

É um processo de passar os detalhes da abstração para uma entidade

  • A inversão de controle (Ioc) é um princípio e a injeção de dependência (ID) é uma forma de implementar a inversão de controle, ou seja: geralmente fazemos a inversão de controle utilizando a injeção de dependência;
  • A DIP é um princípio que nos guia para a DI através da Ioc .

ioc

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 profissional.

Criando o projeto no VS Community

Abra o VS 2015 Community e clique em New Project. Depois selecione a linguagem Visual C# e o template  ASP .NET Web Applications. Em seguida, informe o nome da solução como Mvc_StructureMap e clique no botão OK.

mvc_strmap11

Selecione o template Empty e marque a opção MVC, definindo as opções conforme a figura abaixo e clique no botão OK:

mvc_strmap12

No menu Tools, clique em Nuget Package Manager -> Manage Nugect Packages for Solution. Selecione a biblioteca StructureMap.MVC4 e clique no botão Install.

mvc_strmap13

Ao final teremos os pacotes referenciados no projeto e as seguintes alterações feitas na estrutura do projeto:

mvc_strmap14

Na pasta DependencyResolution, o arquivo Ioc.cs é o mais importante.

using StructureMap;
using StructureMap.Graph;
namespace Mvc_StructureMap.DependencyResolution {
    public static class IoC {
        public static IContainer Initialize() {
            ObjectFactory.Initialize(x =>
                        {
                            x.Scan(scan =>
                                    {
                                        scan.TheCallingAssembly();
                                        scan.WithDefaultConventions();
                                    });
            //                x.For<IExample>().Use<Example>();
                        });
            return ObjectFactory.Container;
        }
    }
}

Ao abri-lo, você vai ver um único método de inicialização onde você irá configurar as suas interfaces e os tipos que devem ser usados por eles para esta aplicação.

Não vamos alterar nada neste arquivo.

Fazendo a injeção de dependência com o StructureMap

Para testar a injeção de dependência usando o StructureMap, precisamos dos seguintes ingredientes:

  • A definição de uma interface;
  • Uma implementação dessa interface;
  • A criação de um controlador que usar a interface;
  • A criação da View;
  • Testar a aplicação.

Vamos criar uma interface IMensagem na pasta Models do projeto com o código abaixo:

namespace Mvc_StructureMap.Models
{
    public interface IMensagem
    {
        string GetMensagem();
    }
}

Ainda na pasta Models, vamos criar a classe concreta Mensagem que implementará esta interface:

namespace Mvc_StructureMap.Models
{
    public class Mensagem : IMensagem
    {
        public string GetMensagem()
        {
            return "Testando a injeção de dependência com o StructureMap";
        }
    }
}

Agora vamos criar o controlador HomeController na pasta Controllers usando o Scaffold MVC 5 Controller Empty:

using Mvc_StructureMap.Models;
using System.Web.Mvc;
namespace Mvc_StructureMap.Controllers
{
    public class HomeController : Controller
    {
        private readonly IMensagem _mensagem;
        public HomeController(IMensagem mensagem)
        {
            _mensagem = mensagem;
        }
        // GET: Home
        public ActionResult Index()
        {
            ViewBag.Mensagem = _mensagem.GetMensagem();
            return View();
        }
    }
}

Neste código vamos fazer a injeção de dependência no controlador usando o construtor.

Precisamos de mais alguma coisa? Não, então vamos testar.

Executando o projeto iremos obter o seguinte resultado:

mvc_strmap15

using StructureMap;
using WebApplication1.Controllers;
namespace WebApplication1.DependencyResolution {
    public static class IoC {
        public static IContainer Initialize() {
            ObjectFactory.Initialize(x =>
            {
                x.For<IDependencia>().Use<Dependencia>();
            });
            return ObjectFactory.Container;
        }
    }
}

Pegue o projeto completo aqui: Mvc_StructureMap.zip

Entity Framework – Lazy Loading e o problema Select N+1

$
0
0

Neste artigo vou apresentar o problema conhecido como Select N+1, que afeta o desempenho da sua aplicação e que se manifesta quando se usa o Lazy Loading no Entity Framework.

Se você usa o Entity Framework em suas aplicações e têm percebido que elas estão muito lentas, você pode ser mais uma vítima do problema Select N+1, que é causado quando se usa o recurso do Lazy Loading, que vem habilitado por padrão, e que afeta de forma significativa aplicações que realizam consultas em entidades com associações um-para-muitos.

Se você ainda não conhece o Entity Framework muito bem, mas pretende usá-lo em suas aplicações, fique atento e acompanhe o artigo que pode livrá-lo de problemas futuros.

Nota: O problema Select N+1 não é um problema específico do Entity Framework; ele pode se manifestar em todos os frameworks ORM que usam o  Lazy Loading como padrão.

O que é Lazy Loading ou Lazy Load?

Lazy Load é o mecanismo utilizado pelos frameworks de persistência para carregar informações sobre demanda. Esse mecanismo torna as entidades mais leves, pois suas associações são carregadas apenas no momento em que o método que disponibiliza o dado associativo é chamado. Assim, quando objetos são retornados por uma consulta, os objetos relacionados não são carregados ao mesmo tempo. Na realidade, eles são carregados automaticamente quando a propriedade de navegação for acessada.

Assim, o mecanismo Lazy Load retarda a inicialização de um objeto até ao ponto que ele for realmente acessado pela primeira vez.

O objetivo do Lazy Load é fazer com que sua aplicação utilize menos memória e seja mais eficiente pela redução da quantidade de dados transferidos de/para o banco de dados.

Pela definição, você pode achar que o Lazy Load é um bom recurso e o fato de ser habilitado por padrão parece que é um aval para sua utilização, mas ele esconde um problema gravíssimo que se manifesta em consultas quando estão envolvidas entidades com associações do tipo um-para-muitos.

A conclusão é que, infelizmente, esse recurso causa mais problemas do que benefícios – e, talvez, o pior problema causado seja o Select N+1.

Afinal o que é o problema conhecido como Select N +1?

Para ver como o problema se manifesta, vamos supor que temos em uma aplicação uma coleção de Filmes e que cada Filme tem uma coleção de atores, ou seja, temos duas entidades expressas no código abaixo:

Filmes.cs

public class Filme
    {
        public int FilmeId { get; set;  }
        public string Titulo { get; set;  }
        public ICollection<Ator> Atores { get; set;  }
    }

Ator.cs

public class Ator
    {
        public int AtorId { get; set; }
        public string Nome { get; set;  }
        public Filme Filme { get; set; }
    }

DBContexto.cs

public class DBContexto : DbContext
    {
        public DbSet<Filme> Filmes {get; set;}
        public DbSet<Ator> Atores { get; set; }
    }

Temos assim uma associação entre a entidade Filme e a entidade Ator do tipo um-para-muitos: um filme pode ter muitos atores.

Nota: O mapeamento será feito para as tabelas Filmes e Atores do banco de dados SQL Server.

Agora vamos supor que precisamos realizar uma consulta que retorne os filmes e, então, para cada filme precisamos retornar todos os atores.

Podemos realizar essa tarefa usando o código abaixo:

static void Main(string[] args)
   {
            using (var ctx = new DBContexto())
            {
                foreach (var filme in ctx.Filmes)
                {
                    foreach(var ator in ctx.Atores)
                    {
                        Console.WriteLine(" {0} : {1} ", filme.Titulo, ator.Nome);
                    }
                }
            }
 }

Aparentemente, não existe erro e o código vai compilar e vai funcionar normalmente, mas devido ao recurso Lazy Loading estar habilitado por padrão, o problema Select N+1 vai se manifestar.

Quando o código for executado, o Entity Framework irá gerar uma consulta SQL para retornar todos os filmes:

SELECT * FROM Filmes

e, a seguir, será gerada N consultas para obter cada ator do respectivo filme:

SELECT * FROM Atores WHERE FilmeId = 1
SELECT * FROM Atores WHERE FilmeId = 2
SELECT * FROM Atores WHERE FilmeId = 3
SELECT * FROM Atores WHERE FilmeId = 4
SELECT * FROM Atores WHERE FilmeId = 5
….

Ou seja, você terá um SELECT para Filmes e, então, N SELECTs adicionais para os atores.

Dessa forma, sua aplicação irá consultar o banco de dados N+1 vezes e isso vai degradar o desempenho da sua aplicação de forma drástica tanto quanto maior for o número de consultas. Esse é o famoso problema SELECT N +1 causado pelo Lazy Loading.

Imagine um cenário mais complexo com muitos relacionamentos e muitas consultas. É de arrepiar, não é mesmo?

Como evitar esse problema no Entity Framework?

Uma das formas de evitar esse problema no Entity Framework é usar o método Include e não usar o Lazy Loading. O método Include realiza o Eager Load na consulta, que é o mecanismo pelo qual uma associação, coleção ou atributo é carregado imediatamente quando o objeto principal é carregado.

Dessa forma, o código corrigido ficaria assim:

static void Main(string[] args)
   {
            using (var ctx = new DBContexto())
            {
                foreach (var filme in ctx.Filmes.Include("Atores"))
                {
                    foreach(var ator in ctx.Atores)
                    {
                        Console.WriteLine(" {0} : {1} ", filme.Titulo, ator.Nome);
                    }
                }
        }
 }

Este código agora usa o método Include para carregar todos os atores para cada filme e será gerado apenas uma consulta SQL contra o banco de dados.

Isso resolve o problema, mas você deve ficar atento ao usar o método Include, visto que ele gera consultas SQL fazendo um JOIN entre todas as tabelas que você deseja retornar – o que também pode afetar o desempenho.

Assim, antes de usar esse artifício, você tem que verificar quais dos dois caminhos afeta menos o desempenho da sua aplicação.

Você pode desabilitar o recurso Lazy Loading definindo a propriedade Configuration.LazyLoadingEnabled, assim como a false no construtor da sua classeDbContext.

No nosso exemplo podemos usar a instância do contexto para desabilitar o Lazy Loading: ctx.Configuration.LazyLoadingEnabled = false;

Para concluir, ficam aqui dois conselhos:

  1. Desabilite o Lazy Loading e verifique o desempenho usando Include (muito recomendado para aplicações web);
  2. Para retornar uma quantidade limitada de dados utilize consultas projeção;

Até o próximo artigo.

ASP .NET – Single Page Application(SPA) usando AngularJS com Web API – Parte 06

$
0
0

Neste artigo eu vou mostrar como criar uma aplicação ASP .NET Single Page Application usando os recursos do AngularJS com Web API: criando um serviço.

Na quinta parte do artigo criamos o serviço definido em filmeService de forma que encapsulasse as funcionalidades da nossa Web API representada pelo controller FilmeController.

Neste artigo, vamos implementar as funcionalidades para deletar, editar e criar filmes em nossa aplicação SPA.

Recursos usados:

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

Deletando filmes

Agora vamos permitir que o usuário possa deletar um filme em nossa aplicação. Para isso, abra a solução Filmoteca, criada no artigo anterior no VS Community 2015 (Open Project). Depois abra o arquivo lista.html e inclua a linha de código para incluir um botão de comando, conforme o código a seguir:

<div ng-controller="listaController">
    <table class="table">
        <tr>
            <th>Título</th>
        </tr>
        <tr ng-repeat="filme in filmes">
            <td>{{filme.Titulo}}</td>
            <td>
                <a class="btn btn-primary" href="#/detalhes/{{filme.Id}}">Detalhes</a>
                <button class="btn btn-danger" ng-click="deleta(filme)">Deletar</button>
            </td>
        </tr>
    </table>
</div>

Nossa view lista.html está usando alguns recursos do bootstrap para definir estilos para o button Deletar e para o link Detalhes.

Nesta view, incluímos um button HTML onde temos uma diretiva ng-click que aciona a function deleta(filme), passando o filme associado.

Precisamos, então, alterar o código do controller listaController incluindo a function deleta(filme) conforme mostra o código a seguir:

(function (app) {
    var listaController = function ($scope, filmeService)
    {
        filmeService
            .getFilmes()
            .success(function (data) {
            $scope.filmes = data;
            });
        $scope.deleta = function (filme) {
            filmeService.deletar(filme)
            .success(function () {
                removerFilmePorId(filme.Id);
            });
        };
        var removerFilmePorId = function (id) {
            for (var i = 0; i < $scope.filmes.length; i++) {
                if ($scope.filmes[i].Id == id) {
                    $scope.filmes.splice(i, 1);
                    break;
                }
            }
        };
    };
    app.controller("listaController", listaController)
}(angular.module("filmoteca")));

Temos agora duas novas functions no controller listaController. A primeira é a function deleta anexado ao objeto $scope e, por isso mesmo, este método é chamado pela diretiva ng-click que usa o serviço filmeService para deletar o filme.

Quando a chamada é feita com sucesso, é feito uma chamada à function removerFilmePorId(), que não está associada ao objeto $scope e, por isso, é uma implementação privada dentro do controlador. Esta function localiza e deleta o filme pelo seu id no modelo e o remove do array dos filmes.

Abaixo vemos a aparência da view lista.html:

asp_spaa611

Editando e criando filmes

Vamos agora implementar a edição e a criação de um novo filme. Podemos fazer isso de diversas formas e neste exemplo vamos adotar a seguinte abordagem:

  • No arquivo lista.html, que exibe a lista de filmes e o botões – Detalhes e Deletar – vamos incluir um novo botão – Novo Filme – e vincular a esse botão uma diretiva ng-click que chama uma function criar();
  • Vamos criar, então, um novo arquivo HTML, chamado edita.html, que vai funcionar como um formulário para criar um novo filme e para editar um filme existente. Este arquivo funciona como uma partial view e deverá ser incluído na view lista.html e também na viewdetalhes.html usando a diretiva ng-include.

Dessa forma, a view edita.html vai compartilhar a funcionalidade de incluir um filme e editar um filme.

Clique com o botão direito do mouse na pasta Html e, a seguir, em Add -> New Item e selecione o template HTML page e informe o nomeedita.html. A seguir, inclua o código abaixo nesta view:

<div ng-controller="editaController">
    <form ng-show="isEditavel()">
        <fieldset>
            <div class="form-group">
                <label for="titulo">
                    Titulo
                </label>
                <input id="titulo" type="text" ng-model="editar.filme.Titulo" required class="form-control" />
            </div>
            <div class="form-group">
                <label for="anoLancamento">
                    Ano de Lançamento
                </label>
                <input id="anoLancamento" type="number" ng-model="editar.filme.AnoLancamento" required min="1900" max="2050" class="form-control" />
            </div>
            <div class="form-group">
                <label for="duracao">
                    Duração
                </label>
                <input id="duracao" type="number" ng-model="editar.filme.Duracao" required min="10" max="500" class="form-control" />
            </div>
            <button class="btn btn-primary" ng-click="salvar()">Salvar</button>
            <button class="btn btn-danger" ng-click="cancelar()">Cancelar</button>
        </fieldset>
    </form>
</div>

É muito importante entender esta view :

  • Nesta view, usamos a diretiva ng-controller=”editaController”, que indica que o controlador editaController é responsável pelas functions usadas nesta view. Como este controlador ainda não existe, vamos ter que criá-lo posteriormente;
  • A diretiva ng-show é usada para ocultar ou mostrar uma seção do DOM baseado na expressão usada: ng-show=”isEditavel()” que deve retornar true ou false; Neste caso, o elemento form somente será exibido quando a function isEditavel() retornar true a partir do model; Estamos usando esta diretiva para ocultar o formulário, exibindo-o somente para criar ou editar um novo filme;
  • A diretiva ng-model define o two-way-binding entre o model e os elementos do formulário (textarea, select, input, etc); No formulário, definimos as seguintes diretivas ng-model:
  1. ng-model=”editar.filme.Titulo”
  2. ng-model=”editar.filme.AnoLancamento”
  3. ng-model=”editar.filme.Duracao”

Fazendo assim, criamos essas propriedades no objeto $scope e permitimos que elas sejam acessadas pelo controlador editaController que iremos criar.

Perceba que o objetivo das diretivas é fazer a vinculação entre o model e a view. O model (ou controller) nunca manipula diretamente os elementos DOM; quem faz isso são as diretivas. Fazendo uma alteração no model ela se reflete na view.

Vamos, então, alterar a view lista.html incluindo o botão para criar um novo filme e usar a diretiva ng-include para incluir a view edita.html:

<div ng-controller="listaController">
    <table class="table">
        <tr>
            <th>Título</th>
        </tr>
        <tr ng-repeat="filme in filmes">
            <td>{{filme.Titulo}}</td>
            <td>
                <a class="btn btn-primary" href="#/detalhes/{{filme.Id}}">Detalhes</a>
                <button class="btn btn-danger" ng-click="deleta(filme)">Deletar</button>
            </td>
        </tr>
    </table>
   <button class="btn btn-success" ng-click="criar()">Novo Filme</button>
   <div ng-include="'/Cliente/Html/edita.html'"></div>
</div>

Agora a view lista.html pode invocar o método criar() que será definido no model.

A diretiva ng-include faz a inclusão da view edita.html nesta view, exibindo o formulário para o usuário digitar as informações do novo livro.

Observe que usamos aspas simples(”) no interior da diretiva para chamar a página edita.html, assim asseguramos que o caminho informado será reconhecido como um literal string.

A function criar() definida deverá ser criada no controlador listaController, que é responsável por esta view. Altere o arquivolistaController.js incluindo a function criar():

(function (app) {
    var listaController = function ($scope, filmeService)
    {
        filmeService
            .getFilmes()
            .success(function (data) {
            $scope.filmes = data;
            });
        $scope.criar = function () {
            $scope.editar = {
                filme: {
                    Titulo: "",
                    Duracao: 0,
                    AnoLancamento: new Date().getFullYear()
                }
            };
        };
        $scope.deleta = function (filme) {
            filmeService.deletar(filme)
            .success(function () {
                removerFilmePorId(filme.Id);
            });
        };
        var removerFilmePorId = function (id) {
            for (var i = 0; i < $scope.filmes.length; i++) {
                if ($scope.filmes[i].Id == id) {
                    $scope.filmes.splice(i, 1);
                    break;
                }
            }
        };
    };
    app.controller("listaController", listaController)
}(angular.module("filmoteca")));

Da mesma forma, vamos alterar a view detalhes.html para incluir um botão de comando vinculado a diretiva ng-click para editar os dados e outro para retornar para a lista. Vamos usar também a diretiva ng-include para incluir a view edita.html na view detalhes para exibir o formulário para editar os dados. Abaixo temos o código da view detalhes.html alterado:

<div ng-controller="detalhesController">
    <h2>
       Filme :  {{filme.Titulo}}
    </h2>
    <div>
       <h3> Lançamento em : {{filme.AnoLancamento}} </h3>
    </div>
    <div>
       <h3>{{filme.Duracao}} minutos de duração.</h3>
    </div>
    <a class="btn btn-primary" ng-click="editar()">Editar</>
    <a class="btn btn-success" href="#/">Retorna</a>
    <div ng-include="'/Cliente/Html/edita.html'"></div>
</div>

Para concluir esta parte do artigo, vamos definir a function editar() no controlador detalhesController, conforme mostra o código a seguir:

(function (app) {
    var detalhesController = function ($scope, $routeParams, filmeService) {
        var id = $routeParams.id;
        filmeService
            .getFilmePorId(id)
            .success(function (data) {
                $scope.filme = data;
            });
        $scope.editar = function () {
            $scope.editar.filme = angular.copy($scope.filme);
        };
    };
        app.controller("detalhesController", detalhesController);
}(angular.module("filmoteca")));

A função editar() apenas faz uma cópia do filme selecionado no escopo para a propriedade filme, atualizando a view e exibindo os dados do filme selecionado para edição.

Executando o projeto agora, teremos o seguinte resultado:

1. A página inicial exibindo a view lista.html:

asp_spaa612

2. A exibição da view detalhes.html quando o usuário clica no botão Detalhes:

asp_spaa614

3. A exibição do formulário representado pela view edita.html, exibindo os dados do filme selecionado quando o usuário clica no botão Editar:

asp_spaa615

4. A exibição do formulário representado pela view edita.html quando o usuário clica no botão Novo Filme:

asp_spaa613

Na próxima parte do artigo, vamos implementar as funcionalidades do controlador editaController e definir as functions para criar um novo filme e alterar dados do filme selecionado.


ASP .NET MVC 5 – 10 boas práticas que fazem a diferença

$
0
0

O framework ASP .NET MVC evoluiu muito desde a sua primeira versão, e agora em sua versão 5 (embora a ASP .NET 5 já tenha sido liberada juntamente com o Visual Studio 2015), temos um framework robusto que permite desenvolver aplicações dinâmicas robustas.

Saber usar de maneira correta esta ferramenta é o grande diferencial. E neste artigo eu vou mostrar 10 boas práticas que colaboram para que suas aplicações realmente façam a diferença.

1. Não utilize o código gerado (demo) em uma aplicação de produção

Delete o controlador AccountController e suas respectivas views da sua aplicação ASP .NET MVC imediatamente. Afinal, é quase certo que você não irá usá-lo e, neste caso, por que manter código de demonstração em uma aplicação de produção?

2. Isole os seus controladores do mundo exterior

Evite criar seus controladores com dependências de HttpContext, classes de acesso a dados, de log, de configuração. Essa abordagem torna a aplicação difícil de testar, de evoluir e de modificar.

3. Use um container IoC

Utilize um Container IoC para gerenciar todas as dependências externas.

O padrão IoC nos diz que “devemos delegar a tarefa de criação de um objeto (classe Pedido) a uma outra entidade, como uma outra classe, interface, componente etc de forma a termos um baixo acoplamento e minimizar a dependências entre os objetos”.

A seguir, uma lista dos principais Containers IoC para a plataforma .NET:

  • Castle Windsor
  • StructureMap
  • Spring.NET
  • Autofac
  • Unity
  • Puzzle.NFactory
  • Ninject
  • S2Container.NET
  • PicoContainer.NET
  • LinFu

A maneira de implementar a inversão de controle chama-se injeção de dependência (DI), que nos trás os seguintes benefícios:

  • Elimina o forte acoplamento entre objetos;
  • Torna a aplicação e o objeto mais flexível;
  • Facilita a criação de objetos fracamente acoplados;
  • Facilita a criação de testes unitários;
  • Em suma, a DI isola a implementação de um objeto da construção do objeto do qual ele depende.

4. Evite utilizar strings mágicas

Existem duas definições diferentes para strings mágicas, mas podemos dizer que ambas constituem antipadrões de projeto. Nas duas definições, as strings mágicas fazem o mesmo nebuloso uso de caracteres ou sequências de caracteres como numa outra inadequada prática de programação que inclui “números mágicos” no código-fonte sem sua definição explícita ou fácil entendimento do motivo daquele valor. A diferença delas se dá na forma de utilização das strings mágicas.

A primeira definição, que pode ser encontrada com o título de “Magic Strings”, trata as strings mágicas como uma constante literal no código fonte que dispara uma funcionalidade escondida (Easter Eggs, por exemplo) ao ser informada pelo usuário. Por exemplo, em um formulário, um usuário digita uma certa string em um campo específico e esta dispara um comportamento inesperado do sistema realmente parecendo ser mágica.

Dessa forma, evite usar declarações como ViewData[“Key”]. Ao invés disso, crie um ViewModel para cada View e utilize views fortemente tipadas.

As strings mágicas muitas vezes fazem com que a sua view falhe devido a um erro de digitação somente em tempo de execução. Usar um modelo fortemente tipado evita isso, pois você obtém um erro em tempo de compilação e ainda pode usar o Intellisense.

5. Não confunda o modelo de domínio com o modelo ViewModel

O modelo de domínio ou Domain Model, representa o domínio enquanto o ViewModel é projetado em torno das necessidades da View; estes dois mundos são diferentes.

Além disso, o Domin Model contém dados e comportamento, é hierárquico e feito de tipo complexos, enquanto que o ViewModel é apenas um DTO, feito de strings.

Saber usar o ViewModel de forma correta desacopla as suas Views do modelo de domínio.

Um ViewModel representa apenas os dados que você deseja exibir nas suas views. Por isso, usar o ViewModel desacopla o seu modelo de domínio de responsabilidades que é somente da view.

6. Empacote e minifique arquivos de estilos e de scripts

Muitos pedidos de uma única página HTML podem causar atrasos significativos e podem afetar as métricas globais do seu web site.

O empacotamento ou Bundling é o processo de agrupamento de recursos distintos: como arquivos CSS em um único recurso para download. Desta forma, vários arquivos CSS, logicamente distintos, podem ser baixados através de um único request HTTP.

Minification ou minificação, por outro lado, é o processo que remove todos os caracteres desnecessários com base em texto de recursos, sem alterar a funcionalidade esperada. A minificação encurta identificadores, funções de mudança de nome, remove comentários e caracteres de espaço em branco. Em geral, a minificação refere-se a remoção de tudo o que foi adicionado principalmente para fins de legibilidade.

Embora o empacotamento e minificação possam ser aplicados em conjunto, eles permanecem como processos independentes. Em um site de produção, geralmente não há nenhuma razão para não agrupar CSS e minificar arquivos de script.

7. Desabilite a validação da requisição

A validação do request é um recurso que previne que conteúdo malicioso e perigoso seja submetido.

Este recurso está habilitado por padrão. Porém, às vezes você pode precisar que sua aplicação poste tags HTML para o servidor e, neste caso, tem que desabilitar esse recurso:

[ValidateInput(false)]
[HttpPost]
public ActionResult Create([Bind(Exclude="Id")]Cliente cliObj)
{}

8. Ponha os seus dados no cache

Você pode aumentar o desempenho da sua aplicação colocado os dados no cache. E também pode colocar no cache páginas que não sofrem muita alteração.

 public class HomeController : Controller
 {
      [OutputCache(Duration=3600,VaryByParam="none")]
      public ActionResult Index()
       {}
 }

9. Use Data Annotations para realizar a validação

Você pode usar o namespace System.ComponentModel.DataAnnotations para fazer a validação do seu modelo do lado do servidor decorando com os atributos necessários:

public class Cliente
 {
     [Required(ErrorMessage="O nome do Cliente deve ser informado")]
     public string Nome { get; set; }
     // ...
  }

10. Utilize os recursos do Model Binding

O Model Binding é o processo de obtenção de objetos do modelo de entrada e saída dos controles, sem que você tenha que escrever um monte de código.

Quando os métodos são chamados, você não tem que escrever muito código para acessar os valores que foram postados de volta, em caso de atualização, inserção ou exclusão. Em vez disso, o modelo de ligação ou Model Binding permite ter as propriedades de um determinado objeto do modelo, automaticamente preenchida com os dados do postback.

Usando o model binding, os nomes dos elementos de entrada são utilizados para definir os valores das propriedades em uma instância da classe do modelo, que é então passado para o nosso método action POST.

O Model Binding é um recurso poderoso e personalizável que elimina o trabalho de lidar com solicitações HTTP, permitindo-nos trabalhar com objetos, em vez de lidar com valores Request.Form[] e Request.QueryString[].

Dessa forma, com o Model Binding é fácil criar e manter aplicações web com muitas informações. Quando você usa o Model Binding com os data templates dynamic, você pode rapidamente adicionar ou alterar propriedades em seu modelo de dados, e essas propriedades são corretamente renderizadas e processadas nos formulários web em todo o site.

Temos, assim, 10 dicas práticas e básicas que podem melhorar o desempenho de suas aplicações ASP .NET MVC.

Visual Basic 6 – Conexão com MySQL via ODBC – Parte 01

$
0
0

No artigo de  hoje, eu vou mostrar como realizar a conexão com o banco de dados MySQL usando um driver ODBC em uma aplicação Windows com a linguagem Visual Basic 6.

Open Database Connectivity (ODBC) é a interface estratégica da Microsoft para acessar dados em um ambiente heterogêneo de sistemas de gerenciamento de banco de dados relacionais e não relacionais. O ODBC fornece uma forma aberta e independente de terceiros para acessar dados armazenados em uma variedade fontes de dados e ambientes como desktop, minicomputador e até mainframe.

O ODBC dispensa a necessidade de você ter que usar drivers de fornecedores de software e de desenvolvedores corporativos e, assim, ter que aprender várias interfaces de programação de aplicativos. O ODBC agora fornece uma interface de acesso de dados universal. Com o ODBC, os desenvolvedores podem permitir que um aplicativo faça acesso concorrente, e visualize e modifique dados de múltiplas e diversas bases de dados.

Neste artigo, veremos como usar um driver ODBC para fazer a conexão com o banco de dados MySQL usando a linguagem Visual Basic 6 e os controles ADODC e DataGrid.

Recursos usados:

Definindo o banco de dados no MySQL

Você precisa ter instalado o banco de dados MySQL e definir qual banco de dados deseja acessar.

Neste exemplo, eu vou acessar a tabela Customers do banco de dados Northwind. Esse banco de dados foi migrado do MS Access para o MySQL usando a ferramenta Access to MySQL (veja no link o guia passo a passo que mostra como fazer isso).

Abaixo, vemos a ferramenta MySQL WorkBench exibindo a tabela Customers do banco de dados Northwind no MySQL:

mysql1

Instalando o driver ODBC

Você precisa instalar um driver ODBC para o MySQL.

Acessa o link https://downloads.mysql.com/archives/c-odbc/ e faça o download do driver ODBC.

A seguir, instale o driver ODBC no seu computador local.

Criando a fonte de dados ODBC

Agora, no Painel de controle do Windows, em Ferramentas Administrativas, clique em Configurar Fonte de dados ODBC 32 bits.

mysql2

Na janela Administrador de Fonte de dados ODBC, guia DSN de Usuário, clique no botão Adicionar.

mysql3

Selecione o driver ODBC para o MySQL e clique no botão Concluir:

mysql4

Defina, a seguir, as informações para:

  • Data Source – MySQL_DNS_32
  • Description – sua_descrição
  • TCP/IP Server – localhost
  • Port – 3306
  • User – use o seu usuário
  • Password – sua_senha
  • DataBase – Northwind

Conforme mostra a figura abaixo (você deve alterar esses valores para se adequar ao seu ambiente):

mysql5

Após concluir, clique no botão Test para verificar se a conexão esta ok. Nossa fonte de dados será identificada pelo nome MySQL_DNS_32.

Pronto! Já temos a nossa fonte de dados ODBC de usuário criada.

Na próxima parte do artigo, vamos criar o projeto no Visual Basic 6 e acessar a tabela Customers do banco de dados Northwind usando o ODBC.

Mensagem do anunciante:

Conheça a Umbler, startup de Cloud Hosting por demanda feita para agências e desenvolvedores. Experimente grátis!

ASP .NET – O compilador Roslyn (csc.exe e vbc.exe ) e a hospedagem compartilhada

$
0
0

Neste artigo, vou comentar sobre o Roslyn, o novo compilador da plataforma .NET e sua utilização em projetos web criados no .NET 4.5.

A compilação Roslyn agora é padrão a partir da versão 4.5 da plataforma .NET, e isso significa que se você criar qualquer aplicação web, Web Forms ou MVC, você terá o compilador Roslyn pré-instalado em seu projeto na pasta bin dentro da pasta Roslyn:

net_rosl11

Porque usar a compilação Roslyn ?

Ao usar a compilação Roslyn, você tem acesso a muitos recursos durante o desenvolvimento do seu aplicativo e também durante a implantação no servidor.

Apenas para citar algumas das vantagens:

  • Durante o desenvolvimento da aplicação

Antes do Roslyn, quando você fazia qualquer alteração no seu código (C#. VB .NET), era preciso realizar um build para ver o resultado no navegador. Com o Rosyln isso não é mais necessário.

  • Durante a implantação no servidor

Ao desenvolver uma aplicação Web, escrevemos código C# e HTML mesclados nas páginas ASPX ou nas views MVC e isso requer algum tipo de compilação para exibir o resultado ao usuário, afetando o tempo de carregamento da página. Dessa forma, usando o Roslyn, essa compilação não será necessária e o tempo de carga da página vai melhorar.

Assim, só por esses dois benefícios já valeria a pena usar o Roslyn. Existem mais recursos que o Roslyn possui e eu não citei aqui.

O problema do Roslyn em hospedagem compartilhada

Se você está tentando publicar sua aplicação com o Roslyn em hospedagem compartilhada, você pode ter problemas.

Quando vamos fazer a implantação de uma aplicação no servidor, ela é executada no modo Full Trust (confiança total), e, empresas de hospedagem compartilhadas não permitem que aplicativos executem no modo Full Trust. Em geral, elas substituem o Full Trust por Medium Trust devido a restrições de segurança, visto que elas hospedam sites de diversos clientes e, assim, evitam que uma aplicação web de um cliente afete a aplicação de outro cliente.

A compilação Roslyn só vai funcionar em modo Full Trust e, dessa forma, em ambientes compartilhados, você terá problemas se a sua hospedagem não permitir esse modo.

Se a hospedagem compartilhada não der suporte ao modo Full Trust, você não poderá implantar a sua aplicação usando o Roslyn.

O que fazer agora?

Como implantar a sua aplicação web sem o Roslyn em servidores compartilhados?

Felizmente você pode implantar a sua aplicação sem o Roslyn e não precisa fazer nenhuma mudança no código.

Abra a janela do Gerenciador de pacotes NuGet e desinstale os pacotes:

  • “Microsoft.CodeDom.Providers.DotNetCompilerPlatform”
  • “Microsoft.Net.Compilers”

Esta desinstalação também vai remover a configuração CodeDom do arquivo web.config e isso vai resolver o problema.

E estamos conversados!

Não cometa esses erros ao utilizar o Entity Framework

$
0
0

Neste artigo vou mostrar alguns dos erros mais comuns cometidos ao se usar o Entity Framework, que é uma poderosa ferramenta ORM, que auxilia o desenvolvimento de aplicações com acesso a dados realizando o mapeamento objeto Relacional.

Como está integrado à plataforma .NET, usar o Entity Framework é muito fácil e simples, bastando mesmo alguns cliques de mouses para mapear as suas tabelas para entidades. Mas nem tudo é tão simples como parece. Existem algumas considerações e práticas que devem ser seguidas para obter um melhor rendimento e desempenho da ferramenta.

Em um outro artigo, eu apresentei dez dicas que permitem melhorar o desempenho do Entity Framework. Hoje eu apresento cinco erros muito comuns cometidos ao se usar o Entity Framework.

Verifique se você está cometendo alguns deles:

1. Está instanciado o DbContext muitas vezes?

Além disso, essa prática afeta a utilização do recurso de Cache do Entity Framework e isso se reflete no desempenho da sua aplicação. Você sabia que existe uma sobrecarga a cada vez que você instancia o objeto DbContext?

Se você está usando o Entity Framework em uma aplicação ASP  .NET MVC, é melhor usar uma única instância do DbContext por toda a duração do Request.

Solução:

  • Mantenha a mesma instância DbContext o máximo que puder.
  • Em uma aplicação ASP .NET MVC, utilize um container IoC para injetar uma única instância que exista por toda a duração do Request.

2. Está rastreando suas entidades quando não precisa disso?

Sempre que uma consulta é executada, as entidades são carregadas no rastreador de estado dos objetos. Isso é feito para rastrear quais alterações foram feitas no modelo de entidades durante a vida do contexto, de forma que uma chamada ao método SaveChanges irá realizar as consultas SQL requeridas no banco de dados. Quando consultamos entidades usando o entity framework, ele guarda as entidades no contexto, realizando o que é conhecido como tracking (rastreamento) das entidades. Ele faz isso para acompanhar o estado das entidades.

Esse é um recurso poderoso, mas ele adiciona uma sobrecarga considerável e que afeta o desempenho das consultas que são rastreadas. As consultas que não são rastreadas têm um desempenho melhor. Uma solução para isso é usar o método AsNoTracking.

O método de extensão AsNoTracking() retorna uma nova consulta e as entidades retornadas não serão armazenadas em cache pelo contexto (DbContext). Isto significa que o Entity Framework não efetua qualquer processamento ou armazenamento adicional das entidades que são devolvidos pela consulta.

Utilizar o AsNoTracking significa que as entidades serão lidas da origem de dados, mas não serão mantidas no contexto.

Nota: Não podemos atualizar estas entidades sem anexá-las ao contexto.

Solução:

  • Use o método AsNoTracking para consultas que são somente leitura.

Exemplo:

using(Entities context = new Entities())  
{  
    var funcionario = context.Funcionarios.AsNoTracking().ToList();  
}

3. Está tendo o problema Select N + 1 em suas consultas?

O EF usa, por padrão, o lazy loading; isso se você tiver definido os relacionamentos entre as suas entidades usando a palavra-chave virtual. Isto significa que os objetos relacionados não serão carregados até que eles sejam acessados pela primeira vez.

Isso parece bom à primeira vista, mas pode diminuir o desempenho das suas consultas porque realiza mais idas e vindas no banco de dados, podendo causar o problema conhecido como Select N+1 degradando a sua aplicação. Você pode impedir isso desabilitando o lazy loading.

Para mais detalhes leia aqui.

Solução:

  • Desabilite o Lazy Loading. Exemplo:
    this.configuration.ladzyloadingenabled = false;
  • Utilize o Eager Loading através do método Include. Exemplo:
using (var context = new BloggingContext()) 
{ 
    //Carrega todos os blogs e posts relacionados
      var blogs = context.Blogs 
                          .Include(b => b.Posts) 
                         .ToList(); 
}

4. Está incluindo mais campos do que precisa em suas consultas?

Às vezes, você só precisa exibir um subconjunto de dados a partir de uma entidade. Quando este for o caso, não faz sentido carregar a entidade completa do banco de dados.

Por exemplo, ao listar os clientes que você pode editar ou apagar, você não precisa carregar os campos com detalhes de endereço ou dados pessoais do cliente.

As consultas de projeção permitem que você selecione alguns campos de uma tabela de banco de dados, projetando os dados em uma entidade mais pequena.

Solução:

  • Utilize consultas projeção e restrinja os campos obtidos aos estritamente necessários.

Exemplo:

var _cliente =  (from cli in db.Clientes
                          select new {
                                cliente. Codigo,
                                cliente.Nome
                           }). ToList (); 
ao invés de :
var _cliente =  (from cli in db.Clientes
                       select cli).ToList();

5. Está executando consultas que retornam muitos resultados?

Dê uma olhada nas consultas abaixo. O que elas têm de errado?

 contexto.Posts.ToList().Where(post => post.Ativo);

  contexto.Posts.Where(post => post.Ativo).ToList();

Percebeu que elas retornam muitos resultados.

  1. A primeira consulta irá carregar todos os posts porque o método ToList() foi chamado antes do método Where;
  2. A segunda consulta vai carregar menos resultados, mas mesmo assim vai carregar mais resultados do que o esperado, pois não houve uma limitação na quantidade de posts ativados a serem retornados;

Solução:

  • Realize um filtro nas consultas antes de chamar o método ToList().
  • Limite a quantidade de resultados retornados realizando a paginação do resultado através de um método de extensão. (Na ASP .NET MVC temos o PagedList).

Exemplo:

using (UnitOfWork uow = new UnitOfWork())
            {
                IEnumerable<Blog> blogs = uow.BlogRepositorio.GetTudo();
                blogs = blogs.OrderByDescending(blog => blog.AtualizadoEm);
                IEnumerable<BlogResumoModel> lista = from blog in blogs
                                                     select new BlogResumoModel
                                                     {
                                                         Id = blog.BlogId,
                                                         Titulo = blog.Titulo,
                                                         Resumo = blog.Corpo.Length > 200 ? blog.Corpo.Substring(0, 200) : blog.Corpo,
                                                         NomeAutor = blog.Usuario.NomeUsuario,
                                                         ComentariosQuantidade = blog.Comentarios.Count(),
                                                         CriadoEm = blog.CriadoEm,
                                                         AtualizadoEm = blog.AtualizadoEm
                                                     };
                return View(lista.ToList().ToPagedList(pagina ?? 1, 2));
            }

Temos, assim, 5 dicas práticas que podem melhorar o desempenho de suas consultas com o Entity Framework.

Bom proveito!

ASP .NET – Single Page Application(SPA) usando AngularJS com Web API – Parte 07

$
0
0

Neste artigo eu mostrar como criar uma aplicação ASP .NET Single Page Application usando os recursos do AngularJS com Web API: Criando um serviço.

Na sexta parte do artigo implementamos as funcionalidades para deletar filmes, criamos a view edita.html que permitirá editar e criar um novo filme e alteramos os controladores listaController e detalhesController, incluindo as functions deletar e editar.

Hoje vamos criar o controlador editaController e implementar as functions isEditavel(), cancelar, salvar, atualizaFilme e criaFilme que já foram definidas.

Recursos usados:

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

Criando o controlador editaController e implementando as funcionalidades para crira e editar filmes

Abra a solução Filmoteca criada no artigo anterior no VS Community 2015 (Open Project).

Clique com o botão direito do mouse na pasta Angular/js e, a seguir, em Add -> New Item e selecione o template JavaScript File. Depois informe o nome editaController.js.

A seguir inclua o código abaixo neste arquivo:

(function (app) {
var editaController = function ($scope, filmeService) {

    $scope.isEditavel = function () {
        return $scope.editar && $scope.editar.filme;
    };
    $scope.cancelar = function () {
        $scope.editar.filme = null;
    };
    $scope.salvar = function () {
        if ($scope.editar.filme.Id) {
            atualizaFilme();
        } else {
            criaFilme();
        }
    };
    var atualizaFilme = function () {
        filmeService.atualizar($scope.editar.filme)
        .success(function() {
            angular.extend($scope.filme , $scope.editar.filme);
            $scope.editar.filme = null;
        });
    };
    var criaFilme = function () {
        filmeService.criar($scope.editar.filme)
        .success(function(filme) {
            $scope.filmes.push(filme);
            $scope.editar.filme = null;
        });
    };
  };
app.controller("editaController", editaController);
}(angular.module("filmoteca")));

No código deste controller temos que:

  1. As functions isEditavel, cancelar e salvar estão definidas no $scope e são acionadas pelas diretivas ng-click nas respectivas views. As functions atualizaFilme e criaFilme não estão vinculadas ao $scope e são chamadas dentro do controller;
  2. A propriedade  $scope.isEditavel ativa a exibição da view edita.html, retornado true quando a propriedade editar.filme está disponível no $scope e exibe a view para editar o filme.

O objeto $scope em um controller herda do objeto $scope em um controller pai. Como o controller editaController está aninhado no interior da listaController e detalhesController, ele pode ler todas as propriedades do $scope no controller pai.

O controlador editaController usa este comportamento para incluir um novo filme no array de filmes quando cria um novo filme e copia as propriedades quando está atualizando (via angular.extend).

Nota: angular.extend é usado em um cenário quando você quer copiar um objeto para outro objeto. Ex: angular.extend(destination, src1, src2 …). Podemos também usar angular.copy() mas ele é mais lento.

Feito isso, basta incluir a referência ao novo controlador editaController.js no arquivo Index.html conforme abaixo:

<div class="well">
    <h4>Macoratti .net</h4>
</div>
<div ng-app="filmoteca">
    <ng-view></ng-view>
</div>
@section scripts
{
    <script src="~/Scripts/angular.js"></script>
    <script src="~/Scripts/angular-route.js"></script>
    <script src="~/AngularApp/js/filmoteca.js"></script>
    <script src="~/AngularApp/js/filmeService.js"></script>
    <script src="~/AngularApp/js/listaController.js"></script>
    <script src="~/AngularApp/js/detalhesController.js"></script>
    <script src="~/AngularApp/js/editaController.js"></script>
}

Agora é só alegria!

Já temos nossa aplicação com todas as funcionalidades implementadas e vamos testar:

1. Incluindo um novo filme:

asp_spaaj72 asp_spaaj71

asp_spaaj72

2. Alterando um filme existente:

asp_spaaj73

asp_spaaj74

Se você acompanhou a série de artigos até aqui, então, parabéns! Você concluiu a criação da sua aplicação Single Page Application usando oASP .NET, o Angular e o Entity Framework.

Pegue o projeto aqui: FilmotecaFinal.zip

Viewing all 293 articles
Browse latest View live