Blog du Pôle .NET

Partager pour mieux développer...

Security Identifier, Binaire et Base 64

clock September 23, 2009 14:11 by author dox

Je me suis laissé entendre dire que la migration des données SharePoint n’était pas ce qu’il y a de plus facile. Ah bon ?

Petite mise en situation : Prenez un expert SharePoint (un vrai hein, comme Yoann par exemple !), une base de données qui contient des informations codées dans un champ binaire, un fichier XML qui contient d’autres données (codées en… vous verrez plus loin) et vos identifiants Windows (les fameux SID qui ressemblent à ça : S-1-5-21-xxx). Vous mélangez bien, et vous obtenez ça :

  • 01050000000000051500000038EDA9CF33F7AFDD94FC17C4F4010000
  • S-1-5-21-3484020024-3719296819-3289906324-500
  • AQUAAAAAAAUVAAAAOO2pzzP3r92U/BfE9AEAAA==

Vous l’aurez deviné le premier est le champ binaire stocké dans SQL Server. Le second, notre fameux SID. Et le troisième : le même codé en Base64 ! (Et là on applaudit Arnaud, parce que c’est lui qui a trouvé !)

Yoann a beau être un expert en SharePoint (et je vous jure que c’est vrai), les méthodes de conversion d’une forme vers une autre ne sont pas si évidentes que ça à trouver. D’ailleurs, en fouillant bien, on n’en a pas trouvé beaucoup.

Alors sous vos yeux ébahis, voici une petite classe utilitaire avec les méthodes qui vont bien pour convertir les données d’une forme vers une autre. Si un jour vous avez une migration de données SharePoint, ça pourra toujours être utile.

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Principal;

public class SharePointUtils {

    private static byte[] BinaryStringToByteArray(string binaryString) {
        return Enumerable.Range(0, binaryString.Length).Where(x => x % 2 == 0).
            Select(x => Convert.ToByte(binaryString.Substring(x, 2), 16)).ToArray();
    }

    public static string BinaryStringToSidString(string binaryString) {
        return new SecurityIdentifier(BinaryStringToByteArray(binaryString), 0).ToString();
    }

    public static string SidStringToBinaryString(string sId) {
        StringBuilder sb = new StringBuilder();
        SecurityIdentifier si = new SecurityIdentifier(sId);
        byte[] array = new byte[si.BinaryLength];
        si.GetBinaryForm(array, 0);
        array.ToList<byte>().ForEach(x => sb.AppendFormat("{0:X2}", x));
        return sb.ToString();
    }

    public static string BinaryStringToBase64String(string binaryString) {
        byte[] array = BinaryStringToByteArray(binaryString);
        return Convert.ToBase64String(array);
    }

    public static string Base64StringToBinaryString(string base64String) {
        byte[] array = Convert.FromBase64String(base64String);
        return SidStringToBinaryString(new SecurityIdentifier(array, 0).ToString());
    }
}

Et un exemple d’utilisation :

    string mySid = 
        "S-1-5-21-3484020024-3719296819-3289906324-500";
    string myBinaryString = 
        "01050000000000051500000038EDA9CF33F7AFDD94FC17C4F4010000";
    string myBase64String = 
        "AQUAAAAAAAUVAAAAOO2pzzP3r92U/BfE9AEAAA==";

    string binaryString = SharePointUtils.SidStringToBinaryString(mySid);
    string sidString = SharePointUtils.BinaryStringToSidString(myBinaryString);
    string b64 = SharePointUtils.BinaryStringToBase64String(myBinaryString);
    binaryString = SharePointUtils.Base64StringToBinaryString(myBase64String);
}

Le coup du Linq dans les méthodes, c’est sur une idée d’Arnaud (perso, je l’avais joué à la McGyver, avec une boucle et un compteur…).

En espérant que ça puisse servir à quelqu’un d’autre.

Dom, bien aidé sur le coup d’Arnaud et Yo.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Binding WPF dans une scène 3D

clock February 6, 2009 23:44 by author dox

