C# 如何在WCF中将参数(id)传递给消息检查器?
我只想用一些id绑定WCF传入和传出的消息,这些id将被记录到数据库中 由于计划在高多线程环境中使用,因此出现了一些问题C# 如何在WCF中将参数(id)传递给消息检查器?,c#,.net,wcf,web-services,service,C#,.net,Wcf,Web Services,Service,我只想用一些id绑定WCF传入和传出的消息,这些id将被记录到数据库中 由于计划在高多线程环境中使用,因此出现了一些问题 后期编辑 以下是我想要记录的方式: public class LogMessageInspector : IClientMessageInspector { public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationS
后期编辑 以下是我想要记录的方式:
public class LogMessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Dictionary<string, object> logParams = (Dictionary<string, object>)correlationState;
logParams["description"] = reply.ToString();
Logger log = LogManager.GetCurrentClassLogger();
log.InfoEx(String.Format("response_{0}", logParams["_action"]), logParams);
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
string iteration_id = "";
// here comes seeking for custom, previously setted header with id
for (int i = 0; i < request.Headers.Count; i++)
{
if ((request.Headers[i].Name == "_IterationId") && (request.Headers[i].Namespace == "http://tempuri2.org"))
{
iteration_id = request.Headers.GetHeader<string>(i);
request.Headers.RemoveAt(i);
break;
}
}
string pair_id = StringGenerator.RandomString(10);
string action_name = request.Headers.Action.Substring(request.Headers.Action.LastIndexOf("/") + 1);
Dictionary<string, object> logParams = new Dictionary<string,object>() { {"iteration_id", iteration_id}, { "description", request.ToString() }, { "request_response_pair", pair_id }, { "_action", action_name } };
Logger log = LogManager.GetCurrentClassLogger();
log.InfoEx(String.Format("request_{0}", action_name), logParams);
return logParams;
}
}
公共类LogMessageInspector:IClientMessageInspector
{
接收后公共无效(参考System.ServiceModel.Channel.Message reply,object correlationState)
{
Dictionary logParams=(Dictionary)correlationState;
logParams[“description”]=reply.ToString();
Logger log=LogManager.GetCurrentClassLogger();
log.InfoEx(String.Format(“response”{0})、logParams[“\u action”]、logParams);
}
发送请求前的公共对象(参考System.ServiceModel.Channels.Message request,System.ServiceModel.IClientChannel)
{
字符串迭代_id=“”;
//这里来寻找自定义的、以前设置的id为的标题
for(int i=0;i
我认为最简单的解决方案是将threadstatic变量放入LogMessageInspector
中。在发送请求之前的中设置该值,并在接收方之后的中再次使用该值
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var correlationState = ... // for example, a new GUID, or in your case
// an id extracted from the message
... do your stuff here
return correlationState;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
// the correlationState parameter will contain the value you returned from
// BeforeSendRequests
}
如果您使用异步操作,我会变得稍微复杂一点,但是您所要做的就是更加关注如何访问和传递这个本地变量
MessageInspector旨在处理消息本身,所以最好的解决方案是在消息中有一些相关的内容,例如requestId、OrderId等
编辑:
我可以想象服务合同是这样的:
[ServiceContract]
public interface IService1
{
[OperationContract]
ServiceResponse Process( ServiceRequest request );
}
class ServiceRequest
{
public Guid RequestID { get; set; }
public string RequestData { get; set; }
}
class ServiceResponse
{
public Guid RequestID { get; set; }
public string ResponseData { get; set; }
}
RequestID将在客户端生成,现在您可以对消息执行xpath,并获取RequestID以关联请求和响应。如果我理解正确,您希望使用ID作为correlationState
将请求与回复链接起来。为此,请将ID作为对象从BeforeSendRequest
返回,它将作为参数传递给afterreceiverply
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var correlationState = ... // for example, a new GUID, or in your case
// an id extracted from the message
... do your stuff here
return correlationState;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
// the correlationState parameter will contain the value you returned from
// BeforeSendRequests
}
更新
问题是如何将参数传递给BeforeSendRequest方法
在这种情况下,如果您的请求消息中没有您需要的所有信息,那么显而易见的解决方案是为我们提供一个字段,以便在发送请求之前将调用者的信息传递给
在调用服务之前设置该字段,然后在发送请求之前提取并使用中的值
更新2
我可以使用的另一个选项是将参数设置为消息本身,但如何在BeforeSendRequest的请求参数中访问它
我不明白这个问题。如果我理解正确,您希望能够将一个参数从调用方传递到BeforeSendRequest
方法。您知道如何使用correlationState将它从发送请求之前的传递到接收方之后的
方法是使用ThreadStatic
字段。例如,您可以创建以下类:
public static class CallerContext
{
[ThreadStatic]
private static object _state;
public static object State
{
get { return _state; }
set { _state = value; }
}
}
然后,调用方将在调用web服务之前设置CallerContext.State
,并且在发送请求之前的和接收之后的都可以使用它。例如
...
try
{
CallerContext.State = myId;
... call web service here ...
}
finally
{
CallerContext.State = null;
}
这将在发送请求之前的中提供:
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var correlationState = CallerContext.State;
... do your stuff here
return correlationState;
}
请注意,严格来说,使用try/finally将调用方上下文.State
重置为null并不是必需的,但会阻止无关代码访问存储在那里的可能敏感数据。@SonerGönül事实上,我甚至不知道如何开始解决这个问题:)每个WCF调用都有与之关联的唯一id:OperationContext.Current.IncomingMessageHeaders。MessageId@Alexander我想定义自己的自定义ID,与数据库中的其他实体关联。您是否可以至少发布服务接口,以及您计划如何生成该ID?您可以给我一些关于RequestID或OrderID的示例吗。找不到此类属性。看起来不错,但在发送请求之前的中没有机会获取RequestID
,正如您在我的代码示例中看到的,我已经这样做了。问题是如何将参数传递给BeforeSendRequest
方法。我可以使用的另一个选项是将参数设置为消息本身,但如何在BeforeSendRequest
中的请求
参数中访问它?