Quelques nouveautés ASP.NET 4

24. August 2010 by Pierre-Luc.ROUAYS

Introduction

Dans cet article, on a voir un aperçu des nouvelles fonctionnalités d’ASP.NET qui sont inclus dans le cadre  du Framework .net et Visual Studio 2010.  

Les nouvelles fonctionnalités

1.     Extensibilité du Output Caching

 

1.1.           Contexte:

Le cache est une zone de la mémoire où sont stockées les opérations et cela dans le but d'améliorer les performances. Lorsque nous avons besoin du cache à nouveau, nous recherchons dans ce dernier contrairement à l'exécution d’une nouvelle opération.

1.2.           Problème:

Cette approche  bien sûr est  limitée au niveau de la mémoire. Si nos serveurs  ont un trafic lourd, alors la mémoire consommée par la mise en cache  peut rivaliser avec les exigences de la mémoire à partir d'autres applications ou composants  propre à cette application web.

1.3.           Solution:

Le Extensible Output Caching  permet de configurer un ou plusieurs fournisseurs de Output-Cache pour divers  mécanismes de persistance, tels que les disques durs (localement ou à distance), le stockage des nuages et could storger.

1.4.           Implémentation de la stratégie:

Il est possible de créer un fournisseur personnalisé d’Output-cache comme une classe qui est dérive de ce nouveau type System.Web.Caching.OutputCacheProvider. Par exemple, nous allons créer un fournisseur à l'aide AppFabric (Velocity) comme il est montré dans suivant :

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Caching;

 

namespace WebAppOutputCacheExperiment.OutputCacheProviders

{

    public class VelocityCacheProvider : OutputCacheProvider, IDisposable

    {

        private DataCache dataCache;

        const String OutputCacheName = "OutputCache";

        public VelocityCacheProvider()

        {

            DataCacheFactory factory = new DataCacheFactory();

            this.dataCache = factory.GetCache(OutputCacheName);

        }

        public override object Add(string key, object entry, DateTime utcExpiry)

        {

            this.dataCache.Add(key, entry, utcExpiry - DateTime.UtcNow);

            return entry;

        }

        public override object Get(string key)

        {

            return this.dataCache.Get(key);

        }

        public override void Remove(string key)

        {

            this.dataCache.Remove(key);

        }

        public override void Set(string key, object entry, DateTime utcExpiry)

        {

            throw new NotImplementedException();

        }

        public void Dispose()

        {

            this.dataCache = null;

        }

    }

}

Exemple 1

-          Vous pouvez ensuite configurer le fournisseur dans le fichier Web.config en utilisant la nouvelle sous-section fournisseur de l'élément OutputCache  voir exemple suivant:

<caching>

      <outputCache defaultProvider="AspNetInternalProvider">

        <providers>

          <add name="VelocityCache" type="WebAppOutputCacheExperiment.OutputCacheProviders.VelocityCacheProvider, WebAppOutputCacheExperiment"/>

        </providers>

      </outputCache>

</caching>

Exemple  2

-          En outre, vous pouvez choisir entre différents fournisseurs d’Output-cache pour chaque contrôle et à chaque demande. La meilleure façon de choisir un autre fournisseur d’Output-cache pour les différents UserControl  est de le faire de façon déclarative en utilisant l'attribut ProviderName, nouveau dans une directive de contrôle :

 

<%@ OutputCache="" Duration="60" VaryByParam="None" providerName="VelocityCache" %>

 

Exemple  3

-          Au lieu de spécifier de manière déclarative le fournisseur, vous pouvez  substituez la méthode GetOuputCacheProviderName dans le fichier Global.asax et préciser le fournisseur à utiliser pour une demande spécifique :

public override string GetOutputCacheProviderName(HttpContext context)

        {

            if (context.Request.Path.EndsWith("CacheWebForm.aspx"))

                return "VelocityCache";

            else

                return base.GetOutputCacheProviderName(context);

        }

Exemple 4

2.     Redirection permanente d'une page

 

2.1.           Contexte :

Il est de pratique courante dans les applications Web pour se déplacer dans les pages et dans le contenu au fil du temps, qui peut conduire à une accumulation de liens périmés dans les moteurs de recherche.

2.2.           Problème:

Traditionnellement, cela se fait en utilisant la méthode Response.Redirect de transmettre une demande à la nouvelle URL. Toutefois, cette méthode émet un HTTP 302 Found  comme réponse, ce qui entraîne un voyage HTTP extra round lorsque les utilisateurs tentent d'accéder aux anciennes URL.

2.3.           Solution:

ASP.NET 4 ajoute une méthode RedirectPermanent inédit qui facilite d’émettre HTTP 301 Moved Permanently.

2.4.           Implémentation de la stratégie:

 

 

Response.RedirectPermanent("newlocation/page.aspx");

 

Exemple 5

3.     Shrinking Session State

 

3.1.           Contexte :

Dans la pratique courante dans les applications Web d’exploiter la session pour stockée des objets.

3.2.           Problème:

Selon la quantité d'information que le développeur veut stocker dans la session, la taille des données sérialisées peut devenir assez grande.

3.3.           Solution:

ASP.NET 4 introduit une nouvelle option de compression pour les deux types de prestataires d'état de session out-of-process. Lorsque l'option de configuration compressionEnabled comme le montre l'exemple suivant est à la valeur true, ASP.NET compresse et décompresser  la session sérialisé en utilisant le class System.IO.Compression.GZipStream .

 

<sessionState

      mode="SQLServer" sqlConnectionString="data source=dbserver;Initial Catalog=aspnetstate" allowCustomSqlDatabase="true" compressionEnabled="true"/>

 

Exemple 6

4.     Réglage de Meta Tags

 

4.1.           Contexte:

 Les balises Meta permettent notamment d’informer la page sur le Web (MetaData), tels que l'auteur, mots clés, contenu, etc.

