Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Atteint de JavaScriptite Aiguë [Cyril Durand]

Expert ASP.net Ajax et WCF, Cyril Durand parle dans son blog de point techniques sur ASP.net, ASP.net Ajax, JavaScript, WCF et .net en général. Cyril est également consultant indépendant, n'hésitez pas à le contacter pour de l'assistance sur vos projets

Actualités

  • Blog de Cyril DURAND, passionné de JavaScript, Ajax, ASP.net et tout ce qui touche au developpement Web Client-Side.

    Consultant freelance, n'hésitez pas à me contacter pour vos projets .net : architecture, accompagnement, formation, ...

    View Cyril Durand's profile on LinkedIn
    hit counters


    Expertise Commerce server et BizTalk

ASP.net – Partager la session entre plusieurs sous-domaines avec http ou https

Dans certains cas il peut être intéressant de pouvoir partager une session entre plusieurs sous-domaines. Cela nous permet par exemple d’avoir une session unique pour les urls fr.monsite.com et en.monsite.com ou http://www.monsite.com et https://secure.monsite.com.

Afin de bien comprendre notre problème, intéressons nous au fonctionnement des sessions.

Tout d’abord une session est partagée entre les pages d’un site via un cookie. Par défaut, ce cookie a pour nom ASP.NET_SessionId et contient une suite de 24 caractères alpha numériques aléatoires.

Lorsque l’on fait une requête vers ASP.net, un HttpContext est instancié. Ce contexte passe au travers de différents HttpModule dont le SessionStateModule, c’est ce module qui va se charger d’orchestrer les différentes étapes de la création / sauvegarde des variables de session. Dans un premier temps, ce module va récupérer un ID de session via le SessionIDManager, ce manager va regarder dans la requête s’il y a ou non le cookie de session contenant l’ID. S’il n’est pas présent, il va alors générer et retourner un ID unique. Le module va ensuite interroger le SessionStateStoreProvider afin de récupérer l’état de la session pour l’assigner au contexte de la requête.

Le traitement de la page s’exécute alors. Viens ensuite l’événement ReleaseRequesState qui va sauvegarder la session dans le SessionStateStoreProvider puis persister le SessionID dans la réponse renvoyé au client.

image

Deux classes sont responsables du fonctionnement des sessions, le SessionIDManager et le SessionStateStoreProvider. Le SessionStateStoreProvider permet de stocker les variables de sessions alors que SessionIDManager permet de sauvegarder côté client l’identifiant de session. ASP.net nous permet de personnaliser ces 2 classes via des interfaces.

Dans notre cas, nous avons besoin de créer notre propre SessionIDManager, en effet c’est lui qui est responsable de la création du cookie. Afin de simplifier l’implémentation, nous allons encapsuler le SessionIDManager natif, lors de la méthode SaveSessionID nous allons modifier la propriété Domain du cookie de session.


public class CustomSessionIDManager : ISessionIDManager { private ISessionIDManager _innerSessionIDManager; public CustomSessionIDManager() { this._innerSessionIDManager = new SessionIDManager(); } public void SaveSessionID(HttpContext context, string id, out bool redirected, out bool cookieAdded) { this._innerSessionIDManager.SaveSessionID(context, id, out redirected, out cookieAdded); // POC : not the best solution if (cookieAdded) { context.Response.Cookies["ASP.NET_SessionId"].Domain = "local.test"; } } // ... }

L’enregistrement de notre SessionIDManager se fait en renseignant la propriété sessionIDManagetType de la section sessionState du fichier de config.

<configuration> <system.web> <sessionState sessionIDManagerType="CustomSessionIDManager, App_Code" /> </system.web> </configuration>

Cette solution n’est pas optimum, en effet le nom du cookie est écrit en dur ainsi que le domaine. Le nom du cookie est spécifié via la propriété cookieName de la section sessionState du web.config, il nous est alors facilement récupérable. Pour le nom du domaine, nous avons 2 solutions, soit l’on réussit à le faire transiter du fichier de config vers notre SessionIDManager, soit on le calcul via le domaine courant. Malheureusement, on ne peut pas ajouter de paramètres au SessionIDManager via la section sessionState. Nous allons utiliser les AppSettings et le calcul si la clé n’est pas définit.

public class CustomSessionIDManager : ISessionIDManager { private String _cookieName; private ISessionIDManager _innerSessionIDManager; public CustomSessionIDManager() { this._innerSessionIDManager = new SessionIDManager(); } public void Initialize() { this._innerSessionIDManager.Initialize(); SessionStateSection sessionStateSection = (SessionStateSection)ConfigurationManager.GetSection("system.web/sessionState"); this._cookieName = sessionStateSection.CookieName; } public void SaveSessionID(HttpContext context, string id, out bool redirected, out bool cookieAdded) { this._innerSessionIDManager.SaveSessionID(context, id, out redirected, out cookieAdded); if (cookieAdded) { String domainName = ConfigurationManager.AppSettings["CustomSessionIDManager.CookieDomain"]; if (String.IsNullOrEmpty(domainName)) { domainName = context.Request.Url.Host; String[] domainParts = domainName.Split('.'); if (domainParts.Length > 1) domainName = String.Join(".", domainParts .Skip(domainParts.Length - 2) .ToArray()); } context.Response.Cookies[_cookieName].Domain = domainName; } } // ... }

Ainsi, nous pouvons accéder à la session entre plusieurs sous-domaines.

Bien sur, il faut que le SessionStateStoreProvider utilisé soit le même entre les différents sites. Si vous avez qu’un seul site définit pour les 2 urls au niveau de IIS, il n’est pas nécessaire de modifier le sessionStateStoreProvider. Par contre, si vous avez 2 sites différents il vous faut utiliser un serveur de session ou un serveur SQL afin de transiter les sessions entre vos 2 sites web. Pour plus d’informations sur la configuration d’un serveur de session, vous pouvez lire l’article ASP.NET Session State 

Pour plus de détails sur le fonctionnement interne des sessions, je vous invite à consulter l’article Fast, Scalable, and Secure Session State Management for Your Web Applications de Michael Volodarsky.

WCF – Interception des operations – comment rajouter du code lors de l’appel de méthode WCF – IOperationBehavior et IOperationInvoker

Lorsque l’on utilise WCF, dans certains cas, on aimerait pouvoir exécuter du code lorsque certaines méthodes sont appelées.

J’ai récemment eu ce besoin. Je travaillais sur un “Ajax-enabled WCF service” accessible depuis JavaScript. Pour différentes raisons j’utilisais l’attribut [WebGet] afin que les méthodes soient directement disponible via la méthode GET.

Malheureusement, lorsque je debuggais mon service, mes appels étaient mis en cache par le client, je devais donc vider mon cache afin de pouvoir rappeler mes méthodes. J’ai donc décidé de rajouter le code suivant au niveau de mes méthodes :

HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);

Mes appels n’étaient alors plus mis en cache!

Cependant je ne trouvais pas cette solution très élégante. J’ai donc cherché une solution me permettant d’intercepter tous les appels à mes méthodes.

Je me suis tourné vers la création d’un attribut implémentant IOperationBehavior. Cette interface possède 4 méthodes :

