Compartilhar via


Adicionar camada de lógica de negócios a um projeto que usa model binding e web forms

por Tom FitzMacken

Esta série de tutoriais demonstra aspectos básicos do uso da model binding com um projeto ASP.NET Web Forms. A model binding torna a interação de dados mais direta do que lidar com objetos de fonte de dados (como ObjectDataSource ou SqlDataSource). Esta série começa com material introdutório e passa para conceitos mais avançados em tutoriais posteriores.

Este tutorial mostra como usar a model binding com uma camada de lógica de negócios. Você definirá o membro OnCallingDataMethods para especificar que um objeto diferente da página atual seja usado para chamar os métodos de dados.

Este tutorial se baseia no projeto criado nas partes anteriores da série.

Você pode baixar o projeto completo em C# ou VB. O código para download funciona com o Visual Studio 2012 ou Visual Studio 2013. Ele usa o modelo do Visual Studio 2012, que é ligeiramente diferente do modelo Visual Studio 2013 mostrado neste tutorial.

O que você criará

A model binding permite que você coloque o código de interação de dados no arquivo code-behind de uma página da Web ou em uma classe de lógica de negócios separada. Os tutoriais anteriores mostraram como usar os arquivos code-behind para código de interação de dados. Essa abordagem funciona para sites pequenos, mas pode levar à repetição de código e a maior dificuldade ao manter um site grande. Também pode ser muito difícil testar programaticamente o código que reside em arquivos code-behind porque não há nenhuma camada de abstração.

Para centralizar o código de interação de dados, você pode criar uma camada lógica de negócios que contém toda a lógica para interagir com os dados. Em seguida, você chama a camada de lógica de negócios de suas páginas da Web. Este tutorial mostra como mover todo o código que você escreveu nos tutoriais anteriores para uma camada de lógica de negócios e, em seguida, usar esse código das páginas.

Neste tutorial, você aprenderá a:

  1. Mover o código de arquivos code-behind para uma camada de lógica de negócios
  2. Alterar os controles associados a dados para chamar os métodos na camada de lógica de negócios

Criar camada de lógica de negócios

Agora, você criará a classe que é chamada nas páginas da Web. Os métodos nessa classe são semelhantes aos métodos usados nos tutoriais anteriores e incluem os atributos de provedor de valor.

Primeiro, adicione uma nova pasta chamada BLL.

adicionar pasta

Na pasta BLL, crie uma nova classe chamada SchoolBL.cs. Ele conterá todas as operações de dados que residiam originalmente em arquivos code-behind. Os métodos são quase os mesmos que os métodos no arquivo code-behind, mas incluirão algumas alterações.

A alteração mais importante a ser observada é que você não está mais executando o código de dentro de uma instância da classe Page . A classe Page contém o método TryUpdateModel e a propriedade ModelState . Quando esse código é movido para uma camada de lógica de negócios, você não tem mais uma instância da classe Page para chamar esses membros. Para contornar esse problema, você deve adicionar um parâmetro ModelMethodContext a qualquer método que acesse TryUpdateModel ou ModelState. Use esse parâmetro ModelMethodContext para chamar TryUpdateModel ou recuperar ModelState. Você não precisa alterar nada na página da Web para considerar esse novo parâmetro.

Substitua o código em SchoolBL.cs pelo código a seguir.

using System;
using System.Linq;
using ContosoUniversityModelBinding.Models;
using System.Web.ModelBinding;
using System.Web.UI.WebControls;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;

namespace ContosoUniversityModelBinding.BLL
{
    public class SchoolBL : IDisposable
    {
        SchoolContext db = new SchoolContext();

        public IQueryable<Student> GetStudents([Control] AcademicYear? displayYear)
        {
            var query = db.Students.Include(s => s.Enrollments.Select(e => e.Course));

            if (displayYear != null)
            {
                query = query.Where(s => s.Year == displayYear);
            }

            return query;
        }

        public void InsertStudent(ModelMethodContext context)
        {
            var item = new Student();

            context.TryUpdateModel(item);
            if (context.ModelState.IsValid)
            {
                db.Students.Add(item);
                db.SaveChanges();
            }
        }

