Mon premier pitch en D1A en Mars 1994
Mot de passe :
Accueil | 
Résultats du mot clé Tutoriel
12/09/2008
Authentification en wsHttpBinding via les MembershipProvider et RoleProvider avec WCF

On peut dire que j’ai pas mal galéré avant de faire fonctionner mon modèle. Le challenge ne s’annonçait pas si compliqué pourtant ! Faire des services WCF et les raccorder à mes Memberships, c’est une simplicité que Microsoft met volontiers en avant. En pratique, moins simple d’autant plus que la documentation MSDN était incomplète. La remontée d’information auprès de Microsoft via Peter Huang du support MS a permis de corriger cette lacune.

La solution était tellement disséminée sur le web que j’ai décidé de vous faire ce tutoriel qui consiste à :

-          Créer un service Web via WCF en wsHttpBinding, tout en autorisant les sessions Http

-          Sécuriser ce flux via mes MemberShip et Role Providers

-          Installer ce fameux certificat sur le poste serveur et client.

1.      Le Service WCF

1.1.          Le service

using System;

using System.ServiceModel;

using System.Web;

using System.ServiceModel.Activation;

using System.Threading;

namespace BusinessLayer

{

[ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode.PerCall)]

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

    public class MyService : ServiceLayer.IService

    {

        public string MyOperation(string myValue)

        {

            if (HttpContext.Current.Session["nb"] == null)

                HttpContext.Current.Session["nb"] = 0;

HttpContext.Current.Session["nb"] = Convert.ToInt32(HttpContext.Current.Session["nb"].ToString()) + 1;

return String.Format("Hello {0}, I mean {1}, visiting for the {2} time with Session {3}", myValue, Thread.CurrentPrincipal.Identity.Name, HttpContext.Current.Session["nb"].ToString(), HttpContext.Current.Session.SessionID) ;

        }

    }

}

Mon service est plutôt simpliste. Il s’agit de récupérer le paramètre envoyé, d’ajouter 1 à la session en cours et de retourner l’information avec le nom de l’utilisateur actuellement connecté.

Attention, veillez à bien mettre l’attribut AspNetCompatibilityRequirements pour être en mesure de traiter le HttpContext. Sans cela, HttpContext.Current sera toujours null.

Notre classe implémente l’interface IService. C’est par ce biais que le service sera exposé via WCF.

1.2.          L’interface

using System;

   using System.ServiceModel;

   namespace ServiceLayer

{

[ServiceContract( Namespace = "http://www.elgee.com/1/0/0/0",     SessionMode = SessionMode.Required)]

    public interface IService

    {

       [OperationContract(IsInitiating=true)]

        string MyOperation(string myValue);

    }

}

Mon interface expose la méthode MyOperation, c’est le contrat. Le service lui est définit au niveau de l’attribut de mon Interface

1.3.          Le Service en frontal

C’est par le biais d’un service.svc que le service peut s’exposer via IIS.

<%@ ServiceHost Language="C#" Debug="true" Service="BusinessLayer.MyService" CodeBehind="~/App_Code/MyService.cs" %>

Là, encore rien de très compliqué.

2.     Le paramétrage du service dans le Web.Config

2.1.          Le Membership Provider

Pour l’occasion, j’ai réalisé un Membership provider très simple, avec les identifiants et mots de passe en dur dans le code.

    <membership defaultProvider="MyMembershipProvider">

        <providers>

           <clear/>

<add name="MyMembershipProvider" type="Secure.SimpleMembershipProvider" applicationName="Test" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression=""/>

        </providers>

</membership>

Mon Membership est dans le namespace Secure.SimpleMembershipProvider.

2.1. Le RoleProvider

Idem pour le RoleProvider, très simplifié aussi.

    <roleManager enabled="true" defaultProvider="MyRoleProvider">

      <providers>

        <clear/>

        <add name="MyRoleProvider" type="Secure.SimpleRoleProvider"/>

      </providers>

    </roleManager>

