close
Kaspersky Endpoint Security

Welcome to

Kaspersky Endpoint Security


By Kaspersky Endpoint Security


Programmatisch Einstellung WCF-Konfiguration



Es scheint, als ob es jemand bei Microsoft ist, die im Leben alleinigen Zweck ist, ist, herauszufinden, wie ich könnte etwas (WCF) verwendet werden soll, und stellen Sie sicher, dass ich es nicht in der Art, wie ich zu wollen, verwenden können. Die heutige Ausgabe, Konfiguration programmatisch einen WCF-Client-Anwendung.

Hintergrund

Ich habe ein zentrales Repository Speicher in Form einer SQL-Datenbank erstellt, die einfach ausgedrückt, enthält Schlüssel / Wert-Paare, die ich abfragen. Alle meine Anwendungen (oder jeder machine.config) benötigen nur eine einzige Datenbank-Verbindungszeichenfolge zu dieser Konfigurationsdatenbank angeben. Alle anderen Konfigurationseinstellungen werden aus der Datenbank (und cached) abgerufen werden, so dass es leicht den Überblick über Konfiguration zu halten, sehen Sie alle aktuellen Konfigurationseinstellungen und die Anwendungen auf neue Server bereitstellen.

Die Erweiterung auf meine einfache Definition, gibt es eine zweite "Schlüssel", der zu welcher Umgebung entspricht (Produktion, Inszenierung, Entwicklung) die Anwendung bereitgestellt wird. So ist meine einzige Konfigurationsdatenbank steuert die Konfiguration aller Anwendungen in allen Umgebungen. Für die Einstellungen, die das gleiche in allen Umgebungen sind, wird keine Deployment-Schlüssel angegeben.

Bisher hat dies funktionierte großartig, und ich wollte Konfigurationsinformationen zu einem WCF-Client-Dienst hinzuzufügen.

WCF

WCF muss zwei Eigenschaften festgelegt, eine Bindung und einen Endpunkt, und jeder dieser zwei Eigenschaften haben Unter Eigenschaften, die eingestellt werden kann oder nicht Werte haben, die müssen. Out of the box, ist WCF am einfachsten mit Anwendung oder Web-Konfigurationsdateien konfiguriert. Alle Werkzeuge unterstützen die Konfigurationsdateien und es ist leicht zu sehen, was (auch eine Art) vor sich geht.

Ich wollte im Grunde die XML-Abschnitte zu nehmen, die die Bindung und Endpunkt, und legen Sie sie in meine Konfigurationsdatenbank zu definieren. Aus irgendeinem Grund habe ich es in meinem Kopf, dass dies wirklich einfach sein würde, zu tun, aber herausgefunden, dass es nicht ist. Suche durch Google ergab keine direkte Lösung. Während Sie programmatisch die Bindung und Endpoint Eigenschaften eines Proxy-Klasse Client-Objekt festlegen können, würde ich entweder pro Objekt 1 Einstellung zu haben (und Sub-Eigenschaft) in meiner Konfigurationsdatenbank oder mit einem XML-Schema kommen, analysieren das Schema und setzen die Werte. Das war der Weg, den ich wurde pursing, sondern mein eigenes Schema zu machen, habe ich nur die XML-Konfigurationsschema aus der Box zur Verfügung gestellt, in der Hoffnung, dass ich eines Tages nur diejenigen Abschnitte der Bindung oder Endpunkt Objekte passieren könnte und haben es analysieren für mich.

Nach dem Erstellen von Klassen eine einzige Bindungs ​​(WsHttpBinding) zu analysieren, habe ich beschlossen, es muss einen besseren Weg geben. Der Code zum Parsen der Konfigurationsdateien müssen irgendwo in System.ServiceModel existieren, so habe ich beschlossen, mit Reflektor zu gehen spelunking, um zu sehen, was los war, und festzustellen, ob ich etwas zusammen hacken könnte.

Implementierung

