การกำหนดค่า WCF โดยไม่มีไฟล์กำหนดค่า


90

มีใครทราบตัวอย่างที่ดีเกี่ยวกับวิธีการแสดงบริการ WCF โดยทางโปรแกรมโดยไม่ต้องใช้ไฟล์กำหนดค่าหรือไม่? ฉันรู้ว่าโมเดลอ็อบเจ็กต์บริการนั้นสมบูรณ์ยิ่งขึ้นในขณะนี้ด้วย WCF ดังนั้นฉันจึงรู้ว่าเป็นไปได้ ฉันยังไม่เห็นตัวอย่างวิธีการทำ ในทางกลับกันฉันต้องการดูว่าการบริโภคโดยไม่มีไฟล์กำหนดค่านั้นทำได้ดีเพียงใด

ก่อนที่ใครจะถามฉันมีความต้องการที่เฉพาะเจาะจงมากที่จะต้องทำสิ่งนี้โดยไม่มีไฟล์กำหนดค่า โดยปกติฉันจะไม่แนะนำวิธีปฏิบัติเช่นนี้ แต่อย่างที่บอกว่ามีความจำเป็นที่เฉพาะเจาะจงมากในกรณีนี้


1
ทำไมคุณไม่แนะนำวิธีปฏิบัติดังกล่าว (การเปิดเผยบริการโดยทางโปรแกรมโดยไม่มีการกำหนดค่า)
BornToCode

คำตอบ:


115

การใช้บริการเว็บโดยไม่มีไฟล์กำหนดค่านั้นง่ายมากอย่างที่ฉันค้นพบ คุณเพียงแค่ต้องสร้างวัตถุที่มีผลผูกพันและออบเจ็กต์ที่อยู่และส่งต่อไปยังตัวสร้างของพร็อกซีไคลเอนต์หรือไปยังอินสแตนซ์ ChannelFactory ทั่วไป คุณสามารถดูที่ app.config เริ่มต้นเพื่อดูว่าจะใช้การตั้งค่าใดจากนั้นสร้างวิธีการช่วยเหลือแบบคงที่ที่ใดที่หนึ่งที่สร้างอินสแตนซ์พร็อกซีของคุณ:

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

โดยส่วนตัวแล้วฉันชอบแนวทางนี้เป็นตัวอย่างเมื่อคุณกำลังจะใช้ไฟล์ในเรื่องอื่นเช่นหากคุณเข้ารหัส app.config (หรือไฟล์ config ที่เทียบเท่า) และไม่จำเป็นต้องใช้ WCF ในตัว ความสามารถของการอ่านในการเชื่อมต่อ
โนอาห์

18
สำหรับการใช้งาน https ให้เพิ่ม binding.Security.Mode = BasicHttpSecurityMode.Transport;
ciscoheat

สิ่งนี้ได้ผลดีสำหรับฉัน ความแตกต่างเพียงอย่างเดียวสำหรับฉันคือฉันยังตั้งค่า ReaderQuotas และข้อมูลความปลอดภัย ฉันใช้คำแนะนำของ ciscoheat และตั้งค่า Security.Transport.Mode to Transport หากใช้ https (สำหรับฉันไม่ทราบเวลาคอมไพล์)
Kirk Liemohn

2
ฉันเพิ่งตรวจสอบว่าคุณสมบัติทั้งหมดที่ตั้งค่านั้นเท่ากับค่าเริ่มต้นใน WCF 4, fwiw (แต่โปรดทราบว่าSecurity.Modeค่าเริ่มต้นเป็นNone)
ภาระใน

19

