没有配置文件的WCF配置


90

有谁知道如何在不使用配置文件的情况下以编程方式公开WCF服务的好例子?我知道现在有了WCF,服务对象模型变得更加丰富,所以我知道这是可能的。我只是没有看到如何执行此操作的示例。相反,我想看看在没有配置文件的情况下如何进行消费。

在有人问之前,我非常需要在没有配置文件的情况下执行此操作。我通常不建议这样做,但是正如我所说,在这种情况下有非常具体的需要。


1
您为什么不推荐这样的做法(在没有配置的情况下以编程方式公开服务)?
BornToCode 2014年

Answers:


115

正如我所发现的,使用没有配置文件的Web服务非常简单。您只需要创建一个绑定对象和地址对象,并将它们传递给客户端代理的构造函数或通用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(或等效的配置文件),而无需使用内置的WCF连接中读取它的功能
诺亚

18
要使用https,请添加binding.Security.Mode = BasicHttpSecurityMode.Transport;
ciscoheat

这对我来说效果很好。对我而言,唯一的不同是,我还设置了ReaderQuotas和Security信息。我使用了ciscoheat的建议,如果使用https,则将Security.Transport.Mode设置为Transport(对我而言,在编译时不知道)。
柯克·利摩恩

2
我刚刚验证了所有设置的属性都等于WCF 4 fwiw中的默认值。(但请注意,Security.Mode默认设置为None。)
ladenedge 2011年

19

如果您有兴趣消除web.config中用于IIS托管的System.ServiceModel部分的用法,请在此处发布一个示例,以了解如何执行此操作(http://bejabbers2.blogspot.com/2010/02/wcf -zero-config-in-net-35-part-ii.html)。我将展示如何自定义ServiceHost来创建元数据和wshttpbinding端点。我以通用方式执行此操作,不需要其他编码。对于不立即升级到.NET 4.0的用户来说,这可能非常方便。


约翰,我敢肯定那是一篇很棒的博客文章,但是既然17个月前有一个公认的答案,那么答案的目的真的有吗?
约翰·桑德斯

36
由于这是我的第一个Stack Overflow答案,可能不是通常的处理方式。熟悉Lowy和Bustamante书籍,它们是很好的参考书,我认为我的回答远远超出了他们提供的样本。我在谷歌搜索时主要使用Stack Overflow,因此我经常阅读较旧的文章。从我的角度来看,拥有更多最新答案只会有所帮助。为了避免重新发明轮子,我在编写代码之前先搜索了这篇文章。
约翰·威格

48
作为经常使用SO的用户,我非常希望阅读有关旧主题的新文章。它可以帮助我更好地完成工作,从而增加了该网站的价值(因为我自己和其他人将会更多地访问它)。为什么不让人们讨论那么多的答案,而不是坚持做规则呢?这不是重点吗?

7
约翰·桑德斯(John Saunders)似乎对他自己的问题的回答被放在了他的位置(我没有补充他可能回答的问题)。我个人对问题的最新答复没有问题,通常很高兴看到几个月后(即使不是几个月)对我提出的问题有了新的答复。具有讽刺意味的是,我获得了自己的死灵法杖徽章,并且得到了我对这个问题的公认答案。:)
devios1 2012年

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

5
我不明白EvalServiceClient如何适合此代码。已引用,但未定义。服务器为什么要创建客户端?
BlueMonkMN


3

所有WCF配置都可以通过编程完成。因此,无需配置文件即可创建服务器和客户端。

我推荐Juval Lowy撰写的“ Programming WCF Services”一书,其中包含许多编程配置示例。


2

在客户端和服务器端都非常容易做到。Juval Lowy的书有很好的例子。

关于您对配置文件的评论,我想说配置文件是在代码中仅次于可怜的人。当您控制将连接到服务器的每个客户端并确保它们已更新,并且用户无法找到它们并进行任何更改时,配置文件非常有用。我发现WCF配置文件模型是受限制的,设计起来有点困难,并且是维护的噩梦。总而言之,我认为MS将配置文件设置为默认的处理方式是一个非常糟糕的决定。

编辑:您无法使用配置文件执行的操作之一是使用非默认构造函数创建服务。这会导致WCF中出现静态/全局变量和单例以及其他类型的废话。


2

我发现下面这个主题的链接上的博客文章非常有趣。

我喜欢的一个想法是,能够将绑定,行为或地址XML部分从配置传递到适当的WCF对象,并让它处理属性的分配-当前您不能执行此操作。

像网络上的其他应用程序一样,我遇到一些问题,需要WCF实现使用与托管应用程序(这是.NET 2.0 Windows服务)不同的配置文件。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.