2.2.          Le ServiceModel

C’est une nouvelle zone disponible à partir du framework 3.0.

2.2.1.     La compatibilité ASP.Net

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

Cet élément permet de pouvoir gérer les notions de Session dans vos services WCF.

2.2.2.     Le Binding

     <bindings>

      <wsHttpBinding>

         <binding name="MyBinding"  messageEncoding="Mtom" >

          <security mode="Message">

            <message clientCredentialType="UserName"/>

             </security>

           </binding>

        </wsHttpBinding>

     </bindings>

Le Binding, en fonction du transport choisit choisit la manière dont les données seront transportées. Pour utiliser les Membership provider, il faut absolument utiliser le wsHttpBinding. Le messagEncoding est optionnel et par contre doit être utilisé si vous transmettez des données binaires volumineuses.

L’élément Message permet de spécifier que lors du transport, l’accès au message est sécurisé par un système d’authentification. La sécurité sur le transport peut également être mise en œuvre dans le cadre d’un flux sécurisé sous SSL.

2.2.3.     Le behavior

<behavior name="Secured">

<serviceCredentials>

<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="MyMembershipProvider"/>

<serviceCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySerialNumber"

findValue="6d 0d 18 03 07 6e fe a0 4b bb 7c fc 76 af 01 48"/>

   </serviceCredentials>

   <serviceDebug includeExceptionDetailInFaults="true"/>

   <serviceMetadata httpGetEnabled="true"/>

<serviceAuthorization impersonateCallerForAllOperations="false" principalPermissionMode="UseAspNetRoles" roleProviderName="MyRoleProvider"/>

</behavior>

Le behavior est le comportement de votre service. Ici, on précise que la sécurité est gérée grâce au MembershipProvider en indiquant son nom et pas son namespace.

Un certificat est nécessaire pour ce mode de fonctionneemnt. J’ai décidé de le rechercher via le SerialNumber, je vous explique plus loin comment le retrouver.

Enfin, ne pas oublier également les autorisations via le RoleProvider. Si vous l’oubliez, il ne sera pas possible de récupérer coté service le nom de l’utilisateur connecté.

2.2.4.     Le Service

   <service behaviorConfiguration="Secured"

            name="BusinessLayer.MyService">

     <endpoint binding="wsHttpBinding"

               bindingConfiguration="MyBinding"

               name="MyServiceEndPoint"

               contract="ServiceLayer.IService">

     </endpoint>

   </service>

Le service doit utiliser notre behavior « Secured ». Son name correspond au nom de la classe avec son namespace. Le service s’expose via un ou plusieurs EndPoints. Notre endpoint retenu est le wsHttpBinding qui doit utiliser notre configuration de binding. Le contrat n’est rien d’autre que le nom de l’interface avec son namespace.

3.     Les certificats X.509

3.1.          Création des certificats

Il est nécessaire d’installer 2 certificats pour utiliser les membership provider dans WCF. Afin d’éviter les mauvaises surprises, je vous conseille de vérifier le fuseau horaire de votre serveur sur lequel vous allez créer les certificats. Checkez que vous êtes sur le bon et que votre machine est à l’heure.

Sur la machine qui hostera les services, lancez une fenètre MSDOS et créez le premier, qui est un certificat Racine :

makecert -n "CN=demoElGeeCA" -r -sv demoElGeeCA.pvk demoElGeeCA.cer

Le certificat est copié dans un .cer.

Exécutez maintenant cette ligne de commande pour le second certificat, qui est signé par le précédent :

makecert -sk TMMCA -iv TMMCA.pvk -n "CN=demoElGeeCA " -ic demoElGeeCA.cer demoElGee.cer -sr LocalMachine -ss My -sky exchange –pe

Il faut également maintenant prépare le certificat pour son installation coté client. Lancez la commande suivante :

pvk2pfx.exe -pvk demoElGeeCA.pvk -spc demoElGeeCA.cer

