Wilfried Woivré & .Net

Silverlight & WCF : Interroger un service via une url relative

JUIN23

Quand on développe une application Silverlight, on a souvent besoin de s’abonner à des services afin d’accéder aux données situées sur un serveur distant, on créé donc le plus généralement un service WCF qui exposera nos données.

Si vous n’utilisez pas IIS pour vos développements, vous avez du remarquer, du moins je l’espère, que Visual Studio démarre un serveur web allégé qui hébergera votre application. On accède donc à notre application via une url de ce type http://localhost:24421/MaSuperApplicationQuiDeboiteTestPage.aspx jusque là aucun problème votre application marche et vous avez accès à votre service via cette url : http://localhost:24421/MonSuperServiceQuiDeboite.svc.

 

Donc quand vous vous abonnez au service via Visual Studio, il va vous générer le proxy, ainsi qu’un fichier de config avec les données de configuration du service, comme on peut le voir ci-dessous :

<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IService1" maxBufferSize="2147483647"
                    maxReceivedMessageSize="2147483647">
                    <security mode="None" />
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:20624/Service1.svc" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
                name="BasicHttpBinding_IService1" />
        </client>
    </system.serviceModel>
</configuration>

Le problème que l’on peut cependant obtenir et que Visual Studio, selon son humeur, peut décider de changer le port de votre application, et donc vos informations de connexion seront incorrectes. Vous pouvez donc soit fixer le port du serveur web, soit changer ces informations comme on va le voir par la suite. Plus concrètement, ce problème arrive très souvent lorsque vous faites du développement pour Azure avec l’émulateur qui vous génère une url de ce type http://127.0.0.1:81, le port peut changer si vous quittez l’appli brutalement, typiquement lorsque vous avec un point d’arrêt déclenché dans votre Visual Studio et que vous arrêtez le debug !

 

Alors pour éviter le soucis, il vous suffit de mettre votre adresse de service en relative, comme ci dessous

<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IService1" maxBufferSize="2147483647"
                    maxReceivedMessageSize="2147483647">
                    <security mode="None" />
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="/Service1.svc" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
                name="BasicHttpBinding_IService1" />
        </client>
    </system.serviceModel>
</configuration>

C’est beaucoup mieux que de reconstruire l’url du service à partir de l’url courante !

Remonter

Utiliser RIA Services & le Table Storage d’Azure

MAI29

Lors d’un Azure Camp organisé par ZeCloud, j’ai montré comment exposer le Table Storage de Windows Azure via un WCF Data Services, cela nous permettait d’avoir une exposition de nos données via OData. Vous pouvez retrouver la démonstration sur le codeplex de ZeCloud, et me demander plus d’infos au prochain Azure Camp

 

Dans la même idée, je me suis aperçu que la dernière version de RIA Services proposait quelque chose du même genre, via son toolkit, on va donc voir comment le mettre en place !

 

Commençons déjà par créer un projet de type Cloud, ainsi qu’une application Silverlight avec un site web et WCF RIA Services. Il nous faut ensuite ajouter les références, par NuGet c’est plus facile

image

 

 

Maintenant, il nous faut créer notre Model, pour cela, on va prendre un cas très simple :

 

public class Person : TableEntity
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    /// <summary>
    /// The property is set to be mentioned explicitly in the DataForm ...
    /// ONLY FOR THE DEMO
    /// </summary>
    public string MyPartitionKey
    {
        get
        {
            return base.PartitionKey;
        }
        set
        {
            base.PartitionKey = value;
        }
    }
}

On peut voir déjà quelques différences, premièrement on n’hérite pas de TableStorageEntity, mais de TableEntity qui hérite lui même de TableServiceEntity, et la deuxième c’est que pour le cas de la démo, j’ai voulu tester plusieurs PartitionKey, j’ai donc réexposé via une autre propriété celle ci afin qu’elle apparaisse dans mon DataForm Silverlight.

 

Maintenant, voyons notre contexte de données pour notre Table Storage

public class AzureServiceContext : TableEntityContext
{      
    public AzureServiceContext() : 
        base(RoleEnvironment
            .GetConfigurationSettingValue("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"))
    {
    }

    public TableEntitySet<Person> People
    {
        get { return base.GetEntitySet<Person>(); }
    }
}

 

Donc de même ici, on peut voir quelques différences, déjà au niveau de l’héritage, ici on hérite de TableEntityContext qui hérite lui même de TableServiceEntity.

De plus, on peut voir que l’on ne gère pas non plus la création des tables dans le Table Storage, vu que le toolkit de RIA Services s’en occupe pour nous.

Il ne vous reste plus qu’à créer votre Domain Service de façon classique, il faut juste renseigner aucun contexte.

image

 

Maintenant, implémentons notre DomainService

[EnableClientAccess()]
public class TSDomainService : TableDomainService<AzureServiceContext>
{

    protected override string PartitionKey
    {
        get
        {
            return null;
        }
    }

    public IQueryable<Person> GetPeople()
    {
        return EntityContext.People;
    }

    public void AddPerson(Person person)
    {
        EntityContext.People.Add(person);
    }

    public void DeletePerson(Person person)
    {
        EntityContext.People.Delete(person);
    }

    public void UpdatePerson(Person person)
    {
        EntityContext.People.Update(person);
    }
}