4.2.           Problème:

 Nous devons inclure dynamiquement des métadonnées dans nous page, par exemple, à partir d'une source de données relationnelle pour le moteur de recherche afin de donner plus de pertinence à notre site. Il s'agit d'un Search Engine Optimization (SEO).

4.3.           Solution:

 ASP.NET 4 introduit la MetaKeywords une nouvelle propriété, et MetaDescription à la classe Page. La directive @ Page contient les mots-clés et l'attribut Description.

4.4.           Implémentation de la stratégie:

 

 

<%@ Page="" Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"

        CodeBehind="Default.aspx.cs" Inherits="WebAppOutputCacheExperiment._Default" Keywords="page par default" Description="description de la page" %>

 

Exemple 7

L’output va être comme ceci :

 

  <head id="Head1" runat="server">

      <title>Page</title>

      <meta name="keywords" content="mots clé de la page" />

      <meta name="description" content="description de la page" />

    </head>

 

Exemple 8

5.      Une meilleur contrôle de la ViewState

 

5.1.           Problème:

L’utilisation de la ViewState pour stocker de grandes quantités de données,  provoque une dégradation des performances significative.

5.2.           Solution:

 ASP.NET 4 introduit la ViewStateMode nouvelle propriété dans les contrôles Web qui vous permet de désactiver l'état d'affichage par défaut et activer ensuite seulement pour les contrôles qui en ont besoin dans la page. Cette propriété peut avoir trois valeurs: Activer, désactiver, et Inherit. Ils notamment possible de définir les ViewStateMode au niveau de la page.

5.3.           Implémentation de la stratégie:

 

 

<%@ Page="" Title="Home" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"

      CodeBehind="Default.aspx.cs" Inherits="WebAppOutputCacheExperiment._Default" ViewStateMode="Disabled" %>

 

Exemple 9

6.     Routage dans ASP.NET 4

 

6.1.           Contexte:

SEO est le moteur de recherche le plus utiliser pour augmenter le trafic sur un site Web,

6.2.           Problème:

 Comment peut-on configurer les applications utilisant notre formulaire de pages Web pour utiliser l'URL se lie pas à des fichiers physiques sur le serveur?

6.3.           Solution:

 Bien que les fonctionnalités de routage soient livrées avec ASP.NET 3.5 SP1, ASP.NET 4 est livré avec de nouveaux atouts pour le rendre plus facile utilisation des mécanismes de routage, y compris les suivantes:

·         La classe PageRouteHandler, qui est un gestionnaire HTTP simple que vous utilisez lorsque vous définissez les routes. La classe transmet les données vers page demandé.

·         Les nouvelles propriétés HttpRequest.RequestContext et Page.RouteData (qui est un raccourci pour HttpRequest.RequestContext.RouteData). Ces propriétés  faciliter l'accès à l'information qui est passée de la route.

·         Les constructrices suivantes qui sont de nouvelles expressions, qui sont définis dans System.Web.Compilation.RouteUrlExpressionBuilder et System.Web.Compilation.RouteValueExpressionBuilder:

o   RouteUrl, qui fournit un moyen simple de créer une URL  correspondante  à une URL de routage dans un contrôle serveur ASP.NET.

o   RouteValue, qui fournit un moyen simple d'extraire des informations de l'objet RouteContext.

·         La classe RouteParameter, facilite la transmission de données contenues dans un objet RouteContext à une requête pour une source de données de contrôle (semblable à FormParameter).

6.4.           Implémentation de la stratégie :

Ouvrez le fichier Global.asax et ajoutez le code suivant pour lier les produits / catégories / (id) format d'URL avec la page physique ProductsCategory.aspx.

Using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.SessionState;

using System.Web.Routing;

using System.Web;

 

namespace WebAppRoutingExperiment

{

    public class Global :HttpApplication

    {

        // New code added

        void RegisterRoutes(RouteCollection routes)

        {

            routes.MapPageRoute("ProductsCategory", "products/category/{id}", "~/ProductsCategory.aspx");

        }

        void Application_Start(object sender, EventArgs e)

        {

            // New code added

            RegisterRoutes(RouteTable.Routes);

        }

    }

}

Exemple 10

Et enfin, nous allons créer le fichier ProductsCategory.aspx  et ajoutez le code pour obtenir la valeur, la catégorie, et l'affichage dans la page.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI;

 

namespace WebAppRoutingExperiment

{

    public partial class ProductsCategory :Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

            string productCategoryId = this.Page.RouteData.Values["id"] != null ? this.Page.RouteData.Values["id"].ToString() : "No Product Category";

            this.lblProductCategoryId.Text = productCategoryId;

        }

    }

}

Exemple 11

7.     Réglage de l’ID de client

 

7.1.           Contexte:

Tous les jours, nous utilisons Ajax et les bibliothèques JavaScript pour créer des Applications Internet Riches (RIA). La nouvelle propriété ClientIDMode traite un problème de longue date dans ASP.NET, à savoir comment créer des contrôles de l'attribut id pour les éléments qu'ils rendent.

Sachant que l'attribut id pour les éléments rendus est important, si votre application contient un script client qui fait référence à ces éléments.

7.2.           Problème:

Jusqu'à ASP.NET 4, l'algorithme de génération de l'attribut id de la propriété ClientID  était concaténer, le conteneur de dénomination (le cas échéant) avec l'ID, et dans le cas des contrôles répétés (comme dans les contrôles de données), d'ajouter un préfixe et un numéro séquentiel.

Même si cela a toujours garanti que les ID des contrôles dans la page sont uniques, l'algorithme a donné lieu à des ID de contrôle qui n'étaient pas prévisibles, ce qui rond difficile de faire référence dans le script client. Cela se produit surtout quand nous utilisons les pages maîtres.

Une astuce pour obtenir une référence à des éléments HTML  comme le montre l’exemple suivant:

var btn = document.getElementById("<% =Button1.ClientID %>");

Exemple 12

Ou, la solution la plus élégante de jQuery, comme montrer dans l’exemple suivant :

var btn = $('<% =Button1.ClientID %>');

Exemple 13

7.3.           Solution:

