Archive

Archive for mai 2012

Comment étendre le binding d’un endpoint par défaut ?

D’habitude lorsque je fais un petit test en WCF, j’ai l’habitude, pour aller plus vite, de laisser mon ServiceHost créer automatiquement les endpoints dont j’aurai besoin suivant l’adresse de base que j’aurai fournie dans le fichier de configuration. C’est cool et les endpoints créés de façon automatique sont appelés en fait des default endpoints (les points de terminaison par défaut).

Sauf que j’ai voulu, lors d’un de mes tests, changer l’encodage utilisé pour les messages alors je me suis dit qu’il fallait obligatoirement passer par un endpoint créé manuellement dans le fichier de configuration et par la suite utiliser l’attribut bindingConfiguration pour lui attribuer le nom de la nouvelle configuration créée. Mais il y a deux méthodes plus simples :

  • Passer par une configuration de binding par défaut. Pour info une configuration de binding par défaut est une configuration qui n’a pas de nom. L’attribut name n’est pas renseigné donc tout endpoint dont l’attribut bindingConfiguration n’est pas défini, utilisera cette configuration associée si son binding lui correspondant. Cela est valable pour les endpoints par défaut.
  • Un peu plus complexe mais le problème avec la première méthode est que si on a déjà une configuration par défaut déjà disponible utilisée par d’autres endpoints et qu’on n’aimerait pas modifier alors cette deuxième méthode nous permet de pallier à ce problème. Pour cela il faut passer par le mappage des endpoints par défaut c’est à dire utiliser l’élément protocolMappings, dans le mappage ajouté pour le protocole http et le binding basicHttpBinding dans notre cas, j’utilse l’attribut bindingConfiguration fourni.

Voilà j’espère que ce billet vous a été utile 😉

Publicités
Catégories :WCF Étiquettes :

Comment déboguer un service windows sous Visual Studio ?

Lorsque vous créez un projet de type Service Windows sous Visual Studio, vous avez remarqué que la boîte de dialogue ci-dessous s’affiche quand on essaie d’exécuter le service :

En résumé il est tout simplement impossible d’exécuter un service windows sous Visual Studio, on doit obligatoirement passer par la commande NET START pour démarrer le service après avoir préalablement installé celui-ci grâce à la commande INSTALLUTIL. Sauf que cette méthode nous empêche de faire facilement un deboguage du service Windows. En effet il faut installer le service, le démarrer, puis dans Visual Studio attacher un processus (qui sera bien sûr le processus du service windows) pour pouvoir déboguer notre code. Sans oublier qu’il va falloir aussi arrêter le service windows pour pouvoir compiler suite à quelques modifications qu’on aura effectuées dans le code du service. Bref c’est un peu lourd :D.

Il y a plus simple. on utilisera les symboles de compilation pour détecter dans quel mode nous sommes : RELEASE ou DEBUG. Si nous sommes en :

  • DEBUG : nous allons traiter notre service windows comme une simple application windows forms en affichant une boîte de dialogue indiquant que le service est démarré
  • RELEASE : le fonctionnement sera le même que quand nous avons essayé d’exécuter notre service windows sous Visual Studio. En d’autres termes, ce mode doit être utilisé en production une fois le débogage terminé