Übersicht Nach ein paar Stunden in Reflektor verbringen, erkannte ich die Hauptstraßensperre die Nutzung des System.Configuration Namespace war die Konfigurationsdaten für System.ServiceModel zu handhaben. System.Configuration unterstützt nur das Dateisystem und bietet keine Erweiterungsmethoden zu dieser Zeit (etwas, Ich mag würde von Microsoft in die Zukunft zu sehen). Dies ließ mich mit einer Option, die mit meiner Konfigurationsdaten aus der Datenbank temporäre XML-Datei zu erstellen sollte, und dann diese Konfigurationsdatei lesen Sie die richtigen Klassen / Methoden in System.Configuration verwenden. Es dauerte eine Weile, um diese Option zu akzeptieren, als eine temporäre Datei zu schreiben chaotisch schien, aber dann merkte ich, temporäre Dateien eine Tatsache des Lebens in .NET, Programmierung, Betriebssysteme etc. Konfigurationsspeicher Meine Konfigurationsspeicher bereits als I definiert wurde zuvor erwähnt. Die 2 XML-Beispiele unten werden als separate Einträge in meiner Konfigurationsdatenbank gespeichert. Unten ist die XML-I für den Umgang mit den Bindungen gespeichert: <Bindungen><WsHttpBinding>   <Binding name = "WSHttpBinding_ITwoWayAsyncVoid" Close = "00.01.00"           Opentimeout = "00.00.30" ReceiveTimeout = "00.02.00" Sendtimeout = "00.00.15"           bypassProxyOnLocal = "false" transactionFlow = "false" HostNameComparisonMode = "Strong"           MaxBufferPoolSize = "524288" MaxReceivedMessageSize = "65536" messageEncoding = "Text"           Textencoding = "utf-8" useDefaultWebProxy = "true" AllowCookies = "false">           <ReaderQuotas maxDepth = "32" maxStringContentLength = "8192" MaxArrayLength = "16384"             maxBytesPerRead = "4096" maxNameTableCharCount = "16384" />           <ReliableSession bestellt = "true" InactivityTimeout = "00.10.00"             enabled = "false" />           <Security mode = "Meldung">             <Transport ClientCredentialType = "Windows" proxyCredentialType = "None"               realm = "" />             <Message ClientCredentialType = "Windows" negotiateServiceCredential = "true"               algorithmSuite = "Default"EstablishSecurityContext = "true" />           </ Security>   </ Binding>  </ WsHttpBinding> </ Bindings>
Ich bin in der Lage mehrere Bindungen zu speichern und Konfigurationen in einem einzigen Eintrag in meiner Konfigurationsdatenbank Bindung (siehe unten). In diesem Beispiel habe ich nur eine einzige Bindung und Bindungskonfiguration. Ich hatte geplant, ursprünglich ein Eintrag für jede Bindung zu haben, aber ich glaube nicht, dass notwendig sein wird, wenn alles, was ich einen einzigen Eintrag für alle notwendigen Bindungen pro Umwelt haben werden, und auch das könnte zu viel des Guten. Dies ist der XML-I für den Endpunkt gespeichert: <Bindungen>  <WsHttpBinding>   <Binding name = "WSHttpBinding_ITwoWayAsyncVoid" />  </ WsHttpBinding> </ Bindings> <Client>  <Endpunktadresse = "Bindung =" wsHttpBinding "bindingConfiguration =" WSHttpBinding_ITwoWayAsyncVoid "         Vertrag = "TsiCbsEsbReceiver.WcfService_TersoSolutions_CBS_Fusion_BizTalk_InitialProcess"         name = "WSHttpBinding_ITwoWayAsyncVoid">         <Identität>           <Userprincipal value = "TERSODEMODEV1BizTalkWebServices" />         </ Identity>  </ Endpunkt> </ Client>
Beachten Sie die Wiederholung der <Bindungen> Abschnitt. Dies ist erforderlich war, wenn ich die Klassen in System.ServiceModel zum Parsen der Endpunkt verwenden wollte, musste ich ein Skelett für die Bindungen zu definieren.
Ich trennte die Endpunkte von den Bindungen, wie das ist, was zwischen Umgebungen die meisten für mich ändern wird. Der Endpunkt gibt an, welcher Server (Test, Produktion, Inszenierung) und Identität (für Single-Server-Test-Szenarien, wird das Konto lokal sein, für Multi-Server-Produktion enviroments, wird die Identität ein Domänenkonto sein).
Code
Ich habe zwei Klassen unter einem Namensraum genannt ConfigSystem. Die erste Klasse, die so genannte ConfigMgr enthält Code, der mich von meiner Konfigurationsdatenbank zu einem System.Configuration.Configuration Objekt durch eine temporäre Datei gehen können. Die zweite Klasse namens Wcf, enthält Code spezifisch für meine Wcf Konfiguration Implementierung und enthält Code aus Reflektor abgeleitet.
Alle der Code in ConfigMgr verwendet öffentliche Klassen und ist ziemlich einfach.
public static Klasse ConfigMgr  {   #region MemberVars   "<1,0 privat const string configFileHeader =? Xml version =" "?> <Konfiguration>";   Privat const string configFileFooter = "</ configuration>";      #endregion   #region Methoden - Public   public static Configuration GetSection (string ConfigKey,    String xmlConfigFileHeaderExtra, string xmlConfigFileFooterExtra, string section)   {    // Ein XML-Dokument aus der Konfigurationsdatenbank holen als tempory Datei zu speichern.    System.Xml.XmlDocument doc = PrepareXmlDocument (ConfigKey, xmlConfigFileHeaderExtra, xmlConfigFileFooterExtra);    // Jetzt schreiben auf die temporäre Datei.    string path = System.IO.Path.GetTempFileName ();    mit (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create (Pfad))    {     doc.WriteTo (Drehbuch);     writer.Close ();    }        // Setup-Konfigurationsdatei Karte, so dass wir Standard Datei-basierte Konfigurationsdatei verwenden    ExeConfigurationFileMap Karte = new ExeConfigurationFileMap ();    map.ExeConfigFilename =Pfad;    System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration (map, ConfigurationUserLevel.None);        // Nun kehren die angegebene Abschnitt    Rückkehr config.GetSection (section);   }   private static System.Xml.XmlDocument PrepareXmlDocument (string ConfigKey, string xmlConfigFileHeaderExtra, string xmlConfigFileFooterExtra)   {    System.Text.StringBuilder sb = new System.Text.StringBuilder ();        // Header anhängen    sb.Append (configFileHeader);    sb.Append (xmlConfigFileHeaderExtra);    sb.Append (ConfigHandler.GetValue (ConfigKey));    // Anfügen Footer    sb.Append (xmlConfigFileFooterExtra);    sb.Append (configFileFooter);    System.Xml.XmlDocument doc = new System.Xml.XmlDocument ();    doc.LoadXml (sb.ToString ());    Rückkehr doc;   }   #endregion  }
Der Code in der WCF-Klasse verwendet, einige Methoden, die ich über Reflektor kopiert, und weil ich nicht die rechtlichen Folgen davon nicht kennen, ich sende nur eine Skizze von dem, was ich tat.
GetBinding: Abschnitt Anrufe ConfigMgr.Get und gibt den <Bindungen> Abschnitt. Dies wird zu einem BindingsSection-Objekt umgewandelt. Code aus System.ServiceModel.Configuration genommen schafft eine BindingCollectionElement, die die richtige Art, mit der Bindung, gespeichert in der XML-Konfigurations assoziiert ist. Ein neues Bindungs ​​Objekt erstellt Activator.CreateInstance (BindingCollectionElement.BindingType) Zusatzcode von System.ServiceModel.Configuration aufgenommen mit Schleifen durch BindingCollectionElement.ConfiguredBindings und initialisiert die Bindung Objekt zuvor erstellt haben. Es wird überprüft, dass mehrere Bindungen des gleichen Typs zu machen sind nicht erstellt. Schließlich wird die Bindungsobjekt an den Aufrufer zurückgegeben.
GetChannelEndpointElement: Diese Klasse verwendet nur öffentliche Klassen und Methoden, damit ich es bin auch. EnpointElement enthält die Konfigurationsdaten für einen Endpunkt, einschließlich der URI, Identität, Bindung und Bindungskonfiguration. Die Bindung und Bindungskonfigurationsdaten tatsächlich an meine GetBinding Methode übergeben die korrekte Bindung mit der richtigen Bindungskonfiguration zurückzukehren. public static ChannelEndpointElement GetChannelEndpointElement (string ConfigKey)   {    Abschnitt ClientSection = (ClientSection) ConfigMgr.GetSection (ConfigKey, system_ServiceModelAsOpenXml, system_ServiceModelAsCloseXml, clientSection);    if (Abschnitt == null)     throw new Argument (string.Format ( "Client Abschnitt zurück von Config db für Schlüssel {0} war null", ConfigKey));    if (section.Endpoints.Count! = 1)     throw new Argument (string.Format ( "Es muss genau 1 Endpunkt aus der Konfiguration zurückgegeben {0} Endpunkte wurden für Schlüssel zurückgegeben {1}.", section.Endpoints.Count, ConfigKey));Rückkehr section.Endpoints [0];       }
GetEndpointAddress: Eine andere Methode, die ich geschaffen, die fast alle öffentlichen Methoden verwendet. Es dauert eine ChannelEnpointElement und gibt einen EndpointAddress, die zu einem WCF-Proxy-Klasse zugeordnet werden können. public static EndpointAddress GetEndpointAddress (ChannelEndpointElement Element)   {    // Erstellen Sie einen neuen Builder, als der Endpunkt-Adresse eine unveränderliche Klasse    EndpointAddressBuilder builder = new EndpointAddressBuilder ();    builder.Identity = LoadIdentity (element.Identity);    builder.Uri = element.Address;    Rückkehr builder.ToEndpointAddress ();   }
LoadIdentity: Diese letzte Methode wurde von System.ServiceModel.Description.Configloader genommen. Diese Methode benötigt ein IdentityElement (eine Eigenschaft von ChannelEnpointElement) und gibt einen EndpointIdentity die dem EndpointAddressBuilder in meinem GetEndpointAddress Methode übergeben wird. Das Verfahren prüft grundsätzlich die das Vorhandensein bestimmter Eigenschaften, und wenn ein solches vorhanden ist, gibt es die entsprechende Identität öffentlichen Factory-Methoden verwenden. EndpointIdentity.CreateUpnIdentity EndpointIdentity.CreateSpnIdentity EndpointIdentity.CreateDnsIdentity EndpointIdentity.CreateRsaIdentity EndpointIdentity.CreateX509CertificateIdentity
Es gibt eine Identität Zertifikattyp Referenz, die ich war nicht in der Lage, Unterstützung für, weil es zusätzliche interne Klassen verwiesen, die ich zu diesem Zeitpunkt nicht zu kopieren wollte, da ich keine Notwendigkeit für diese Identität Typ hatte.

Probleme

Da dies völlig ohne Unterstützung von Microsoft ist, und verwendet Code, der nie für den externen Gebrauch bestimmt war, in einer zukünftigen Version des Rahmens könnte etwas zu Bruch geht. Ich bin auch kein Rechtsexperte, wenn es mit kommt, was jemand mit MSIL Code durch Reflektor entdeckt tun können, so jetzt der eigentliche Code, den ich nicht öffentlich zugänglich geschrieben. Hoffentlich vorausgesetzt ich genügend Informationen, um jemandem erlauben, meine Schritte zu reproduzieren und etwas auf eigene Faust umzusetzen.

Ein weiterer etwas enttäuschend Realisierung ich wieder zu mir kam, war, dass dies machen es schwer Schreiboperationen in meine Konfigurationsdatenbank zu unterstützen. Derzeit ist die Konfigurationsdatenbank wird durch Skripte und direkte Bearbeitung verwaltet. Wenn Schreib Unterstützung für die Konfigurationsdatenbank eine Anforderung wurde, würde ich wahrscheinlich versuchen, das Gegenteil zu tun, und die eingebaute Datei speichern Funktionalität in System.Configuration eine temporäre XML-Datei zu speichern, lesen Sie es und dann speichern Sie sie in meine Config-Datenbank.

Schlussfolgerung

Das war mein erster Versuch, so etwas wie dies zu tun, graben in Framework-Code zu sehen, wie es wirklich funktioniert und versuchen, mit einer Lösung zu kommen. Ich gehe vorwärts zu gehen mit dem Code ich in diesem Beitrag skizziert geschrieben habe, als ich die Leser Unterstützung für WCF XML-Konfiguration. Die Menge an Code musste ich schreiben und zu testen ist deutlich weniger dann, wenn ich die gleiche Menge an Funktionalität (Konfiguration von allen Bindungen und Endpunkt-Konfigurationen) zu erhalten gewünscht hätte.

Teile das:

Endpoint-Security 2014 gartner     Endpoint-Security-10 Produkthandbuch

Categories and tags