.net 为具有属性的方法添加消息检查器

.net 为具有属性的方法添加消息检查器,.net,wcf,idispatchmessageinspector,.net,Wcf,Idispatchmessageinspector,对于某些应用了自定义属性的服务方法,是否可以只使用消息检查器?我在网上看到的所有示例都添加了一个消息检查器,作为应用于服务上每个方法的行为扩展。我不确定是否可以将检查器仅应用于有限的一组方法,但是您可以尝试创建一个常规的消息检查器,以检查目标方法是否有自定义方法应用的属性: public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientC

对于某些应用了自定义属性的服务方法,是否可以只使用消息检查器?我在网上看到的所有示例都添加了一个消息检查器,作为应用于服务上每个方法的行为扩展。

我不确定是否可以将检查器仅应用于有限的一组方法,但是您可以尝试创建一个常规的消息检查器,以检查目标方法是否有自定义方法应用的属性:

public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
        string actionName = request.Headers.Action.Substring(request.Headers.Action.LastIndexOf('/') + 1);
        if (!string.IsNullOrEmpty(actionName))
        {
            var methodInfo = instanceContext.Host.Description.ServiceType.GetMethod(actionName);
            if (methodInfo != null)
            {
                var customAttributes = methodInfo.GetCustomAttributes(false);
                if (customAttributes.Any(ca => ca.GetType().Equals(typeof(MyCustomAttribute))))
                { 

                }
            }
        }
        ...

这只是一个快速而肮脏的实现,您可能需要重构一下。您可能还想将过滤过程从检查器本身之外抽象出来,或者有某种责任链来处理它。希望这能有所帮助。

是的,你可以这样做。您需要一个继承自soapextension的类和另一个继承自SOAPExtensionAttribute的类。soapextensionattribute类就是用来设置web服务方法属性的类

比如说

