« Dev »

FormAuthentication, Session et UpdatePanel : PageRequestManagerParserErrorException

30 novembre 2006

Je me suis retrouvé lors d’un dev d’une application Web dans une petite galère avec l’ASP.NET AJAX Extention !

La situation est simple, j’ai une page ASPX contenant une gridview dans un UpdatePanel qui est protégée par un formulaire d’authentification (authentication mode= »Forms » dans mon Web.Config), bref cas des plus classiques !

Seul problème, au bout d’un certain temps d’inactivité, votre session expire (timeout paramétrable dans la balise froms du Web.config). Avec un postback classique, le serveur détecte que vous n’êtes plus authentifié et donc vous renvoie vers la page de login (paramétré lui aussi dans la balise froms du Web.config).
Mais avec un UpdatePanel, vous recevrez un beau message d’erreur :

Après analyse, cela est tout à fait normal car coté client, on ne sait pas que la session a expirée ! L’appel Javascript de la librairie Atlas, qui est sensé recevoir les données sous forme XML pour mettre à jour votre UpdatePanel, va tomber sur la page de login (classique, c’est ce qu’il se passe côté serveur lorsque que vous tentez accéder à une page protégé !).

On peut vérifier cela très facilement en supprimant le « DocType » au début de votre page de login. Vous verrez que l’erreur change et maintenant n’arrive pas a parser la ligne <head runat= »server »> ce qui nous prouve que c’est bien la page login ;)

C’est en lisant le blog de Cyril qui relayé un post de Luis Abreu que j’ai découvert comment gérer facilement les erreurs avec Atlas pour pouvoir écrire ce petit script et résoudre le problème :

1
2
3
4
5
6
7
8
9
10
11
12
<script type="text/javascript" language="javascript">
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
    function EndRequestHandler(sender, args) {
       if (args.get_error() != undefined) {
          if(args.get_error().message.substring(0, 51) ==
                "Sys.WebForms.PageRequestManagerParserErrorException") {
             window.location.reload();
          }
       args.set_errorHandled(true);
       }
    }
</script>

Avec ce bout petit de Javascript, on vient abonner notre fonction EndRequestHandler à l’évènement déclenché de la réponse du serveur. Notre fonction quand à elle, vient checker la présence d’une erreur dans la reponse du serveur, si oui regarde si les 51 premières caractères sont Sys.WebForms.PageRequestManagerParserErrorException. Dans ce cas on vient juste recharger la page par un window.location.reload() (postback classique) qui nous redirigera vers la page de login !

Et le tour est joué…. :)

[NetFx3] Présentation du Windows Communication Foundation (WCF)

8 novembre 2006

Résumé:
WCF pour Windows Communication Foundation est l’une de quatre nouvelles briques apportées par .NET Framework 3.0. Cette brique unifie le développement des applications distribuées. Cet article présentera les bases de cette plateforme avec un exemple concret d’application en mode de client-service.

Sommaire:

   * Introduction
    * 1 Présentation du WCF
          o    1.1 Présentation
          o    1.2 Installation
    * 2 Fonctionnement et l'ABC du WCF
          o     2.1 Presentation
          o     2.2 Les EndPoints : l'ABC du WCF
    * 3 Développer avec WCF
          o     3.1 Création du service
          o     3.2 Création de l'host (partie serveur)
          o     3.3 Création du client
    * 4 Demo : Développer un mini service d'annuaire
          o     4.1 Création du service MonPremierServiceWCF
          o     4.2 Création de l'host MaPremiereHostWCF
          o     4.3 Création du client MonPremierClientWCF
          o     4.4 Conclusion
    * 5 Aller plus loin dans WCF
          o     5.1 IsOneWay et CallbackContract
          o     5.2 Gestion des sessions
          o     5.3 Gestion de la sécurité
    * Conclusion

Pour ceux qui serait intéressé :

[Atlas] UpdatePanelAnimation : la galere des animations OnUpdating/ed