ASP.NET 4 introduit de nouvelles propriétés ClientIDMode vous permet de spécifier plus précisément la façon dont l'ID client est généré pour les contrôles. Vous pouvez définir la propriété ClientIDMode pour tout contrôle, y compris pour la page.

Les réglages possibles sont les suivantes:

·         AutoID. Ceci est équivalent à l'algorithme de génération de valeurs de propriété ClientID qui a été utilisé dans les versions antérieures d’ASP.NET.

 

·         Statique. Ceci indique que la valeur ClientID sera le même que l'ID, sans la concaténation des identifiants de nommage du conteneur parent. Cela peut être utile dans les UserControl. Parce qu’un UserControl  peut être situés sur des pages différentes et dans les contrôles de conteneurs différents, il peut être difficile d'écrire un script client pour les UserControl qui utilisent l'algorithme AutoID parce que vous ne pouvez pas prédire  les  valeurs d'identité.

 

·         Prévisibles. Cette option est destinée principalement à des contrôles de données qui utilisent des modèles de répétition. Il concatène les propriétés ID de conteneurs de nommage du contrôle, mais la valeur du ClientID  générer ne contiennent pas de chaînes de caractères comme "ctlxxx". Ce paramètre fonctionne en conjonction avec la propriété ClientIDRowSuffix. Vous définissez la propriété cette dernière au nom d'un champ de données, et la valeur de ce champ est utilisé comme suffixe pour la valeur générée ClientID. En règle générale vous devez utiliser la clé primaire d'un enregistrement de données comme la valeur ClientIDRowSuffix.

 

·         Hériter. Ce paramètre est le comportement par défaut pour les contrôles, il précise que la production d'un contrôle d'identité est le même que son parent.

7.4.           Implémentation de la stratégie :

 

Un exemple d’AutoID :

 

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <asp:Panel ID="PanelParent"  runat="server">        

        <asp:Panel ID="PanelChild" runat="server">        

            <asp:TextBox ID="txtEcho" runat="server" ClientIDMode="AutoID" />

        </asp:Panel>

    </asp:Panel>

</asp:Content>

Exemple 14

L’output va être comme ceci :

 

<div id="MainContent_PanelParent">              

   <div id="MainContent_PanelChild">            

     <input name="ctl00$MainContent$txtEcho" type="text" id="ctl00_MainContent_txtEcho" /> 

  </div>

</div>

 

 

Un exemple de Statique

 

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <asp:Panel ID="PanelParent"  runat="server">

        <asp:Panel ID="PanelChild" runat="server">

            <asp:TextBox ID="txtEcho" runat="server" ClientIDMode="Static" />

        </asp:Panel>

    </asp:Panel>

</asp:Content>

 

 

L’output va être comme ceci :

 

<div id="MainContent_PanelParent">

    <div id="MainContent_PanelChild">

        <input name="ctl00$MainContent$txtEcho" type="text" id="txtEcho" />

    </div>

</div>

 

 

 

L’exemple de Predictable.

 

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <asp:Panel ID="PanelParent"  runat="server">

        <asp:Panel ID="PanelChild" runat="server">

            <asp:TextBox ID="txtEcho" runat="server" ClientIDMode="Predictable" />

        </asp:Panel>

    </asp:Panel>

</asp:Content>

 

 

L’output va être comme ceci :

 

<div id="MainContent_PanelParent">

    <div id="MainContent_PanelChild">

        <input name="ctl00$MainContent$txtEcho" type="text" id="MainContent_txtEcho" />

    </div>

</div>

 

 

8.     Chart Control

 

8.1.           Problème :

 Vous avez besoin de visualiser les données d'une manière compréhensible dans une application Web, par exemple, un rapport d'analyse financière.

8.2.            Solution :

 ASP.NET 4 introduit un nouveau chart control avec un ensemble de fonctionnalités tels que la pie, area, range, des points, et la distribution de données  avec un support en Ajax. A l'exécution, le contrôle génère une image (un fichier pgn.) Qui est référencé par le côté client.

8.3.           Implémentation de la stratégie :

La première étape est d'ajouter un gestionnaire HTTP pour votre application dans le web.config.

 

<httpHandlers>

    <add path="ChartImg.axd" verb="GET,HEAD,POST" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false" />

</httpHandlers>

 

Exemple 20

Plus tard, nous ajoutons le contrôle Chart à notre page.

 

<asp:Chart ID="Chart1" runat="server" />

 

Exemple 21

La Web Form est affichée  dans l’exemple 22..

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="SalesByDayOfWeek.aspx.cs" Inherits="WebAppCharting.SalesByDayOfWeek" %>

    <%@ Register

    Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

    Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>

        <asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">

        </asp:Content>

        <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

            <div>

                <h3>Sales Reports (By days of the week)</h3>

            </div>

            <div>

                <asp:Chart ID="chrSalesByDayOfWeek" runat="server" Width="500" Height="350">

                    <Series>

                        <asp:Series ChartType="Area" Palette="EarthTones" ChartArea="MainChartArea"></asp:Series>

                    </Series>

                    <ChartAreas>

                        <asp:ChartArea Name="MainChartArea" Area3DStyle-Enable3D="true">

                        </asp:ChartArea>

                    </ChartAreas>

                </asp:Chart>

            </div>

        </asp:Content>

 

Exemple 22

Le code-code-behind  del Web Form.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI;

 

namespace WebAppChartingExperiement

{

    public partial class SalesByDayOfWeek :Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

            Random random = new Random();

            string[] listDaysOfWeek = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

            foreach (string dayOfWeek in listDaysOfWeek)

            {

                double totalSales = random.NextDouble() * 5000 + 1000;

                this.chrSalesByDayOfWeek.Series[0].Points.AddXY(dayOfWeek, totalSales);

            }

        }

    }

}

Exemple 23

Le rapport va être affiché tel qu’il est dans la figure 1 :

Figure 1