On a dorénavant la possibilité de faire un TableDomainService pour englober notre contexte Azure, de même les méthodes standards de CRUD sont facilitées.

Voyons maintenant la PartitionKey, par défaut  le toolkit met la PartitionKey à la valeur du nom du Domain Service, pour éviter qu’elle soit définit ainsi, il suffit de surcharger la PartitionKey, cependant cela veut dire qu’il vous faudra la spécifier à chaque fois, ce qui est mieux si vous voulez une bonne structure de donnée dans votre Table Storage

 

Et voilà le résultat dans un DataForm Silverlight

image

 

Vous pouvez retrouver les sources de la solution ici

Remonter

Afficher des informations dans la fenêtre de sortie de Visual Studio

MAI19

Quand on fait du XAML que ce soit en WPF, Silverlight ou WP7, on est bien heureux de voir apparaitre ces petits messages d’erreur dans la fenêtre de sortie lorsque l’on est en mode debug de notre application !

Ici comme on peut le voir il s’agit uniquement d’une erreur de binding, qui nous informe que la propriété “FirstName” n’a pas été trouvée :

 

image

 

Et si on voyait comment ajouter nos propres messages dans cette fenêtre, et bien tout est là pour nous aider, c’est très facilement faisable grâce au namespace System.Diagnotics

 

this.Loaded += (sender, e) => System.Diagnostics.Debug.Print("Message perso => Un petit test ?");

On obtient en mode DEBUG, notre message personnel dans la fenêtre de sortie

image

Et comme la vie est bien faite, en mode release, rien n’apparait !

 

Bon bien entendu, rien ne sert de polluer cette fenêtre outre mesure, mais c’est toujours mieux qu’une trentaine de message box d’information pour lancer votre programme et être sûr que tout ce passe bien !

Remonter

Silverlight 5 : Arrivée de l’Ancestor RelativeSource Binding

AVRI13

Et oui, le voilà, comme quoi, on n’arrête pas le progrès dans Silverlight !

Une petite démonstration sur l’ancestor RelativeSource Binding pour commencer cette soirée ….

Je vous ai montré à plusieurs reprises comment lier vos commandes ou vos actions de vos datatemplate compris dans des ItemsControl à des méthodes de vos ViewModel !

 

Vous avez donc accès à une solution qui pouvait être amélioré mais qui était tout de même bien pratique, vous pouvez la retrouver ici ou en vidéo.

 

On va déjà commencer par créer une application en Silverlight 5 !

image

Ensuite on va créer notre ViewModel de façon on ne peut plus classique

public class MainViewModel : ViewModelBase
{
    private readonly ObservableCollection<Person> _people = new ObservableCollection<Person>();
    public ObservableCollection<Person> People
    {
        get { return _people; }
    }

    private ICommand _callCommand;
    public ICommand CallCommand
    {
        get { return _callCommand ?? (_callCommand = new RelayCommand<Person>(Call)); }
    }

    public MainViewModel()
    {
        People.Add(new Person() { FirstName = "Wilfried", LastName = "Woivré" });
        People.Add(new Person() { FirstName = "Harry", LastName = "Cover" });
    }

    public void Call(Person person)
    {
        MessageBox.Show(string.Format("Call Person : {0} {1}", person.FirstName, person.LastName));
    }

    public void Call()
    {
        MessageBox.Show("Call Method");
    }
}

On lie correctement notre Vue à notre ViewModel, comme cela :

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
        this.Loaded += (sender, e) => this.DataContext = new MainViewModel();
    }
}

Et maintenant passons à la vue, puisque le model c’est juste deux propriétés ….

    <Grid x:Name="LayoutRoot" Background="White">

        <ListBox ItemsSource="{Binding People}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Button Content="CallMethodAction" Margin="5"  >
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="Click">
                                    <ei:CallMethodAction MethodName="Call" TargetObject="{Binding DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}" />
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        </Button>
                        <Button Content="Command" Margin="5" >
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="Click">
                                    <i:InvokeCommandAction 
                                        Command="{Binding DataContext.CallCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" 
                                        CommandParameter="{Binding}"/>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        </Button>
                        <TextBlock Text="{Binding FirstName}" Margin="5" />
                        <TextBlock Text="{Binding LastName}" Margin="5" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

 

Et donc quelle est la principale différence par rapport à avant, c’est l’apparition de RelativeSource={RelativeSource AncestorType=UserControl} , cela permet d’appeler notre command ou notre méthode selon le DataContext lié à notre UserControl, nous n’avons donc plus besoin de passer via une méthode dans une classe partielle du model !

 

Vous pouvez retrouver les sources de la solution ici

Pour plus d’infos sur les autres nouveautés de Silverlight 5, je vous conseille le blog de Tim Heuer

Remonter

Silverlight 5 Beta disponible

AVRI13

Voilà si vous avez loupé cette annonce au MIX, Silverlight 5 est disponible ainsi que le Blend qui va avec !

 

Silverlight 5 => Silverlight 5 Beta Tools for Visual Studio SP1

Expression Blend 5 => Expression Blend Preview for Silverlight 5

 

Voilà il vous faudra Visual Studio 2010 SP1 pour pouvoir l’installer !

Et si vous voulez revivre le MIX, c’est à cette adresse => http://live.visitmix.com/

Remonter