WCF-Konfiguration ohne Konfigurationsdatei


90

Kennt jemand ein gutes Beispiel dafür, wie ein WCF-Dienst programmgesteuert ohne Verwendung einer Konfigurationsdatei verfügbar gemacht werden kann? Ich weiß, dass das Serviceobjektmodell jetzt mit WCF viel umfangreicher ist, daher weiß ich, dass es möglich ist. Ich habe nur kein Beispiel dafür gesehen. Umgekehrt würde ich gerne sehen, wie viel Aufwand auch ohne Konfigurationsdatei gemacht wird.

Bevor jemand fragt, muss ich dies ganz speziell ohne Konfigurationsdateien tun. Normalerweise würde ich eine solche Praxis nicht empfehlen, aber wie gesagt, in diesem Fall besteht ein sehr spezifischer Bedarf.


1
Warum würden Sie eine solche Vorgehensweise nicht empfehlen (den Dienst ohne Konfiguration programmgesteuert verfügbar machen)?
BornToCode

Antworten:


115

Wie ich festgestellt habe, ist es sehr einfach, einen Webdienst ohne Konfigurationsdatei zu verwenden. Sie müssen lediglich ein Bindungsobjekt und ein Adressobjekt erstellen und diese entweder an den Konstruktor des Client-Proxys oder an eine generische ChannelFactory-Instanz übergeben. Sie können in der Standardeinstellung app.config nachsehen, welche Einstellungen verwendet werden sollen, und dann irgendwo eine statische Hilfsmethode erstellen, die Ihren Proxy instanziiert:

internal static MyServiceSoapClient CreateWebServiceInstance() {
    BasicHttpBinding binding = new BasicHttpBinding();
    // I think most (or all) of these are defaults--I just copied them from app.config:
    binding.SendTimeout = TimeSpan.FromMinutes( 1 );
    binding.OpenTimeout = TimeSpan.FromMinutes( 1 );
    binding.CloseTimeout = TimeSpan.FromMinutes( 1 );
    binding.ReceiveTimeout = TimeSpan.FromMinutes( 10 );
    binding.AllowCookies = false;
    binding.BypassProxyOnLocal = false;
    binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
    binding.MessageEncoding = WSMessageEncoding.Text;
    binding.TextEncoding = System.Text.Encoding.UTF8;
    binding.TransferMode = TransferMode.Buffered;
    binding.UseDefaultWebProxy = true;
    return new MyServiceSoapClient( binding, new EndpointAddress( "http://www.mysite.com/MyService.asmx" ) );
}

Ich persönlich mag diesen Ansatz für Beispiele, wenn Sie die Datei in einer anderen Angelegenheit verwenden möchten, beispielsweise wenn Sie Ihre app.config (oder eine entsprechende Konfigurationsdatei) verschlüsselt haben und die integrierte WCF nicht verwenden müssen Fähigkeiten des Lesens in einer Verbindung
Noah

18
Fügen Sie für die Verwendung von https binding.Security.Mode = BasicHttpSecurityMode.Transport hinzu.
Ciscoheat

Das hat bei mir ganz gut funktioniert. Der einzige Unterschied für mich ist, dass ich auch die ReaderQuotas und Sicherheitsinformationen festgelegt habe. Ich habe den Rat von ciscoheat verwendet und den Security.Transport.Mode auf Transport gesetzt, wenn ich https verwende (für mich ist dies zum Zeitpunkt der Kompilierung nicht bekannt).
Kirk Liemohn

2
Ich habe gerade überprüft, dass alle Eigenschaften, die festgelegt werden, den Standardeinstellungen in WCF 4, fwiw, entsprechen. (Beachten Sie jedoch, dass Security.Modestandardmäßig None.)
Beladung

19

