Konfigurasi WCF tanpa file konfigurasi

90

Adakah yang tahu tentang contoh yang baik tentang bagaimana mengekspos layanan WCF secara terprogram tanpa menggunakan file konfigurasi? Saya tahu model objek layanan jauh lebih kaya sekarang dengan WCF, jadi saya tahu itu mungkin. Saya hanya belum melihat contoh bagaimana melakukannya. Sebaliknya, saya ingin melihat bagaimana proses memakan tanpa file konfigurasi dilakukan juga.

Sebelum ada yang bertanya, saya memiliki kebutuhan khusus untuk melakukan ini tanpa file konfigurasi. Saya biasanya tidak merekomendasikan praktik semacam itu, tetapi seperti yang saya katakan, ada kebutuhan yang sangat spesifik dalam kasus ini.

Kilhoffer
sumber
1
Mengapa Anda tidak merekomendasikan praktik seperti itu (mengekspos layanan secara terprogram tanpa konfigurasi)?
BornToCode

Jawaban:

115

Mengkonsumsi layanan web tanpa file konfigurasi sangat sederhana, seperti yang saya temukan. Anda hanya perlu membuat objek binding dan objek alamat dan meneruskannya ke konstruktor proxy klien atau ke instance ChannelFactory generik. Anda dapat melihat app.config default untuk melihat setelan apa yang akan digunakan, lalu membuat metode pembantu statis di suatu tempat yang membuat instance proxy Anda:

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" ) );
}
devios1
sumber
Saya pribadi menyukai pendekatan ini untuk contoh ketika Anda akan menggunakan file dalam masalah yang berbeda, misalnya, jika Anda telah mengenkripsi app.config Anda (atau file konfigurasi yang setara) dan tidak perlu menggunakan WCF bawaan kemampuan membaca dalam koneksi
Noah
18
Untuk penggunaan https, tambahkan binding.Security.Mode = BasicHttpSecurityMode.Transport;
ciscoheat
Ini bekerja cukup baik untuk saya. Satu-satunya perbedaan bagi saya adalah saya juga mengatur informasi ReaderQuotas dan Keamanan. Saya memanfaatkan saran ciscoheat dan mengatur Security.Transport.Mode ke Transport jika menggunakan https (bagi saya ini tidak diketahui pada waktu kompilasi).
Kirk Liemohn
2
Saya baru saja memverifikasi bahwa semua properti yang disetel sama dengan default di WCF 4, fwiw. (Tapi perhatikan bahwa Security.Modedefault-nya None.)
ladenedge
19

Jika Anda tertarik untuk menghilangkan penggunaan bagian System.ServiceModel di web.config untuk hosting IIS, saya telah memposting contoh cara melakukannya di sini ( http://bejabbers2.blogspot.com/2010/02/wcf -zero-config-in-net-35-bagian-ii.html ). Saya menunjukkan cara menyesuaikan ServiceHost untuk membuat metadata dan titik akhir wshttpbinding. Saya melakukannya dengan cara tujuan umum yang tidak memerlukan pengkodean tambahan. Bagi mereka yang tidak segera memutakhirkan ke .NET 4.0 ini bisa sangat nyaman.

John Wigger
sumber
John, saya yakin itu posting blog yang bagus, tetapi karena ada jawaban yang diterima dari 17 bulan yang lalu, apakah benar-benar ada tujuan dari jawaban Anda?
John Saunders
36
Karena ini adalah jawaban Stack Overflow pertama saya yang mungkin bukan cara yang biasanya dilakukan. Mengenal buku-buku Lowy dan Bustamante, yang merupakan referensi yang bagus, saya rasa jawaban saya melampaui contoh yang mereka tawarkan. Saya terutama menggunakan Stack Overflow saat googling jadi saya sering membaca posting yang lebih lama. Memiliki lebih banyak jawaban terkini hanya membantu dari sudut pandang saya. Saya mencari postingan ini di Google sebelum menulis kode saya untuk menghindari penemuan ulang roda.
John Wigger
48
Sebagai pengguna SO yang sering, saya merasa sangat ingin membaca posting baru tentang topik lama. Ini membantu saya melakukan pekerjaan saya dengan lebih baik, yang meningkatkan nilai situs ini (karena saya dan orang lain akan lebih sering mengunjunginya). Daripada menjadi kaku dengan aturan, mengapa tidak membiarkan orang berdiskusi sehingga jawaban yang lebih baik dapat ditemukan? Bukankah itu intinya?
7
Tampaknya John Saunders menggantikannya dengan jawaban atas pertanyaannya sendiri (tidak ada yang dia terima sebagai jawaban yang dapat saya tambahkan). Saya pribadi tidak memiliki masalah dengan jawaban terlambat untuk pertanyaan, dan biasanya senang melihat jawaban baru untuk pertanyaan yang saya ajukan, berbulan-bulan jika tidak bertahun-tahun kemudian. Ironisnya, saya mendapatkan lencana Necromancer saya sendiri dengan jawaban yang saya terima untuk pertanyaan ini. :)
devios1
3
Saya memiliki masalah yang sama, dan jawaban yang diterima tidak membantu saya, tetapi ini berhasil, hore untuk jawaban yang terlambat! Seandainya bukan karena jawaban yang terlambat, saya harus membuat pertanyaan duplikat tentang ini.
Didier A.
15