  • AddBindingParameters méthode permettant d’envoyer des données personnalisées aux bindings lors de l’exécution.

  • ApplyClientBehavior méthode permettant de modifier, examiner ou insérer des extensions lors de l'exécution de l’opération du côté du client.
    ==> on utilise cette méthode lorsque l’on veut faire un Behavior qui s’exécutera coté client.

  • ApplyDispatchBehavior : méthode permettant de modifier, examiner ou insérer des extensions dans l'exécution de l’opération du côté du service.
    ==> on utilise cette méthode lorsque l’on veut faire un Behavior qui s’exécutera coté serveur.

  • Validate pour confirmer qu'un OperationDescription remplit les conditions requises. Elle permet d'assurer qu'une opération dispose d'un certain paramètre de configuration activé, qu'elle prend en charge une fonctionnalité particulière et d'autres spécifications.

Ces méthodes seront appelées seulement lors de la création du service. Afin d’avoir la main sur l’exécution de chaque méthode/opération nous devons créer notre propre inspector. Nous allons pour cela créer une classe implémentant IParameterInspector.

Cette interface possède 2 méthodes aux noms explicites : AfterCall et BeforeCall.

Voici l’implémentation de mon OperationBehavior :

public class PouetAttribute : Attribute, IOperationBehavior { public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { dispatchOperation.ParameterInspectors.Add(new PouetInspector()); } public void Validate(OperationDescription operationDescription) { IOperationBehavior webGetOperationBehavior = operationDescription.Behaviors .FirstOrDefault(operationBehavior => operationBehavior is WebGetAttribute) as WebGetAttribute; if (webGetOperationBehavior == null) throw new NotSupportedException("WebGetAttribute is required for PouetAttribute"); } }

Ainsi que l’implémentation de mon ParameterInspector

public class PouetInspector : IParameterInspector { public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState) { if (HttpContext.Current != null) HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache); } public object BeforeCall(string operationName, object[] inputs) { return null; } }

Ainsi, au niveau de mon service, il ne me reste plus qu’a décorer ma méthode de l’attribut Pouet.

[Pouet] [WebGet] [OperationContract] public String Hello(String s) { // won't stay in client cache return s + " - " + DateTime.Now.ToLongTimeString(); }

Nous avons vus comment se greffer à l’appel de nos operations via un ParameterInspector. Les méthodes BeforeCall et AfterCall nous renseignent également sur les paramètres envoyés à notre opération ainsi que son retour. Il n’est cependant pas possible de faire des modifications. Un inspecteur ne permet que d’analyser, regarder, ce qu’il se passe. Si l’on souhaite modifier le comportement de l’opération, il faut alors passer par un OperationInvoker

Bug IE8 – Invalid viewstate lors de chargement des fichiers ScriptResource.axd et WebResource.axd

Depuis quelques temps, on m’a remonté des soucis avec les fichiers ScriptResource.axd ou WebResource.axd.

L’erreur que l’on obtient est “System.Web.HttpException: Invalid viewstate

[HttpException (0x80004005): Invalid viewstate.] System.Web.UI.Page.DecryptStringWithIV(String s, IVType ivType) +2648697 System.Web.UI.Page.DecryptString(String s) +30 System.Web.Handlers.ScriptResourceHandler.DecryptParameter(NameValueCollection queryString) +81 System.Web.Handlers.ScriptResourceHandler.ProcessRequestInternal(HttpResponse response, NameValueCollection queryString, VirtualFileReader fileReader) +45 System.Web.Handlers.ScriptResourceHandler.ProcessRequest(HttpContext context) +184 System.Web.Handlers.ScriptResourceHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext context) +7 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75

L’url posant problème était toujours composée de la clé identifiant le script à charger ainsi que de données aléatoires ressemblant à un submit d’un formulaire avec la méthode GET ou d’autres valeurs provenant de fonctions JavaScript. Par exemple :

/WebResource.axd?d=D-wd7RbHCvS/../../images/icons/Ico_resize.gif')}}function%20ShowFilter_Manufacturer(){var%20div.......

Jusque la, je me suis dit qu’il s’agissait surement d’un navigateur ou d’un robot mal codé. Mais récemment on m’a remonté ce problème sur un intranet avec un panel d’utilisateurs très restreint, de plus le problème survient de plus en plus souvent et sur différents sites.

J’ai réussit à le reproduire une fois, le problème ne survient sans raison particulière, très rarement. Puisqu’il s’agit d’une erreur lors du chargement d’un fichier externe, aucune erreur n’est remontée au client. Cependant lorsque cela se produit, le navigateur est figé lors du chargement de la page, il faut alors la rafraichir manuellement.

Après quelques recherches, j’ai trouvé d’autres personnes rencontrant le même souci. Il semblerait que le problème provient d’un bug de IE8 ! Dans certains cas IE8, construirait mal les urls de fichiers externes !

Le bug a été remonté à Microsoft via Connect, je vous invite tous à voter pour le bug afin que l’on obtienne une correction rapide de IE8 : [Connect] Feedback : Invalid Webresource.axd parameters being generated 


Mais à quoi sert ces fichiers ScriptResource.axd et WebResource.axd ?

Ces handlers permettent de retourner une ressource stockée dans une assembly.

Par exemple, si vous construisez un contrôle, il est possible que vous ayez besoin d’images ou de fichiers JavaScript. Afin de faciliter le déploiement, vous pouvez inclure ces ressources directement dans une assembly, celles ci seront alors accessible via les handler ci-dessus. Pour cela, ces handlers nécessitent une clé contenant le nom de la ressource et de l’assembly chiffré en base64. L’algorithme de chiffrement et de déchiffrement utilisé et le même que celui du viewstate.
Le code de l’algorithme a été conçut en pensant que seule le viewstate l’utiliserait. Lorsqu’un problème survient lors du déchiffrage de la clé, une exception parlant de viewstate est remonté.
Malgré que le message d’erreur parle de viewstate, il est en aucun cas question de viewstate ! Le problème provient du déchiffrage de la clé de ressource.

Et vous, avez vous rencontré le même genre de bug sur vos sites web ? Toujours avec IE8 ?

WCF – erreur 404.3 – lors d’un accès à un fichier .svc avec IIS7

Lorsque vous configurez un service WCF avec IIS (via un fichier .svc), il se peut que vous ayez l’erreur suivante lorsque vous tentez d’accéder au fichier .svc

HTTP Error 404.3 - Not Found
The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.

Cette erreur survient car le fichier de config ne possède pas de handler configuré pour ce type de fichier.

