有谁知道如何在不使用配置文件的情况下以编程方式公开 WCF 服务的一个很好的例子?我知道现在使用 WCF 服务对象模型更加丰富,所以我知道这是可能的。我只是没有看到如何做到这一点的例子。相反,我想看看没有配置文件的消耗是如何完成的。
在任何人问之前,我有一个非常具体的需要在没有配置文件的情况下执行此操作。我通常不会推荐这种做法,但正如我所说,在这种情况下有一个非常具体的需求。
有谁知道如何在不使用配置文件的情况下以编程方式公开 WCF 服务的一个很好的例子?我知道现在使用 WCF 服务对象模型更加丰富,所以我知道这是可能的。我只是没有看到如何做到这一点的例子。相反,我想看看没有配置文件的消耗是如何完成的。
在任何人问之前,我有一个非常具体的需要在没有配置文件的情况下执行此操作。我通常不会推荐这种做法,但正如我所说,在这种情况下有一个非常具体的需求。
正如我所发现的,使用没有配置文件的 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" ) );
}
如果您有兴趣消除 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 的人来说,这可能非常方便。
在这里,这是完整且有效的代码。我想这会对你有很大帮助。我一直在搜索,但从未找到完整的代码,这就是我试图放置完整且有效的代码的原因。祝你好运。
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;
}
}
服务器端不容易..
对于客户端,您可以使用ChannelFactory
所有 WCF 配置都可以通过编程方式完成。所以可以在没有配置文件的情况下创建服务器和客户端。
我推荐 Juval Lowy 的《Programming WCF Services》一书,其中包含许多编程配置的示例。
我发现以下链接中围绕该主题的博客文章非常有趣。
我喜欢的一个想法是,能够将配置中的绑定或行为或地址 XML 部分传递给适当的 WCF 对象,并让它处理属性的分配——目前你不能这样做。
像网络上的其他人一样,我遇到了需要我的 WCF 实现使用与我的托管应用程序(这是一个 .NET 2.0 Windows 服务)不同的配置文件的问题。
http://salvoz.com/blog/2007/12/09/programmatically-setting-wcf-configuration/
在客户端和服务器端都非常容易做到。Juval Lowy 的书中有很好的例子。
至于您对配置文件的评论,我想说配置文件是穷人在代码中做的第二个。当您控制将连接到您的服务器的每个客户端并确保它们已更新并且用户无法找到它们并进行任何更改时,配置文件非常棒。我发现 WCF 配置文件模型受到限制,设计起来有点困难,而且是维护的噩梦。总而言之,我认为 MS 将配置文件作为默认的处理方式是一个非常糟糕的决定。
编辑:您不能使用配置文件做的一件事是使用非默认构造函数创建服务。这会导致 WCF 中出现静态/全局变量和单例以及其他类型的无意义。