Wenn Sie daran interessiert sind, die Verwendung des Abschnitts System.ServiceModel in der Datei web.config für IIS-Hosting zu vermeiden, habe ich hier ein Beispiel veröffentlicht ( http://bejabbers2.blogspot.com/2010/02/wcf) -zero-config-in-net-35-part-ii.html ). Ich zeige, wie Sie einen ServiceHost anpassen, um sowohl Metadaten als auch wshttpbinding-Endpunkte zu erstellen. Ich mache es auf eine allgemeine Art und Weise, die keine zusätzliche Codierung erfordert. Für diejenigen, die nicht sofort auf .NET 4.0 aktualisieren, kann dies sehr praktisch sein.


John, ich bin mir sicher, dass dies ein großartiger Blog-Beitrag ist, aber da es eine akzeptierte Antwort von vor 17 Monaten gibt, hat Ihre Antwort wirklich einen Zweck?
John Saunders

36
Da dies meine erste Antwort auf einen Stapelüberlauf ist, ist dies möglicherweise nicht die übliche Vorgehensweise. Da ich mit den Büchern Lowy und Bustamante vertraut bin, die großartige Referenzen sind, denke ich, dass meine Antwort weit über die angebotenen Beispiele hinausgeht. Ich benutze hauptsächlich Stack Overflow beim Googeln, damit ich häufig ältere Beiträge lese. Es hilft nur aus meiner Sicht, aktuellere Antworten zu haben. Ich habe diesen Beitrag gegoogelt, bevor ich meinen Code geschrieben habe, um das Rad nicht neu zu erfinden.
John Wigger

48
Als häufiger SO-Benutzer finde ich es sehr wünschenswert, neue Beiträge zu alten Themen zu lesen. Es hilft mir, meine Arbeit besser zu machen, was den Wert dieser Website erhöht (da ich und andere sie mehr besuchen werden). Warum nicht zulassen, dass die Leute diskutieren, um bessere Antworten zu finden? Ist das nicht der Punkt?

7
Anscheinend wurde John Saunders mit der Antwort auf seine eigene Frage an seine Stelle gesetzt (von denen er keine als Antwort akzeptiert hat, die ich hinzufügen könnte). Ich persönlich habe kein Problem mit verspäteten Antworten auf Fragen und freue mich normalerweise über eine neue Antwort auf eine Frage, die ich gestellt habe, Monate, wenn nicht Jahre später. Ironischerweise habe ich mir mit meiner akzeptierten Antwort auf diese Frage mein eigenes Nekromanten-Abzeichen verdient. :)
devios1

3
Ich hatte das gleiche Problem und die akzeptierte Antwort half mir nicht, aber das tat es, Hurra für späte Antworten! Wäre es nicht zu späten Antworten gekommen, hätte ich eine doppelte Frage dazu erstellen müssen.
Didier A.

15

Hier ist dies vollständiger und funktionierender Code. Ich denke, es wird dir sehr helfen. Ich habe gesucht und nie einen vollständigen Code gefunden, deshalb habe ich versucht, vollständigen und funktionierenden Code einzufügen. Viel Glück.

public class ValidatorClass
{
    WSHttpBinding BindingConfig;
    EndpointIdentity DNSIdentity;
    Uri URI;
    ContractDescription ConfDescription;

    public ValidatorClass()
    {  
        // In constructor initializing configuration elements by code
        BindingConfig = ValidatorClass.ConfigBinding();
        DNSIdentity = ValidatorClass.ConfigEndPoint();
        URI = ValidatorClass.ConfigURI();
        ConfDescription = ValidatorClass.ConfigContractDescription();
    }


    public void MainOperation()
    {
         var Address = new EndpointAddress(URI, DNSIdentity);
         var Client = new EvalServiceClient(BindingConfig, Address);
         Client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerTrust;
         Client.Endpoint.Contract = ConfDescription;
         Client.ClientCredentials.UserName.UserName = "companyUserName";
         Client.ClientCredentials.UserName.Password = "companyPassword";
         Client.Open();

         string CatchData = Client.CallServiceMethod();

         Client.Close();
    }



    public static WSHttpBinding ConfigBinding()
    {
        // ----- Programmatic definition of the SomeService Binding -----
        var wsHttpBinding = new WSHttpBinding();

        wsHttpBinding.Name = "BindingName";
        wsHttpBinding.CloseTimeout = TimeSpan.FromMinutes(1);
        wsHttpBinding.OpenTimeout = TimeSpan.FromMinutes(1);
        wsHttpBinding.ReceiveTimeout = TimeSpan.FromMinutes(10);
        wsHttpBinding.SendTimeout = TimeSpan.FromMinutes(1);
        wsHttpBinding.BypassProxyOnLocal = false;
        wsHttpBinding.TransactionFlow = false;
        wsHttpBinding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
        wsHttpBinding.MaxBufferPoolSize = 524288;
        wsHttpBinding.MaxReceivedMessageSize = 65536;
        wsHttpBinding.MessageEncoding = WSMessageEncoding.Text;
        wsHttpBinding.TextEncoding = Encoding.UTF8;
        wsHttpBinding.UseDefaultWebProxy = true;
        wsHttpBinding.AllowCookies = false;

        wsHttpBinding.ReaderQuotas.MaxDepth = 32;
        wsHttpBinding.ReaderQuotas.MaxArrayLength = 16384;
        wsHttpBinding.ReaderQuotas.MaxStringContentLength = 8192;
        wsHttpBinding.ReaderQuotas.MaxBytesPerRead = 4096;
        wsHttpBinding.ReaderQuotas.MaxNameTableCharCount = 16384;

        wsHttpBinding.ReliableSession.Ordered = true;
        wsHttpBinding.ReliableSession.InactivityTimeout = TimeSpan.FromMinutes(10);
        wsHttpBinding.ReliableSession.Enabled = false;

        wsHttpBinding.Security.Mode = SecurityMode.Message;
        wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
        wsHttpBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
        wsHttpBinding.Security.Transport.Realm = "";

        wsHttpBinding.Security.Message.NegotiateServiceCredential = true;
        wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
        wsHttpBinding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256;
        // ----------- End Programmatic definition of the SomeServiceServiceBinding --------------

        return wsHttpBinding;

    }

