0

我正在使用 WCF IClientMessageInspector 将标头中的信息发送到 WCF 服务 (wsHTTP)。我正在使用 IDispatchMessageInspector 接收信息并填充 String 属性。

当我在特定方法中使用 FindHeader 时,我验证了标头正在正确发送信息,但我宁愿只访问具有 Token 属性的自定义类并从那里获取 Token 而不必在单独的方法中执行 FindHeader所有其他方法调用以获取标头值。

所以我的问题是,从服务器端(我假设是 OperationContext)我如何访问这个类实例,它的 Token 属性填充了标头信息?

下面是整个类的代码:

地区“进口”

Imports System.ServiceModel
Imports System.ServiceModel.Dispatcher
Imports System.ServiceModel.Description
Imports System.ServiceModel.Channels
Imports System.ServiceModel.Configuration

结束区域

Public Class MessageInspector
    Inherits BehaviorExtensionElement
    Implements IClientMessageInspector, IDispatchMessageInspector, IEndpointBehavior

    Private Const headerName As String = "HeaderToken"
    Private Const headerNamespace As String = "urn:com.nc-software.services:v1"

    Private _token As String
    Public Property Token() As String
        Get
            Return _token
        End Get
        Set(ByVal Value As String)
            _token = Value
        End Set
    End Property

    Public Overrides ReadOnly Property BehaviorType() As System.Type
        Get
            Return GetType(MessageInspector)
        End Get
    End Property

    Protected Overrides Function CreateBehavior() As Object
        Return New MessageInspector
    End Function

区域“IEndpointBehavior”

Public Sub AddBindingParameters(ByVal endpoint As System.ServiceModel.Description.ServiceEndpoint, ByVal bindingParameters As System.ServiceModel.Channels.BindingParameterCollection) Implements System.ServiceModel.Description.IEndpointBehavior.AddBindingParameters
End Sub

Public Sub ApplyClientBehavior(ByVal endpoint As System.ServiceModel.Description.ServiceEndpoint, ByVal clientRuntime As System.ServiceModel.Dispatcher.ClientRuntime) Implements System.ServiceModel.Description.IEndpointBehavior.ApplyClientBehavior
    clientRuntime.MessageInspectors.Add(Me)
End Sub

Public Sub ApplyDispatchBehavior(ByVal endpoint As System.ServiceModel.Description.ServiceEndpoint, ByVal endpointDispatcher As System.ServiceModel.Dispatcher.EndpointDispatcher) Implements System.ServiceModel.Description.IEndpointBehavior.ApplyDispatchBehavior
    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(Me)
End Sub

Public Sub Validate(ByVal endpoint As System.ServiceModel.Description.ServiceEndpoint) Implements System.ServiceModel.Description.IEndpointBehavior.Validate
End Sub

结束区域

区域“ IClientMessageInspector ”

Public Sub AfterReceiveReply(ByRef reply As System.ServiceModel.Channels.Message, ByVal correlationState As Object) Implements System.ServiceModel.Dispatcher.IClientMessageInspector.AfterReceiveReply
End Sub

Public Function BeforeSendRequest(ByRef request As System.ServiceModel.Channels.Message, ByVal channel As System.ServiceModel.IClientChannel) As Object Implements System.ServiceModel.Dispatcher.IClientMessageInspector.BeforeSendRequest
    Dim header As New MessageHeader(Of String)(Token)
    Dim untypedHeader As MessageHeader = header.GetUntypedHeader(headerName, headerNamespace)
    request.Headers.Add(untypedHeader)
    Return Nothing
End Function

结束区域

区域“IDispatchMessageInspector”

Public Function AfterReceiveRequest(ByRef request As System.ServiceModel.Channels.Message, ByVal channel As System.ServiceModel.IClientChannel, ByVal instanceContext As System.ServiceModel.InstanceContext) As Object Implements System.ServiceModel.Dispatcher.IDispatchMessageInspector.AfterReceiveRequest
    Try
        Dim headers As MessageHeaders = OperationContext.Current.IncomingMessageHeaders
        Dim headerIndex As Integer = headers.FindHeader(headerName, headerNamespace)
        If headerIndex >= 0 Then
            Token = headers.GetHeader(Of String)(headerIndex)
        End If
    Catch
    End Try
    Return Nothing
End Function

Public Sub BeforeSendReply(ByRef reply As System.ServiceModel.Channels.Message, ByVal correlationState As Object) Implements System.ServiceModel.Dispatcher.IDispatchMessageInspector.BeforeSendReply
End Sub

结束区域

结束类

4

1 回答 1

2

根据我看到 WCF 团队正在建立的模式,我的建议是让您的 IDispatchMessageInspector 将标头的值推送到当前 OperationContext 的IncomingMessageProperties字典中。通过这样做,该值将与当前操作上下文相关联,并由 WCF 运行时为您正确执行所有阶段。

至于如何在堆栈中进一步读取该值,您可以做两件事。首先,您可以公开您将用于读取/写入值到属性集合中的静态只读字符串的字符串键,其他代码可以使用它从 OperationContext.Current 本身检索值,如下所示:

int value = (int)OperationContext.Current.IncomingMessageProperties[MyMessageProperty.MyHeader];

现在,这仍然需要所有需要读取值的人进行大量编码。获取当前上下文,使用键索引到字典中并将结果转换为正确的类型(我使用 int 作为上面的示例)。如果你想变得花哨,你可以采取的下一步是通过你自己的上下文类公开这些属性,这样人们就可以像普通的强类型 CLR 属性一样访问它们。这可能看起来有点像这样:

首先,在一个名为 MyOperationContext 的类上实现一个静态访问器属性:

public static int MyHeader
{
    get
    {
        return (int)OperationContext.Current.IncomingMessageProperties[MyMessageProperty.MyMessageProperty];
    }

    set
    {
        OperationContext.Current.IncomingMessageProperties[MyMessageProperty.MyMessageProperty] = value;
    }
}

现在,在您需要读取此标头的各种实现中,他们只需执行以下操作:

int value = MyOperationContext.MyHeader;
于 2010-03-29T17:37:57.660 回答