22 octobre 2006

Est-ce un bug, un oublie ou juste moi qui me prend la tête pour rien ? Les UpdatePanelAnimation sont des extendeurs du controle UpdatePanel nous permettant de jouer une animation au rafraichissement d’un UP.

Je mets donc un ScriptManager, 2 UpdatePanel en mode Conditional et 2 UpdatePanelAnimationExtender mappés sur les UP respectifs (TargetControlID= »…. »). Je remplis en suite une animation sur le OnUpdating pour faire un FadeOut de l’UP et sur le OnUpdated un FadeIn.

Wahou c’est beau… La page disparait en fondu, se met à jour et hop reapparait :)

OUI, mais voila, le problème est que ces animations sont joués à chaque AsyncPostBack pour tous les UpdatePanels.
Dans mon cas les animations s’executés sur les deux UpdatePanels alors qu’un seul d’entre eux etaient mis a jour ! :-(

On peux tester cela très facilement en rajoutant un Button sur la page qu’on enregistre à son chargement comme controle AsyncPostBack (ScriptManager1.RegisterAsyncPostBackControl(monButton)).
Sur le code du bouton on change le contenu d’un labelA d’un UpdatePanelA et met à ajout un UpdatePanelB (UpdatePanelB.Update()).
On constatera que le labelA n’a pas changé (vu que le UpdatePanelA n’a pas été Update()) mais l’animation sur celui ci c’est quand même executé.

Alors là, expliquez moi l’interet de jouer les animations qui portent le nom: OnUpdating et OnUpdated sur un UpdatePanel qui ne s’est pas Updating/Updated ?!?!?%% J’utilise la beta 1 fraichement téléchargé de vendredi, avait-on ce probleme avant ?

Enfin soit, ma petite astuce pour pouvoir me sortir de cette galere et controler l’execution des animations à été de poser une condition dans la sequence des animations:

1
2
3
<Condition ConditionScript="ToPlay('UpdatePanel1')">
    <FadeOut duration=".25" Fps="30" minimumOpacity=".2" />
</Condition>

Et dans ma page un petit script JS :

1
2
3
4
5
6
7
8
9
     <script language="javascript" type="text/javascript">
         var _UPtoPlay;
         function setUPtoPlay(sender) {
             _UPtoPlay = sender;
         }
         function ToPlay(sender) {
             return sender == _SenderCallback ? true:false;
         }
     </script>

Enfin j’ajoute l’attribut OnClick sur les triggers de mon UpdatePanel A et B pour appeler la fonction setUPtoPlay :

1
2
Button1.Attributes.Add("onClick",
       "UPtoPlay('UpdatePanel1');");

De tel maniere chaque controle émettant un ASyncPostBack appele la fonction setUPtoPlay() qui stoque coté client le nom de l‘UpdatePanel qui est mis à jour et doit jouer l’animation.

Pour revenir sur ce que je disais au debut : Est-ce un bug, un oublie ou juste moi qui me prend la tête pour rien ??? :)

[Atlas] Microsoft ASP.NET AJAX Beta 1

21 octobre 2006

Hop la, depuis hier est sortie la version Beta 1 du projet Atlas maintenant renommé en Microsoft ASP.NET AJAX ainsi qu’une nouvelle release du AJAX Control ToolKit avec 3 nouveaux controls (DropDown, MutuallyExlcusiveCheckBox et ValidatorCallout).

Des deux cotés l’on remarque pas mal de gros changements au niveau des proprietes des controls. Déjà le ScriptManager ne propose plus de ErrorMessage. Les Triggers des UpdatePanel ont eux aussi changés. On retrouve deux types de triggers : PostBackTrigger et AsyncPostBackTrigger. Ex:

1
2
<asp:AsyncPostBackTrigger
         ControlID="imgGalerie" EventName="Click" />

Vous remarquez aussi le changement du TagPrefix des controls d‘atlas à asp. De même l’assembly à renommé en Microsoft.Web.Extensions.