    public static Uri ConfigURI()
    {
        // ----- Programmatic definition of the Service URI configuration -----
        Uri URI = new Uri("http://localhost:8732/Design_Time_Addresses/TestWcfServiceLibrary/EvalService/");

        return URI;
    }

    public static EndpointIdentity ConfigEndPoint()
    {
        // ----- Programmatic definition of the Service EndPointIdentitiy configuration -----
        EndpointIdentity DNSIdentity = EndpointIdentity.CreateDnsIdentity("tempCert");

        return DNSIdentity;
    }


    public static ContractDescription ConfigContractDescription()
    {
        // ----- Programmatic definition of the Service ContractDescription Binding -----
        ContractDescription Contract = ContractDescription.GetContract(typeof(IEvalService), typeof(EvalServiceClient));

        return Contract;
    }
}

Sehr schönes Beispiel! Sie demonstrieren nahezu jeden Aspekt der manuellen Konfiguration. Schön gemacht!
Kilhoffer

5
Ich verstehe nicht, wie EvalServiceClient in diesen Code passt. Es wird referenziert, aber nicht definiert. Warum erstellt der Server einen Client?
BlueMonkMN


3

Alle WCF-Konfigurationen können programmgesteuert durchgeführt werden. So ist es möglich, sowohl Server als auch Clients ohne Konfigurationsdatei zu erstellen.

Ich empfehle das Buch "Programming WCF Services" von Juval Lowy, das viele Beispiele für die programmatische Konfiguration enthält.


2

Dies ist sowohl auf Client- als auch auf Serverseite sehr einfach. Juval Lowys Buch enthält hervorragende Beispiele.

In Bezug auf Ihren Kommentar zu den Konfigurationsdateien würde ich sagen, dass die Konfigurationsdateien die zweite sind, die ein armer Mann im Code macht. Konfigurationsdateien eignen sich hervorragend, wenn Sie jeden Client steuern, der eine Verbindung zu Ihrem Server herstellt, und sicherstellen, dass sie aktualisiert werden und dass Benutzer sie nicht finden und nichts ändern können. Ich finde das WCF-Konfigurationsdateimodell einschränkend, leicht schwierig zu entwerfen und ein Wartungsalptraum. Alles in allem war es meiner Meinung nach eine sehr schlechte Entscheidung von MS, die Konfigurationsdateien zur Standardmethode zu machen.

BEARBEITEN: Mit der Konfigurationsdatei können Sie unter anderem keine Dienste mit nicht standardmäßigen Konstruktoren erstellen. Dies führt zu statischen / globalen Variablen und Singletons und anderen Arten von Unsinn in WCF.


2

Ich fand den Blog-Beitrag unter dem folgenden Link zu diesem Thema sehr interessant.

Eine Idee, die mir gefällt, ist die, einfach einen Bindungs- oder Verhaltens- oder Adress-XML-Abschnitt aus der Konfiguration an das entsprechende WCF-Objekt übergeben und die Zuweisung der Eigenschaften übernehmen zu lassen - derzeit ist dies nicht möglich.

Wie andere im Web habe ich Probleme damit, dass meine WCF-Implementierung eine andere Konfigurationsdatei als die meiner Hosting-Anwendung (bei der es sich um einen .NET 2.0-Windows-Dienst handelt) verwenden muss.

http://salvoz.com/blog/2007/12/09/programmatic-setting-wcf-configuration/

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.