Une boite de dialogue vous demandera de saisir le mot de passe de la clé. Saisissez-le et accédez aux écrans suivants. Cochez le bouton Oui, Exporter la clé privée.

Cochez les cases comme ci-dessous :

Fournissez un nouveau mot de passe lié au certificat que vous donnerez à votre client :

Donnez un nom à votre fichier pfx :

Générez alors votre fichier. Vous devrez fournir à votre client :

-          Le .pfx et son mot de passe

-          Le demoElGee.cer

3.1.          Déploiement du certificat coté Serveur

Il faut maintenant les mettre dans le bon magasin sur votre serveur

Double cliquez sur le .pfx. A la saisie du mot de passe, cochez les cases comme dans la copie d’écran ci-dessous.

Placez le dans le magasin de certificats « Autorités de certification racines de confiance »

Sur demoElGee.cer, double cliquez et placez le dans le magasin de certificats « Personnes autorisées ».

3.2.          Vérification de l’installation des certificats

Pour vérifier leurs installations, lancez la commande certmgr.msc pour atteindre le gestionnaire de certificats

Dans Action, Cliquez sur Recherche des certificats :

Nos deux certificats apparaissent maintenant. Cliquez sur demoElGee pour trouver le SerialNumber dans l’onglet Détails. Son Serial est 6d 0d 18 03 07 6e fe a0 4b bb 7c fc 76 af 01 48. C’est bien celui déployé dans le Web.Config.

4.     Les autorisations sur les certificats

Il faut maintenant autoriser le compte qui exécute le site qui héberge les services à accéder à mon certificat. Pour cela, il faut utiliser les outils de WSE 3.0,  installé avec les composants WCF de Visual Studio.

Tout d’abord, il vous faut créer un utilisateur local, nous le nommerons IIS. Il devra :

-          Etre membre de Network Configuration Operators

-          Etre membre de IIS_WPG

-          Avoir les droits en écriture sur le répertoire temporaire de Windows (par défaut c:\windows\temp). Ce répertoire est utilisé par WCF pour créer ces fichiers temporaires.

Créez ensuite un pool d’application dans IIS. Ce pool devra être exécuté sous l’utilisateur IIS que nous venons de paramétrer.

Dans C:\Program Files\Microsoft WSE\v3.0\Samples, lancez la ligne de commande suivante :

winhttpcertcfg -g -c LOCAL_MACHINE\My -s demoElGee -a IIS

5.     Le Client

J’ai développé comme d’habitude une petite application Console qui utilise mon WebService.

Ajoutez une Référence de Service sur l’url http://monserveur:2174/WebWCF/service.svc. Cette référence est nommée myWS.

5.1.          Le Web.Config

Visual Studio, en fonction des paramètres du service aura paramétré votre Web.Config. Attention néanmoins, il est possible que la référence au ClientBehavior ne soit pas implémentée. Voici ce que vous devez avoir :

<system.serviceModel>

    <client>

      <endpoint address="http:// monserveur:2174/WebWCF/service.svc"

        binding="wsHttpBinding" bindingConfiguration="MyServiceEndPoint" behaviorConfiguration="ClientBehavior"

        contract="WCFClient.myWs.IService" name="MyServiceEndPoint">

        <identity>

          <certificate encodedValue="AwAAAAEAAAAUAAAAxbZa1hFs3b1