Du coté des Controls Toolkits, les proprietes de plusieurs controls sont à mettre directement dans la balise mère et non dans des balises filles du type « …..Details » ou « …Property ». Exemple :

1
2
3
<atlasToolkit:RoundedCornersExtender ID="rcViewer"
                runat="server" Color="White" Radius="6"
                TargetControlID="plViewer" />

Bref, compter de 10min à une bonne heure, en fonction de la taille de votre projet pour migrer votre code pour la beta 1 de ce magifique Framework :)

  • Microsoft ASP.NET AJAX :

http://ajax.asp.net/

  • Microsoft ASP.NET AJAX Beta 1 :

http://www.microsoft.com/downloads/……

  • ASP.NET AJAX Controls ToolKit :

http://ajax.asp.net/ajaxtoolkit/

[WPF] S’amuser avec le MediaElement sous WPF

21 octobre 2006

Le contrôle MediaElement que j’ai decouvert au cours de cette semaine a revolutionné ma petite vie de developpeur :) Ce contrôle permet de contenir des images, sons ou videos.
Pour charger un media, rien de plus simple :

1
2
MediaElement monMedia = new MediaElement();
monMedia.Source = new Uri("monURI");

Sachant que mon Uri peut pointer sur un fichier local (c:\….) ou distant (http://…..) que se soit une video, une image ou un son….

Le media sera joué immédiatement. Bien que vous disposez des methodes Play(), Stop() et Pause() pour contrôler le media, utilisez plutot la proprieté LoadedBehavior qui permet de definir et/ou obtenir l’etat du media :

1
2
3
monMedia.LoadedBehavior = MediaState.Pause; //Pause
monMedia.LoadedBehavior = MediaState.Stop; //Arret
monMedia.LoadedBehavior = MediaState.Play; //Play

A ce sujet, pour pouvoir jouer une video (ou son) en boucle, la seule doc que j’avais trouvé sur le msdn2 était de mettre un MediaTimeline. Chose un peu tordu dans le code alors qu’il y a une solution toute simple :
1) Abonnez-vous à l’evenement MediaEnded (fin du media) :

1
2
monMedia.MediaEnded +=
          new RoutedEventHandler(monMedia_MediaEnded);

2) Remettez la position du media à zero (debut) et relancez le media :

1
2
3
4
5
void monMedia_MediaEnded(object sender, RoutedEventArgs e) {
     ((MediaElement)sender).LoadedBehavior = MediaState.Stop;
     ((MediaElement)sender).Position = new TimeSpan(0);
     ((MediaElement)sender).LoadedBehavior = MediaState.Play;
}

Ce qui est quand même beaucoup plus simple :)

C’est bien beau tout ca, mais la vous n’avez aucun apercu à l’ecran ce qui est quand meme un peu dommage ^^ Mais là où ca devient fort bien interressant, c’est qu’un VisualBrush peut prendre en parametre un MediaElement pour pouvoir remplir un rectangle par exemple :

1
2
Rectangle monRectangle = new Rectangle();
monRectangle.Fill = new VisualBrush(monMedia);

Et hop la, votre video (par exemple) sera joué dans ce rectangle. Enfin pour rajouter votre rectangle à un canvas que vous aurez au préalable placé dans votre code XAML :

1
monCanvas.Children.Add(monRectangle);

A partir de la on peut vraiement s’amuser et aller plus loin dans la démarche.. Par exemple, les rectangles ont une proprieté Clip qui va nous permettre de clipper notre media, OpacityMask pour appliquer un masque d’opacité, et bien d’autre chose pour appliquer differents effets a notre rectangle/video, … Et encore je ne parle que des rectangles, a partir du moment où votre controle pourra etre remplit par un VisualBrush on pourra tout y mettre :)
Je ne vais pas vous devoiler sur ce quoi je travaille en ce moment, mais il faut bien se rendre compte de tout ce qu’on peut faire avec car c’est carrement dément…