wcf - 以编程方式将自定义 WCF header 添加到终结点以实现可靠 session

标签 wcf session header reliability

我正在构建一个 WCF 路由器,我的客户端使用可靠 session 。在这种情况下,当客户端打开一个 channel 时,会发送一条消息(建立可靠 session ?)。其内容如下:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://docs.oasis-open.org/ws-rx/wsrm/200702/CreateSequence</a:Action>
    <a:MessageID>urn:uuid:1758f794-c5d3-4573-b252-7a07344cc257</a:MessageID>
    <a:To s:mustUnderstand="1">http://localhost:8010/RouterService</a:To>
  </s:Header>
  <s:Body>
    <CreateSequence xmlns="http://docs.oasis-open.org/ws-rx/wsrm/200702">
      <AcksTo>
        <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
      </AcksTo>
      <Offer>
        <Identifier>urn:uuid:64a12658-71d9-4967-88ec-9bb0610f7ecb</Identifier>
        <Endpoint>
          <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </Endpoint>
        <IncompleteSequenceBehavior>DiscardFollowingFirstGap</IncompleteSequenceBehavior>
      </Offer>
    </CreateSequence>
  </s:Body>
</s:Envelope>

这里的问题是标题不包含任何我可以用来查找将消息路由到哪个服务的信息。在 Busatmante 的路由器示例代码中,她通过向端点添加 header 来解决此问题:

  <client>
    <endpoint address="http://localhost:8010/RouterService" binding="ws2007HttpBinding"
      bindingConfiguration="wsHttp"
      contract="localhost.IMessageManagerService" >
      <headers>
        <Route xmlns="http://www.thatindigogirl.com/samples/2008/01" >http://www.thatindigogirl.com/samples/2008/01/IMessageManagerService</Route>
      </headers>
    </endpoint>
  </client>

当打开可靠 session 时,消息包含此自定义 header 。

<Route a:IsReferenceParameter="true" xmlns="http://www.thatindigogirl.com/samples/2008/01">http://www.thatindigogirl.com/samples/2008/01/IMessageManagerService</Route>

这太棒了;但是,我需要以编程方式配置客户端。我认为 ChannelFactory 端点会有一个 Header 对象,我可以手动将自定义 header 添加到该对象。不幸的是它没有。因此,我进行了一些搜索并找到了一些建议,通过实现 IClientMessageInspector 来添加我的 header 并将其作为一种行为添加到我的端点来扩展 WCF。

public class ContractNameMessageInspector : IClientMessageInspector {

    private const string HEADER_NAME = "ContractName";
    private readonly string _ContractName;

    public ContractNameMessageInspector(string contractName) {
        _ContractName = contractName;
    }

    #region IClientMessageInspector Members

    public void AfterReceiveReply(ref Message reply, object correlationState) { }

    public object BeforeSendRequest(ref Message request, IClientChannel channel) {

        HttpRequestMessageProperty httpRequestMessage;
        object httpRequestMessageObject;

        if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject)) {
            httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
            if (httpRequestMessage != null && string.IsNullOrEmpty(httpRequestMessage.Headers[HEADER_NAME])) {
                httpRequestMessage.Headers[HEADER_NAME] = this._ContractName;
            }
        }
        else {
            httpRequestMessage = new HttpRequestMessageProperty();
            httpRequestMessage.Headers.Add(HEADER_NAME, this._ContractName);
            request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
        }
        return null;
    }

    #endregion
}

因此,当我的客户端进行服务调用时,消息包含自定义 header ,但建立可靠 session 的消息仍然没有。

所以我的问题是;如何以可靠 session 消息包含自定义 header 的方式以编程方式将自定义 header 添加到端点?

非常感谢

最佳答案

想通了。尽管没有向 EndpointAddress 添加 header 的属性或方法,但构造函数上有一个可选参数。

_Binding = bindingFactory.GetBinding(serviceUri, typeof(T));
AddressHeader header = AddressHeader.CreateAddressHeader("ContractName", "NameSpace", typeof (T).ToString());

_Address = new EndpointAddress(serviceUri, header);
_ChannelFactory = new ChannelFactory<T>(_Binding, _Address);

现在,当我收到建立可靠 session 的消息时,它实际上确实包含我的自定义 header 。这是有道理的,因为消息检查器很可能只对分派(dispatch)的消息进行操作,而建立可靠 session 的消息是由较低级别的 WCF 代码生成的。

关于wcf - 以编程方式将自定义 WCF header 添加到终结点以实现可靠 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3152056/

相关文章:

PHP 函数 - 无法取消设置 $_SESSION 变量

hibernate - 将 Hibernate 条件查询转换为 JPA 2 条件查询

css - 如何使用 HTML 在文档的每个打印页面上打印页眉和页脚?

android - 在带有边距的布局中使用带有标题的 ListView

c# - 通过 WCF 发送图像的有效方法?

session - JSF - 访问 SessionScoped 托管 bean

asp.net - 无法访问 wcf 服务中的 asp.net session

http - X-Cloud-Trace-Context 的目的是什么?

c# - 使用 OData 在我的数据库中插入一条新记录

asp.net - 以某种方式在 WCF 服务中存储单词?