Accueil Nos publications Blog [WP7] – Utiliser une API XMLRPC, partie 2

[WP7] – Utiliser une API XMLRPC, partie 2

Dans mon précédent article, j’avais eu une approche très simple pour consommer des services XmlRpc. Approche simple qui imposait quand même un peu de travail pour travailler avec les réponses des services. J’avais parlé de XmlRpc.NET qui n’était pas encore supporté sur Windows Phone, et c’est maintenant chose faite :-).

XmlRpc.NET, rappel

XmlRPC.NET est un framework qui permet facilement de mettre en place des services ou des clients XMLRPC dans un environnement .NET. Avec la dernière version, le support pour les applications Windows Phone est maintenant assuré.

Quelle version récupérer ?

Sur le site du framework, la dernière version supportée par Windows Phone est la version 3.0.0.241. Cependant, cette version a quelques bugs :
– Le premier concerne la désérialisation de réponses pour certains types (le type XmlRpc struct).
– Le second bug est assez gênant (et existe toujours au moment où j’écris ces lignes). Il est impossible de pouvoir exécuter des méthodes qui ne prennent aucun paramètre. La solution consiste pour le moment à créer un paramètre neutre dans vos services distants (en espérant que vous ayez la main dessus) et rajouter ce paramètre dans vos appels.

L’ensemble des bugs ont été transmis à l’auteur du Framework (Charles Cook). Le premier a d’ores et déjà été corrigé et le second est en cours. Il est recommandé en tout cas de récupérer la dernière version disponible sur le gestionnaire de sources de la librairie à l’aide de SVN. Les informations relatives au trunk sont disponibles à cette adresse : https://code.google.com/p/xmlrpcnet/source/checkout.

Créer un serveur XmlRpc

Pour créer votre serveur, vous pouvez le faire en utilisant .NET Remoting (haa, le bon vieux temps :-)), des Web Services ou de simples Handlers. Je n’entrerai pas dans les détails car c’est déjà bien documenté sur le site du framework, mais également dans les sources du projet. J’ai aussi mis 2 exemples dans les sources jointes à cet article.

Créer son service

Pour cet exemple, je vais créer 2 services différents au sein de notre application Windows Phone afin de vous montrer son utilisation avec des types de retour différents (simple et complexe).

Commençons d’abord par créer dans notre application Windows Phone une interface pour chacun de nos services :

[csharp]
public interface IAuthenticationServiceProxy
{
#region Authentication

IAsyncResult BeginAuthentication(string login, string password, AsyncCallback callback);

bool EndAuthentication(IAsyncResult iasr);

#endregion
}

public interface INewsServiceProxy
{
#region Get News

IAsyncResult BeginGetNews(int voidParam, AsyncCallback callback);

XmlRpcStruct EndGetNews(IAsyncResult iasr);

#endregion
}
[/csharp]

Quand on désire travailler avec XmlRpc, surtout en mode asynchrone, il y a plusieurs méthodes pratiques recommandées. La plus courante est de créer une méthode pour initialiser et effectuer l’appel et une autre terminer l’appel et récupérer (et désérialiser) la réponse. Il faudra obligatoirement que vos méthodes commencent par Begin et End sinon, le framework ne comprendra pas vos souhaits.

Le type de retour de l’appel (celle qui commence par Begin) est toujours IAsyncResult.
Le type de votre méthode de retour est du type du retour renvoyé par le service que vous avez appelé.
Le paramètre d’entrée de notre méthode de retour est toujours de type IAsyncResult.

Qu’en est-il du paramètre AsyncCallback des méthodes d’appel ?

Il n’est pas obligatoire. Cependant, si vous souhaitez pouvoir effectuer un traitement après votre appel (dans 99% des cas ?), vous devrez obligatoirement l’inclure. Vous verrez comment s’y prendre un peu plus bas.

Maintenant que les interfaces sont créées, attaquons nous aux services.