Maintenant nous allons alimenter la charte avec des données de manière statique.

 

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="SalesByDayOfWeekStatic.aspx.cs" Inherits="WebAppChartingExperiment.SalesByDayOfWeekStatic" %>

    <%@ Register Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

    Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>

        <asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">

        </asp:Content>

        <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

            <div>

                <h3>Sales Reports (By days of the week)</h3>

            </div>

            <div>

                <asp:Chart ID="chrSalesByDayOfWeek" runat="server" Width="500" Height="350">

                    <Series>

                        <asp:Series ChartType="Area" Palette="EarthTones" ChartArea="MainChartArea">

                            <Points>

                                <asp:DataPoint AxisLabel="Sun" YValues="17" />

                                <asp:DataPoint AxisLabel="Mon" YValues="15" />

                                <asp:DataPoint AxisLabel="Tue" YValues="6" />

                                <asp:DataPoint AxisLabel="Wed" YValues="4" />

                                <asp:DataPoint AxisLabel="Thu" YValues="3" />

                                <asp:DataPoint AxisLabel="Fri" YValues="3" />

                                <asp:DataPoint AxisLabel="Sat" YValues="3" />

                            </Points>

                        </asp:Series>

                    </Series>

                    <ChartAreas>

                        <asp:ChartArea Name="MainChartArea" Area3DStyle-Enable3D="true">

                        </asp:ChartArea>

                    </ChartAreas>

                </asp:Chart>

            </div>

        </asp:Content>

 

Exemple 24

Le résultat du rapport sera traduit par la figure 2.

Figure 2

 

Conclusion:

Nous avons vu dans cet articles les principales nouveautés d’APS.NET 4 qui introduite avec l’arrivé du Framework 4. A présent vous pouvez exploiter ces fonctionnalités après cette introduction sur ASP.NET 4.

 

ASP.NET AJAX, C#, Visual Studio 2010 , , ,

Comment créer une application Silverlight utilisant LinQ à travers un service WCF

21. April 2010 by Jerome.Antoine

De base Silverlight ne permet pas de se connecter à une base de données, alors que cela peut être extrêmement utile. La méthode la plus simple pour contourner ce problème est de passer par un service WCF. Voici comment faire.


1. Créer l’application Silverlight


Pour commencer nous allons créer un projet de type « Silverlight Application ». Visual Studio nous propose ici de créer automatiquement le projet web en ASP.NET qui implémentera notre application Silverlight.

 

 

 

2. Créer la page principale de l’application Silverlight


Dans le page principale de l’application Silverlight nous définissons un « DataGrid », que vous pouvez trouver dans la ToolBox, et qui est un contrôle de base permettant de mettre en forme n’importe quelle collection. Nous lui mettons un « x :Name » pour pouvoir le retrouver dans notre code behind.

 

 

3. Créer le DataContext avec LinQ to SQL


Pour pouvoir accéder à notre base de donnée nous allons utiliser LinQ to SQL, pour cela ajouter un élément de type « LinQ to SQL Classes » à votre projet Web.

 

 

Dans l’explorateur de serveur, créez une nouvelle connexion à votre base de donnée NorthWind.
Si vous n’avez pas cette base de données de test fournie par Microsoft vous pouvez la télécharger ici :
http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46a0-8da2-eebc53a68034&displaylang=en

 

Une fois votre connexion établie, parcourez la liste des tables de votre base de données et glissez-déposez la table « Employee » dans votre DataContext « NorthWind.dbml ». Vous devriez voir le schéma de la table s’afficher.
Attention, vous devez permettre la sérialisation de votre DataContext, pour ce faire changer le « Serialization Mode » dans ses propriétées, en le mettant à « Unidirectional ».

 

 

4. Créer le service WCF


Pour que l’application Silverlight puisse récupérer des données de la base de données nous allons utiliser un web service en WCF. Celui-ci s’occupera de récupérer ces données et pourra les fournir à l’application Silverlight quand celle-ci les demandera.
Pour ce faire nous allons ajouter un élément de type « WCF Service » à notre application Web.

 

 

Un service de base est constitué de deux classes : le contrat du service et la définition du service. L’application Silverlight n’aura connaissance que du contrat. Il s’agit d’un interface énonçant les méthodes que le service possède. Ici nous allons écrire une fonction simple permettant de lister les employés existant dans la base de donnée NorthWind.

 

 

 

Dans la définition du service nous écrivons ce que doit faire cette fonction. Ici nous utilisons une requête LinQ to SQL pour récupérer les employés.

 

 

Enfin pour que le service soit utilisable par l’application Silverlight nous devons définir un « endpoint », qui représente la façon dont communique le service. Ici nous devons définir le « binding » en « basicHttpBinding » pour que le service puisse communiquer avec Silverlight.

 

 

5. Ajouter la référence du service à l’application Silverlight


Une fois le service réalisé, il faut le faire connaitre à l’application Silverlight. Pour ce faire il faut ajouter une référence à ce service dans l’application Silverlight (clique droit sur « Service References » et choisir « Add a Service Reference »).
Cliquez sur « Discover » pour voir votre service et cliquez sur « OK ». Il se peut que vous ayez une erreur si vous n’avez pas compilé votre service dans l’application web avant cette étape.

 

 

 

 

Si vous deviez changer le code de votre service, pensez à faire une mise à jour de cette référence (clique droit sur « NorthWindServiceReference » et « Update Service Reference »).

 

6. Récupérer et mettre en forme les données


Pour finir nous devons utiliser notre service pour récupérer les données et les mettre en forme dans le « DataGrid » de notre application Silverlight. Pour ce faire nous devons tout d’abord récupérer une instance du service. Ensuite nous devons abonner cette instance à l’événement « getEmployeesCompleted » pour que lorsque le service ait fini de récupérer les employés, soit appelée une méthode, ici « serviceNorthWind_getEmployeesCompleted ».
Dans cette méthode nous pouvons mettre la liste des employés récupérée comme source de notre « DataGrid ».

 

 

7. Test de l’application

 

 

ASP.NET AJAX, C#, Silverlight , , , , ,

