gpt4 book ai didi

c# - MessageInspector 和 Web 服务之间的共享信息

转载 作者:太空狗 更新时间:2023-10-30 01:06:29 24 4
gpt4 key购买 nike

我有一个关于在 MessageInspector 和网络服务之间共享信息的问题。

我有一个标识符 (Guid),用于“绑定(bind)”AfterReceiveRequest 和 BeforeSendReply。它工作正常。但是我希望这个标识符也可以在网络服务中使用的方法中使用。这非常有用,例如用于跟踪日志中的问题。

下面是一个小的演示示例来说明这个想法。我的问题是找到一个解决方案,可以从 AfterReceiveRequest 方法访问返回对象。与“MagicStuff”一致。

namespace Demo.MessageInspector
{
public class DemoMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
Guid activityId = Guid.NewGuid();
MyLog.Message("AfterReceiveRequest", activityId);
return activityId;
}

public void BeforeSendReply(ref Message reply, object correlationState)
{
Guid activityId = (Guid)correlationState;
MyLog.Message("BeforeSendReply", activityId);
}
}
}

namespace Demo.WebServices
{
[ServiceBehavior]
[MessageInterceptionServiceBehaviour]
public class MyWebService : IMyWebService
{
public void MyWebServiceMethod()
{
Guid activityId = (Guid)MagicStuff; // <-- correlationState from AfterReceiveRequest

bool success = DoSomthing();

if (!success)
MyLog.Message("Error happened in MyWebServiceMethod", activityId);
}
}
}

我将不胜感激任何类型的帮助或提示。

最佳答案

您可以使用 OperationContext.IncomingMessageProperties Property .这是您场景中的用法:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Demo.MessageInspector;
using Demo.Utilities;

namespace Demo.WebServices
{
public class MyWebService : IMyWebService, IServiceBehavior
{
public void MyWebServiceMethod()
{
// get the activityId from the incoming message properties
var activityIdProperty = OperationContext.Current.IncomingMessageProperties
.FirstOrDefault(property => property.Key == Properties.ActivityId.ToString());

// create an empty Guid
Guid activityId = new Guid();
if (activityIdProperty.Value != null)
{
// replace the empty Guid with the activityId
activityId = (Guid)activityIdProperty.Value;
}
bool success = DoSomething();
if (!success)
MyLog.Message("Error happened in MyWebServiceMethod", activityId);
}

private bool DoSomething()
{
// TODO: implement
return false;
}

public void AddBindingParameters(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters
)
{
return;
}

public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher epDisp in chDisp.Endpoints)
{
var messageInspector = new DemoMessageInspector();
epDisp.DispatchRuntime.MessageInspectors.Add(messageInspector);
}
}
}

public void Validate(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
// TODO: implement validation
//throw new NotImplementedException();
}
}
}

namespace Demo.MessageInspector
{
public class DemoMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request,
IClientChannel channel, InstanceContext instanceContext)
{
Guid activityId = Guid.NewGuid();

// add the activityId to the incoming message properties
OperationContext.Current.IncomingMessageProperties
.Add(Properties.ActivityId.ToString(), activityId);

MyLog.Message("AfterReceiveRequest", activityId);
return activityId;
}

public void BeforeSendReply(ref Message reply, object correlationState)
{
Guid activityId = (Guid)correlationState;
MyLog.Message("BeforeSendReply", activityId);
}
}
}

namespace Demo.Utilities
{
public enum Properties
{
ActivityId
}

public class MyLog
{
internal static void Message(string p, Guid guid)
{
File.AppendAllText(@"C:\Temp\log.txt",
String.Format("{0} {1} {2}\r\n", DateTime.Now, p, guid));
}
}
}

[更新]

或者,您可以使用 CorrelationManager.ActivityId Property .为此,首先将以下内容添加到您的配置文件( 客户端和服务器):

<system.diagnostics>
<sources>
<source name="System.ServiceModel" propagateActivity="true">
<listeners>
<add name="ignored" type="System.Diagnostics.DefaultTraceListener" />
</listeners>
</source>
</sources>
</system.diagnostics>

然后,在 Demo.Utilities.Helper 类中添加以下方法:

namespace Demo.Utilities
{
internal class Helper
{
internal static Guid GetCorrelationId()
{
var headerPosition = OperationContext.Current.IncomingMessageHeaders.FindHeader("ActivityId",
"http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics");
if (headerPosition > -1)
{
var activityIdHeader = OperationContext.Current.IncomingMessageHeaders
.GetReaderAtHeader(headerPosition);
var activityIdAttribute = activityIdHeader.GetAttribute("CorrelationId");
return Guid.Parse(activityIdAttribute);
}
else
{
return Guid.Empty;
}
}
}
}

现在您可以在 DemoMessageInspector 中使用这样的方法:

public object AfterReceiveRequest(ref Message request,
IClientChannel channel, InstanceContext instanceContext)
{
var correlationId = Helper.GetCorrelationId();
MyLog.Message("AfterReceiveRequest\tCorrelationId", correlationId);
// ...
}

在您的服务方法中像这样:

public void MyWebServiceMethod()
{
var correlationId = Helper.GetCorrelationId();
MyLog.Message("MyWebServiceMethod\tCorrelationId", correlationId);

// ...
}

关于c# - MessageInspector 和 Web 服务之间的共享信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15371733/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com