JAfYwpE9Il/zo6aggAAAAAQAAAP4BAAAwggH6MIIBY6ADAgECAhBt
DRgDB27+oEu7fPx2rwFIMA0GCSqGSIb3DQEBBAUAMBYxFDASBgNVBAMTC2RlbW9FbEdl
ZUNBMB4XDTA3MTAxOTExMDkwOVoXDTM5MTIzMTIzNTk1OVowFDESMBAGA
1UEAxMJZGVtb0VsR2VlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDT+M9mMWez9Rws
PdmeEl2MPbyNbbpuGH1L1nWOfZrdpSw9oleMH9Lj+wsvbypH7kpb/+qdej7IL3PAI1
ILaBh/KJSJinSNwl31ogwc1ajf+4FKuL81JxmYGyNXNP1i+1Lqi1nDFrHE8gstWPIRG0vqJgF
ZKmD32dds9pjPOqU9GwIDAQABo0swSTBHBgNVHQEEQDA+gBD6aWNw7LnwnUlJxU9bL3NIoRg
wFjEUMBIGA1UEAxMLZGVtb0VsR2VlQ0GCEC4wB2m1DKisScmh4S808NMwDQYJKoZIhvcNAQE
EBQADgYEAwkvKxeN6NiCvucmoK7cajGiKCNVOmI5biPmOt6yoFRvlX9iVVKPgUaG6o3t2iej
ljFxdQsR5DFIN+Rkrk6rV1SyGrGkUvJOhEZtdAfSjoCdiTbf1c6YAnU4a12t433si3R
Mz8XcGiFg4oWiHHj+MyYgmR4trDnCTfqQTYDBGppg=
" />

        </identity>

      </endpoint>

    </client>

Le service est bien référencé sur mon URL en wsHttpBinding. Il utilise un behavior et une identité qui correspond au certificat installé sur le serveur. Je n’ai pas tester l’application en client / Serveur. Il est peut être possible de devoir déployer le certificat sur le poste client.

    <bindings>

      <wsHttpBinding>

        <binding name="MyServiceEndPoint" closeTimeout="00:01:00" openTimeout="00:01:00"

          receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"

          transactionFlow="false" hostNameComparisonMode="StrongWildcard"

          maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Mtom"

          textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="true">

          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"

            maxBytesPerRead="4096" maxNameTableCharCount="16384" />

          <reliableSession ordered="true" inactivityTimeout="00:10:00"

            enabled="false" />

          <security mode="Message">

            <transport clientCredentialType="Windows" proxyCredentialType="None"

              realm="" />

            <message clientCredentialType="UserName" negotiateServiceCredential="true"

              algorithmSuite="Default" establishSecurityContext="true" />

          </security>

        </binding>

      </wsHttpBinding>

    </bindings>

Le paramétrage de mon EndPoint. J’ai mis allowCookies a true. Attention, à chaque update du ServiceReference, cette valeur se remet à false.

    <behaviors>

      <endpointBehaviors>

        <behavior name="ClientBehavior">

          <clientCredentials>

            <serviceCertificate>

             <authentication certificateValidationMode="PeerOrChainTrust" trustedStoreLocation="LocalMachine" revocationMode="NoCheck"/>

            </serviceCertificate>

          </clientCredentials>

        </behavior>

      </endpointBehaviors>

    </behaviors>

  </system.serviceModel>

Mon behavior qui est important. Sans lui, la requête échoue.

5.2.          Le code coté client

            myWs.ServiceClient ws = null;

            try

            {

                ws = new WCFClient.myWs.ServiceClient();

                ws.ClientCredentials.UserName.UserName = "elgee";

                ws.ClientCredentials.UserName.Password = "elgee";               

                Console.WriteLine(ws.MyOperation("toto1"));

                Console.WriteLine(ws.MyOperation("toto2"));

                ws = new WCFClient.myWs.ServiceClient();

                ws.ClientCredentials.UserName.UserName = "elgee";

                ws.ClientCredentials.UserName.Password = "elgee";

                Console.WriteLine(ws.MyOperation("toto3"));

                Console.WriteLine(ws.MyOperation("toto4"));

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex.Message);

                if (ex.InnerException != null)

                    Console.WriteLine(ex.InnerException.Message);

            }

            finally

            {

                ws = null;

            }

            Console.ReadLine();

Ne pas oublié donc de passer le credential, c'est-à-dire l’identifiant et le mot de passe qu’attendent le Membership Provider. Mon service est lancé deux fois pour voir comment les Sessions se comportent.