Je viens de terminer une formation WPF et une fois le chapitre sur le binding de données terminé, un stagiaire me pose une colle, à peu près dans ce genre là :


"Il existe beaucoup d'applis de démos en WPF où l'on peut facilement changer l'angle de la caméra, à la souris ou autrement, mais comment faire pour binder la lumière, sur un contrôle Slider par exemple ?"

Bon, j’avais bien une idée en tête, mais sur le coup, je ne voyais pas comment l’implémenter. Je me suis mis au boulot en rentrant, et au bout d’une demi heure, j’ai terminé une petite application WPF que voici

Décortiquons un peu le contenu.
On commence par jeter un œil à la définition de la lumière en XAML, ce qui donne ceci :

<DirectionalLight x:Name="light" Color="White" 
    Direction="-5,-5,-5/>


On creuse un peu et on se rend compte que la propriété Direction est de type Vector3D, défini dans System.Windows.Media.Media3D, et qu’elle contient 3 valeurs : X, Y et Z (entre autres). La valeur « -5,-5,-5 » ne serait donc que le résultat de l’appel à la méthode ToString() sur la classe Vector3D.


On réalise que ça va être un peu dur (ou un peu long) de binder ça sur 3 contrôles différents, ou 3 sources différentes. Je commence donc par créer un UserControl, que j’appelle VectorControl et qui contient 3 contrôles de type Slider. J’ajoute les DependencyProperties qui me permettent de lier les valeurs des Sliders à mes propres propriétés : X, Y, Z et Vector3D, et j’ajoute les notifications correspondantes.

// dependencies
public static readonly DependencyProperty XProperty = 
    DependencyProperty.Register("X", typeof(double), 
    typeof(VectorControl), new UIPropertyMetadata((double)0));
...
public static readonly DependencyProperty Vector3DProperty = 
    DependencyProperty.Register("Vector3D", typeof(Vector3D), 
    typeof(VectorControl), new PropertyMetadata(
    new Vector3D(0, 0, 0)));

// constructeur
public VectorControl() {
    InitializeComponent();
    DependencyPropertyDescriptor.FromProperty(XProperty, 
        typeof(VectorControl)).AddValueChanged(this,
        delegate { Vector3D = new Vector3D(X, Y, Z); });
    ...
    DependencyPropertyDescriptor.FromProperty(Vector3DProperty, 
        typeof(VectorControl)).AddValueChanged(this,
        delegate { 
        X = Vector3D.X; Y = Vector3D.Y; Z = Vector3D.Z; });
}

Au final, j’obtient un UserControl qui ne paye pas de mine, mais qui est fully functionnal !

VectorControl
 
L’étape suivante consiste à intégrer mon UserControl dans mon application, qui contient déjà un ViewPort3D hébergeant ma scène 3D, et à renseigner ses propriétés. Au passage, j’en ai profité pour en créer 2 :

• Un pour la lumière
• Un pour la caméra (puisque la direction est aussi une propriété de type Vector3D)

<!-- les usercontrol ici --> 
<StackPanel Orientation="Vertical" Grid.Column="0"> 
    <local:VectorControl x:Name="lightVectorControl" 
        Title="Lumière ambiente" X="-4" Y="-2" Z="-1"/> 
    <local:VectorControl x:Name="lookDirectionVectorControl" 
        Title="Caméra" X="-5" Y="-5" Z="-5"/> 
</StackPanel>

Il ne me reste plus qu’à modifier la ligne de définition de la lumière (et celle de la caméra), et de binder la propriété Direction à mon UserControl, ce qui donne ceci :

<DirectionalLight x:Name="light" Color="White" 
    Direction="{Binding ElementName=lightVectorControl, 
    Path=Vector3D}"/>

Un test en runtime pour vérifier que tout fonctionne bien, et on obtient une application dans laquelle on peut modifier directement la direction de la lumière, et celle de la caméra :

 VectorControlApp


En espérant que ça pourra être utile à quelqu’un ;-)

Dominique Thery