Depuis IIS7, les handlers et modules sont directement gérés par IIS et non ASP.net, il s’agit de l’une des caractéristiques du pipeline mode integrated. Si votre fichier de config contient une entrée pour les handlers au niveau de la section system.web/httpHandlers, il est conseillé de migrer cette config vers la section system.webServer/httpHandlers propre à IIS7.

Pour cela, on peut utiliser l’outil de migration via la commande

c:\windows\System32\inetsrv\appcmd migrate config “PouetSiteName/”

Si l’erreur persiste ou si votre fichier original ne contient pas le handler requis, il faut le rajouter manuellement.

<configuration> <system.webServer> <handlers> <add name="ServiceHandler" verb="*" path="*.svc" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> </handlers> </system.webServer> <configuration>

Cette erreur n’est pas lié à WCF, il se peut que vous obtenez la même erreur avec un autre type de fichier. Dans ce cas, il faut rajouter le handler associé à la ressource demandé. N’hésitez pas à me contactez via les commentaires si vous ne savez pas quel handler utiliser pour d’autres types de fichiers.

FastStone Capture – un outil agréable pour faire des captures d’écran

Rédigeant de plus en plus de documentations, formations, … J’ai souvent besoin de faire des captures d’écran. Pour cela, j’utilise simplement les fonctionnalités de Windows via la touche “imprim écran” ce qui envoie la capture dans le presse papier, je la modifie ensuite via Paint.net si besoin. Il m’arrive aussi d’utiliser le Snipping tool de Vista lorsque je me sers de ce système d’exploitation.

Il existe de nombreuses autres solutions permettant de faire des captures d'’écran, j’en ai essayé quelques unes mais aucun ne m’a vraiment convaincu :

  • SnagIT : une des références en la matière
    • Beaucoup trop lourd pour ce que j’en ai besoin
    • Propose beaucoup trop d’options inutiles
    • etc …
  • Snipping Tool de windows Vista : plutôt sympa
    • Pas besoin d’installation
    • Pas possible de faire une capture tout en défilant la page
      • très utile pour une page web ou un menu de configuration un peu trop long
    • Disponible seulement sur vista
      • J’ai travaillé très peu de temps sous Vista au profit de server 2008 et maintenant seven

image 

Un collègue m’a récemment fait découvrir FastStone Capture, j’ai été très réticent avant de l’essayer. J’ai finalement craqué et j’en suis plutôt satisfait.

  • Très léger
  • Fais seulement ce qu’on attend de lui
  • Peut se lancer au démarrage de la machine
  • Pas d’installation requise
  • Peut faire des captures d’une fenêtre tout en défilant la page.
  • Permet de sélectionner seulement une partie de l’écran
    • via un zoom agréable
  • Possibilité d’envoyer la capture vers plusieurs endroits
    • Editeur
    • Presse papier
    • Fichier – l’outil nous demande alors le nom du fichier à chaque capture
    • Fichier - enregistrement automatique
    • Imprimante
    • Email
    • Powerpoint
    • FTP
  • Reduisable dans le systray
  • touche de raccourci par défaut très pratique
  • Possibilité d’enregistrer sous forme de film dans la derniere version.

image

Je ne suis généralement pas fan de ce genre d’outils. Celui ci m’a vraiment plus, cela fait maintenant quelques semaines que je l’utilise et je n’ai encore rien trouvé à lui reprocher.

Pour le tester c’est par ici : FastStone Capture Download n’oublier pas qu’aucune installation n’est requise.

Et vous, quels outils utilisez vous pour vos captures d’écran ?

Windows 7 - Problem Steps Recorder (PSR), enfin un outil permettant d’expliquer comment reproduire un problème

Qui n’a jamais eu un client / collègue vous disant “ça marche pas !” mais pas moyen de reproduire / comprendre le soucis ? PSR (Problem Steps Recorder) est justement un outil intégré à Windows 7 expliquant les étapes à effectuer pour reproduire un soucis.

Pour lancer PSR, il suffit de faire une recherche dans le menu windows

image

L’outil se lance :

image

Il faut alors appuyer sur le bouton “Start Record”, reproduire le problème puis appuyer sur le bouton “Stop Record”. Cela va automatiquement proposer d’enregistrer un fichier .zip contenant un fichier .mht expliquant les étapes afin de reproduire l’erreur.

Voici une capture d’écran de ce que nous génère l’outil.

image


Les plus :

  • intégré dans Windows 7
  • utile / simple / efficace
  • Qualité de l’explication des étapes
    • Chaque étape est accompagnée d’une capture d’écran 
    • Chaque action est notifié (click, clavier, etc…)
  • Fonctionne dans du bureau à distance (TSE) / VPC
  • possibilité de commenter une étape

Les moins :

  • Pas assez de détails sur la configuration de la machine
    • utilisateur administrateur ou pas
    • Versions des MAJ
  • Pas de version standalone / redistribuable sur vista et XP
  • Très peu d’options :
    • une option vidéo + son  !
    • Possibilité de sélectionner seulement une portion de l’écran
    • etc …
  • Pas de possibilité d’héberger automatiquement le rapport sur le net (espace live ou autre) afin de faciliter la publication de rapport via des forums d’entraide.

En plus de sa fonction première, cet outil peut également nous aider lors de création de documentation.
On peut aussi le voir comme un outil que l’on exécute avant chaque installation, cela permet de vérifier les étapes de l’installation / configuration en cas de soucis.

Et vous, connaissez vous d’autres outils similaire ? Fonctionnant sur vista et XP ?

ASP.net : Response.Redirect – Attention au piège. “Thread was being aborted.” / “Le thread a été abandonné.” - l’exception ThreadAbortException

La méthode Response.Redirect permet de rediriger un utilisateur vers une URL, pour cela ASP.net utilise le code d’erreur HTTP 302.

Je me suis récemment retrouvé face à un scénario où cette méthode m’a posé problème.
Au niveau de mon application, je lance une opération complexe utilisant des transactions et redirigeant l’utilisateur lorsque le traitement se déroule avec succès. En cas d’erreur, je fais un rollback sur mes transactions. Ci-dessous, le pseudo code illustrant le problème :

