我在控制台应用程序中有一个SOAP服务客户端,我需要将服务客户端移动到sharepoint 2010.我不想做配置文件部署和其他与sharepoint相关的东西,所以我决定硬编码绑定信息,唯一可配置的选项是URL.但是我在这方面遇到了一些麻烦.我有一个配置:
另外,我有一个代码:
var service = new ServiceClient(); service.ClientCredentials.Windows.ClientCredential = new NetworkCredential("user", "password"); service.ClientCredentials.UserName.UserName = "user"; service.ClientCredentials.UserName.Password = "password"; var resp = service.Operation(); Console.WriteLine(resp.Response);
它按预期工作.现在我想摆脱xml配置并完全将其移动到代码:
public class CustomHttpTransportBinding : CustomBinding { public CustomHttpTransportBinding() { } public override BindingElementCollection CreateBindingElements() { var result = new BindingElementCollection(); result.Add(new TextMessageEncodingBindingElement { MaxReadPoolSize = 64, MaxWritePoolSize = 16, MessageVersion = MessageVersion.Soap11, WriteEncoding = Encoding.UTF8, //ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas //{ // MaxDepth = 10000000, // MaxStringContentLength = 10000000, // MaxArrayLength = 67108864, // MaxBytesPerRead = 65536, // MaxNameTableCharCount = 100000 //} }); result.Add(new HttpTransportBindingElement { AuthenticationScheme = AuthenticationSchemes.Basic, BypassProxyOnLocal = false, HostNameComparisonMode = System.ServiceModel.HostNameComparisonMode.StrongWildcard, KeepAliveEnabled = false, ProxyAuthenticationScheme = AuthenticationSchemes.Basic, Realm = "XISOAPApps", UseDefaultWebProxy = true }); return result; } }
我这样使用它:
var service = new ServiceClient(new CustomHttpTransportBinding(), new EndpointAddress(url)); service.ClientCredentials.Windows.ClientCredential = new NetworkCredential("user", "password"); service.ClientCredentials.UserName.UserName = "user"; service.ClientCredentials.UserName.Password = "password"; var resp = service.Operation(); Console.WriteLine(resp.Response);
它到达服务器,但抛出异常("服务器错误"),所以我认为我的配置有问题.我也无法指定读者配额.我已经尝试从字符串加载配置,但它不适合我,同样的错误.Confi似乎我无法将自定义绑定从XML转换为.net 3.5中的代码.有人可以查看我的代码并确认吗?是否有其他方法可以在代码中使用自定义绑定的服务客户端?
我还没有找到一种方法将配置从app.config移动到自定义绑定的代码,它对basicHttpBinding有效,但不适用于customBinding.
我最终使用自定义chanell工厂从文件加载动态配置.
public class CustomChannelFactory<T> : ChannelFactory<T> { private readonly string _configurationPath; public CustomChannelFactory(string configurationPath) : base(typeof(T)) { _configurationPath = configurationPath; base.InitializeEndpoint((string)null, null); } protected override ServiceEndpoint CreateDescription() { ServiceEndpoint serviceEndpoint = base.CreateDescription(); ExeConfigurationFileMap executionFileMap = new ExeConfigurationFileMap(); executionFileMap.ExeConfigFilename = _configurationPath; System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(executionFileMap, ConfigurationUserLevel.None); ServiceModelSectionGroup serviceModeGroup = ServiceModelSectionGroup.GetSectionGroup(config); ChannelEndpointElement selectedEndpoint = null; foreach (ChannelEndpointElement endpoint in serviceModeGroup.Client.Endpoints) { if (endpoint.Contract == serviceEndpoint.Contract.ConfigurationName) { selectedEndpoint = endpoint; break; } } if (selectedEndpoint != null) { if (serviceEndpoint.Binding == null) { serviceEndpoint.Binding = CreateBinding(selectedEndpoint.Binding, serviceModeGroup); } if (serviceEndpoint.Address == null) { serviceEndpoint.Address = new EndpointAddress(selectedEndpoint.Address, GetIdentity(selectedEndpoint.Identity), selectedEndpoint.Headers.Headers); } if (serviceEndpoint.Behaviors.Count == 0 && !String.IsNullOrEmpty(selectedEndpoint.BehaviorConfiguration)) { AddBehaviors(selectedEndpoint.BehaviorConfiguration, serviceEndpoint, serviceModeGroup); } serviceEndpoint.Name = selectedEndpoint.Contract; } return serviceEndpoint; } private Binding CreateBinding(string bindingName, ServiceModelSectionGroup group) { BindingCollectionElement bindingElementCollection = group.Bindings[bindingName]; if (bindingElementCollection.ConfiguredBindings.Count > 0) { IBindingConfigurationElement be = bindingElementCollection.ConfiguredBindings[0]; Binding binding = GetBinding(be); if (be != null) { be.ApplyConfiguration(binding); } return binding; } return null; } private void AddBehaviors(string behaviorConfiguration, ServiceEndpoint serviceEndpoint, ServiceModelSectionGroup group) { EndpointBehaviorElement behaviorElement = group.Behaviors.EndpointBehaviors[behaviorConfiguration]; for (int i = 0; i < behaviorElement.Count; i++) { BehaviorExtensionElement behaviorExtension = behaviorElement[i]; object extension = behaviorExtension.GetType().InvokeMember("CreateBehavior", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, behaviorExtension, null); if (extension != null) { serviceEndpoint.Behaviors.Add((IEndpointBehavior)extension); } } } private EndpointIdentity GetIdentity(IdentityElement element) { EndpointIdentity identity = null; PropertyInformationCollection properties = element.ElementInformation.Properties; if (properties["userPrincipalName"].ValueOrigin != PropertyValueOrigin.Default) { return EndpointIdentity.CreateUpnIdentity(element.UserPrincipalName.Value); } if (properties["servicePrincipalName"].ValueOrigin != PropertyValueOrigin.Default) { return EndpointIdentity.CreateSpnIdentity(element.ServicePrincipalName.Value); } if (properties["dns"].ValueOrigin != PropertyValueOrigin.Default) { return EndpointIdentity.CreateDnsIdentity(element.Dns.Value); } if (properties["rsa"].ValueOrigin != PropertyValueOrigin.Default) { return EndpointIdentity.CreateRsaIdentity(element.Rsa.Value); } if (properties["certificate"].ValueOrigin != PropertyValueOrigin.Default) { X509Certificate2Collection supportingCertificates = new X509Certificate2Collection(); supportingCertificates.Import(Convert.FromBase64String(element.Certificate.EncodedValue)); if (supportingCertificates.Count == 0) { throw new InvalidOperationException("UnableToLoadCertificateIdentity"); } X509Certificate2 primaryCertificate = supportingCertificates[0]; supportingCertificates.RemoveAt(0); return EndpointIdentity.CreateX509CertificateIdentity(primaryCertificate, supportingCertificates); } return identity; } private Binding GetBinding(IBindingConfigurationElement configurationElement) { if (configurationElement is CustomBindingElement) return new CustomBinding(); else if (configurationElement is BasicHttpBindingElement) return new BasicHttpBinding(); else if (configurationElement is NetMsmqBindingElement) return new NetMsmqBinding(); else if (configurationElement is NetNamedPipeBindingElement) return new NetNamedPipeBinding(); else if (configurationElement is NetPeerTcpBindingElement) return new NetPeerTcpBinding(); else if (configurationElement is NetTcpBindingElement) return new NetTcpBinding(); else if (configurationElement is WSDualHttpBindingElement) return new WSDualHttpBinding(); else if (configurationElement is WSHttpBindingElement) return new WSHttpBinding(); else if (configurationElement is WSFederationHttpBindingElement) return new WSFederationHttpBinding(); return null; } }
有用的链接:
从不同文件加载WCF配置(源代码不可用)
具有CustomChannelFactory源代码的线程
.NET 4.0 ChanellFactory(希望它在.net 3.5中)