5.3.          L’installation du certificat

Comme pour le serveur, les deux certificats sont nécessaires pour faire fonctionner votre service. C’est contraignant, pas il n’y a pas le choix. Suivez la même procédure que le chapitre 3.2 avec le fichier .pfx et le DemoElGee.cer.

Entrez le mot de passe qui a été défini à la création du fichier PFX :

Déployez le certificat dans le magasin « Autorités de certification racines de confiance » :

Prenez maintenant fichier .CER (DemoElGee.cer) et double cliquez dessus pour l’installer (bouton installer le certificat). Installez le dans le magasin « Personnes autorisées ».

5.4.          Le résultat final

Cela marche nickel !!! Mon utilisateur est bien reconnu et son nom affiché ! Mes sessions fonctionnent parfaitement, ou presque, puisqu’à la connexion suivante, je ne récupère pas ma session.

6.     Conclusion

WCF apporte une grande souplesse sur la création de vos services au niveau du métier. Par contre, les couches de transport et le paramétrage s’est grandement complexifié. Le moindre paramètre de travers, vos services ne fonctionnent plus.

Pour aider à tracer l’exécution de vos services, je ne serai vous recommander ces quelques lignes dans votre Web.Config :

<configuration>

   <system.diagnostics>

      <sources>

            <source name="System.ServiceModel"

                    switchValue="Information, ActivityTracing"

                    propagateActivity="true">

            <listeners>

               <add name="traceListener"

                   type="System.Diagnostics.XmlWriterTraceListener"

                   initializeData= "c:\log\Traces.svclog" />

            </listeners>

         </source>

     </sources>

  </system.diagnostics>

</configuration>

Mots clés associés : WCF X.509 Tutoriel Membership Microsoft  | Lien permanent | Laissez le premier votre commentaire
Publiée dans la zone Tutoriels .Net
17/05/2007
Mon Portail : CustomControl d'encadrement de vos formulaires et éléments

Les éléments graphiques du portail sont inclus dans un encadrement aux cotés arrondis. Cet encadrement peut prendre plusieurs couleurs et afin d'optimiser les développements j'ai réalisé un CustomControl très simple qui permet d'y inclure vos éléments. Nous allons donc voir comment ce CustomControl est utilisé dans l'interface graphique, ces implications au niveau des feuilles de style et la construction du CustomControl.

1. Utilisation du CustomControl

<elgee:Frame ID="FR12" runat="server" Couleur="jaune" Taille="275">

    <div class="billet_titre">Rechercher sur ce site</div><br />

    <div id="container_search_controls">

        <div id="google_search_form"></div>

        <div id="google_search_control"></div>

        <div id="live_search_container">

            <div id="live_search_query"></div>

            <div id="live_search_control"></div>   

        </div>

    </div>

</elgee:Frame>

Je prend l'exemple de la zone de recherche. Mon CustomControl s'appelle Frame et comme vous pouvez vous en rendre compte il inclut des éléments externes en son sein. Il dispose de 2 attributs, sa taille et la couleur à appliquer.

2. La gestion de l'apparence

On se basera donc sur une feuille de style. En se basant sur la valeur de l'attribut Couleur, on déclinera l'ensemble des éléments nécessaires au rendu graphique de l'encadrement.

.jaune_haut_gauche      {border-style: none; width:12px; height:21px; background-image: url(/App_themes/default/pics/box/jaune/haut_gauche.png);background-repeat: no-repeat; line-height:0; font-size:0;}

.jaune_haut             {border-style: none; height:21px; background-image: url(/App_themes/default/pics/box/jaune/haut.png);background-repeat: repeat-x; line-height:0; font-size:0;}

.jaune_haut_droite      {border-style: none; width:14px; height:21px; background-image: url(/App_themes/default/pics/box/jaune/haut_droite.png);background-repeat: no-repeat; line-height:0; font-size:0;}

