Partager via


Ajout d’une couche de logique métier à un projet qui utilise la liaison de modèle et les formulaires web

par Tom FitzMacken

Cette série de tutoriels présente les aspects de base de l’utilisation de la liaison de modèle avec un projet ASP.NET Web Forms. La liaison de modèle rend l’interaction des données plus simple que la gestion des objets sources de données (par exemple, ObjectDataSource ou SqlDataSource). Cette série commence par des documents d’introduction et passe à des concepts plus avancés dans les didacticiels ultérieurs.

Ce tutoriel montre comment utiliser la liaison de modèle avec une couche de logique métier. Vous allez définir le membre OnCallingDataMethods pour spécifier qu’un objet autre que la page active est utilisé pour appeler les méthodes de données.

Ce tutoriel s’appuie sur le projet créé dans les parties antérieures de la série.

Vous pouvez télécharger le projet complet en C# ou VB. Le code téléchargeable fonctionne avec Visual Studio 2012 ou Visual Studio 2013. Il utilise le modèle Visual Studio 2012, qui est légèrement différent du modèle Visual Studio 2013 présenté dans ce tutoriel.

Ce que vous allez créer

La liaison de modèle vous permet de placer votre code d’interaction de données dans le fichier code-behind d’une page web ou dans une classe de logique métier distincte. Les tutoriels précédents ont montré comment utiliser les fichiers code-behind pour le code d’interaction de données. Cette approche fonctionne pour les petits sites, mais elle peut entraîner une répétition du code et une plus grande difficulté lors de la maintenance d’un site volumineux. Il peut également être très difficile de tester par programmation du code qui réside dans des fichiers code-behind, car il n’existe aucune couche d’abstraction.

Pour centraliser le code d’interaction des données, vous pouvez créer une couche de logique métier qui contient toute la logique d’interaction avec les données. Vous appelez ensuite la couche de logique métier à partir de vos pages web. Ce tutoriel montre comment déplacer tout le code que vous avez écrit dans les didacticiels précédents dans une couche de logique métier, puis utiliser ce code à partir des pages.

Dans ce didacticiel, vous allez :

  1. Déplacer le code des fichiers code-behind vers une couche de logique métier
  2. Modifier vos contrôles liés aux données pour appeler les méthodes dans la couche de logique métier

Créer une couche de logique métier

Maintenant, vous allez créer la classe appelée à partir des pages web. Les méthodes de cette classe ressemblent aux méthodes que vous avez utilisées dans les didacticiels précédents et incluent les attributs du fournisseur de valeurs.

Tout d’abord, ajoutez un nouveau dossier appelé BLL.

ajouter un dossier

Dans le dossier BLL, créez une classe nommée SchoolBL.cs. Il contient toutes les opérations de données qui se trouvent à l’origine dans des fichiers code-behind. Les méthodes sont presque les mêmes que celles du fichier code-behind, mais elles incluent certaines modifications.

La modification la plus importante à noter est que vous n’exécutez plus le code à partir d’un instance de la classe Page. La classe Page contient la méthode TryUpdateModel et la propriété ModelState . Lorsque ce code est déplacé vers une couche de logique métier, vous n’avez plus de instance de la classe Page pour appeler ces membres. Pour contourner ce problème, vous devez ajouter un paramètre ModelMethodContext à toute méthode qui accède à TryUpdateModel ou ModelState. Vous utilisez ce paramètre ModelMethodContext pour appeler TryUpdateModel ou récupérer ModelState. Vous n’avez pas besoin de modifier quoi que ce soit dans la page web pour prendre en compte ce nouveau paramètre.

Remplacez le code dans SchoolBL.cs par le code suivant.

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

Réviser les pages existantes pour récupérer des données à partir de la couche de logique métier

Enfin, vous allez convertir les pages Students.aspx, AddStudent.aspx et Courses.aspx de l’utilisation de requêtes dans le fichier code-behind à l’aide de la couche de logique métier.

Dans les fichiers code-behind pour Students, AddStudent et Courses, supprimez ou commentez les méthodes de requête suivantes :

  • studentsGrid_GetData
  • studentsGrid_UpdateItem
  • studentsGrid_DeleteItem
  • addStudentForm_InsertItem
  • coursesGrid_GetData

Vous ne devez maintenant avoir aucun code dans le fichier code-behind relatif aux opérations de données.

Le gestionnaire d’événements OnCallingDataMethods vous permet de spécifier un objet à utiliser pour les méthodes de données. Dans Students.aspx, ajoutez une valeur pour ce gestionnaire d’événements et remplacez les noms des méthodes de données par les noms des méthodes dans la classe de logique métier.

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

Dans le fichier code-behind pour Students.aspx, définissez le gestionnaire d’événements pour l’événement CallingDataMethods. Dans ce gestionnaire d’événements, vous spécifiez la classe de logique métier pour les opérations de données.

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

Dans AddStudent.aspx, apportez des modifications similaires.

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

Dans Courses.aspx, apportez des modifications similaires.

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

Exécutez l’application et notez que toutes les pages fonctionnent comme précédemment. La logique de validation fonctionne également correctement.

Conclusion

Dans ce tutoriel, vous avez restructé votre application pour utiliser une couche d’accès aux données et une couche de logique métier. Vous avez spécifié que les contrôles de données utilisent un objet qui n’est pas la page actuelle pour les opérations de données.