[XmlRpcUrl("https://localhost:5310/AuthenticationService.rem")]
    public class AuthenticationProxyService : XmlRpcClientProtocol, IAuthenticationServiceProxy
    {
        #region Authenticate

        [XmlRpcBegin("AuthenticateUser")]
        public IAsyncResult BeginAuthentication(string login, string password, AsyncCallback callback)
        {
            object[] parameters = new object[] { login, password };
            return this.BeginInvoke(MethodBase.GetCurrentMethod(), parameters, callback, null);
        }

        [XmlRpcEnd]
        public bool EndAuthentication(IAsyncResult iasr)
        {
            bool result = (bool)this.EndInvoke(iasr);
            return result;
        }

        #endregion
    }

    [XmlRpcUrl("https://localhost:5310/NewsService.rem")]
    public class NewsProxyService : XmlRpcClientProtocol, INewsServiceProxy
    {
        #region GetNews

        [XmlRpcBegin("GetAllNews")]
        public IAsyncResult BeginGetNews(int voidParam, AsyncCallback callback)
        {
            return this.BeginInvoke(MethodBase.GetCurrentMethod(), new object[] { voidParam }, callback, null);
        }

        [XmlRpcEnd]
        public XmlRpcStruct EndGetNews(IAsyncResult iasr) {
            var result = (XmlRpcStruct)this.EndInvoke(iasr);
            return result;
        }

        #endregion
    }

Analysons de plus près notre 1er service.

1. Tout d’abord, la classe est marquée avec un attribut XmlRpcUrl. Cet attribut est obligatoire afin de pouvoir indiquer l’url du service distant pour lequel vous avez défini votre service local (dans votre application).
2. Notre classe hérite de XmlRpcClientProtocol. Il est obligatoire de le faire, sans quoi il sera impossible d’utiliser les méthodes propres aux appels XmlRpc.
3. Chaque méthode de notre service doit être marquée d’un attribut selon qu’elle soit une méthode d’appel ou une méthode de retour ([XmlRpcBegin] ou [XmlRpcEnd]). Ces méthodes peuvent prendre en paramètre le nom explicite de la méthode que vous ciblez sur le serveur.
Est-il possible d’utiliser ces flags sur les méthodes définies dans l’interface ?
Hélàs, non pour les projets mobiles.
4. Selon que l’on soit dans une méthode d’appel ou de retour, il faudra appeler BeginInvoke ou EndInvoke.

Et c’est tout pour nos services dans notre application Windows Phone :-). Oui oui ! Grâce à XmlRpc.NET, le mécanisme de « requêtage » (requêtes via HttpWebRequest, (dé)serialisation de types) est automatiquement géré, ce qui simplifie grandement notre code.

Il existe des possibilités assez nombreuses liées au potentiel de ce framework. Par exemple, il est possible de passer des cookies / headers à votre proxy. (via MonServiceProxy.Headers etc…).

Comment utiliser les services maintenant ?

Comme des exemples parlent souvent mieux que beaucoup d’écrits, analysons quelques extraits du contenu du code behind de ma page MainPage.xaml
On créé une instance de nos services…

[csharp]
private IAuthenticationServiceProxy _AuthProxy = new AuthenticationProxyService();
private INewsServiceProxy _NewsProxy = new NewsProxyService();
[/csharp]

Mon traitement s’effectue lors du clic sur un bouton :


private void btLogin_Click(object sender, RoutedEventArgs e)
        {
            string login = tblLogin.Text;
            string password = tblPassword.Password;

            if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password))
            {
                MessageBox.Show("login and password can not be empty");
                return;
            }

            _AuthProxy.BeginAuthentication(login, password, asr =>
            {
                this.Dispatcher.BeginInvoke(() =>
                {
                    var isSuccess = _AuthProxy.EndAuthentication(asr);
                    Color resultColor = Colors.Green;
                    string message = "Authenticated !";

                    if (!isSuccess)  {
                        resultColor = Colors.Red;
                        message = "Invalid Credentials !";
                    }
                    tblAuthenticationResult.Foreground = new SolidColorBrush(resultColor);
                    tblAuthenticationResult.Text = message;
                });
            });
        }

Nous appelons notre méthode d’authentification (BeginAuthentication) et dans son callback, nous appelons la méthode de retour (dans un Dispatcher.BeginInvoke surtout si vous allez modifier des propriétés d’objets UI).
Et c’est fini ! Par rapport à l’exemple de l’article précédent, toutes les méthodes de décodage / encodage restent valables, n’ayant aucun rapport avec XmlRpc.

Conclusion

J’espère que ce petit article vous aura aidé à mieux vous en sortir avec XmlRpc (aspect client). C’est un framework où l’auteur n’hésite pas à faire des mises à jour, donc, à votre tour, n’hésitez pas à lui faire remonter vos besoins. Un exemple complet d’application Windows Phone (avec les serveurs XmlRpc créés) sont joints à cet article en cliquant ici. Je me tiens à votre disposition si vous souhaitez en savoir davantage (sur l’aspect serveur par exemple).

A bientôt ! 🙂