Sonntag, 11. April 2010

Endpoint configurations (WCF) for Silverlight applications

Wer kennt nicht die Pein von der Ablage von Konfigurationsinformationen für unterschiedliche Zielumgebungen? Der Entwickler neigt meistens dazu, in den Konfigurationsdateien die unterschiedlichen Definitionen rein zu schreiben und immer nur diejenige nicht zu kommentieren, welcher er gerade nicht benötigt. Wenn man aber ein großes Projekt hat, kann diese Kommentierung-/Auskommentierungs-Fronarbeit aber ganz schön lästig sein. Was wäre es nicht schön, wenn wir beim Buildvorgang einfach unsere Zielumgebung auswählen könnten und schon haben wir die richtig konfigurierte Version. Als Ansatz für diese Lösung können wir – zumindest bis Microsoft hier eine Lösung in Visual Studio liefert – die bedingte Kompilierung verwenden.

Wi gehen dazu zunächst in den Buildmanager und legen uns für jede Umgebung (außer Development, den hier haben wir ja schon Debug) einen neue Konfiguration an. In meinem Fall sind das STAGING und PRODUCTION. In der Eigenschaft Conditional compilation symbols der Build-Konfiguration sollte dann z.B. SILVERLIGHT;STAGING usw. stehen.

Ab Silverlight 4 haben wir bei der Konfiguration von WCF-Services übrigens eine schöne Erweiterung: RelativeBinding. Hier kann die Endpoint-URI des Services in der ServiceReferences.ClientConfig relativ zur Silverlight-Ursprungs-Domäne angegeben werden.

(1) ServiceReferences.ClientConfig des Silverlight-Clients

In der ServiceReferences.ClientConfig definiert man für jede Umgebung einen Endpoint mit dem entsprechenden Binding.

<configuration>
    <system.serviceModel>
        <bindings>
            <customBinding>
                <binding name="DevelopmentServiceBinding">
                    <binaryMessageEncoding />
                    <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                </binding>
                <binding name="StagingServiceBinding">
                    <binaryMessageEncoding />
                    <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                </binding>
                <binding name="ProductionServiceBinding">
                    <binaryMessageEncoding />
                    <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                </binding>
                <binding name="RelativeBinding">
                    <binaryMessageEncoding />
                    <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                </binding>
            </customBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:40473/HelloWorldService.svc"
                binding="customBinding" bindingConfiguration="DevelopmentServiceBinding"
                contract="HelloServices.HelloWorldService" name="DevelopmentServiceBinding" />
            <endpoint address="http://localhost:40848/HelloWorldService.svc"
                binding="customBinding" bindingConfiguration="StagingServiceBinding"
                contract="HelloServices.HelloWorldService" name="StagingServiceBinding" />
            <endpoint address="http://localhost:40849/HelloWorldService.svc"
                binding="customBinding" bindingConfiguration="ProductionServiceBinding"
                contract="HelloServices.HelloWorldService" name="ProductionServiceBinding" />
          <!-- New at Silverlight 4 !!! -->
          <endpoint address="../HelloWorldService.svc"
               binding="customBinding" bindingConfiguration="RelativeBinding"
               contract="HelloServices.HelloWorldService" name="RelativeBinding" />
        </client>
    </system.serviceModel>
</configuration>

Die URIs der unterschiedlichen Endpoints zeigen hier zum Ausprobieren auf die lokalen Services und müssen letztendlich mit den richtigen Adressen der Staging- und Production-Services versorgt werden.

(2) Durch bedingte Kompilierung Endpoint setzen

Mittels der bedingten Kompilierung kann man dann den Endpoint entsprechend der ausgewählten Build-Konfiguration auswählen.

   1: void MainPage_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     _endpointName = "DevelopmentServiceBinding";
   4:     // oder für SL 4
   5:     _endpointName = "RelativeBinding";
   6:  
   7:     #if PRODUCTION
   8:         _endpointName = "ProductionServiceBinding";
   9:     #endif
  10:  
  11:     #if STAGING
  12:         _endpointName = "StagingServiceBinding";
  13:     #endif
Schlussbetrachtung

Wenn man diese Variante verwendet, muss man sich vergegenwärtigen, dass die ServiceReferenences.clientconfig als Resource kompiliert wird und so natürlich die Dev/Staging-URIs für jeden ersichtlich sind (zu mindestens diejenigen, die ein Tool wie Silverlight Spy oder Reflector ihr eigen nennen).

Die ergänzende Variante wäre, die Endpoints im Coding hart zu codieren, aber auch hier kann natürlich jeden den Silverlight-Client dekompilieren. Also eine echte Sicherheit zum Verbergen der Konfigurationsinformationen, gibt es erst, wenn Microsoft mal den Punkt “Config-Informationen in Abhägigkeit von der Umgebung” von der Wishlist von Visual Studio umsetzt.

[Quelle: Beitrag von Method ~ of ~ failed by Tim Heuer]

Keine Kommentare:

Kommentar veröffentlichen