Accès aux données générique avec Linq To SQL et C#

25. February 2010 by Pierre-Luc.ROUAYS

Accès aux données générique avec Linq To SQL et C#

Introduction :

Cet article permet de construire une couche d’accès aux données générique en utilisant LINQ To SQL. Ceci permettra par la suite d’effectuer les opérations basiques du CRUD. Nous créerons une classe nommée EntityCrud qui implémentera ces fonctionnalités.

Vous pourrez par la suite créer des Adapters pour chacune de vos classe dérivant ce cette classe.

 

Place à l’action !

Nous allons créer une simple solution contenant 2 projet : le programme et la couche d’accès aux données (DAL).

 

 

Ajouter un élément de type classe LINQ To SQL :

Puis ensuite ajouter les Tables à votre projet par le biais de l’explorateur de solution.

Code Projet MonProgramme.DAL

La classe EntityCrud contient tout le code nécessaire pour communiquer avec la base de donnée par le biais de LinqToSQL.

Voici la classe AdapterFactory :

 

 

using System;

using System.Collections;

using System.Collections.Specialized;

using System.Collections.Generic;

using System.Collections.ObjectModel;

using System.Linq;

using System.Data.Linq;

using System.Data.Linq.Mapping;

using System.Text;

using System.ComponentModel;  

The next section contains the namespace and class declarations. 

namespace MonProgramme.DAL

{

 

    /// <summary>

    /// Generic Interface to Database

    /// using LINQ to SQL

    /// </summary>

          public class EntityCrud

          {

 

 

Première fonction permettant de récuperer un objet par sa clé Primaire.

               /// <summary>

                   /// Select by Primary Key Value

                   /// </summary>

                   /// <typeparam name="T"></typeparam>

                   /// <param name="id">The PK value to search for</param>

                   /// <returns>Single matching PK to id</returns>

                   public static T SelectByPK<T>(String id) where T : class

                   {

                             try

                             {

                                      using (NWindDataContext context = new

                        NWindDataContext())

                                      {

                              // Récupère la table du type passé

                                                var table = context.GetTable<T>();

 

                              // Récupère le mapping de l’objet avec la Base

                                                MetaModel modelMap = table.Context.Mapping;

 

                              // Récupère les members de l’objet

                              ReadOnlyCollection<MetaDataMember> dataMembers

                              = modelMap.GetMetaType(typeof(T)).DataMembers;

 

                              // Cherche le nom du champ de la clé primaire

                              string pk = 

                              (dataMembers.Single<MetaDataMember>(m =>

                              m.IsPrimaryKey)).Name;

 

                              // Retourne l’objet unique qui correspond à cette clé primaire

                              // passée en argument

                                    return table.SingleOrDefault<T>(delegate(T t)

                                    {

                                    String memberId =

      t.GetType().GetProperty(pk).GetValue(t,

                                    null).ToString();

                                    return memberId.ToString() == id.ToString();

                                    }

      );

                                      }

                             }

                             catch (Exception)

                             {

                                      throw;

                             }

                   }

 

 

Seconde méthode permettant de récupérer toutes les objets de la base.

 

        /// <summary>

        /// Select All by Type

        /// </summary>

        /// <typeparam name="T"></typeparam>

        /// <returns>Matching table as typed list</returns>

        public static IList<T> SelectAll<T>() where T : class

        {

            try

            {

                using (NWindDataContext context = new NWindDataContext())

                {

                    // Récupère la table qui correspond au type

                    // et retourne tous les enregistrement sous forme de liste

                    var table = context.GetTable<T>().ToList<T>();

                    return table;

                }

            }

            catch (Exception)

            {

                throw;

            }

        }

 

Méthode d’insertion de donnée dans la base.

                   /// <summary>

                   /// Insert an Object into a Table

                   /// </summary>

                   /// <typeparam name="T"></typeparam>

                   /// <param name="item"></param>

                   public static void Insert<T>(T item) where T : class

                   {

                             try

                             {

                // Récupère la table du type passé en argument

                // Insert l’enregistrement et soumet les changements à la Base

                                      using (NWindDataContext context = new

                        NWindDataContext())

                                      {

                              // Récupère la table correspondante

                                                var table = context.GetTable<T>();

 

                              // Passe l’objet à la method InsertOnSubmit

                              // et Soumet les changements

                                                table.InsertOnSubmit(item);

                              context.SubmitChanges();

                                      }

                             }

                             catch (Exception)

                             {

                                      throw;

                             }

              }

 

Méthode de mise à jour de donnée.

 

       /// <summary>

                   /// Update an Existing Object

                   /// </summary>

                   /// <typeparam name="T"></typeparam>

                   /// <param name="item">The object to update</param>

                   public static void Update<T>(T item) where T : class

                   {

                             try

                             {

                        // Crée une nouvelle instance de l’objet

                                      Object newObj = Activator.CreateInstance(typeof(T),    

                        new object[0]);

 

                                      PropertyDescriptorCollection originalProps =

                        TypeDescriptor.GetProperties(item);

 

                        // Donne la valeur de la donnée passée en argument à l’objet

                                      foreach (PropertyDescriptor currentProp in

                        originalProps)

                                      {

                                                if (currentProp.Attributes[typeof(

                              System.Data.Linq.Mapping.ColumnAttribute)] !=

                              null)

                                                {

                                                          object val = currentProp.GetValue(item);

                                                          currentProp.SetValue(newObj, val);

                                                }

                                      }

 

                        // Lie l’objet à un nouveau context de donnée

                        // et soumet les changement à la Base.

                                      using (NWindDataContext context = new

                        NWindDataContext())

                                      {

                                                var table = context.GetTable<T>();

                                                table.Attach((T)newObj, true);

                                                context.SubmitChanges();

                                      }

                             }

                             catch (Exception)

                             {

                                      throw;

                             }

                   }

 

Code de suppression d’un objet.

               /// <summary>

                   /// Remove an object

                   /// </summary>

                   /// <typeparam name="T"></typeparam>

