没有配置文件的 WCF 配置

Posted

技术标签:

【中文标题】没有配置文件的 WCF 配置【英文标题】:WCF Configuration without a config file 【发布时间】:2010-09-08 10:46:01 【问题描述】:

有谁知道如何在不使用配置文件的情况下以编程方式公开 WCF 服务的一个很好的例子?我知道现在使用 WCF 服务对象模型更加丰富,所以我知道这是可能的。我只是没有看到如何做到这一点的例子。相反,我想看看没有配置文件的消费是如何完成的。

在任何人问之前,我有一个非常具体的需要,不需要配置文件。我通常不会推荐这种做法,但正如我所说,在这种情况下有一个非常具体的需求。

【问题讨论】:

为什么不推荐这样的做法(以编程方式公开服务而无需配置)? 【参考方案1】:

在这里,这是完整且有效的代码。我想这会对你有很大帮助。我一直在搜索,但从未找到完整的代码,这就是我试图放置完整且有效的代码的原因。祝你好运。

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;
    

【讨论】:

非常好的例子!您演示了手动配置的几乎所有方面。做得很好! 我不明白 EvalServiceClient 如何适合此代码。它被引用,但未定义。服务器为什么要创建客户端?【参考方案2】:

我发现以下链接中围绕该主题的博客文章非常有趣。

我喜欢的一个想法是能够将配置中的绑定或行为或地址 XML 部分传递给适当的 WCF 对象,并让它处理属性的分配——目前你不能这样做。

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

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

【讨论】:

【参考方案3】:

如果您有兴趣消除 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 个月前的答案已经被接受,那么你的答案真的有任何意义吗? 因为这是我的第一个 Stack Overflow 答案,这可能不是通常的做法。熟悉 Lowy 和 Bustamante 的书籍,它们是很好的参考,我认为我的回答远远超出了他们提供的示例。我主要在谷歌搜索时使用 Stack Overflow,所以我经常阅读较旧的帖子。从我的角度来看,拥有更多最新的答案只会有所帮助。我在编写代码之前搜索了这篇文章以避免重新发明***。 作为一个经常使用 SO 的用户,我发现阅读关于旧主题的新帖子非常可取。它帮助我更好地完成我的工作,从而增加了这个网站的价值(因为我和其他人会更多地访问它)。与其坚持规则,为什么不让人们讨论这样可能会发现更好的答案呢?这不是重点吗? 似乎约翰·桑德斯(John Saunders)在回答他自己的问题时被放在了他的位置上(他没有接受我可能添加的答案)。我个人对迟到的问题回复没有任何问题,并且通常很高兴看到对我提出的问题的新回复,即使不是数年也数月。具有讽刺意味的是,我通过对这个问题的接受回答获得了自己的死灵法师徽章。 :) 我遇到了同样的问题,接受的答案对我没有帮助,但确实如此,为迟到的答案万岁!如果不是因为迟到的答案,我将不得不为此创建一个重复的问题。【参考方案4】:

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

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

编辑:使用配置文件不能做的一件事是使用非默认构造函数创建服务。这会导致 WCF 中出现静态/全局变量和单例以及其他类型的无意义。

【讨论】:

【参考方案5】:

正如我所发现的,使用没有配置文件的 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 功能 对于https使用,添加binding.Security.Mode = BasicHttpSecurityMode.Transport; 这对我来说效果很好。对我来说唯一的不同是我还设置了 ReaderQuotas 和安全信息。如果使用 https,我使用了 ciscoheat 的建议并将 Security.Transport.Mode 设置为 Transport(对我而言,这在编译时是未知的)。 我刚刚验证了所有设置的属性都等于 WCF 4 中的默认值,fwiw。 (但请注意,Security.Mode 默认为 None。)【参考方案6】:

所有 WCF 配置都可以通过编程方式完成。所以可以在没有配置文件的情况下创建服务器和客户端。

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

【讨论】:

【参考方案7】:

服务器上不容易side..

对于客户端,您可以使用ChannelFactory

【讨论】:

以上是关于没有配置文件的 WCF 配置的主要内容,如果未能解决你的问题,请参考以下文章

WCF入门二[WCF的配置文件]

WCF入门教程四[WCF的配置文件]

使用 ACL 保护 WCF 配置文件

无法使用基本领域配置凭据 WCF?

wcf 配置文件与代码配置的优缺点

WCF中配置文件解析