'定义跟踪SOAP请求和SOAP响应的SOAP扩展 '对于XML Web服务方法,SOAP扩展应用于。 '//blog.encoresystems.net/articles/how-to-capture-soap-envelopes-when-consuming-a-web-service.aspx '和//bytes.com/topic/net/answers/426481-how-log-soap-messages-client-side '和//www.codeproject.com/KB/cpp/SerializationFun.aspx 好友类SoapdbTraceExtension 继承SoapExtension

    Private _originalStream As Stream
    Private _newStream As Stream

    Private _methodname As String

    Sub New()
    End Sub

    ' Save the Stream representing the SOAP request (or SOAP response) into
    ' a local memory buffer.
    ' basically due to the nature of streams, this creates a copy so that 
    ' we have something that we can work on. This function is called automatically
    ' when this soapextension is invoked.
    ' see //msdn.microsoft.com/en-us/magazine/cc164007.aspx
    ' the goal here is to save the stream containing the SOAP message
    ' We also create a NewStream for holding a working copy of the message
    ' The stream passed into Chainstream creates a memory stream and passes it back to the caller
    ' the stream returned from chainstream contains the serialised SOAP message
    Public Overrides Function ChainStream(ByVal stream As Stream) As Stream

        ' this is called prior to BeforeDeserialize and BeforeSerialize 
        ' see http://hyperthink.net/blog/inside-of-chainstream/
        ' In the former case (i.e. the one we are interested in here
        ' oldstream contains the contents of the soap request and newstream will be empty

        _originalStream = stream
        _newStream = New MemoryStream()
        Return _newStream
    End Function

    ' When the SOAP extension is accessed for the first time, the XML Web
    ' service method it is applied to is accessed to store the parameter values
    ' passed in, using the corresponding SoapExtensionAttribute.  So in the case 
    ' of the database trace this might be the method name (as shown below)
    Public Overloads Overrides Function GetInitializer(ByVal methodInfo As  _
                                                          LogicalMethodInfo,
                                                       ByVal attribute As SoapExtensionAttribute) As Object
        ' We use this to establish
        ' the method name (though it could be any attribute from the
        ' SOAPDatabaseTrace class) i.e. any attribute that can be 
        ' passed from the use of the attribute on the web service method declaration

        ' here we store the name of the method in the property we have setup

            ' name of the calling method

            Me._methodname = CType(attribute, SOAPDatabaseTrace).Method

            Return _methodname

    End Function


    Public Overloads Overrides Function GetInitializer(ByVal webServiceType As  _
                                                          Type) As Object

        Return _methodname
    End Function

    ' Receive the method name stored by GetInitializer and store it in a
    ' member variable for this specific instance.
    Public Overrides Sub Initialize(ByVal initializer As Object)

        ' this is called once per soap request and is therefore the ideal place to add appropriate data

            _methodname = CStr(initializer)


    End Sub


    ' This is automatically called after the chainstream function.
    ' this is called multiple times
    Public Overrides Sub ProcessMessage(ByVal message As SoapMessage)
            Select Case message.Stage
                Case SoapMessageStage.BeforeSerialize
                    ' chainstream is called prior to BeforeSerialize
                Case SoapMessageStage.AfterSerialize
                    WriteOutput(message)

                Case SoapMessageStage.BeforeDeserialize
                    ' chainstream is called prior to BeforeDeserialize 
                    WriteInput(message)
                Case SoapMessageStage.AfterDeserialize
            End Select
    End Sub

    ' Write the SOAP response to the database
    Public Sub WriteOutput(ByVal message As SoapMessage)

            CopyAndKeepXMLStream(_newStream, _originalStream)
    End Sub

    ' Write the SOAP request message to the database

    Public Sub WriteInput(ByVal message As SoapMessage)

            CopyAndKeepXMLStream(oldStream:=_originalStream, cleanedUpStream:=_newStream)

    End Sub

    Private Sub CopyAndKeepXMLStream(ByVal oldStream As Stream, ByVal cleanedUpStream As Stream)

            ' from //google-api-adwords-dotnet.googlecode.com/svn-history/r50/trunk/src/lib/TraceExtension.cs
            Dim oldposition As Long
            If oldStream.CanSeek Then
                oldposition = oldStream.Position
                oldStream.Position = 0
            End If
            ' load the XML writer
            Dim xmlwriter As XmlTextWriter = New XmlTextWriter(cleanedUpStream, Encoding.UTF8)
            ' pretty it all up
            xmlwriter.Indentation = 2
            xmlwriter.IndentChar = Char.Parse(" ")
            xmlwriter.Formatting = Formatting.Indented

            ' load from old stream and write to the new cleaned up stream
            Dim xmlreader As XmlReader = New XmlTextReader(oldStream)
            Dim xml As XmlDocument = New XmlDocument
            xml.Load(xmlreader)
            xml.WriteTo(xmlwriter)
            xmlwriter.Flush()
            cleanedUpStream.Flush()

            If cleanedUpStream.CanSeek Then
                cleanedUpStream.Position = 0
            End If

            If oldStream.CanSeek Then
                oldStream.Position = oldposition
            End If
            'Dim result As String
            'result = xml.OuterXml

            ' now we have the string we can write to the database
            StoreSOAP(xml)
    End Sub

    ''' <summary>
    ''' Parse and store the soap message 
    ''' </summary>
    ''' <param name="xml">The SOAP message</param>
    ''' <remarks>Stores the SOAP message in a database</remarks>
    Private Sub StoreSOAP(ByVal xml As XmlDocument)
Private\u原始流作为流
Private\u新闻流作为流
Private _methodname作为字符串
次新
端接头
'将表示SOAP请求(或SOAP响应)的流保存到
'本地内存缓冲区。
“基本上,由于流的性质,这会创建一个副本,以便
“我们有一些事情可以做。此函数将自动调用
'当调用此soapextension时。
'请参见//msdn.microsoft.com/en-us/magazine/cc164007.aspx
'这里的目标是保存包含SOAP消息的流
'我们还创建了一个新闻流,用于保存邮件的工作副本
'传递到Chainstream的流创建一个内存流,并将其传递回调用方
'从chainstream返回的流包含序列化的SOAP消息
Public将函数ChainStream(ByVal stream作为stream)重写为stream
'这是在BeforeDeserialize和BeforeSerialize之前调用的
”“看到了吗http://hyperthink.net/blog/inside-of-chainstream/
“在前一种情况下(即我们感兴趣的情况下
'oldstream包含soap请求的内容,而newstream将为空
_原始流=流
_newStream=newmemoryStream()
Return\u newStream
端函数
'首次访问SOAP扩展时,XML Web
'访问应用它的服务方法以存储参数值
'传入,使用相应的SoapExtensionAttribute
'这可能是方法名(如下所示)
公共重载重写函数GetInitializer(ByVal methodInfo作为_
逻辑方法信息,
ByVal属性作为SoapExtensionAttribute)作为对象
"我们用此来建立
'方法名称(尽管它可以是
'SOAPDatabaseTrace类),即可以
'通过使用web服务方法声明上的属性传递
'在这里,我们将方法的名称存储在已设置的属性中
'调用方法的名称
Me.\u methodname=CType(属性,SOAPDatabaseTrace).Method
Return\u methodname
端函数
公共重载重写函数GetInitializer(ByVal webServiceType为_
类型)作为对象
Return\u methodname
端函数
'接收GetInitializer存储的方法名称,并将其存储在
'此特定实例的成员变量。
公共重写子初始化(ByVal初始值设定项作为对象)
'这是每个soap请求调用一次,因此是添加适当数据的理想位置
_methodname=CStr(初始值设定项)
端接头
'这是在chainstream函数之后自动调用的。
这叫多次
公共覆盖子进程消息(ByVal消息作为SoapMessage)
选择案例消息。阶段
Case SoapMessageStage.BeforeSerialize
'在BeforeSerialize之前调用chainstream
Case SoapMessageStage.AfterSerialize
写输出(消息)
案例SoapMessageStage.BeforeDeserialize
'在BeforeDeserialize之前调用chainstream
写入输入(消息)
案例SoapMessageStage.AfterDeserialize
结束选择
端接头
'将SOAP响应写入数据库
公共子写入输出(ByVal消息作为SoapMessage)
CopyAndKeepXMLStream(_newStream,_originalStream)
端接头
'将SOAP请求消息写入数据库
公共子写入输入(ByVal消息作为SoapMessage)
CopyAndKeepXMLStream(旧流:=\u原始流,干净流:=\u新流)
端接头
私有子CopyAndKeepXMLStream(ByVal oldStream作为流,ByVal cleanedUpStream作为流)
'来自//google-api-adwords-dotnet.googlecode.com/svn-history/r50/trunk/src/lib/TraceExtension.cs
位置尽可能长
如果oldStream.CanSeek那么
oldposition=oldStream.Position
oldStream.Position=0
如果结束
'加载XML编写器
将xmlwriter设置为XmlTextWriter=新X
  End Sub


    Private Sub Copy(ByVal fromStream As Stream, ByVal toStream As Stream)
        Dim reader As New StreamReader(fromStream)
        Dim writer As New StreamWriter(toStream)
        writer.WriteLine(reader.ReadToEnd())
        writer.Flush()
    End Sub
End Class

' Create a SoapExtensionAttribute for our SOAP Extension that can be
' applied to an XML Web service method.
' these are the attributes we have available
' they are available in the web service of interest
' and can be used here for logging etc.
<AttributeUsage(AttributeTargets.Method)>
Friend Class SOAPDatabaseTrace
    Inherits SoapExtensionAttribute

    Private _mPriority As Integer
    Private _mMethod As String = "Unknown"

    Public Overrides ReadOnly Property ExtensionType() As Type
        Get
            Return GetType(SoapdbTraceExtension)
        End Get
    End Property


    ''' <summary>
    '''     Priority
    ''' </summary>
    ''' <value>Integer</value>
    ''' <returns>
    '''     Indicates the priority in which the extension will be executed relative to other soapextensions.
    '''     1 is the highest priority
    ''' </returns>
    ''' <remarks>Required by the inheritance</remarks>
    Public Overrides Property Priority() As Integer
        Get
            Return _mPriority
        End Get
        Set(ByVal value As Integer)
            _mPriority = value
        End Set
    End Property

    Public Property Method() As String
        Get
            Return _mMethod
        End Get
        Set(ByVal value As String)
            _mMethod = value
        End Set
    End Property

End Class
    <WebMethod(Description:="Some web method"), _
    SOAPDatabaseTrace(method:="MyFunction")> _
    Public Function MyFunction(ByVal Param1 As String) as object