                   /// <param name="item"></param>

                   public static void Remove<T>(T item) where T : class

                   {

                             try

                             {

                        // Crée une instance de l’objet avec le type passé en argument

                                      Type tType = item.GetType();

                                      Object newObj = Activator.CreateInstance(tType, new 

                        object[0]);

 

                        // Récupère les proprieties de l’objet passé en argument

                                      PropertyDescriptorCollection originalProps =

                        TypeDescriptor.GetProperties(item);

 

                        // Copie le contenue de la donnée passée en argument

                        // au nouveau objet du meme type

                                      foreach (PropertyDescriptor currentProp in

                        originalProps)

                                      {

                                                if (currentProp.Attributes[typeof(

                              System.Data.Linq.Mapping.ColumnAttribute)] !=

                              null)

                                                {

                                                          object val = currentProp.GetValue(item);

                                                          currentProp.SetValue(newObj, val);

                                                }

                                      }

 

                        //lie l’objet à la table, appel de la function deleteOnSubmit

                        // et soumet les changement à la base.

                                      using (NWindDataContext context = new

                        NWindDataContext())

                                      {

                                                var table = context.GetTable<T>();

                              table.Attach((T)newObj, true);

                                                table.DeleteOnSubmit((T)newObj);

                                                context.SubmitChanges();

                                      }

                             }

                             catch (Exception)

                             {

                                      throw;

                             }

                   }

 

Utilisation :

Une fois l’EntityCrud créé vous pouvez l’utiliser comme dans les exemples suivant :

Exemple Insert :

           try

                             {

                             Customer c = new Customer();

                             c.CustomerID = "AAAAA";

                             c.Address = "554 Westwind Avenue";

                             c.City = "Wichita";

                             c.CompanyName = "Holy Toledo Bibles";

                             c.ContactName = "Frederick Flintstone";

                             c.ContactTitle = "Boss";

                             c.Country = "USA";

                             c.Fax = "316-335-5933";

                             c.Phone = "316-225-4934";

                             c.PostalCode = "67214";

                             c.Region = "EA";

 

                             Order_Detail od = new Order_Detail();

         od.Discount = .25f;

                             od.ProductID = 1;

                             od.Quantity = 25;

                             od.UnitPrice = 25.00M;

 

                             Order o = new Order();

                             o.Order_Details.Add(od);

                             o.Freight = 25.50M;

                             o.EmployeeID = 1;

                             o.CustomerID = "AAAAA";

 

                             c.Orders.Add(o);

 

                             EntityCrud.Insert<Customer>(c); //INSERT Customer mais aussi les autres champs qui lui sont associés (order, order_detail).

 

                             }

                             catch (Exception ex)

                             {

                                      MessageBox.Show(ex.Message);

                             }

 

Les données seront toutes insérée en base : Le Customer, L’order et l’order_detail avec seulement cet appel : EntityCrud.Insert<Customer>(c);

Exemple Delete :

                             try

                             {

                             Customer doa = EntityCrud.SelectByPK<Customer>("AAAAA");

                                     EntityCrud.Remove<Customer>(doa); //DELETE

                             }

                             catch (Exception ex)

                             {

                                      MessageBox.Show(ex.Message);

                             }

Exemple Update :

 

         try

                             {

                                      var q = EntityCrud.SelectByPK<Customer>("AAAAA");

 

                                      q.City = "Calgary";

                                      q.Country = "Canada";

                                      q.Address = "100 Longhorn Drive";

                                      q.CompanyName = "Holy Moses Bibles";

                                      q.Region = "EE";

                                      q.ContactTitle = "Gopher";

                                      q.ContactName = "Moxie Peroxide";

 

                                      EntityCrud.Update<Customer>(q);//UPDATE

                             }

                             catch (Exception ex)

                             {

                                      MessageBox.Show(ex.Message);

                             }

 

ADO.NET, ASP.NET AJAX, C#, WPF , , , ,

ASP.NET AJAX 4 : Exemple d’utilisation

8. June 2009 by Davy.Houareau

Nous allons aborder dans cet article un exemple d’utilisation de l’ASP.NET AJAX 4. Cet exemple consiste en l’affichage de produits en fonction de la catégorie sélectionnée. Tout en avançant, nous allons nous attarder sur le fonctionnement de ce nouvel aspect d’ASP.NET AJAX.

Le but de cette nouvelle approche de l’AJAX avec l’ASP.NET est de faire en sorte que le serveur se concentre plus sur l’aspect « donnée » que sur l’aspect « présentation ». En effet, il est possible de faire un site web qui interagit avec une base de données sans aucun contrôle serveur très facilement. C’est sur ce modèle que notre exemple d’utilisation portera (Client « pur » AJAX). On avait l’habitude d’utiliser un script manager couplé à un update panel pour faire de l’AJAX avec nos contrôles serveur et cette technique de rendement partiel nous rendait déjà la tâche assez facile puisqu’on avait de l’AJAX sans patauger dans le JAVASCRIPT. Maintenant, on peut faire de l’AJAX tout aussi simplement sans script manager et sans update panel. Nous verrons ce que sont les nouveaux contrôles client « DataView » et « DataContext »

1. Préparatifs (Exposition de la base de données)

Dans cet exemple nous allons utiliser un ADO.NET Data Service pour interagir avec la base de données, mais il est possible d’utiliser un ASMX ou encore WCF. Les possibilités sont multiples à conditions que le service soit compatible JSON (JavaScript Object Notation -> un format d’échange de données). Commençons par créer un nouveau projet « ASP.NET Web Application » puis ajoutons un ADO.NET Entity Data Model qui pointe sur la base de données que nous intéresse (ici Northwind). Appelons le, ADOEntityDataModel.

Maintenant nous allons pouvoir exposer cet Entity Data Model via un ADO.NET Data Service que nous appellerons MyWebDataService. Puis nous pourrons modifier MyWebDataService.svc pour pouvoir lui associer l’Entity Data Model.

Il faut modifier l’héritage en rajoutant le nom de classe de la source de données. Ici NorthwindEntities. Par défaut c’est le [nom_de_la_base_de_données+Entities]. Vous trouverez ce nom dans le fichier designer de l’Entity Data Model. Notre Entity Data Model est maintenant associé au service mais nous n’avons pas défini ce qui était exposé et de quelle manière. Pour cela nous utiliserons config.SetEntitySetAccessRule("*", EntitySetRights.All);. « * » pour dire que tout est visible et EntitySetRights.All pour autoriser la lecture et l’écriture.

Ce qui donne le code ci-dessous :

public class MyWebDataService : DataService<NorthwindEntities>

