Yapılandırma dosyası olmadan WCF Yapılandırması


90

Bir yapılandırma dosyası kullanmadan bir WCF hizmetinin programlı olarak nasıl ortaya çıkarılacağına dair iyi bir örnek bilen var mı? Hizmet nesnesi modelinin WCF ile artık çok daha zengin olduğunu biliyorum, bu yüzden bunun mümkün olduğunu biliyorum. Bunun nasıl yapılacağına dair bir örnek görmedim. Tersine, bir yapılandırma dosyası olmadan nasıl tüketildiğini de görmek isterim.

Herhangi biri sormadan önce, bunu yapılandırma dosyaları olmadan yapmak için çok özel bir ihtiyacım var. Normalde böyle bir uygulamayı tavsiye etmem ama dediğim gibi bu durumda çok özel bir ihtiyaç var.


1
Neden böyle bir uygulamayı önermiyorsunuz (hizmeti programlı olarak yapılandırma olmadan sunma)?
BornToCode

Yanıtlar:


115

Bir web hizmetini yapılandırma dosyası olmadan kullanmak, keşfettiğim gibi çok basit. Yalnızca bir bağlama nesnesi ve adres nesnesi oluşturmanız ve bunları istemci proxy'sinin yapıcısına veya genel bir ChannelFactory örneğine iletmeniz yeterlidir. Hangi ayarların kullanılacağını görmek için varsayılan app.config dosyasına bakabilir, ardından proxy'nizi başlatan bir yerde statik bir yardımcı yöntem oluşturabilirsiniz:

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" ) );
}

Dosyayı farklı bir konuda kullanacağınız zaman, örneğin app.config (veya eşdeğer yapılandırma dosyasını) şifrelemişseniz ve yerleşik WCF'yi kullanmanız gerekmiyorsa, örnekler için bu yaklaşımı kişisel olarak seviyorum bir bağlantıda okuma yetenekleri
Noah

18
Https kullanımı için, binding.Security.Mode = BasicHttpSecurityMode.Transport;
ciscoheat

Bu benim için oldukça iyi çalıştı. Benim için tek fark, ReaderQuotas ve Güvenlik bilgilerini de ayarlamam. Ciscoheat'in tavsiyesinden yararlandım ve https kullanılıyorsa Security.Transport.Mode'u Transport olarak ayarladım (benim için bu, derleme zamanında bilinmiyor).
Kirk Liemohn

2
Ayarlanan tüm özelliklerin WCF 4, fwiw'deki varsayılan değerlere eşit olduğunu doğruladım. (Ancak Security.Modevarsayılan değerinin olduğunu unutmayın None.)
40'ta yüklü

19

IIS barındırma için web.config içindeki System.ServiceModel bölümünün kullanımını ortadan kaldırmakla ilgileniyorsanız, burada nasıl yapılacağına dair bir örnek yayınladım ( http://bejabbers2.blogspot.com/2010/02/wcf -zero-config-in-net-35-part-ii.html ). Hem meta verileri hem de wshttpbinding uç noktaları oluşturmak için bir ServiceHost'u nasıl özelleştireceğimi gösteriyorum. Ek kodlama gerektirmeyen genel amaçlı bir şekilde yapıyorum. Hemen .NET 4.0'a yükseltmeyenler için bu oldukça uygun olabilir.


John, eminim bu harika bir blog yazısı, ama 17 ay öncesinden kabul edilmiş bir cevap olduğuna göre, cevabının gerçekten bir amacı var mı?
John Saunders

36
Bu benim ilk Yığın Taşması cevabım olduğundan, işler genellikle böyle yapılmayabilir. Harika referanslar olan Lowy ve Bustamante kitaplarına aşina olduğum için cevabımın sundukları örneklerin çok ötesine geçtiğini düşünüyorum. Google'da çalışırken öncelikle Stack Overflow kullanıyorum, bu yüzden daha eski olan yazıları okuyorum. Daha güncel cevaplara sahip olmak sadece benim bakış açımdan yardımcı oluyor. Tekerleği yeniden icat etmekten kaçınmak için kodumu yazmadan önce bu gönderiyi araştırdım.
John Wigger

48
Sık sık SO kullanıcısı olarak, eski konularla ilgili yeni yazıları okumayı oldukça cazip buluyorum. İşimi daha iyi yapmama yardımcı oluyor, bu da bu sitenin değerini artırıyor (çünkü kendim ve başkaları onu daha çok ziyaret edecek). Kurallara sadık kalmak yerine, neden insanların tartışmasına izin vermiyorsunuz ki daha iyi cevaplar bulunabilsin? Konu bu değil mi?

7
Görünüşe göre John Saunders, kendi sorusuna verilen yanıtla (hiçbirini ekleyebileceğim yanıt olarak kabul etmedi) yerine konmuş. Kişisel olarak sorulara geç cevaplarla ilgili bir sorunum yok ve genellikle yıllar sonra değilse de aylar sonra sorduğum bir soruya yeni bir yanıt görmekten çok memnunum. İronik olarak, bu soruya verdiğim yanıtla kendi Necromancer rozetimi kazandım. :)
devios1

