ASP .NET - Model Binding com Web Forms - Criando uma camada de Negócios - VI (final)


Na quinta parte desta série de tutoriais vimos como passar um valor em uma query string e usar o valor para retornar os dados através do model binding

Neste tutorial veremos como usar o model binding com uma camada de negócios ou business logic layer (BLL) onde iremos definir o membro OnCallingDataMethods para especificar que um objeto diferente da página atual é usado para chamar os métodos de dados.

Você já deve saber que uma aplicação em n-camadas possui no mínimo 3 camadas lógicas :
  1. Camada de acesso aos dados - DAL - Data Access Layer
  2. Camada da lógica de negócios - BLL - Business Logic Layer
  3. Camada de apresentação  - UI - User Interface

As vezes a camada de dados e a camada de negócios estão presentes na mesma camada em algumas aplicações .

A camada de dados é responsável pela conexão com a fonte de dados.

A camada de negócios é responsável por retornar , incluir , modificar e excluir os dados da camada de dados além de repassar os dados da camada de dados para a camada de apresentação.

A camada de apresentação apenas exibe os dados.

A camada de apresentação interage com a camada de negócios mas não com a de dados. Desta forma existe um nível de abstração entre as camadas. Isto torna possível alterar ou atualizar uma camada sem ter que interferir com a outra camada.

O Model Binding permite colocar o código da interação com os dados ou no arquivo code-behind para uma página web ou em um classe de negócios separada. Nos tutoriais anteriores mostramos como usar os arquivos code-behind para definir o código para interagir com os dados. Essa abordagem funciona para sites pequenos mas pode se tornar difícil de manter e testar para projetos mais complexos.

Para centralizar o código de interação com os dados vamos criar uma camada de lógica de negócios que irá conter toda a lógica de interação com os dados. Vamos então chamar a camada de negócios a partir das páginas webs. Este tutorial mostra como mover todo o código que escrevemos anteriormente para uma camada de negócios e então usar este código a partir das páginas web.

Vamos continuar usando o projeto criado na primeira parte do tutorial : Escola_Macoratti

Neste tutorial você vai aprender a:

Recursos usados neste tutorial:

Criando uma camada de lógica de negócios (BLL)

Vamos agora criar a classe que será chamada a partir das páginas webs. Os métodos nesta classe serão parecidos com os métodos que usamos anteriormente apenas os nomes serão trocados. Vamos iniciar criando uma nova pasta no projeto.

Abra a solução Escola_Macoratti criada na primeira parte deste artigo.

Clique com o botão direito do mouse sobre o nome do projeto e selecione Add -> New Folder e Informe o nome BLL;

Ao final teremos criado a pasta BLL no projeto:

Vamos agora criar na pasta BLL uma nova classe chamada EscolaBLL.vb que irá conter todo o código das operações com os dados que antes residiam nos arquivos code-behind. Os métodos serão praticamente os mesmos com pequenos ajustes.

A alteração mais importante que iremos fazer é que não vamos precisar mais executar o código a partir de uma instância da classe Page. Esta classe contém o método TryUpdateModel e a propriedade ModelState. Quando o código é movido para a nossa camada de negócios (BLL) não vamos precisar ter uma instância da classe Page para chamar esses membros.

Para contornar isso precisaremos adicionar um parâmetro ModelMethodContext para qualquer método que acessa TryUpdateModel ou ModelState. Usaremos este parâmetro para chamar TryUpdateModel ou retornar ModelState. Não vamos ter que mudar nada nas páginas web por conta este parâmetro.

Clique com o botão direito sobre a pasta BLL e a seguir clique em Add->Class;

Selecione o template Class e informe o nome EscolaBLL.vb;

A seguir digite o código abaixo neste arquivo:

Imports Escola_Macoratti.Macoratti.Models
Imports System.Data.Entity.Infrastructure
Imports System.Web.ModelBinding
Imports System.Linq
Imports System.Data.Entity