Pour notre cas d’utilisation ce sera très simple. Il s’agira ici de rendre possible l’exécution du service Windows et de déboguer un service WCF qu’il héberge. Voici les étapes à suivre :

  1. Modification du code du service windows : nous allons ajouter deux méthodes StartWCFService et StopWCFService qui ont pour tâches respectives de démarrer et d’arrêter l’écoute des requêtes entrantes WCF. La première méthode sera appelée dans la rédéfinition de la méthode OnStart et la seconde dans celle de la méthode OnStop. Ci-dessous le code :
    private ServiceHost host;
    
    public MyWindowsService() {
        InitializeComponent();
    }
    
    protected override void OnStart(string[] args) {
        this.StartWCFService();
    }
    
    protected override void OnStop() {
        this.StopWCFService();
    }
    
    public void StartWCFService() {
        this.host = new ServiceHost(typeof(IWCFService));
        this.host.Open();
    }
    
    public void StopWCFService() {
        if (this.host != null && this.host.State == CommunicationState.Opened)
            this.host.Close();
    }
    
  2. Modification du fichier Program.cs : c’est dans la méthode Main que nous allons faire la détection du mode de compilation dans lequel nous sommes. Si nous sommes en mode RELEASE, alors le service windows s’exéctute comme d’habitude et forcément on aura la fameuse boîte de dialogue si on essaie de l’exécuter sous Visual Studio avec ce mode. Si par contre, nous sommes en mode DEBUG, alors c’est très simple on fait appel directement à la méthode StartWCFService de l’instance de notre service windows (donc la méthode OnStart ne sera pas appelée) puis on affiche une boîte de dialogue pour en informer l’utilisateur. si ce dernier ferme la boîte de dialogue alors la méthode StopWCFService est appelée pour arrêter le service WCF (donc la méthode OnStop du service Windows ne sera pas appelée).
    Ci-dessous le code de la méthode Main :

    static void Main() {
    
        MyWindowsService service = new MyWindowsService();
    
    #if DEBUG
        service.StartWCFService();
        MessageBox.Show("Le service a démarré...");
        service.StopWCFService();
    #else
    
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[]
    	{
    		service
    	};
        ServiceBase.Run(ServicesToRun);
    #endif
    }
    

J’espère que ce billet vous a été utile 😉

Catégories :.Net, WCF Étiquettes : , , ,

ExtendedWebClient : une extension de la classe WebClient

[EDIT]

La méthode Abort ajoutée précédemment ne sert pas à grand chose 😀 Apparemment je suis passé à côté de l’existence de la méthode CancelAsync.

Récemment j’ai voulu augmenter le Timeout d’exécution des méthodes (téléchargement et téléversement) de la classe WebClient. Ce besoin est venu du fait que je travaillais avec une requête qui prenait pas de mal de temps parce que le serveur devait effectuer différentes tâches qui prenaient pas mal de temps or la classe WebClient telle que définie n’expose pas et donc ne permet la modification de la propriété Timeout alors qu’elle utilise bien en interne un objet de Type WebRequest qui lui expose une propriété Timeout qui peut être modifiée.

J’ai trouvé une solution à ce problème en créant une classe ExtendedWebClient qui dérive de la classe de base WebClient et par la suite j’ai redéfini la méthode GetWebRequest (qui est chargée de créer l’objet WebRequest qui sera utilisé par la suite par notre WebClient). Dans la redéfinition j’attribue la valeur de mon Timeout à la propriété Timeout de l’instance WebRequest créée . Voilà.

Suite à cette discussion postée ici, j’ai par la suite ajouté une propriété CookieContainer pour de la gestion des cookies (uniquement pour les requêtes HTTP/S).

Ci-dessous le code complet de classe ExtendedWebClient :

/// <summary>
/// Classe dérivée de la classe WebClient
/// </summary>
public class ExtendedWebClient : WebClient
{
    #region Fields

    private WebRequest request;

    #endregion // Fields

    #region Properties

    /// <summary>
    /// Obtient la durée du timeout
    /// </summary>
    public int Timeout { get; private set; }

    /// <summary>
    /// Obtient le container de cookies
    /// </summary>
    public CookieContainer CookieContainer { get; private set; }

    #endregion // Properties

    #region  Consctuctors

    /// <summary>
    /// Constructeur de la classe ExtendedWebClient
    /// </summary>
    /// <param name="timeout">Durée en millisecondes </param>
    public ExtendedWebClient(int timeout)
    {
        this.Timeout = timeout;
        this.CookieContainer = new CookieContainer();
    }

    #endregion // Constructors

    #region Overriden methods

    protected override WebRequest GetWebRequest(Uri address)
    {
        this.request = base.GetWebRequest(address);

        // S'il s'agit d'une instance de type HttpWebRequest alors on instancie le container de cookie
        if (this.request is HttpWebRequest)
        {
            (this.request as HttpWebRequest).CookieContainer = this.CookieContainer;
        }

        // Si this.Timeout <= 0 alors la valeur par défaut qui sera utilisée.
        this.request.Timeout = this.Timeout <= 0 ? this.request.Timeout : this.Timeout;
        return this.request;
    }

    #endregion // Overriden methods
}

J’espère que cette classe vous sera utilse :).

Catégories :.Net, Astuces
%d blogueurs aiment cette page :