3
Ben de aynı sorunu yaşadım ve kabul edilen cevap bana yardımcı olmadı, ama bu yardımcı oldu, geç cevaplar için yaşasın! Geç cevaplar olmasaydı, bunun bir kopyasını oluşturmam gerekirdi.
Didier A.

15

İşte, bu eksiksiz ve çalışma kodudur. Sana çok yardımcı olacağını düşünüyorum. Arıyordum ve hiçbir zaman tam bir kod bulamadım, bu yüzden eksiksiz ve çalışan bir kod koymaya çalıştım. İyi şanslar.

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;
    }
}

Çok güzel örnek! Manuel yapılandırmanın neredeyse her yönünü sergiliyorsunuz. Güzel yapılmış!
Kilhoffer

6
EvalServiceClient'in bu koda nasıl uyduğunu anlamıyorum. Referans verildi, ancak tanımlanmadı. Sunucu neden bir istemci yaratıyor?
BlueMonkMN


3

Tüm WCF yapılandırması programlı olarak yapılabilir. Dolayısıyla, bir yapılandırma dosyası olmadan hem sunucuları hem de istemcileri oluşturmak mümkündür.

Juval Lowy'nin birçok programlı yapılandırma örneği içeren "Programming WCF Services" kitabını öneriyorum.


2

Hem istemci hem de sunucu tarafında yapmak çok kolaydır. Juval Lowy'nin kitabında mükemmel örnekler var.

Yapılandırma dosyaları hakkındaki yorumunuza gelince, yapılandırma dosyalarının bunu kodda yapmak için ikinci sırada olduğunu söyleyebilirim. Sunucunuza bağlanacak her istemciyi kontrol ettiğinizde ve güncellendiğinden ve kullanıcıların bunları bulup hiçbir şeyi değiştiremeyeceğinden emin olduğunuzda yapılandırma dosyaları harikadır. WCF yapılandırma dosyası modelini sınırlayıcı, tasarımı biraz zor ve bakım kabusu buluyorum. Sonuç olarak, yapılandırma dosyalarını işleri yapmanın varsayılan yolu yapmak için MS tarafından çok kötü bir karar olduğunu düşünüyorum.

DÜZENLEME: Yapılandırma dosyasıyla yapamayacağınız şeylerden biri, varsayılan olmayan kurucularla hizmetler oluşturmaktır. Bu, WCF'de statik / global değişkenlere ve tekillere ve diğer anlamsız türlere yol açar.


2

Bu konuyla ilgili aşağıdaki bağlantıdaki blog gönderisini çok ilginç buldum.

Sevdiğim bir fikir, yapılandırmadan uygun WCF nesnesine yalnızca bir bağlama veya davranış veya adres XML bölümünü geçirebilmek ve özelliklerin atamasını yapmasına izin verebilmektir - şu anda bunu yapamazsınız.

Web'deki diğerleri gibi, WCF uygulamamın barındırma uygulamamdan (bir .NET 2.0 Windows hizmeti olan) farklı bir yapılandırma dosyası kullanmasına ihtiyaç duyma konusunda sorunlar yaşıyorum.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.