try { // Complex operation call which use transaction Response.Redirect("otherPage.aspx"); } catch (Exception) { // transaction.rollback() throw; }

Mon problème est que dans tous les cas le rollback est exécuté, c’est à dire que le code passe dans le catch, cependant rien n’est affiché au client.

Après quelques minutes de debug, je me suis rendu compte que le message d’erreur était “Thread was being aborted.” ou bien en français “Le thread a été abandonné.”. Ce problème vient du fonctionnement interne du Response.Redirect, en effet celui-ci lance une exception afin de stoper la requête active.

Voyons comment Response.Redirect fonctionne.

Response.Redirect possède 2 signatures, l’une qui nécessite seulement une url, et l’autre qui possède en plus un paramètre endResponse. Voici le pseudo code de la méthode Redirect.

public void Redirect(string url) { this.Redirect(url, true); } public void Redirect(string url, bool endResponse) { // writing some HTML and 302 status code if(endResponse){ Response.End(); } }

Le paramètre endResponse permet de mettre fin à l’exécution de la requête, pour cela ASP.net appelle la méthode Response.End qui met fin au thread courant via la méthode Thread.CurrentThread.Abort. C’est dans cette dernière qu’une exception de type ThreadAbortException est levé. Cette exception est cependant déclenché après l’envoie de la réponse au client, c’est pour cela que l’on ne voit aucune erreur coté client.

Pour résoudre ce soucis, le plus simple est d’ignorer les exceptions de type ThreadAbortException.

try { // Complex operation call which use transaction Response.Redirect("otherPage.aspx"); } catch (ThreadAbortException) {/* do nothing, it might be a response.Redirect exception */} catch (Exception) { // transaction.rollback }

Bien sur, ce bout de code n’est pas optimal, cela risque de cacher les vrais exceptions de type ThreadAbortException, celles-ci sont plutôt rares, on peut généralement les ignorer.

Cependant, si vous voulez faire les choses un peu plus proprement, il est possible d’analyser le callstack afin de savoir de quelle méthode provient l’exception.

private static MethodInfo _redirectMethod = typeof(HttpResponse) .GetMethod("Redirect", new Type[] { typeof(String), typeof(Boolean) }); // ... try { Response.Redirect("otherPage.aspx"); } catch (Exception ex) { if (ex is ThreadAbortException) { Boolean ignore = false; // use with caution if internal implementation change, // this solution can be broken // a little expensive - see JBEvain's comment StackTrace stackTrace = new StackTrace(ex); for (int i = stackTrace.FrameCount - 1; i > 0; i--) { StackFrame frame = stackTrace.GetFrame(i); if (frame.GetMethod() == _redirectMethod) { ignore = true; break; } } if (ignore) { Debug.WriteLine("Redirect exception"); return; } } Debug.WriteLine("Not a redirect exception"); }

Comme nous l’a fait remarquer JBEvain dans les commentaires, cette solution n’est pas idéale. L’analyse du StackTrace est un peu couteuse et surtout si l’implémentation interne du Redirect change, il se peut que le code ne fonctionne plus. De plus, cela rend le code moins lisible, cette dernière solution est donc à utiliser seulement si vous en avez vraiment besoin.

Des questions ?

Astuce UpdatePanel : faciliter le debuggage des UpdatePanels – les désactiver tous

Bien souvent, lorsque l’on a un problème sur une page qui inclut des UpdatePanels, on se dit que le souci provient des ceux-ci. Pour être certain que le problème vient ou non des UpdatePanels, il existe une astuce simple qui permet de les désactiver tous.

Pour cela, il faut mettre la propriété EnablePartialRendering du ScriptManager à false.

<asp:ScriptManager runat="server" EnablePartialRendering="false"> ... </asp:ScriptManager>

Ainsi tout vos UpdatePanels seront désactivés. De part le fonctionnement des UpdatePanels, la page doit fonctionner de la même façon, si votre problème persiste vous savez désormais que le problème ne vient pas des UpdatePanels.

Pour rappel, voici une liste de “best practices” sur les UpdatePanels : UpdatePanel : Best Practices

WCF – “Ajax-enabled WCF Service” ne peut pas avoir plusieurs bindings - “Cette collection contient déjà une adresse avec le schéma http.”

Afin de communiquer avec le serveur depuis le client en JavaScript, il est possible d’utiliser un “Ajax-enabled WCF Service”. Il s’agit d’un service WCF classique qui possède un binding et un behavior personnalisé afin de générer du JSON.

Si votre site web possède plusieurs binding il se peut que vous soyez face à ce problème.

This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.

ou en français

Cette collection contient déjà une adresse avec le schéma http. Une adresse tout au plus par schéma est possible dans cette collection.

Mais tout d’abord, quand est-ce que notre site web utilisera plusieurs bindings ? C’est le cas lorsque vous configurez un seul site web au niveau de IIS pour plusieurs urls. Par exemple si vous avez un site web accessible via

image

Ce problème est assez bien connu sur le net, il existe 2 bidouilles.

La première est de rajouter l’url dans le fichier de configuration :

<serviceHostingEnvironment> <baseAddressPrefixFilters> <add prefix="http://www.mydomain.com"/> </baseAddressPrefixFilters> </serviceHostingEnvironment>

La seconde est de créer un ServiceHostFactory personnalisé

public class CustomHostFactory : ServiceHostFactory { protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { return base.CreateServiceHost(serviceType, new Uri[]{ baseAddresses[0]}); } }

<%@ ServiceHost Language="C#" Debug="true" Service="DataService" CodeBehind="~/App_Code/DataService.cs" Factory="CustomHostFactory" %>

Malheureusement ces 2 bidouilles permettent de faire fonctionner le service seulement pour un domaine. Cela pose des soucis car à partir d’un appel AJAX il n’est pas possible de faire des requêtes crossdomain.

Afin de remonter le problème à Microsoft, j’ai recherché le bug sur connect : Feedback : Can't host WCF service in a website with multiple identities. Celui-ci est en état “Closed (By design)” ! Microsoft ne nous indique aucune piste afin de résoudre ce souci.

Ne me satisfaisant pas de cette solution, j’ai testé d’autres bidouilles. J’ai réussit à faire fonctionner le service avec plusieurs bindings en créant un ServiceHostFactory personalisé qui consiste à créer manuellement les ServiceEndpoint.

// use this class with caution ! // it's a workaround for this bug // https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=322896 public class CustomHostFactory : ServiceHostFactory { protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { // a valid url is required ServiceHost host = new ServiceHost(serviceType, new Uri[] { baseAddresses[0] }); // manually create endpoint for each uri - ignore WCF config file for (int i = 0; i < baseAddresses.Length; i++) { WebHttpBinding webHttpBinding = new WebHttpBinding(); ServiceEndpoint endpoint = host.AddServiceEndpoint(serviceType, webHttpBinding, baseAddressesIdea); endpoint.Behaviors.Add(new WebScriptEnablingBehavior()); } return host; } }

Cette solution n’est pas idéale puisqu’elle ne prend pas en compte la configuration WCF stocké dans le fichier de configuration, cependant cela me permet de faire fonctionner mon service WCF sur 2 URLs distinct.

Si vous avez d’autres astuces ou informations à ce problème, je suis preneur.

N’oublier pas de voter pour ce bug si vous rencontrez ce soucis : Feedback : Can't host WCF service in a website with multiple identities

UpdatePanel : Best Practices – ASP.net Ajax

Il y a quelques temps, j’ai effectué une formation interne sur l’utilisation des UpdatePanels.

Voici les principaux points à retenir :

Vous pouvez retrouver le powerpoint de ma présentation via le lien ci dessous

Untitled


Si vous avez des questions ou d’autres choses à rajouter sur ces “Best Practices”, utilisez les commentaires.

[mix09] .net 4.0 Velocity - Building scalable and available web applications with Microsoft Project codename “Velocity”

Par Muralidhar Krishnaprasad – Principal Software Architect

DSCF0889

Lors de cette session, nous avons eu un aperçue du projet “Velocity”. Il s’agit d’un système de cache mémoire distribué permettant de stocker toute sorte d’objets. Il est principalement focalisé pour les applications web mais peut être utilisé pour tous types d’applications .net. Velocity se compose de 2 parties : un service windows que l’on doit installer sur les serveurs de cache et une partie client qui utilisera le ou les serveurs de cache. La partie cliente sera intégrée à .net 4.0

DSCF0898 DSCF0897 

Partitionnement et routage

La partie cache peut être composée de plusieurs serveurs. Lorsque l’un des clients, généralement IIS, a besoin d’une information, ou veut stocker une information, Velocity utilisera automatiquement le bon serveur : il existe un système de routage. Cela veut dire que si vous rajoutez un objet dans le pool de serveur de cache, celui-ci se trouvera dans un seul des serveurs, c’est ce que l’on appelle le partitionnement.

Il est possible d’ajouter à chaud des serveurs de cache afin de très facilement améliorer les performances sans même redémarrer les sites web. Si un des serveurs de cache meurt, grâce à un système de backup, les éléments seront automatiquement redistribués sur les autres serveurs de cache.

Afin d’éviter des accès réseaux trop fréquents, il existe un système de cache local, celui-ci contiendra beaucoup moins d’objets que le cache global avec une durée de vie généralement plus court. L’intégrité du cache sera respecté via le système de notification.

DSCF0919DSCF0923 DSCF0922DSCF0926

Concrétement, comment cela se passe ?

Lorsque l’on veut utiliser Velocity, il faut créer un “named cache”, ce cache nommé sera ensuite distribué sur les différents serveurs de cache. Lorsque l’on veut utiliser ce cache nommé, il suffit d’obtenir ce cache via une factory. Grâce au routage et au partitionnement, on obtiendra les informations souhaitées automatiquement : inutile de savoir où sont physiquement stocké les données. Il s’agit d’un système de cache classique, il y a donc des méthodes Get, Put, Remove, …

DSCF0914 DSCF0916

Si vous voulez utiliser Velocity pour votre site web, il vous faut :

  1. Installer velocity sur un ou plusieurs serveurs de cache. Cela installe :
    1. le service windows
    2. la console d’administration powershell
    3. configure la consommation mémoire maximal du service windows
    4. et configure un partage réseau ou une base SQL pour le partage d’information entre les serveurs de cache
  2. Créer un cache via la console d’administration powershell
  3. Modifier le fichier de configuration de votre site web pour utiliser Velocity

DSCF0910

Physiquement, chaque serveur de cache est découpé en différentes entités de caches nommés, qui eux même sont découpés en région, celles-ci contiennent les “Cache items”, qui eux contiennent l’objet stocké en cache (ou caché :) ).

DSCF0915

Synchronisation 

Il est possible de “locker” des éléments afin d’éviter toute modification par un autre thread, il y a 2 modes de fonctionnement :

  • Optimistic locking : les objets sont automatiquement versionnés, l’envoi d’une modification sur un objet n’ayant pas le bon numéro de version renvera une exception
  • Pessimistic locking : un thread prend un objet, si un autre thread veut lire l’objet tout se passera bien, par contre si un autre client veut locker le fichier alors qu’il est déjà utilisé : il y aura une exception

DSCF0928DSCF0929

Notification

Velocity dispose d’un système permettant de notifier aux clients les changements d’un objet : modification, fin de vie, etc …

DSCF0930DSCF0931

Administration, Azure, Linq …

Velocity dispose d’une console d’administration powershell, qui nous permet de voir les statistique sur le nombre d’objets dans le cache, etc …

Au niveau de la sécurité, comme pour un serveur de session, il n’y a rien, tout doit être géré au niveau du réseau. Velocity fonctionne également dans les nuages avec azure et possède un provider Linq (linq to velocity).

DSCF0934 DSCF0937

Enfin ASP.net 4.0 pourra utiliser nativement Velocity : il sera possible de stocker les sessions ! ASP.net 4 aura également un nouveau système de Cache (System.Caching) à base de provider, l’un des provider utilisera Velocity, c’est à dire que si vous utilisez les @OutputCache tout sera stocké dans des serveurs spécifique.

DSCF0927 DSCF0935

Conclusion

Velocity est un projet très intéressant, les concepts sont très simples, au niveau utilisation on ne fait que ajouter, lire des données dans un espace de stockage mais ces fonctionnalités sont très puissantes.

J’ai particulièrement aimé la console d’administration qui permet vraiment de connaitre l’utilisation du cache et ce qu’il contient vraiment. Tous les sites web n’auront pas besoin de Velocity : il s’agit de “l’artillerie lourde” si votre site web est hébergé sur une seule machine, Velocity ne vous sera pas utile. Par contre à partir du moment où vous utilisez du Load Balancing, vous avez tout intérêt à utiliser ce système.

DSCF0939 DSCF0943

Ce projet est actuellement en CTP, il fera partie .net 4.0. Vous pouvez le télécharger ici : http://msdn.microsoft.com/en-us/data/cc655792.aspx.

Merci à Olivier pour le relecture.

[Mix09] Microsoft ASP.net 4 : Taking Ajax to the Next Level

Suite à la session des nouveautés de ASP.net 4 Webforms : [Mix09] Microsoft ASP.net 4 : What’s next ?, je me suis décidé à aller voir la session Microsoft ASP.net 4 : Taking Ajax to the Next Level, toujours par Stephen Walther

DSCF0773

Après un bref récapitulatif de l’historique des applications web, nous avons vu qu’il existait 3 façons de faire des applications web.

  • ASP.net Server side
    • Classic ASP.net avec les postback & co
  • ASP.net Server side Ajax
    • Utilisation des UpdatePanels
    • On garde le même fonctionnement, mais on rafraichit seulement une partie de la page.
    • Il s’agit en fait d’AJAH plutôt qu’Ajax : Asynchronous JavaScript and HTML
  • ASP.net Client side Ajax
    • Utilisation des services retournant du JSON et de JavaScript.
    • Utilisation des nouveautés de ASP.net 4 Ajax

DSCF0779

Le reste de la session présentait une application ASP.net utilisant les différentes façons de faire. L’application en question était composée d’un simple gridview filtré par une DropDownList.

Server Side ASP.net

  • Avantages
    • Sure : pas de problème de compatibilité JavaScript coté client
    • Puissant : utilisation de n’importe quel langage .net
    • Concept objet bien compris des développeurs
  • Inconvénients
    • Temps de réponse
    • Performance

Server Side ASP.net Ajax

  • Avantages
    • Les mêmes que ASP.net classique
    • plus interactifs qu’ASP.net classique
    • ne requiert aucun pré requis JavaScript
  • Inconvenients
    • Temps de réponse
    • Performance

Client Side ASP.net Ajax

Nous nous sommes principalement arrêtés sur cette façon de faire, Stephen nous a présenté quelques une des nouveautés de ASP.net Ajax 4.0.

Tout d’abord le principe général : le serveur envoie une fois le HTML au client, puis le client utilise le serveur pour mettre à jour la page, c’est le client qui est responsable de gérer le HTML.

DSCF0780

Tout d’abord nous avons vu comment créer un DataView, un DataView est un composant qui permet de répéter un template : un Repeater coté client. Cela nous a permis de voir le moteur de template ainsi que le fonctionnement du binding.

DSCF0784DSCF0785

A propos du binding, il y en a 3 sortes :

  • “one way – one time” : Le composant est bindé qu’une seule fois à la source de donnée, si la source de donnée change, le binding n’est pas actualisé
  • “one way – live ” : idem ci dessus, sauf que si la source de donnée change, le binding est actualisé
  • “two way – live” : idem ci dessus, sauf que si le composant change, la source de donnée est mise à jour.

DSCF0802 DSCF0804

Nous avons ensuite vu différentes façons d’accéder aux données : soit via un classique “Ajax Enable WCF service” disponible depuis .net 3.5 SP1, cela nécessite alors de coder toute la couche d’accès aux données, soit on utilise un DataContext. Lorsque l’on utilise un DataContext, la mis à jour des données envoie seulement les données modifiés vers le serveur. Il est également possible d’utiliser un AdoNetDataContext si l’on utilise ADO.net Data Services (aka Astoria).
Pour rappel ADO.net Data Services est un projet permettant de publier les données d’un context Linq to Entities via REST ou JSON.

DSCF0805DSCF0806

Nous avons enfin vu comment utiliser toutes ces fonctionnalités sans écrire une seule ligne de JavaScript grâce à une combinaison très astucieuses de namespace XML, d’attributs et de classes CSS. Il s’agit du mode déclaratif.

DSCF0795

Si l’on veut faire un dataview de façon déclarative, il faut faire un template normal, puis simplement rajouter l’attribut sys:attach=”dataview” au niveau de la balise du template. ASP.net Ajax 4 va automatiquement convertir cet élément en template.
Pour binder notre dataview a une source de donnée, il suffit de rajouter des attributs dataview:propname=”value” tout sera automatiquement géré.

DSCF0810 DSCF0799

Je ferais un post dédié expliquant en détail le mode de fonctionnement des contrôles déclaratifs. 

En conclusion, Stephen nous expliquait à quel point la partie cliente était importante dans une application web.

DSCF0812

J’ai vraiment apprécié cette session, j’ai entendu des choses plaisante comme "I love JavaScript" ou encore "it's a real simple language"

Si vous voulez en savoir plus sur ASP.net Ajax, je vous invite à consulter le projet codeplex ASP.net Ajax 4.0

 


Il y a beaucoup de choses à dire sur ASP.net Ajax 4, je vais bientôt revenir avec des posts plus techniques expliquant toutes ces nouveautés.

Des questions ? commentaires ? un besoin de précision ? n’hésitez pas à me contacter.

[Mix09] Keynote Day 2 – Part 2 – Changing behavior by design

2ème partie du Keynote présenté par Deborah Adler - Creator and Principal Designer of ClearRx Prescription System

Bien que ne traitant pas de concepts techniques, j’ai apprecié cette partie. Deborah nous a expliqué comment elle a conçu le système ClearRx : un système qui a revu l’étiquetages des médicaments aux états unis. Nous avons ainsi vu à quel point le design d’un produit peut changer le comportement des utilisateurs.

En effet, l’étiquetage était flou, il était très facile de se tromper.

DSCF0678DSCF0680

Désormais l’étiquetage a été simplifié

DSCF0683DSCF0684image

Les logos ont également été repensés

DSCF0685

En conclusion :

DSCF0687

[Mix09] Keynote Day2 – Part1 – IE8 version finale

Par Dean Hachamotiv – Internet explorer General manager

P1020598  P1020599

Comme le titre l’indique : IE8 est en version finale. vous pouvez le télécharger ici : www.microsoft.com/ie8

P1020608

Performance

P1020620 P1020627

Une vidéo illustrant les résultats sont disponibles ici : [video] IE8 Performance

image

Securité

P1020626

Developper

P1020630P1020632

 

Quelques liens :

P1020660

Un grand merci à Sébastien Warin pour les photos.

[Mix09] Design Prototyping - Bringing Wireframes to Life

Par Dan Harrelson

DSCF0614 

Tout d’abord, nous avons vu ou revu ce qu’était un prototype et un WireFrame (fil de fer). Les 2 concepts permettent de mieux concevoir le produit / l’application que nous devons produire / développer, de répondre plus efficacement aux besoins des clients. Un wireframe est plus light qu’un prototype, cela montre principalement l’interaction entre les écrans, il n’y a pas forcément la représentation de l’expérience utilisateur (UX) contrairement au proto

DSCF0620

Les prototypes permettent de faire des tests d’utilisabilité, de réduire et simplifier la documentation, etc … La création d’un prototype doit être dynamique, c’est à dire qu’il doit être sans cesse en mouvement, il ne doit en aucun cas rester figé.

La réalisation d’un POC (Proof Of Concept) est un proto

DSCF0618 

Un bon prototype doit respecter 4 points :

  • Interactive
    • Il faut qu’un proto nous mettre l’expérience utilisateur, que les interactions soient bien mise en valeur
      DSCF0621
  • Fast
    • On ne doit pas prendre/perdre du temps avec la création d’un prototype
  • Disposable
    • Un proto doit être jeté sans gène, ce n’est en aucun cas une base pour le produit final
    • “It’s not about the prototype, it’s about the ideas!”
      DSCF0622
  • Focused
    • Il doit se focaliser sur certains points
      • Core interactions
      • important patterns
      • Risky functionality
    • mais ne doit pas se focaliser sur
      • solved problems => sur la réalisation de la problématique : c’est le produit final qui s’en charge
      • Agreed upon solutions
        DSCF0623 DSCF0626

Enfin, nous avons vu comment concrètement faire des prototypes, le speaker nous a présenté 2 solutions, puis via une grosse session de questions/réponses, la salle à cité de nombreux autres facons de faire.

  • Papier :
    • J’ai adoré cette solution. Il s’agit en fait de dessiner les boutons, les blocs de l’application, etc … sur du papier ! de découper ces bouts d’applications avec des ciseaux et ensuite de mettre en place ces différents bouts d’applications, de prendre des photos puis de les assembler dans un film ou autre.
    • Un film a été passé illustrant ce principe et le rendu est vraiment très sympathique
  • Animation Flash
  • LiveMotion
  • HTML / JavaScript

En conclusion :

  • La livraison des applications doivent être plus dynamiques
  • La création de protos peuvent aider
  • Un bon proto est un proto rapide à créer, jetable et ciblé

DSCF0628

[Mix09] Microsoft ASP.net 4 : What’s next ?

Par Stephen Walther (MSFT)

ASP.net 4 se compose de 4 projets ainsi qu’un socle commun :

  • ASP.net WebForms
    • Il s’agit de la plateforme ASP.net que nous connaissons depuis ASP.net 1.0 : les pages, le viewstate, les postbacks, etc …
  • ASP.net Ajax
    • Il s’agit des UpdatePanels et de Microsoft Ajax Library
    • Actuellement, ce projet est couplé à ASP.net WebForms, les prochaines releases seront plus découplées. ASP.net Ajax 4 (aka Microsoft Ajax Library) pourra fonctionner avec une application PHP
  • ASP.net MVC
    • Il s’agit du “concurrent” à ASP.net WebForms
    • En beta depuis quelques mois sur codeplex (www.codeplex.com/aspnet)
    • RTM depuis ce matin – voir le résumé du Keynote
  • ASP.net Dynamic Data
    • Projet reposant actuellement sur ASP.net WebForms
    • Utile pour faire rapidement un back office

DSCF0584

Cette session s’est principalement focalisé sur les améliorations de ASP.net Webforms, d’autres sessions traitent des autres projets.

Il n’y a pas de grosses améliorations, cela est normal puisque ASP.net WebForms existe depuis 2001, le framework est mature. Cependant il y a quelques améliorations importantes et plusieurs nouveautés sympathiques. Parmis les innovations, les principales sont :

Routing

Avec cette nouveauté, on perd la notion de page, on travaille sur des URL. Cela permet d’avoir des URL propres. Il s’agit d’un module de rewriting. Ce module a été apporté par ASP.net MVC, il fait cependant partie de ASP.net Core.

Mix 187Mix 190Mix 191Mix 193   

Un Expression Builder a été rajouté pour connaitre facilement l’url d’une route.

ViewState

Une propriété ViewstateMode a été rajoutée sur la classe Control. Cela permet de complètement désactiver le ViewState pour le controle ainsi que les controles enfants. Le cas typique sera la désactivation du ViewState au niveau de la page, et l’activation au niveau d’un controle précis. La différence avec la propriété EnableViewState se situe au niveau de l’héritage, la propriété ViewStateMode supprime le viewstate des controles enfants sauf s’il est explicitement demandé.

Mix 178 

ControlID

Il est désormais possible de spécifier le ClientID final. Pour cela une propriété ClientIDMode a été rajoutée au niveau de la classe Control. 3 valeurs sont possibles :

  • Legacy : option par défaut, aucune modification par rapport à l’implémentation actuelle, le ClientID est généré à partir du NamingContrainer
  • Static : Le ClientID vaut l’id du controle, très utile pour les applications JavaScript, il n’est plus nécessaire de devoir récuperer le ClientID d’un controle.
  • Predictable : Utile pour les controles d’un ITemplate comme le ListView ou le Repeater. Cela permet de prédire l’id du controle repeté à partir du ClientID du controle parent (repeater, listview, …), de la propriété CilentIDRowSuffix (nouveau) et de l’index de la ligne.

Mix 180Mix 184Mix 185Mix 181

Cache

Je n’ai pas obtenu beaucoup d’infos à ce sujet. ASP.net 4 apporte un système de cache entierement nouveau, on peut désormais créer son propre provider de cache. Velocity a été prononcé mais cela restait très flou.

En vrac

  • snippet disponible en mode HTML et JavaScript
  • Ajout d’une propriété RenderTable sur le FormView : permet d’avoir du HTML plus joli. Les CSS adapters permettent déjà ce rendu 
    Mix 174
  • Le controle ListView se voit doté de vrai template et non d’un mix bizarre nécessitant des ID prédéfinis
    Mix 175
  • Ajout des propriétés Description et Keywords au niveau de la page ainsi
  • Ajout d’une méthode Page.RedirectPermanent qui renvoie un code HTTP 301 plutot qu’un 302
    Mix 194
  • Compressions de la session lorsqu’on utilise le mode Out Of Process
    Mix 202 

Si vous avez des questions ou des compléments d’information, les commentaires sont là pour ça.

BizTalk : Gérer les erreurs de parsing des Receive Port

Lorsque l’on fait du BizTalk, nous avons des messages en entrées qui viennent de personnes tierces. Ces fichiers peuvent ne pas être conformes avec ce que BizTalk attend : fichier XML mal formé, non conforme au schéma, etc … Par défaut, BizTalk ne fait que lever une erreur au niveau des logs Windows. Ce mécanisme est rarement suffisant.

Comment gérer ce genre d’erreur via une orchestration BizTalk ?

Il faut tout d’abord créer une nouvelle orchestration, puis un nouveau ReceivePort. Celui ci devra avoir un binding “direct” avec l’option “Routing between ports will be defined by filter expressions on incoming messages in the Mesage Box database”. Cette option permet d’attraper tous les messages de la messagebox tout en spécifiant un filtre au niveau du receive shape “activé” :

image 

Ce port sera lié à un “Receive Shape”  recevant un message de type System.Xml.XmlDocument, et ayant la propriété Activate à true. La propriété “Filter Expression” de ce receive shape, doit être édité afin que l’on filtre seulement les messages ayant la propriété “ErrorReport.ErrorType” valant “FailedMessage

image

Le reste de l’orchestration se fait classiquement.

Dans mon exemple, j’envoie le message en erreur vers un autre port.

image

Le message que l’on récupère est le message d’origine, c’est à dire celui en erreur. Pour avoir d’avantages d’informations sur l’erreur, on peut utiliser les propriétés suivantes :

FailedMessage(ErrorReport.Description) Le message d’erreur complet que l’on retrouve également dans les logs windows
FailedMessage(ErrorReport.ReceivePortName) Le nom du ReceivePort
FailedMessage(ErrorReport.InboundTransportLocation) L’uri de la receive Location

Enfin, au niveau du Receive Port physique, il faut cocher la case “Enable routing for failed messages

image

 

Au niveau du déploiement, on peut ajouter cette orchestration dans l’application à monitorer. L’autre solution, est de déployer cette orchestration dans une application distincte. Vos applications devant être monitorés devront seulement référencer cette application.

Pour faire référence à une autre application, cela se passe au niveau de la console BizTalk. Dans les propriétés de l’application il y a un onglet References qui permet de rajouter d’autres applications.

image 

A partir de là, on peut assez facilement envoyer un mail à l’administrateur, etc …

D’autres infos sur cette gestion d’erreur sont disponible ici : BizTalk 2006 FailedMessage Routing

WCF : Ajax Enabled WCF service et authentification windows (ou basic)

Si vous utilisez les “Ajax Enabled WCF Service” et que votre site nécessite une authentification windows, vous obtiendrez certainement cette erreur :

“Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.”

Afin de ne plus avoir cette erreur, il est nécessaire de modifier le binding du service. Il faut utiliser le mode TransportCredentialOnly ou Transport si vous utilisez https, et le TransportClientCredentialType doit être à Windows ou Basic suivant le type d’authentification utilisé :

 image

Voila ce que cela donne au niveau du fichier de configuration :

<system.serviceModel>
    <bindings>
        <webHttpBinding>
            <binding name="webHttpBinding">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Windows" proxyCredentialType="None" />
                </security>
            </binding>
        </webHttpBinding>
    </bindings>
    <behaviors>
        <endpointBehaviors>
            <behavior name="DataServiceAspNetAjaxBehavior">
                <enableWebScript />
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <services>
        <service name="DataService">
            <endpoint address="" behaviorConfiguration="DataServiceAspNetAjaxBehavior"
                binding="webHttpBinding" bindingConfiguration="webHttpBinding"
                name="webHttpEndpoint" contract="DataService" />
        </service>
    </services>
</system.serviceModel>

Si le service WCF n’utilise pas le même type d’authentification que IIS, vous obtiendrez alors cette erreur :

Security settings for this service require 'Basic' Authentication but it is not enabled for the IIS application that hosts this service.

Si vous utilisez le mode transport alors que vous n’avez pas configuré https, vous obtiendrez cette erreur :

Could not find a base address that matches scheme https for the endpoint with binding WebHttpBinding. Registered base address schemes are [http].

Enfin, si vous avez configuré le mode Transport, http ET https au niveau de IIS, et que vous tentez d’accéder à votre service en http, vous aurez seulement une erreur 404, lorsque vous tenterez d’invoquer une méthode du service.

Lancer SOS directement depuis Visual Studio

Lors de la session sur la programmation dynamique, j’ai découvert qu’il était possible de lancer SOS directement depuis Visual Studio.

SOS est une extension à windbg qui permet d’avoir des informations très détaillé sur les applications .net. On l’utilise pour analyser des dump mémoire dans des situations critiques. Pour plus d’info sur SOS : SOS Debugging Extension (SOS.dll) et WinDbg / SOS Cheat Sheet

Pour lancer SOS depuis Visual Studio, il faut tout d’abord que vous autoriser le code natif à être debugger. Cela se configure au niveau des propriétés du projet.

image

Attention, si vous avez un OS en 64 bits, vous devez configurer votre application à tourner sur du 32 bits. Pour configurer cela, c’est au niveau du “Configuration Manager” des propriétés de la solution.

image

Ensuite, dans la fenêtre “Immediate windows”, on peut lancer SOS grâce à la commande

.load sos

Il est désormais possible de lancer vos commandes SOS et windbg directement depuis Visual Studio.

image

[WCF] Service Reference : à jeter ou à garder ?

Lorsque l’on écrit une application utilisant un service WCF, nous avons forcément besoin d’un proxy qui va interroger ce service.

Pour cela, il y a 2 solutions : soit on fait un “Add Service Reference”, cela va nous générer le proxy, soit on écrit manuellement le proxy.

image

Lorsque l’on fait un “Add Service Reference…” l’outil svcutil nous génère automatiquement du code. Pour voir ce code, il faut afficher les fichiers cachés du Solution Folder

image

Nous avons ainsi accès au fichier Reference.cs qui contient le code du proxy auto-généré.

image

[GeneratedCodeAttribute("", "3.0.0.0")] [ServiceContractAttribute(ConfigurationName="Proxy.IMyService")] public interface IMyService { [OperationContractAttribute(Action="http://tempuri.org/IMyService/Add", ReplyAction="http://tempuri.org/IMyService/AddResponse")] int Add(int a, int b); [OperationContractAttribute(Action="http://tempuri.org/IMyService/AddPerson", ReplyAction="http://tempuri.org/IMyService/AddPersonResponse")] void AddPerson(Contract.Person p); } [GeneratedCodeAttribute("", "3.0.0.0")] public interface IMyServiceChannel : IMyService, IClientChannel { } [DebuggerStepThroughAttribute()] [GeneratedCodeAttribute("", "3.0.0.0")] public partial class MyServiceClient : ClientBase<IMyService>, IMyService { public MyServiceClient() { } public MyServiceClient(string endpointConfigurationName) : base(endpointConfigurationName) { } public MyServiceClient(string endpointConfigurationName, string remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public MyServiceClient(string endpointConfigurationName, EndpointAddress remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public MyServiceClient(Binding binding, EndpointAddress remoteAddress) : base(binding, remoteAddress) { } public int Add(int a, int b) { return base.Channel.Add(a, b); } public void AddPerson(Person p) { base.Channel.AddPerson(p); } }

Le code généré est relativement simple, il faut créer une classe héritant de ClientBase<TServiceContract>. Cependant, svcutil va réécrire l’interface du contrat ! C’est à dire que notre solution contiendra du code dupliqué.

Si vous véhiculez un type complexe, par exemple un type Person, il ne sera pas forcément dupliqué. Si votre client possède une référence vers l’assembly décrivant le type Person alors svcutil ne regénèrera pas cette classe. On peut toutefois modifier ce comportement en décochant la case “Reuse types in all referenced assemblies” ou en cochant la case “Always generate message contracts

image

Je n’ai pas trouvé de solution pour que svcutil ne regénère pas automatiquement le contrat du service, je trouve ce comportement particulièrement pénible. En effet la duplication du contrat, entraine du code en double, la perte des commentaires sur les méthodes et la nécessité de mettre à jour la référence dès que l’on modifie le contrat.

Personnellement, je préfère écrire moi même le proxy et utiliser les interfaces déjà définit.

Et vous ?  Comment faites vous vos service Reference ?

Plus de Messages Page suivante »


Les 10 derniers blogs postés

- [Refactoring] ReSharper pour Visual Studio 2010 (Preview) par Thomas Jaskula le il y a 1 heure et 30 minutes

- [Refactoring] Analyser vos exceptions avec ReSharper Exceptional par Thomas Jaskula le il y a 2 heures et 44 minutes

- SharePoint 2007 : patterns & practices SharePoint Guidance par Philippe Sentenac [MVP SharePoint] le il y a 16 heures et 23 minutes

- [Visual Studio 2010] Les tests cases c’est bien, mais je vais devoir tout réécrire ? par Etienne Margraff le il y a 17 heures et 20 minutes

- MVP[Gribouillon].AddYear par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le il y a 17 heures et 35 minutes

- Clinique INSIA - Projet de fin d’Etudes (Silverlight 3 MVVM et OutOfBrowser, WCF, TFS) - Part 1 par David REI le 07-02-2009, 23:38

- C’est la crise ? Bah pourquoi cramer du budget pub alors ? par Nix's Blog le 07-02-2009, 15:31

- Soyons MVP ! par TheSaib .NET blog le 07-02-2009, 12:15

- SharePoint : Gestion des Erreurs 6398, 7076 et 6482 par Blog Technique de Romelard Fabrice le 07-02-2009, 11:53

- EF avec WPF par Matthieu MEZIL le 07-02-2009, 10:18