        public void DeleteStudent(int studentID, ModelMethodContext context)
        {
            var item = new Student { StudentID = studentID };
            db.Entry(item).State = EntityState.Deleted;
            try
            {
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException)
            {
                context.ModelState.AddModelError("",
                    String.Format("Item with id {0} no longer exists in the database.", studentID));
            }
        }

        public void UpdateStudent(int studentID, ModelMethodContext context)
        {
            Student item = null;
            item = db.Students.Find(studentID);
            if (item == null)
            {
                context.ModelState.AddModelError("", String.Format("Item with id {0} was not found", studentID));
                return;
            }

            context.TryUpdateModel(item);
            if (context.ModelState.IsValid)
            {
                db.SaveChanges();
            }
        }

        public IQueryable<Enrollment> GetCourses([QueryString] int? studentID)
        {
            var query = db.Enrollments.Include(e => e.Course)
                .Where(e => e.StudentID == studentID);
            return query;
        }

        private bool disposedValue = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposedValue)
            {
                if (disposing)
                {
                    db.Dispose();
                }
            }
            this.disposedValue = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}

Revisar páginas existentes para recuperar dados da camada de lógica de negócios

Por fim, você converterá as páginas Students.aspx, AddStudent.aspx e Courses.aspx de usar consultas no arquivo code-behind para usar a camada de lógica de negócios.

Nos arquivos code-behind para Alunos, AddStudent e Cursos, exclua ou comente os seguintes métodos de consulta:

  • studentsGrid_GetData
  • studentsGrid_UpdateItem
  • studentsGrid_DeleteItem
  • addStudentForm_InsertItem
  • coursesGrid_GetData

Agora você não deve ter nenhum código no arquivo code-behind pertencente a operações de dados.

O manipulador de eventos OnCallingDataMethods permite que você especifique um objeto a ser usado para os métodos de dados. Em Students.aspx, adicione um valor para esse manipulador de eventos e altere os nomes dos métodos de dados para os nomes dos métodos na classe lógica de negócios.

<asp:GridView runat="server" ID="studentsGrid"
    ItemType="ContosoUniversityModelBinding.Models.Student" DataKeyNames="StudentID"
    SelectMethod="GetStudents"
    UpdateMethod="UpdateStudent" DeleteMethod="DeleteStudent"
    AllowSorting="true" AllowPaging="true" PageSize="4"
    AutoGenerateEditButton="true" AutoGenerateDeleteButton="true"
    AutoGenerateColumns="false" 
    OnCallingDataMethods="studentsGrid_CallingDataMethods">

No arquivo code-behind para Students.aspx, defina o manipulador de eventos para o evento CallingDataMethods. Nesse manipulador de eventos, você especifica a classe lógica de negócios para operações de dados.

protected void studentsGrid_CallingDataMethods(object sender, CallingDataMethodsEventArgs e)
{
    e.DataMethodsObject = new ContosoUniversityModelBinding.BLL.SchoolBL();
}

Em AddStudent.aspx, faça alterações semelhantes.

<asp:FormView runat="server" ID="addStudentForm"
    ItemType="ContosoUniversityModelBinding.Models.Student"
    InsertMethod="InsertStudent" DefaultMode="Insert"
    OnCallingDataMethods="addStudentForm_CallingDataMethods"
    RenderOuterTable="false" OnItemInserted="addStudentForm_ItemInserted">
protected void addStudentForm_CallingDataMethods(object sender, CallingDataMethodsEventArgs e)
{
    e.DataMethodsObject = new ContosoUniversityModelBinding.BLL.SchoolBL();
}

Em Courses.aspx, faça alterações semelhantes.

<asp:GridView runat="server" ID="coursesGrid"
    ItemType="ContosoUniversityModelBinding.Models.Enrollment"
    SelectMethod="GetCourses" AutoGenerateColumns="false"
    OnCallingDataMethods="coursesGrid_CallingDataMethods">
protected void coursesGrid_CallingDataMethods(object sender, CallingDataMethodsEventArgs e)
{
    e.DataMethodsObject = new ContosoUniversityModelBinding.BLL.SchoolBL();
}

Execute o aplicativo e observe que todas as páginas funcionam como antes. A lógica de validação também funciona corretamente.

Conclusão

Neste tutorial, você reestruturou seu aplicativo para usar uma camada de acesso a dados e uma camada de lógica de negócios. Você especificou que os controles de dados usam um objeto que não é a página atual para operações de dados.