Currently rated 5.0 by 4 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Workflow Foundation Part #1

clock August 14, 2008 09:00 by author dox

J'étais parti pour faire un article sur WCF, mais comme tout a déjà été dit, ça attendra un peu.
Cet article est le premier d'une série consacrée à Workflow Foundation (WF). Je vais essayer tout au long de ces articles, d'illustrer quelques une des fonctionnalités de WF, entre autres :

  • les workflows séquentiels
  • les workflows à états
  • les activités parallèles, conditionnelles et les conditions
  • la persistence dans Workflow Foundation
  • le tracking...

On va commencer doucement, avec un premier workflow de type séquentiel. Et pour ça, nous allons partir d'un exemple : Il fait beau dehors et Bob aimerait poser quelques jours de congés. Bob va donc déposer une demande de congés, qui devra être validée par son chef, puis par les ressources humaines. Une fois sa demande acceptée, Bob sera notifié qu'il peut aller profiter du soleil.
Cool

Première Etape : Le Workflow

Pour réaliser tout ça, nous allons avoir besoin d'un workflow (de type séquentiel ici, puisque les étapes se déroulent les unes après les autres). Voilà à quoi pourrait ressembler notre workflow

 

Il est composé de 3 activités de type HandleExternalEvent, et d'une activité CallExternalMethod qui vont permettre de :

  • d'abord réagir à une demande de congés
  • ensuite réagir à la validation par le supérieur de Bob
  • puis celle des ressources humaines
  • et enfin, appeler une méthode qui notifiera Bob de l'état de sa demande.

Deuxième Etape : L'interface 

Puisque notre workflow réagit à des événements et qu'il appelle une méthode externe, il nous faut définir ces éléments. Pour cela, nous crééons une interface qui contient les définitions suivantes :

[ExternalDataExchange]
public interface IDemandeCongesService {
  event EventHandler<DemandeCongesEventArgs> CongesDemandes;
 
event EventHandler<DemandeCongesEventArgs> ValidesSuperieur;
 
event EventHandler<DemandeCongesEventArgs> ValidesRH;
 
void NotifierDemandeAcceptee(Guid instanceId, DemandeCongesData data);
}

Ce qu'il faut noter dans la définition de cette interface :

  • L'interface est marquée de l'attribut ExternalDataExchange pour indiquer qu'elle sert à communiquer avec un workflow.
  • Les événements sont typés et héritent de la classe ExternalDataEventArgs. Ils sont également marqués de l'attribut Serializable.
  • L'objet DemandeCongesEventArgs contient une propriété de type DemandeCongesData. Cet objet contient les informations propres à notre demande de congés (nom de l'employé, le nombres de jours...), lui aussi marqué de l'attribut Serializable.

Il ne nous reste plus qu'à associer les propriétés de nos activités aux événements et méthodes correspondants.

Troisième Etape : L'implémentation et l'application hôte 

Un worfklow dans WF fonctionne un peu de la même façon qu'un service WCF. Il ne peut être démarré tel quel. Il a besoin d'une application hôte pour héberger le runtime de Workflow Foundation, qui se chargera ensuite de charger/créer une instance de notre workflow et de la démarrer.

Pour faire simple, nous regrouperons toute la logique métier dans une application de type Windows (le Web c'est mal Tongue out). Cette application contient une fenêtre principale et une classe qui contient l'implémentation de notre interface IDemandeCongesService. Voici un petit aperçu de notre application finale :

Ceci reste un exemple assez simple de ce qu'on peut faire avec Workflow Foundation. Les autres fonctionnalités de WF seront abordées dans les prochains articles de cette série. Dans le prochain épisode... Le workflow a états. En attendant, vous pouvez télécharger le contenu complet de l'exemple en suivant ce lien : WFpart01.zip (20,96 kb).

Par Dominique Thery,
To be continued...

Currently rated 4.3 by 3 people

  • Currently 4.333333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Calendrier

<<  July 2010  >>
MoTuWeThFrSaSu
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678
Afficher en pleine page

Visiteurs