    {

        // This method is called only once to initialize service-wide policies.

        public static void InitializeService(IDataServiceConfiguration config)

        {

            config.SetEntitySetAccessRule("*", EntitySetRights.All);

        }

    }

Certes pour notre exemple la sécurité n’est pas optimale mais nous voici avec une base de données exposée assez simplement. Il ne nous reste plus qu’a nous concentrer sur l’ASP.NET AJAX 4 :).

2. Utilisation

Puisque notre exemple porte sur un client « pur » AJAX, supprimons le fichier Default.aspx et ajoutons un simple fichier html que nous nommerons categories.htm. Pour pouvoir utiliser ASP.NET AJAX 4 nous avons besoin de quelques fichiers JavaScript que vous pouvez trouver sur CODEPLEX.

3 Fichiers sont nécessaires:

  • MicrosoftAjax.js (base obligatoire)
  • MicrosoftAjaxAdoNet.js (on utilise de l’ADO.NET)
  • MicrosoftAjaxTemplates.js (pour avoir des templates où nous afficherons les données)

Ajoutons donc un répertoire « Scripts » et nos 3 fichiers JavaScript puis incluons-les dans notre page categories.htm.

Ce n’est pas tout, il nous faut aussi ajouter deux namespaces:

  • xmlns:sys="javascript:Sys"
  • xmlns:dataview="javascript:Sys.UI.DataView" (nous verrons un peu plus tard le Dataview)
  • sys:activate="*" (activer tous les éléments de la page pour le support d’attributs sys, On l’utilisera pour la sélection)

Notre page categories.html ressemble donc à ceci :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

<head>

    <title>Categories</title>

    <link type="text/javascript" href="Content/Scripts/MicrosoftAjax.js" />

    <link type="text/javascript" href="Content/Scripts/MicrosoftAjaxAdoNet.js" />

    <link type="text/javascript" href="Content/Scripts/MicrosoftAjaxTemplates.debug.js" />

</head>

<body xmlns:sys="javascript:Sys"

      xmlns:dataview="javascript:Sys.UI.DataView"

      sys:activate="*">

</body>

</html>

Maintenant, nous sommes prêts à aborder le template client.

Grâce à ASP.NET AJAX 4, presque n’importe quelle balise html peut devenir un template dans le lequel on pourra faire du binding. Pour qu’une balise soit reconnue en tant que template, il faut qu’elle possède l’attribut class="sys-template". Ce nom est une convention et doit être utilisé simplement parce que le moteur de rendu cherchera ce nom de classe pour manipuler le template. Il est conseillé de définir cette classe dans le CSS en tant que display:none;. Lors de l’affichage, ce style sera modifié automatiquement afin de voir le résultat.

Pour notre exemple, notre template sera une balise tbody.

    <table cellspacing="0">

        <thead>

            <tr><th colspan="2">Categories</th></tr>

            <tr><th>Name</th><th>Description</th></tr>

        </thead>

        <tbody class="sys-template">

        </tbody>

    </table>

.sys-template

{

    display: none;

}

Une fois la balise reconnue en tant que template, il ne reste plus qu’à faire du binding et il est possible d’en faire n’importe où à l’intérieur du template. Il existe deux écritures possibles : une courte, une longue. L’écriture courte se contente de rendre la valeur de la propriété de l’objet telle quelle et elle se présente de cette façon : {{ MyProperty }}. Ce type de binding se fait dans un seul sens et une seule fois (one-time binding). En ce qui concerne l’écriture longue, l’équivalent de {{ MyProperty }} est : {binding MyProperty, mode=oneWay}. L’écriture longue permet de faire du binding bidirectionnelle et d’utiliser une fonction pour « convertir » le rendu de la Valeur. Pour faire du bidirectionnel, il suffit de { binding MyProperty }. Quand on parle ici de binding bidirectionnelle, c’est au sein du même contexte.

Le template fourni également des pseudo-colonnes prédéfinies qui permettent d’accéder à des valeurs bien utiles comme $index, $dataitem, $id, $element.

  • $index : l’index de l’élément courant. (pratique un style alternatif)
  • $dataitem : l’élément courant
  • $id("ID") : créer ou accède à un identifiant unique pour l’élément en court. La valeur sera le nom spécifié + l’index (ici « ID3 » par exemple)
  • $element : récupère la balise dans laquelle ce mot clé est spécifié (ex :<div>{{$element}}</div>retournera la balise div).
C’est le bon moment pour aborder les deux nouveaux contrôles client que nous apporte ASP.NET AJAX 4 : le DataView et le DataContext.

Le DataContext est un proxy qui va communiquer avec un service sachant utiliser des données sous forme de JSON. C’est lui qui fera la liaison entre le client et le service.

Voici comment le déclarer :

<script type="text/javascript">

        var dataContext = $create(

            Sys.Data.AdoNetDataContext, { serviceUri: "MyWebDataService.svc" });

</script>

Vu que nous utilisons ADO.NET nous sommes obligés de déclarer notre DataContext de cette façon avec Sys.Data.AdoNetDataContext.

Le DataView, quant à lui, doit être associé à un template. Il peut traiter une collection d’éléments en répliquant l’instance de son template pour chaque élément de la collection. Il peut être utilisé pour un affichage sous forme de détail ou de liste. Il possède pas mal de points important pour sa configuration. Nous ne verrons que ceux dont nous aurons besoin.

Pour notre exemple voici à quoi doit ressembler notre balise tbody :

<tbody class="sys-template"

