将服务配置从配置移动到代码

时间:2019-01-10 13:34:53

标签: c# wcf

我的app.config中具有以下配置:

<bindings>
  <customBinding>
    <binding name="myBinding">
      <textMessageEncoding messageVersion="Soap12"/>
      <httpTransport/>
    </binding>
  </customBinding>
  <wsHttpBinding>
    <binding name="myBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8">
      <security mode="Transport">
        <transport clientCredentialType="Windows"/>
      </security>
    </binding>
  </wsHttpBinding>
</bindings>
<client>
  <endpoint address="/../" binding="wsHttpBinding" bindingConfiguration="myBinding" contract="myContract" name="myName"/>
</client>

使用此配置,服务将按预期工作。

由于多种原因,我无法在生产环境中使用app.config文件,因此我想改用c#定义绑定。我做了以下事情:

        var binding = new BasicHttpBinding();
        var address = new EndpointAddress(url);

        binding.Security = new BasicHttpSecurity() { Mode = BasicHttpSecurityMode.Transport };
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

        var client = new MyClient(binding, address);

这适用于第一部分,但随后使用错误的消息版本失败。我可以看到这是在custombinding中定义的,但是我不确定如何将该绑定转换为我的代码。我确实做了很多尝试,但到目前为止都没有结果。

有人知道该怎么做吗?

4 个答案:

答案 0 :(得分:1)

我建议您利用ConfigurationChannelFactory<TChannel>类来利用来自app.config文件以外的源(例如,从数据库,可执行文件中的资源中读取的XML字符串,或其他自定义来源)。

与使用代码构建的配置相比,XML格式更易于阅读和维护。

为此,步骤如下:

  • 获取包含您的XML配置数据的字符串,例如:

    string configurationData = @"<configuration>
        <system.serviceModel>
        ...
        ";
    
  • 将其保存到临时文件中

    var tempFileName = Path.GetTempFileName();
    File.WriteAllText(tempFileName, configurationData);
    
  • 从临时文件生成System.Configuration.Configuration对象:

    var filemap = new ExeConfigurationFileMap
    {
        ExeConfigFilename = tempFileName
    };
    var config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
    
  • 从配置中创建ChannelFactory<TChannel>

    var channelFactory = new ConfigurationChannelFactory<TChannel>(endpointConfigurationName, config, remoteAddress);
    
  • 创建ChannelFactory<TChannel>后,您可以删除临时文件。

答案 1 :(得分:0)

您使用的是BasicHttpBinding而不是CustomBinding

您应该执行以下操作:

var binding = new CustomBinding();
TextMessageEncodingBindingElement textBindingElement = new TextMessageEncodingBindingElement
{
    MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None),
    WriteEncoding = System.Text.Encoding.UTF8,
    ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max
};
binding.Elements.Add(textBindingElement);

但是,如果您使用的是.net core,则可能会有问题,因为在GitHub上有一个未解决的问题:https://github.com/dotnet/wcf/issues/2711

答案 2 :(得分:0)

似乎您正在使用wshttpbinding。 您可以尝试下面的代码。请更改您的地址和合同。

  WSHttpBinding wsbinding = new WSHttpBinding();
        wsbinding.MaxBufferPoolSize = 2147483647;
        wsbinding.MaxReceivedMessageSize = 2147483647;
        wsbinding.MessageEncoding = WSMessageEncoding.Mtom;
        wsbinding.TextEncoding = Encoding.UTF8;
        wsbinding.Security.Mode = SecurityMode.Transport;
        wsbinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

        using (ChannelFactory<ICalculatorService> channelFacoty = new ChannelFactory<ICalculatorService>(wsbinding, new EndpointAddress("http://localhost")))
        {
            ICalculatorService cal = channelFacoty.CreateChannel();
           Console.WriteLine( cal.Add(1, 3));
            Console.Read();
        }

答案 3 :(得分:0)

尝试WebHttBinding:

binding = new WebHttpBinding
{
    TransferMode = TransferMode.Buffered,
    ReceiveTimeout = TimeSpan.FromMinutes(1),
    SendTimeout = TimeSpan.FromMinutes(1),
    MaxReceivedMessageSize = 2147483647,
    MaxBufferPoolSize = 2147483647,
    ReaderQuotas =
        {
            MaxDepth = 2147483647,
            MaxStringContentLength = 2147483647,
            MaxArrayLength = 2147483647,
            MaxBytesPerRead = 2147483647,
            MaxNameTableCharCount = 2147483647
        },
    Security = new WebHttpSecurity()
    {
        Mode = WebHttpSecurityMode.Transport,
        Transport = new HttpTransportSecurity()
        {
            ClientCredentialType = HttpClientCredentialType.Ntlm
        }
    }
};