หากคุณสนใจที่จะกำจัดการใช้งานส่วน System.ServiceModel ใน web.config สำหรับโฮสติ้ง IIS ฉันได้โพสต์ตัวอย่างวิธีการดำเนินการที่นี่ ( http://bejabbers2.blogspot.com/2010/02/wcf -zero-config-in-net-35-part-ii.html ) ฉันแสดงวิธีปรับแต่ง ServiceHost เพื่อสร้างทั้งข้อมูลเมตาและปลายทาง wshttpbinding ฉันทำโดยวัตถุประสงค์ทั่วไปที่ไม่ต้องการการเข้ารหัสเพิ่มเติม สำหรับผู้ที่ไม่ได้อัปเกรดเป็น. NET 4.0 ในทันทีสิ่งนี้สามารถทำได้ค่อนข้างสะดวก


จอห์นฉันแน่ใจว่าเป็นบล็อกโพสต์ที่ยอดเยี่ยม แต่เนื่องจากมีคำตอบที่เป็นที่ยอมรับเมื่อ 17 เดือนที่แล้วคำตอบของคุณมีจุดประสงค์จริงหรือ
John Saunders

36
เนื่องจากนี่เป็นคำตอบ Stack Overflow แรกของฉันซึ่งอาจไม่ใช่วิธีที่มักจะทำ ด้วยความคุ้นเคยกับหนังสือ Lowy และ Bustamante ซึ่งเป็นข้อมูลอ้างอิงที่ดีฉันคิดว่าคำตอบของฉันดีกว่าตัวอย่างที่เสนอ ฉันใช้ Stack Overflow เป็นหลักในการ googling ดังนั้นฉันจึงอ่านโพสต์ที่เก่ากว่าบ่อยๆ การมีคำตอบที่ทันสมัยมากขึ้นช่วยได้จากมุมมองของฉันเท่านั้น ฉัน googled โพสต์นี้ก่อนที่จะเขียนโค้ดเพื่อหลีกเลี่ยงการประดิษฐ์วงล้อขึ้นมาใหม่
John Wigger

48
ในฐานะที่เป็นผู้ใช้ SO บ่อยฉันพบว่าการอ่านโพสต์ใหม่ในหัวข้อเก่า ๆ เป็นเรื่องที่พึงปรารถนา มันช่วยให้ฉันทำงานได้ดีขึ้นซึ่งจะเพิ่มมูลค่าของไซต์นี้ (เนื่องจากตัวฉันเองและคนอื่น ๆ จะเข้าชมเว็บไซต์มากขึ้น) แทนที่จะเป็นคนยึดติดกับกฎเกณฑ์ทำไมไม่เปิดโอกาสให้ผู้คนพูดคุยกันเพื่อจะได้ค้นพบคำตอบที่ดีกว่านี้ นั่นไม่ใช่ประเด็นเหรอ?

7
ดูเหมือนว่าจอห์นแซนเดอร์สถูกแทนที่ด้วยการตอบคำถามของเขาเอง (ไม่มีข้อใดที่เขายอมรับว่าเป็นคำตอบที่ฉันอาจเพิ่ม) โดยส่วนตัวแล้วฉันไม่มีปัญหากับการตอบคำถามล่าช้าและโดยปกติแล้วฉันรู้สึกยินดีเป็นอย่างยิ่งที่ได้เห็นการตอบกลับใหม่สำหรับคำถามที่ฉันถามเป็นเวลาหลายเดือนหากไม่ใช่ปีต่อมา แดกดันฉันได้รับตราเนโครแมนเซอร์ของตัวเองพร้อมกับคำตอบที่ฉันยอมรับสำหรับคำถามนี้ :)
devios1

3
ฉันมีปัญหาเดียวกันและคำตอบที่ได้รับการยอมรับไม่ได้ช่วยฉัน แต่สิ่งนี้ได้รับคำตอบที่ล่าช้า! หากไม่ได้รับคำตอบที่ล่าช้าฉันจะต้องสร้างคำถามที่ซ้ำกันในเรื่องนี้
Didier A.

15