               sys:attach="dataview"

               dataview:sys-key="master"

               dataview:dataprovider="{{dataContext}}"

               dataview:autofetch="true"

               dataview:fetchoperation="Categories"

               dataview:selecteditemclass="rowSelected"

               dataview:fetchparameters="{{ {$expand: 'Products'} }}"

               dataview:initialselectedindex="0">

</tbody>

Quelques explications s’imposent non ?

  • sys:attach="dataview" : permet de déclarer le DataView
  • dataview:sys-key="master" : permet d’identifier le DataView (ici notre DataView s’appelle master)
  • dataprovider="{{dataContext}}" : permet de binder le DataView au DataContext déclaré plus haut.
  • dataview:autofetch="true" : récupérer les données au chargement de la page.
  • dataview:fetchoperation="Categories" : La fonction du service à appeler pour récupérer les données
  • dataview:selecteditemclass="rowSelected" : style pour la ligne sélectionnée.
  • dataview:fetchparameters="{{ {$expand: 'Products'} }}" : fetchparameters pour passer des paramètres à la requête et ici $expand permet de récupérer les éléments de la propriété de navigation « Products » de l’Entity Set « Categories » (Ce qui nous servira pour afficher les produits des catégories plus tard).
  • dataview:initialselectedindex="0" : Présélectionner un élément par défaut.

Il nous manque maintenant le binding. Vu que nous n’avons pas besoin ici de binding bidirectionnel, nous utiliserons l’écriture courte.

Voici à quoi notre binding ressemble :

<tr sys:command="select" class:alternaterow="{{ $index % 2 != 0 }}">

    <td>

        {{ CategoryName }}

    </td>

    <td>

        {{ Description }}

    </td>

</tr>

Notez la présence deux attributs « spéciaux » :

  • sys:command="select" : permet la sélection de l’élément.
  • class:alternaterow="{{ $index % 2 != 0 }}" : petite astuce pour avoir un style alternatif. Le style ici sera alternaterow.

N’oublions pas de rajouter ces classes dans le style :

.rowSelected

{

    color:Red;

}

.alternaterow

{

    background-color:#A3B8FF;

}

Il ne nous reste plus qu’a nous occuper de l’affichage des produits. Là aussi, il nous faut utiliser un DataView que nous lierons au premier.

Voici le DataView pour l’affichage des produits :

<table cellspacing="0">

        <thead>

            <tr>

                <th colspan="2">

                    Products

                </th>

            </tr>

            <tr>

                <th>

                    Name

                </th>

                <th>

                    Price

                </th>

            </tr>

        </thead>

        <tbody id="product-template" class="sys-template" sys:attach="dataview" dataview:data="{binding selectedData.Products, source={{master}} }">

            <tr>

                <td>

                    {binding ProductName}

                </td>

                <td>

                    {binding UnitPrice}

                </td>

            </tr>

        </tbody>

    </table>

Ici, la seule nouveauté c’est : dataview:data="{binding selectedData.Products, source={{master}} }" : Tout simplement pour indiquer que les données qui vont être utilisées par ce DataView proviennent de l’élément sélectionné dans le DataView « master ».

Et nous voici au résultat tant attendu :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title>Categories</title>

    <link href="Style/style.css" rel="stylesheet" type="text/css" />

    <script src="Scripts/MicrosoftAjax.js" type="text/javascript"></script>

    <script src="Scripts/MicrosoftAjaxTemplates.js" type="text/javascript"></script>

    <script src="Scripts/MicrosoftAjaxAdoNet.js" type="text/javascript"></script>

    <script type="text/javascript">

        var dataContext = $create(Sys.Data.AdoNetDataContext, { serviceUri: "MyWebDataService.svc" });

    </script>

    <style type="text/css">

        .sys-template

        {

            display: none;

        }

        .rowSelected

        {

            color:Red;

        }

        .alternaterow

        {

             background-color:#A3B8FF;

        }

    </style>

</head>

<body xmlns:sys="javascript:Sys"

      xmlns:dataview="javascript:Sys.UI.DataView"

      sys:activate="*">

       

    <table cellspacing="0">

        <thead>

            <tr>

                <th colspan="2">

                    Categories

                </th>

            </tr>

            <tr>

                <th>

                    Name

                </th>

                <th>

                    Description

                </th>

            </tr>

        </thead>

        <tbody class="sys-template"

               sys:attach="dataview"

               dataview:sys-key="master"

               dataview:dataprovider="{{dataContext}}"

               dataview:autofetch="true"

               dataview:fetchoperation="Categories"

               dataview:selecteditemclass="rowSelected"

               dataview:fetchparameters="{{ {$expand: 'Products'} }}"

               dataview:initialselectedindex="0">

            <tr sys:command="select" class:alternaterow="{{ $index % 2 != 0 }}">

                <td>

                    {{ CategoryName }}

                </td>

                <td>

                    {{ Description }}

                </td>

            </tr>

        </tbody>

    </table>

    <table cellspacing="0">

        <thead>

            <tr>

                <th colspan="2">

                    Products

                </th>

            </tr>

            <tr>

                <th>

                    Name

                </th>

                <th>

                    Price

                </th>

            </tr>

        </thead>

        <tbody id="product-template" class="sys-template" sys:attach="dataview" dataview:data="{binding selectedData.Products, source={{master}} }">

            <tr>

                <td>

                    {binding ProductName}

                </td>

                <td>

                    {binding UnitPrice}

                </td>

            </tr>

        </tbody>

    </table>

</body>

</html>

3.Conclusion

Comme vous avez pu le constater, nous avons pu réaliser un client « pure » AJAX en écrivant deux lignes de JAVASCRIPT grâce a ASP.NET AJA 4 . Evidement nous avons abordé un exemple précis mais cette nouvelle façon de faire de l’AJAX offre beaucoup d’autres possibilités d’utilisation.

ADO.NET, ASP.NET AJAX