2014-09-29 81 views
3

我对SOAP服务的客户端在一个控制台应用程序,我需要移动服务客户端到SharePoint 2010,我不想做配置文件的部署和其他SharePoint相关的东西,所以我决定硬编码绑定信息,唯一可配置的选项是URL。但我遇到了一些麻烦。我有一个配置:转换Web服务配置代码

<system.serviceModel> 
<bindings> 
    <customBinding> 
    <binding name="SI_PMProjectMaintain_SOUTBinding"> 
     <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" 
     messageVersion="Soap11" writeEncoding="utf-8"> 
     <readerQuotas maxDepth="10000000" maxStringContentLength="10000000" 
      maxArrayLength="67108864" maxBytesPerRead="65536" maxNameTableCharCount="100000" /> 
     </textMessageEncoding> 
     <httpTransport authenticationScheme="Basic" bypassProxyOnLocal="false" 
     hostNameComparisonMode="StrongWildcard" keepAliveEnabled="false" 
     proxyAuthenticationScheme="Basic" realm="XISOAPApps" useDefaultWebProxy="true" /> 
    </binding> 
    </customBinding> 
</bindings> 
<client> 
    <endpoint address="http://url/XISOAPAdapter/MessageServlet?senderParty=&amp;senderService=Param1&amp;receiverParty=&amp;receiverService=&amp;interface=interface&amp;interfaceNamespace=url" 
    binding="customBinding" bindingConfiguration="SI_PMProjectMaintain_SOUTBinding" 
    contract="PmProjectMaintain.SI_PMProjectMaintain_SOUT" name="HTTP_Port" /> 
</client> 

另外,我有一个代码:

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

它到达服务器,但会抛出异常(“服务器错误” ),所以我相信我的配置有问题。我也无法指定读者配额。我试过加载configuration from string,但它不适用于我,同样的错误。 Confi 看来我无法将自定义绑定从XML转换为.net 3.5中的代码。有人可以看看我的代码并确认吗?有没有其他方法可以让代码中的自定义绑定服务客户端?

+0

当您尝试指定读者配额会发生什么?另外,您是否检查过事件查看器以查看是否有关于该错误的任何信息? – Tim 2014-09-29 18:02:48

+0

我试图在.net 4.5中指定阅读器配额,同样的错误。你的意思是服务器上的事件查看器?不幸的是,它是SAP服务,我无法访问该环境。 – boades 2014-09-29 18:39:34

回答

5

我还没有找到一种方法来从App.config复制到代码自定义绑定移动的配置,它的工作原理为马丽娟basicHttpBinding的,但对于customBinding不起作用。

我已经结束了使用自定义chanell工厂从文件加载配置dynamicaly。

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

有用的链接:

1

发现代码中boades引用的问题回答,因为如果你有混合传输绑定(https/http)在basicHttpbinding下,您很可能会得到与此类似的异常:

提供的URI方案'https'无效;预计'http'。参数名:通过

我还指望你也会有意想不到的授权发生,又因为代码将使用在web.config而不是按名称列出的第一个bindingConfiguration

出错的行不采取名字的结合,而是只需要一日一(!)

IBindingConfigurationElement是= bindingElementCollection。ConfiguredBindings [0];

这可以通过更新CreateBinding方法和像这样在CreateDescription通话进行修正:

protected override ServiceEndpoint CreateDescription() 
{ 
    ServiceEndpoint description = base.CreateDescription(); 
    if (CustomisedChannelFactory<TChannel>.ConfigurationPath == null || !System.IO.File.Exists(CustomisedChannelFactory<TChannel>.ConfigurationPath)) 
     return base.CreateDescription(); 
    ServiceModelSectionGroup sectionGroup = ServiceModelSectionGroup.GetSectionGroup(ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap() 
    { 
     ExeConfigFilename = CustomisedChannelFactory<TChannel>.ConfigurationPath 
    }, ConfigurationUserLevel.None)); 
    ChannelEndpointElement channelEndpointElement1 = (ChannelEndpointElement)null; 
    foreach (ChannelEndpointElement channelEndpointElement2 in (ConfigurationElementCollection)sectionGroup.Client.Endpoints) 
    { 
     if (channelEndpointElement2.Contract == description.Contract.ConfigurationName) 
     { 
      channelEndpointElement1 = channelEndpointElement2; 
      break; 
     } 
    } 
    if (channelEndpointElement1 != null) 
    { 
     if (description.Binding == null) 
      description.Binding = this.CreateBinding(channelEndpointElement1.Binding, channelEndpointElement1.BindingConfiguration, sectionGroup); 
     if (description.Address == (EndpointAddress)null) 
      description.Address = new EndpointAddress(channelEndpointElement1.Address, this.GetIdentity(channelEndpointElement1.Identity), channelEndpointElement1.Headers.Headers); 
     if (description.Behaviors.Count == 0 && !string.IsNullOrEmpty(channelEndpointElement1.BehaviorConfiguration)) 
      this.AddBehaviors(channelEndpointElement1.BehaviorConfiguration, description, sectionGroup); 
     description.Name = channelEndpointElement1.Contract; 
    } 
    return description; 
} 

private Binding CreateBinding(string bindingName, string bindingConfigurationName, ServiceModelSectionGroup group) 
{ 
    BindingCollectionElement collectionElement = group.Bindings[bindingName]; 
    if (collectionElement.ConfiguredBindings.Count <= 0) 
     return (Binding)null; 

    IBindingConfigurationElement configurationElement = null; 
    foreach (IBindingConfigurationElement bce in collectionElement.ConfiguredBindings) 
    { 
     if (bce.Name.Equals(bindingConfigurationName)) 
     { 
      configurationElement = bce; 
      break; 
     } 
    } 
    if (configurationElement == null) throw new Exception("BindingConfiguration " + bindingConfigurationName + " not found under binding " + bindingName); 

    Binding binding = this.GetBinding(configurationElement); 
    if (configurationElement != null) 
     configurationElement.ApplyConfiguration(binding); 
    return binding; 
}