นี่คือรหัสที่สมบูรณ์และใช้งานได้ ผมคิดว่ามันจะช่วยคุณได้มาก ฉันกำลังค้นหาและไม่พบรหัสที่สมบูรณ์นั่นคือเหตุผลที่ฉันพยายามใส่รหัสที่สมบูรณ์และใช้งานได้ โชคดี.

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

เป็นตัวอย่างที่ดีมาก! คุณแสดงให้เห็นเกือบทุกแง่มุมของการกำหนดค่าด้วยตนเอง ทำได้ดีมาก!
Kilhoffer

6
ฉันไม่เข้าใจว่า EvalServiceClient เข้ากับรหัสนี้อย่างไร มีการอ้างอิง แต่ไม่ได้กำหนดไว้ เหตุใดเซิร์ฟเวอร์จึงสร้างไคลเอนต์
BlueMonkMN


3

การกำหนดค่า WCF ทั้งหมดสามารถทำได้โดยใช้โปรแกรม ดังนั้นจึงเป็นไปได้ที่จะสร้างทั้งเซิร์ฟเวอร์และไคลเอนต์โดยไม่มีไฟล์กำหนดค่า

ขอแนะนำหนังสือ "Programming WCF Services" โดย Juval Lowy ซึ่งมีตัวอย่างการกำหนดค่าแบบเป็นโปรแกรมมากมาย


2

ทำได้ง่ายมากทั้งในฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์ หนังสือของ Juval Lowy มีตัวอย่างที่ยอดเยี่ยม

สำหรับความคิดเห็นของคุณเกี่ยวกับไฟล์คอนฟิกูเรชันฉันจะบอกว่าไฟล์คอนฟิกูเรชันเป็นสิ่งที่น่าสงสารคนที่สองในการทำโค้ด ไฟล์การกำหนดค่านั้นยอดเยี่ยมเมื่อคุณควบคุมไคลเอนต์ทุกตัวที่จะเชื่อมต่อกับเซิร์ฟเวอร์ของคุณและตรวจสอบให้แน่ใจว่าได้รับการอัปเดตแล้วผู้ใช้ไม่พบและเปลี่ยนแปลงอะไร ฉันพบว่าโมเดลไฟล์คอนฟิกูเรชัน WCF มีข้อ จำกัด ออกแบบยากเล็กน้อยและเป็นฝันร้ายในการบำรุงรักษา สรุปแล้วฉันคิดว่ามันเป็นการตัดสินใจที่แย่มากโดย MS ที่ทำให้ไฟล์คอนฟิกูเรชันเป็นวิธีเริ่มต้นในการทำสิ่งต่างๆ

แก้ไข: สิ่งหนึ่งที่คุณไม่สามารถทำได้กับไฟล์การกำหนดค่าคือการสร้างบริการด้วยตัวสร้างที่ไม่ใช่ค่าเริ่มต้น สิ่งนี้นำไปสู่ตัวแปรคงที่ / ทั่วโลกและ singletons และประเภทอื่น ๆ ของความไม่รู้สึกใน WCF


2

ฉันพบว่าบล็อกโพสต์ที่ลิงค์ด้านล่างเกี่ยวกับหัวข้อนี้น่าสนใจมาก

ความคิดหนึ่งที่ฉันชอบคือความสามารถในการส่งผ่านในส่วนการเชื่อมโยงหรือพฤติกรรมหรือที่อยู่ XML จากการกำหนดค่าไปยังวัตถุ WCF ที่เหมาะสมและปล่อยให้มันจัดการกับการกำหนดคุณสมบัติ - ขณะนี้คุณไม่สามารถทำได้

เช่นเดียวกับคนอื่น ๆ บนเว็บฉันกำลังมีปัญหาเกี่ยวกับการต้องติดตั้ง WCF เพื่อใช้ไฟล์การกำหนดค่าที่แตกต่างจากแอปพลิเคชันโฮสติ้งของฉัน (ซึ่งเป็นบริการ. NET 2.0 Windows)

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.