【问题标题】:Programmatically define WCF Endpoints with Behaviours以编程方式定义具有行为的 WCF 端点
【发布时间】:2016-06-03 22:49:41
【问题描述】:

谁能告诉我如何以编程方式创建具有端点行为的 WSHttpBindings?

这是从 WCF 添加服务对 6 个 Web 服务的引用生成的,我手动编辑这些 Web 服务以添加行为,以便所有端点使用相同的行为。

<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="epBehaviour">
        <clientCredentials>
          <clientCertificate findValue="This is my TEST Cert" storeLocation="LocalMachine" x509FindType="FindBySubjectName" storeName="My" />
        </clientCredentials>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <bindings>
    <wsHttpBinding>
      <binding name="WSHttpBinding_IQuote" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
      <binding name="WSHttpBinding_ICommit" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
      <binding name="WSHttpBinding_IRetrieve" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
      <binding name="WSHttpBinding_IInfo" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
      <binding name="WSHttpBinding_IPurge" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
      <binding name="WSHttpBinding_ISearch" messageEncoding="Mtom">
        <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" />
          <message clientCredentialType="Certificate" establishSecurityContext="false" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <client>
    <endpoint address="https://my.service.com/WCFServices/Info.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IInfo" contract="InfoWcfWS.IInfo" name="WSHttpBinding_IInfo" />
    <endpoint address="https://my.service.com/WCFServices/Quote.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IQuote" contract="QuoteWcfWS.IQuote" name="WSHttpBinding_IQuote" />
    <endpoint address="https://my.service.com/WCFServices/Commit.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICommit" contract="CommitWcfWS.ICommit" name="WSHttpBinding_ICommit" />
    <endpoint address="https://my.service.com/WCFServices/Retrieve.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IRetrieve" contract="RetrieveWcfWS.IRetrieve" name="WSHttpBinding_IRetrieve" />
    <endpoint address="https://my.service.com/WCFServices/Purge.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IPurge" contract="PurgeWcfWS.IPurge" name="WSHttpBinding_IPurge" />
    <endpoint address="https://my.service.com/WCFServices/Search.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISearch" contract="SearchWcfWS.ISearch" name="WSHttpBinding_ISearch" />
  </client>
</system.serviceModel>

目前使用“添加服务”生成的代理并将端点中引用的行为“epBehaviour”添加​​为行为配置,我可以调用端点。

现在,我的下一步是将行为部分和 URL 定义为配置(可能在 web.config 中),以便我可以为暂存和生产提供不同的配置。

所以我的示例暂存配置将具有如下定义的 URL

<appSettings>
  <add key="ServiceUrl.Tls12.Quote" value="https://my.service.com/WCFServices/Quote.svc" />
  <add key="ServiceUrl.Tls12.Commit" value="https://my.service.com/WCFServices/Commit.svc" />
  <add key="ServiceUrl.Tls12.Retrieve" value="https://my.service.com/WCFServices/Retrieve.svc" />
  <add key="ServiceUrl.Tls12.Info" value="https://my.service.com/WCFServices/Info.svc" />
  <add key="ServiceUrl.Tls12.Purge" value="https://my.service.com/WCFServices/Purge.svc" />
  <add key="ServiceUrl.Tls12.Search" value="https://my.service.com/WCFServices/Search.svc" />
</appSettings>

因此,如果我使用“Info”WebService,我的代码应该类似于

//Code is missing how to define all the specifics like behaviours.
WSHttpBinding binding = new WSHttpBinding();
                EndpointAddress endpoint = new EndpointAddress(new Uri(ConfigurationManager.AppSettings["ServiceUrl.Tls12.Info"]));
             InfoWcfWS.InfoClient proxyNew = new InfoWcfWS.InfoClient(binding, endpoint);

总而言之,鉴于在“添加服务”之后生成的配置,为了生成我的代理类,我想删除 VS 生成的所有配置并定义我自己的配置来保存 URL;其他一切,如端点 URI、行为 ..等都应该以编程方式实例化。

谢谢

【问题讨论】:

  • 如果我理解正确,那么您想手动创建客户端代理。而且我认为您可以控制服务器和客户端。我说的对吗?

标签: c# web-services wcf


【解决方案1】:

您必须从 System.ServiceModel.Description 命名空间创建所需行为的实例,或者自己创建它们,然后将它们添加到 ChannelFactory

对于您的示例,您为您想要的界面和您喜欢的任何绑定创建一个ChannelFactory。然后实例化一个ClientCredentials 行为,配置您需要的任何设置并将其添加到ChannelFactory 的EndPointBehaviors。然后,您就可以创建一个客户端通道,该通道将为您提供一个实现您的服务接口的对象。您可以将其用作生成的客户端。

// binding
var binding = new WSHttpBinding();
// using System.ServiceModel
var channelFactory = new ChannelFactory<InfoWcfWS.IInfo>(binding);
// using System.ServiceModel.Description
var endpointClientbehavior = new ClientCredentials();
endpointClientbehavior.ClientCertificate
    .SetCertificate(
    "This is my TEST Cert", 
    StoreLocation.LocalMachine, 
    StoreName.My);
// add the behavior to the endpoint
channelFactory.Endpoint.EndpointBehaviors.Add(endpointClientbehavior);

// done configuring;
channelFactory.Open();
var endpoint = new EndpointAddress(
    new Uri(ConfigurationManager.AppSettings["ServiceUrl.Tls12.Info"]));
// create the clientChannel
var client = channelFactory.CreateChannel(endpoint);
client.Open();
// client implements the operations on InfoWcfWS.IInfo

【讨论】:

  • 在你的 sn-p 结尾你提到我可以访问接口上的操作,但是,我需要访问一个部分类,它继承了包含我的方法的接口,带有 2 个参数 - 即 InfoWcfWS .InfoClient proxyNew = new InfoWcfWS.InfoClient(binding, endpoint);其中 InfoClient 是继承 CLietnBase 和 IInfo 的部分类,并具有一堆公共方法
  • 我在示例中忽略了生成的 ClientBase 并让您完全控制界面。在我的代码示例中,您仍然有两个参数,绑定和来自配置文件的 Uri。您不再需要生成的客户端。
  • 谢谢,稍后我将探索 channelFactory,因为它似乎是访问任何类型服务的更通用的方式......现在,我已经探索了直接访问 InfoClient 的最初目标代理类生成的方法。
【解决方案2】:

最后,我找到了一种更简单的方法来实现这一点 - 这是我正在访问的方法 Info 之一:

WSHttpBinding binding = new WSHttpBinding();
EndpointAddress endpoint = new EndpointAddress(new Uri("https://my.service.com/WCFServices/Info.svc"));

binding.Name = "WSHttpBinding_IInfo";
binding.MessageEncoding = WSMessageEncoding.Mtom;
binding.Security = new WSHttpSecurity();
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Transport = new HttpTransportSecurity();
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Message = new NonDualMessageSecurityOverHttp();
binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
binding.Security.Message.EstablishSecurityContext = false;

InfoClient proxy = new InfoClient(binding, endpoint);

proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My,                                              X509FindType.FindBySubjectName, "This is my TEST Cert");

object response = proxy.ServiceMethod();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    相关资源
    最近更新 更多