jeudi 1 avril 2010

Silverlight - WPF - Autoriser les communications (WCF) "cross-domain" entre Silverlight 2 et des services "self-hosted" dans une "Windows Form"

Afin de permettre à une application Silverlight d'un domaine de pouvoir consommer les services d'un autre domaine, le service doit autoriser l'application en lui fournissant les règles d'accès. Les règles doivent être placées à la racine du domaine.
 
Or dans le cas d'une application (Windows Form ou WPF) hébergeant des services WCF et une application silverlight, on risque d'être confronté à un problème. En effet, l'application silverlight n'est pas dans le même domaine que le service WCF et ne dispose d'aucun serveur web pour héberger les règles.
 
Pour "ajouter" les règles à la racine du domaine, on doit ajouter un nouveau "EndPoint" à la racine du domaine.
 
Au moment de la demande d'accès "Cross-Domain" par Silverlight, celui-ci appellera le fichier http://domaine:port/clientaccesspolicy.xml. Cette url est également un allias de l'appel au contrat d'opération sur "GetSilverlightPolicy" (Voir code ci-dessous). Cette méthode retourne comme résultat les règles d'accès sous forme de Stream.
Silverlight dispose alors de toutes les informations nécessaires pour communiquer avec les services WCF hébergé dans l'application.
 
public class SelfHostedServiceWithSilverlightPolicy {
    [
ServiceContract]     public interface ITest     {
        [
OperationContract]         string Echo(string text);
    }
    [
ServiceContract]     public interface IPolicyRetriever     {
        [
OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]         Stream GetSilverlightPolicy();
    }
    public class Service : ITest, IPolicyRetriever     {         public string Echo(string text) { return text; }

        Stream StringToStream(string result)
        {
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";             return new MemoryStream(Encoding.UTF8.GetBytes(result));
        }

        public Stream GetSilverlightPolicy()
        {
            string result = @"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
    <cross-domain-access>         <policy>             <allow-from http-request-headers=""*"">                 <domain uri=""*""/>             </allow-from>             <grant-to>                 <resource path=""/"" include-subpaths=""true""/>             </grant-to>         </policy>     </cross-domain-access>
</access-policy>"
;             return StringToStream(result);
        }
    }     public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000";         ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        host.AddServiceEndpoint(
typeof(ITest), new BasicHttpBinding(), "basic");
        host.AddServiceEndpoint(
typeof(IPolicyRetriever), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());         ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
        smb.HttpGetEnabled =
true;
        host.Description.Behaviors.Add(smb);
        host.Open();
        Console.WriteLine("Host opened");         Console.Write("Press ENTER to close");         Console.ReadLine();
        host.Close();
    }
}
Référence :
http://blogs.msdn.com/carlosfigueira/archive/2008/03/07/enabling-cross-domain-calls-for-silverlight-apps-on-self-hosted-web-services.aspx

Aucun commentaire:

Enregistrer un commentaire