Public Class EscolaBLL
    Implements IDisposable

    Private db As EscolaContext = New EscolaContext()

    Public Function GetDados(<Control> ByVal ExibirAno As Nullable(Of AnoAcademico)) As IQueryable(Of Aluno)
        Dim consulta = db.Alunos.Include(Function(s) s.Matriculas.Select(Function(e) e.Curso))
        If Not ExibirAno Is Nothing Then
            consulta = consulta.Where(Function(s) s.Ano = ExibirAno)
        End If
        Return consulta
    End Function


    Public Sub InserirAluno(context As ModelMethodContext)
        Dim item = New Aluno()
        context.TryUpdateModel(item)
        If context.ModelState.IsValid Then
            db.Alunos.Add(item)
            db.SaveChanges()
        End If
    End Sub

    Public Sub Deletaluno(ByVal _alunoID As Integer, context As ModelMethodContext)
        Dim item As Aluno = New Aluno() With {.AlunoID = _alunoID}
        db.Entry(item).State = System.Data.EntityState.Deleted
        Try
            db.SaveChanges()
        Catch ex As DbUpdateConcurrencyException
            context.ModelState.AddModelError("", String.Format("O item com ID =  {0} não existe no banco de dados.", _alunoID))
        End Try
    End Sub


    Public Sub AtualizaAluno(ByVal _alunoID As Integer, context As ModelMethodContext)
        Dim item As Aluno = Nothing
        item = db.Alunos.Find(_alunoID)
        If item Is Nothing Then
            context.ModelState.AddModelError("", String.Format("Item com id {0} não foi encontrado", _alunoID))
            Return
        End If
        context.TryUpdateModel(item)
        If context.ModelState.IsValid Then
            db.SaveChanges()
        End If
    End Sub

    Public Function GetCursos(<QueryString> _alunoID As Nullable(Of Integer)) As IQueryable(Of Matricula)
        Dim query = db.Matriculas.Include(Function(e) e.Curso) _
                .Where(Function(e) e.AlunoID = _alunoID)
        Return query
    End Function

    Private disposedValue As Boolean
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                db.Dispose()
            End If
        End If
        Me.disposedValue = True
    End Sub
    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

End Class

Neste código temos a classe EscolaBLL que implementa a interface IDisposable. Nesta classe definimos os métodos:

Nestes métodos o código foi movido dos arquivos code-behind como veremos a seguir.

Revisar as páginas para retornar dados da camada de negócios

Agora que já temos a nossa camada de negócio e a classe com os métodos para acesso aos dados vamos converter as páginas Alunos.aspx, Cursos.aspx e IncluirAluno.aspx de forma a que elas passem a acessar os dados a partir da camada de negócios.

Assim nos arquivos citados vamos comentar ou deletar os métodos que faziam o acesso aos dados. Delete ou comente os seguintes métodos destes arquivos:

Após realizar essa tarefa não teremos mais código nos arquivos code-behind que acessam os dados.

O tratamento do evento OnCallingDataMethods permite especificar um objeto para usar com os métodos dos dados. Abra o arquivo Alunos.aspx no modo Source e no controle GridView vamos alterar os nomes para os métodos de dados usando os nomes definidos na classe EscolaBLL da camada de negócios.

......
   <asp:GridView runat="server" ID="alunosGrid"
        ItemType="Escola_Macoratti.Macoratti.Models.Aluno" DataKeyNames="AlunoID" 
        SelectMethod="GetDados" UpdateMethod="AtualizaAluno"
        DeleteMethod="DeletaAluno"
        OnCallingDataMethods="alunoGrid_CallingDataMethods"
        AutoGenerateEditButton="true" AutoGenerateDeleteButton="true" 
        AutoGenerateColumns="false" AllowPaging="True" AllowSorting="True" PageSize="5">
        <Columns>
   .....

No arquivo code-behind Alunos.aspx.vb vamos definir o evento alunoGrid_CallingDataMethods conforme o código abaixo:

Protected Sub alunoGrid_CallingDataMethods(ByVal sender As Object, ByVal e As CallingDataMethodsEventArgs)
   e.DataMethodsObject = New EscolaBLL
 End Sub

Neste tratamento de evento especificamos a classe da camada de negócios para as operações com dados.

Vamos realizar as mesmas alterações no arquivo IncluirAluno.aspx:

1- No arquivo IncluirAluno.aspx no modo Source definimos os nomes do novos métodos conforme abaixo:

2- No arquivo code-behind IncluirAluno.aspx.vb inclua o tratamento para o evento addAlunoForm_CallingDataMethods:

 Protected Sub addAlunoForm_CallingDataMethods(ByVal sender As Object, ByVal e As CallingDataMethodsEventArgs)
        e.DataMethodsObject = New EscolaBLL
    End Sub

Agora é a vez do arquivo Cursos.aspx

1- O arquivo Cursos.aspx no modo Source:

<%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/Site.Master" CodeBehind="Cursos.aspx.vb" Inherits="Escola_Macoratti.Cursos" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <asp:GridView runat="server" ID="cursosGrid"
        ItemType="Escola_Macoratti.Macoratti.Models.Matricula"
        SelectMethod="GetCursos" 
        OnCallingDataMethods="cursosGrid_CallingMethods"
        AutoGenerateColumns="false">
        <Columns>
.....

2 - O arquivo code-behind Cursos.aspx.vb :

    Protected Sub cursosGrid_CallingMethods(ByVal sender As Object, ByVal e As CallingDataMethodsEventArgs)
        e.DataMethodsObject = New EscolaBLL
    End Sub

Execute a aplicação e perceba que o todas as páginas funcionam da mesma forma que anteriormente e que a validação lógica também funciona corretamente. (Lembre-se de comentar o código de acesso aos dados nos arquivos code-behind)

E assim concluímos essa série de tutoriais sobre o recurso Model Binding agora presente no ASP .NET Web Forms.

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

Referências:


José Carlos Macoratti