Share via


Hinzufügen der Geschäftslogikebene zu einem Projekt, das Modellbindung und Webformulare verwendet

von Tom FitzMacken

In dieser Tutorialreihe werden grundlegende Aspekte der Verwendung der Modellbindung mit einem ASP.NET Web Forms-Projekt veranschaulicht. Die Modellbindung macht die Dateninteraktion einfacher als den Umgang mit Datenquellenobjekten (z. B. ObjectDataSource oder SqlDataSource). Diese Reihe beginnt mit einführungsmaterial und geht in späteren Tutorials zu komplexeren Konzepten über.

In diesem Tutorial erfahren Sie, wie Sie die Modellbindung mit einer Geschäftslogikebene verwenden. Sie legen den OnCallingDataMethods-Member fest, um anzugeben, dass ein anderes Objekt als die aktuelle Seite zum Aufrufen der Datenmethoden verwendet wird.

Dieses Tutorial baut auf dem Projekt auf, das in den früheren Teilen der Reihe erstellt wurde.

Sie können das gesamte Projekt in C# oder VB herunterladen . Der herunterladbare Code funktioniert entweder mit Visual Studio 2012 oder Visual Studio 2013. Es verwendet die Visual Studio 2012-Vorlage, die sich geringfügig von der in diesem Tutorial gezeigten vorlage Visual Studio 2013 unterscheidet.

Funktion des erstellten Programms

Mit der Modellbindung können Sie Ihren Dateninteraktionscode entweder in der CodeBehind-Datei für eine Webseite oder in einer separaten Geschäftslogikklasse ablegen. In den vorherigen Tutorials wurde gezeigt, wie Sie die CodeBehind-Dateien für Dateninteraktionscode verwenden. Dieser Ansatz funktioniert für kleine Websites, kann jedoch zu Einer Wiederholung von Code und größeren Schwierigkeiten bei der Verwaltung einer großen Website führen. Es kann auch sehr schwierig sein, Code programmgesteuert zu testen, der sich in CodeBehind-Dateien befindet, da keine Abstraktionsebene vorhanden ist.

Um den Dateninteraktionscode zu zentralisieren, können Sie eine Geschäftslogikebene erstellen, die die gesamte Logik für die Interaktion mit Daten enthält. Anschließend rufen Sie die Geschäftslogikebene von Ihren Webseiten auf. In diesem Tutorial erfahren Sie, wie Sie den gesamten Code, den Sie in den vorherigen Tutorials geschrieben haben, in eine Geschäftslogikebene verschieben und dann diesen Code von den Seiten verwenden.

In diesem Tutorial gehen Sie wie folgt vor:

  1. Verschieben des Codes aus CodeBehind-Dateien in eine Geschäftslogikebene
  2. Ändern Der datengebundenen Steuerelemente, um die Methoden auf der Geschäftslogikebene aufzurufen

Erstellen einer Geschäftslogikebene

Nun erstellen Sie die Klasse, die von den Webseiten aufgerufen wird. Die Methoden in dieser Klasse ähneln den Methoden, die Sie in den vorherigen Tutorials verwendet haben, und enthalten die Wertanbieterattribute.

Fügen Sie zunächst einen neuen Ordner mit dem Namen BLL hinzu.

Ordner hinzufügen

Erstellen Sie im Ordner BLL eine neue Klasse mit dem Namen SchoolBL.cs. Sie enthält alle Datenvorgänge, die sich ursprünglich in CodeBehind-Dateien befinden. Die Methoden sind fast identisch mit den Methoden in der CodeBehind-Datei, enthalten jedoch einige Änderungen.

Die wichtigste Änderung ist, dass Sie den Code nicht mehr innerhalb einer instance der Page-Klasse ausführen. Die Page-Klasse enthält die TryUpdateModel-Methode und die ModelState-Eigenschaft . Wenn dieser Code in eine Geschäftslogikebene verschoben wird, haben Sie keine instance der Page-Klasse mehr, um diese Member aufzurufen. Um dieses Problem zu umgehen, müssen Sie jeder Methode, die auf TryUpdateModel oder ModelState zugreift, einen ModelMethodContext-Parameter hinzufügen. Sie verwenden diesen Parameter ModelMethodContext, um TryUpdateModel aufzurufen oder ModelState abzurufen. Sie müssen nichts auf der Webseite ändern, um diesen neuen Parameter zu berücksichtigen.

Ersetzen Sie den Code in SchoolBL.cs durch den folgenden Code.

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);
        }
    }
}

Überarbeiten vorhandener Seiten zum Abrufen von Daten aus der Geschäftslogikebene

Schließlich konvertieren Sie die Seiten Students.aspx, AddStudent.aspx und Courses.aspx von der Verwendung von Abfragen in der CodeBehind-Datei in die Verwendung der Geschäftslogikebene.

Löschen oder kommentieren Sie in den CodeBehind-Dateien für Students, AddStudent und Courses die folgenden Abfragemethoden aus oder kommentieren Sie sie aus:

  • studentsGrid_GetData
  • studentsGrid_UpdateItem
  • studentsGrid_DeleteItem
  • addStudentForm_InsertItem
  • coursesGrid_GetData

Sie sollten jetzt keinen Code in der CodeBehind-Datei enthalten, der sich auf Datenvorgänge bezieht.

Mit dem OnCallingDataMethods-Ereignishandler können Sie ein Objekt angeben, das für die Datenmethoden verwendet werden soll. Fügen Sie in Students.aspx einen Wert für diesen Ereignishandler hinzu, und ändern Sie die Namen der Datenmethoden in die Namen der Methoden in der Geschäftslogikklasse.

<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">

Definieren Sie in der CodeBehind-Datei für Students.aspx den Ereignishandler für das CallingDataMethods-Ereignis. In diesem Ereignishandler geben Sie die Geschäftslogikklasse für Datenvorgänge an.

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

Nehmen Sie in AddStudent.aspx ähnliche Änderungen vor.

<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();
}

Nehmen Sie in Courses.aspx ähnliche Änderungen vor.

<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();
}

Führen Sie die Anwendung aus, und beachten Sie, dass alle Seiten wie zuvor funktionieren. Die Validierungslogik funktioniert ebenfalls ordnungsgemäß.

Zusammenfassung

In diesem Tutorial haben Sie Ihre Anwendung so strukturiert, dass sie eine Datenzugriffsebene und eine Geschäftslogikebene verwendet. Sie haben angegeben, dass die Datensteuerelemente ein Objekt verwenden, das nicht die aktuelle Seite für Datenvorgänge ist.