.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