.jaune_gauche           {border-style: none; width:12px; background-image: url(/App_themes/default/pics/box/jaune/gauche.png);background-repeat: repeat-y; line-height:0; font-size:0;}

.jaune_contenu          {border-style: none; background-color: #FFFFCC;}

.jaune_droite           {border-style: none; width:14px; background-image: url(/App_themes/default/pics/box/jaune/droite.png);background-repeat: repeat-y; line-height:0; font-size:0;}

.jaune_bas_gauche {border-style: none; width:12px; height:21px; background-image: url(/App_themes/default/pics/box/jaune/bas_gauche.png);background-repeat: no-repeat; line-height:0; font-size:0;}

.jaune_bas              {border-style: none; height:21px; background-image: url(/App_themes/default/pics/box/jaune/bas.png);background-repeat: repeat-x; line-height:0; font-size:0;}

.jaune_bas_droite {border-style: none; width:14px; height:21px; background-image: url(/App_themes/default/pics/box/jaune/bas_droite.png);background-repeat: no-repeat; line-height:0; font-size:0;}

Il y a donc une classe pour chaque coin de l'encadrement, pour chaque coté et le contenu. La règle de nommage consiste à commencer par le nom de la couleur, suivi de sa localisation. Comme vous le voyez, j'ai choisi un format PNG, qui gère mieux la transparence que le GIF. Mais attention aux surprises sur les navigateurs de type IE6 qui ne gère pas la transparence du format PNG.

3. Le code du CustomControl

Dans les attributs de la classe du CustomControl on définit la propriété par défaut et l'apparence coté designer en indiquant le nom du tag, ici Frame. Ne pas oublier les accesseurs publiques des propriétés.

   [DefaultProperty("Taille"), ControlValueProperty("Taille"), PersistChildren(true), ParseChildren(false),

   ToolboxData("<{0}:Frame runat=server></{0}:Frame>"), PersistenceModeAttribute(PersistenceMode.InnerProperty),

 Designer(typeof(System.Web.UI.Design.ContainerControlDesigner))]

    public partial class Frame : System.Web.UI.WebControls.WebControl

    {

        public int Taille

        {

            get { return _taille; }

            set { _taille = value; }

        }

        public string Couleur

        {

            get { return _couleur; }

            set { _couleur = value; }

        }

        private string _couleur = "blanc";

        private int _taille = 200;

        int _width = 0;

Il est ensuite nécessaire de surcharger les deux méthodes RenderBeginTag et RenderEndTag pour ajouter notre code. Vous noterez que la taille fournie au CustomControl est la taille totale, à laquelle je retire 26, car mes deux bordures ont 13 pixels de large. J'opte plutôt pour une table, plus fiable qu'un DIV dans ce cadre là.  

        public override void RenderBeginTag(HtmlTextWriter writer)

        {

            base.RenderBeginTag(writer);

            //Controls.Clear();

            _width = _taille - 26;

writer.AddStyleAttribute(HtmlTextWriterStyle.Width, _taille.ToString() + "px");

            writer.AddAttribute("cellpadding", "0");

            writer.AddAttribute("cellspacing", "0");

            writer.AddAttribute("border","0");

            writer.RenderBeginTag("table");     // Table container

            writer.RenderBeginTag("tr");        // TR de la premiere ligne

            writer.AddAttribute("class", _couleur + "_haut_gauche");

            writer.RenderBeginTag("td");

            writer.RenderEndTag();

            writer.AddAttribute("class", _couleur + "_haut");

writer.AddStyleAttribute(HtmlTextWriterStyle.Width, _width.ToString());

            writer.RenderBeginTag("td");

            writer.RenderEndTag();

            writer.AddAttribute("class", _couleur + "_haut_droite");

            writer.RenderBeginTag("td");

            writer.RenderEndTag();

writer.RenderEndTag();          // Fin du TR de la premiere ligne

            writer.RenderBeginTag("tr");        // TR de la seconde ligne

            writer.AddAttribute("class", _couleur + "_gauche");

            writer.RenderBeginTag("td");

            writer.RenderEndTag();

            writer.AddAttribute("class", _couleur + "_contenu");

writer.AddStyleAttribute(HtmlTextWriterStyle.Width, _width.ToString());

            writer.RenderBeginTag("td");

        }

        public override void RenderEndTag(HtmlTextWriter writer)

        {

            writer.RenderEndTag();

            writer.AddAttribute("class", _couleur + "_droite");

            writer.RenderBeginTag("td");

            writer.RenderEndTag();

writer.RenderEndTag();          // Fin du TR de la seconde ligne

            writer.RenderBeginTag("tr");        // TR de la troisieme ligne

            writer.AddAttribute("class", _couleur + "_bas_gauche");

            writer.RenderBeginTag("td");

            writer.RenderEndTag();

            writer.AddAttribute("class", _couleur + "_bas");

writer.AddStyleAttribute(HtmlTextWriterStyle.Width, _width.ToString());

            writer.RenderBeginTag("td");

            writer.RenderEndTag();

            writer.AddAttribute("class", _couleur + "_bas_droite");

            writer.RenderBeginTag("td");

            writer.RenderEndTag();

writer.RenderEndTag();          // Fin du TR de la premiere ligne

            writer.RenderEndTag();          // Fin de la table

            base.RenderEndTag(writer);

        }

    }  

Le tour est joué, votre CustomControl d'encadrement est fait. Reste plus qu'a jouer sur le panel de couleurs disponibles dans les feuilles de styles. Pour plus de fiabilité, on peut s'appuyer sur une énumération pour la liste des couleurs.

Mots clés associés : ASP.Net Tutoriel CustomControl Microsoft c#  | Lien permanent | Laissez le premier votre commentaire
Publiée dans la zone Technologies
20/04/2007
Tutoriel : PicasaNet et Composant Ajax



Droit de diffusion et copyrights :

Ce tutoriel ne peut être diffusé sur d’autres sites Web ou tout autre support sans l’autorisation préalable de son auteur. L’utilisation des sources est totalement libre de droits. Toutes les marques citées appartiennent à leurs auteurs, en particulier les marques Google, Picasa, ainsi que leurs logos respectifs sont des marques déposées par Google Inc.

Avant propos :

Cela fait bientôt un an que j’ai découvert  le framework Atlas, renommé ASP.Net Ajax 1.0. La richesse de cette technologie offre de nombreuses voies pour des tutoriels et la sortie de Picasa2 me permet d’aborder sur un cas concret. Début Janvier 2007, me voila en route pour faire un SlideShow en Ajax. 3 jours plus tard, le voici disponible dans la AjaxControlToolkit, réduisant à néant mes premières approches !!! Restait à l’améliorer et à l’adapter quelque peu.

Picasa dispose donc d’une API assez simple, qui s’attaque par une requête http en GET toute simple. L’exposition se fait via un flux rss, assez verbeux et qu’il convient de nettoyer. Nous aborderons ici des points techniques que j’ai pu déjà exposer lors de précédents tutoriels. Mais mieux vaut se répéter et disposer d’un tutoriel complet.

Ainsi nous aborderons les points suivants :

-          Récupération du flux XML via un HttpResponse

-          Transformation du flux via XSL

-          Désérialisation des données dans une classe .Net

-          L’utilisation du composant PicasaNet

Puis coté Ajax

-          Le WebService permettant de récupérer les requêtes

-          Le Toolkit Ajax et son fonctionnement

Le tutoriel s’articule sur une solution disposant :

-          Du projet PicasaNet qui permet d’interagir avec l’API de Picasa et qui dispose d’un AjaxControlToolkit

-          Un projet Web qui exploite le composant Ajax et l’API de PicasaNet

1.  PicasaNet

1.1       Qu’est-ce que c’est ?

PicasaNet est un composant gratuit et libre de droits qui vous permet d’interroger l’API de Google Picasa. Les données récupérées sont stockées dans des classes propres à PicasaNet, ce qui simplifie grandement l’accès, la manipulation et d’utilisation des informations fournies par Google Picasa. Le mode de récupération est plutôt évolutif. En ayant accès aux sources vous pouvez parfaitement enrichir les informations récupérées par PicasaNet.

La récupération est assez originale car elle se base sur une transformation XSL pour se caler aux structures des classes PicasaNet. Ce n’est peut être pas forcément la manière la plus efficace de faire, mais elle permet d’aborder une méthode différente et techniquement plus intéressante.

projetPicasaNet.jpg

Le dossier AjaxToolkit dispose du composant Ajax qui permet de restituer le contenu d’un WebAlbum Picasa.

Notez que le fichier JS doit absolument être une ressource incorporée. Pour cela, sélectionnez votre fichier, puis dans l’écran de propriétés, Action de génération choisissez « Ressource incorporée ».

Les dossiers Collections et Elements disposent de classes qui permettent de stocker les données issues de Picasa.

Response dispose des classes de base à utiliser. ListOfAlbums pour disposer de l’ensemble des albums d’un compte et PictureAlbum pour avoir l’ensemble des images d’un album.

Dans Xsl vous trouverez les deux feuilles de style qui permettent de transformer le flux RSS Picasa vers la structure PicasaNet. Ces feuilles de styles devront être déployées manuellement sur le site Web.

Picasa.cs est la classe de base à instancier pour utiliser le composant.

Il est à préciser que vous devez avoir installer l’environnement AJAX 1.0 pour modifier ou compiler ce composant.

Rendez vous sur http://ajax.asp.net/downloads/default.aspx?tabid=47 et installez :

-          ASP.Net 2.0 AJAX Extensions

-          ASP.Net AJAX Control Toolkit

-          ASP.Net Ajax Futures CTP

1.2       La récupération des flux XML

1.2.1     Tester son application avec ces propres URL

Il vous est bien entendu possible de tester vos propres Url de flux RSS Picasa notamment lorsque vous être en mode déconnecté. L’objet Picasa dispose d’une propriété AllowUrlChanging que vous pouvez mettre à True. Cela permet ensuite d’être en mesure de fournir vos propres Url locales ou distantes en modifiant ensuite les propriétés SetGoogleAlbumsListUrl (pour le flux de liste des albums) et SetGoogleAlbumUrl (pour le flux d’un album). Si ces propriétés ne sont pas initialisées, l’API prendra l’Url par défaut de Google Picasa, à laquelle il ajoutera les données variables comme le compte Picasa et éventuellement le numéro d’Album.

1.2.2     La liste des albums

La méthode GetAlbumsList() vous permet de récupérer dans une classe ListOfAlbums l’ensemble des albums d’un compte Google Picasa déterminé.

La première étape consiste à vérifier si le compte Picasa est bien fourni. C’est la méthode privée CheckRequiredArgs qui s’en charge. Elle ne vérifie la présence des données obligatoires que si vous laissez à l’API le soin de définir les Url de destination (voir chapitre 1.2.1). En fonction, BuildRequestForListOfAlbums construira la requête dans la variable _request qui est une variable membre.

                if (CheckRequiredArgs(_user))

                {

                    // Build httpRequest set _request variable

                    BuildRequestForListOfAlbums();

                    // Send Request the Google Picasa

                    HttpWebResponse v_response = DoGetResponse(_request);

DoGetResponse  récupère le contenu du flux RSS. Il s’agit d’invoquer un HttpWebRequest sur l’url construite. Il aurait été possible d’utiliser ici directement la variable membre _request plutôt qu’un paramètre dans la méthode.

        private HttpWebResponse DoGetResponse(string p_url)

        {

            HttpWebRequest v_request = null;

            HttpWebResponse v_response = null;

            // Initialise the web request