Di sini, ini adalah kode lengkap dan berfungsi. Saya pikir itu akan banyak membantu Anda. Saya mencari dan tidak pernah menemukan kode lengkap itu sebabnya saya mencoba memasukkan kode lengkap dan berfungsi. Semoga berhasil.

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;
    }
}
SM Khaled Reza
sumber
Contoh yang sangat bagus! Anda mendemonstrasikan hampir setiap aspek konfigurasi manual. Selamat!
Kilhoffer
5
Saya tidak mengerti bagaimana EvalServiceClient cocok dengan kode ini. Ini direferensikan, tetapi tidak ditentukan. Mengapa server membuat klien?
BlueMonkMN
5

Tidak mudah di sisi server ..

Untuk sisi klien, Anda dapat menggunakan ChannelFactory

Gulzar Nazim
sumber
3

Semua konfigurasi WCF dapat dilakukan secara programatik. Jadi dimungkinkan untuk membuat server dan klien tanpa file konfigurasi.

Saya merekomendasikan buku "Programming WCF Services" oleh Juval Lowy, yang berisi banyak contoh konfigurasi programatik.

Paul Lalonde
sumber
2

Ini sangat mudah dilakukan di sisi klien dan server. Buku Juval Lowy memiliki contoh yang sangat bagus.

Mengenai komentar Anda tentang file konfigurasi, saya akan mengatakan bahwa file konfigurasi adalah orang miskin kedua yang melakukannya dalam kode. File konfigurasi sangat bagus ketika Anda mengontrol setiap klien yang akan terhubung ke server Anda dan memastikannya diperbarui, dan pengguna tidak dapat menemukannya dan mengubah apa pun. Saya menemukan model file konfigurasi WCF menjadi membatasi, agak sulit untuk dirancang, dan mimpi buruk pemeliharaan. Secara keseluruhan, saya pikir itu adalah keputusan yang sangat buruk oleh MS untuk menjadikan file konfigurasi sebagai cara default dalam melakukan sesuatu.

EDIT: Salah satu hal yang tidak dapat Anda lakukan dengan file konfigurasi adalah membuat layanan dengan konstruktor non-default. Hal ini menyebabkan variabel statis / global dan singletons serta jenis non-sense lainnya di WCF.

Steve
sumber
2

Saya menemukan posting blog pada tautan di bawah tentang topik ini sangat menarik.

Satu ide yang saya suka adalah bahwa dapat meneruskan bagian XML pengikatan atau perilaku atau alamat dari konfigurasi ke objek WCF yang sesuai dan membiarkannya menangani penugasan properti - saat ini Anda tidak dapat melakukan ini.

Seperti orang lain di web, saya mengalami masalah seputar perlunya implementasi WCF saya untuk menggunakan file konfigurasi yang berbeda dari yang ada di aplikasi hosting saya (yang merupakan layanan Windows .NET 2.0).

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

Nada
sumber