gpt4 book ai didi

c# - 自定义终结点行为未在具有服务引用的 WCF 客户端中使用

转载 作者:行者123 更新时间:2023-11-30 12:11:26 26 4
gpt4 key购买 nike

我有一个问题,我不太确定它是如何开始的。我相当确定它之前工作正常,但不记得进行过任何更改。

首先,请不要过分关注设置,除非它直接影响它为什么不工作。我不是在寻求批评,因为我是导致它不起作用的原因。

我正在公开一个使用 HTTP header 身份验证的 API。我在我的解决方案中使用来自此 API 的操作。为了避免样板代码,我创建了一个要初始化服务的 ClientFactory,使用 CustomClientMessageInspector 和一个 CustomCredentialBehavior 负责将 header 添加到消息中。

想法是,当我需要使用服务时,代码看起来类似于:

IClientCredentials credentials = ClientCredentials.FromToken();
var service = ClientFactory.CreateClientInstance<API.Clients.ClientServiceClient>(credentials);

ClientFactory 如下所示(请不要过多判断)。

public class ClientFactory
{
public static T CreateClientInstance<T>(IClientCredentials clientCredentials)
{

T t = Activator.CreateInstance<T>();
var factory = t.GetType().GetProperty("ChannelFactory");
using (var scope = new OperationContextScope((IContextChannel) t.GetType().GetProperty("InnerChannel").GetValue(t,null)))
{

var endpointBehavior = new CustomCredentialBehavior(clientCredentials);
if (((ChannelFactory) factory.GetValue((t),null)).Endpoint.Behaviors.Any(p => p.GetType() == typeof(CustomCredentialBehavior)))
{
var behavior =
((ChannelFactory) factory.GetValue((t),null)).Endpoint.Behaviors.FirstOrDefault(
p => p.GetType() == typeof (CustomCredentialBehavior));
((ChannelFactory) factory.GetValue((t),null)).Endpoint.Behaviors.Remove(behavior);
}

((ChannelFactory)factory.GetValue((t),null)).Endpoint.Behaviors.Add(endpointBehavior);

return t;
}
}
}

自定义端点行为:

public class CustomCredentialBehavior:IEndpointBehavior
{
private IClientCredentials _clientCredentials { get; set; }

public CustomCredentialBehavior(IClientCredentials clientCredentials)
{
_clientCredentials = clientCredentials;
}



public void Validate(ServiceEndpoint endpoint)
{

}

public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{

}

public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{

}

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new ClientCredentialMessageInspector(_clientCredentials));
}
}

ClientMessageInspector:

public class ClientCredentialMessageInspector:IClientMessageInspector
{
private IClientCredentials _clientCredentials;

public ClientCredentialMessageInspector(IClientCredentials clientCredentials)
{
_clientCredentials = clientCredentials;
}

public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var buffer = request.CreateBufferedCopy(Int32.MaxValue);
request = buffer.CreateMessage();

HttpRequestMessageProperty messageProperty =
(HttpRequestMessageProperty) request.Properties["httpRequest"];
messageProperty.Headers.Add("AccessKey", _clientCredentials.AccessKey.ToString());
messageProperty.Headers.Add("ClientKey", _clientCredentials.ClientKey.ToString());
messageProperty.Headers.Add("AuthorizationKey", _clientCredentials.AuthorizationKey);
return null;
}

public void AfterReceiveReply(ref Message reply, object correlationState)
{

}
}

我面临的问题是,即使我可以看到从 ClientFactory 返回的服务具有正确的端点行为,ApplyClientBehavior() 也从未被调用。出于某种原因,它似乎并没有像最初那样使用 WCF 管道。

如何让 ClientFactory 创建一个实例,以便使用我添加的 EndpointBehavior?

编辑 为了展示我正在查看的内容,这里是调用服务操作之前的监 window 口的屏幕截图。它显示我的 CustomCredentialBehavior 使用所有正确的值进行了初始化。

enter image description here

编辑 我采纳了卡洛斯的建议(在评论中)并简化了调用,并改用了以下有效的调用。我很高兴它能正常工作,但是,我想找出我的原始代码中的问题所在,这样我就不必在每次需要使用服务引用时都调用样板代码。

以下代码有效:

        API.Clients.Client client = new API.Clients.Client();
client.Active = true;
client.Enabled = true;
client.Name = model.ClientName;

API.Clients.ClientServiceClient service = new ClientServiceClient();
service.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentialBehavior(ClientCredentials.FromToken()));
var response = service.CreateClient(new CreateClientRequest() { Client = client });

知道为什么初始代码不起作用,而这个代码可以吗?

最佳答案

我可能在这里遗漏了一些东西,但我真的不明白你为什么要走这么复杂的路线。

如果您有接口(interface)(不是 Client 类)契约,只需执行以下操作:

var factory = new ChannelFactory<T>(); //T is the interface of the service

factory.Endpoint.Behaviors.Add() 将为您提供添加行为的方法。然后要创建实际服务,您只需调用返回 Tfactory.CreateChannel()

总结一下:

public T Create<T>()
{
var factory = new ChannelFactory<T>();
factory.Endpoint.Behaviors.Add(<here goes your behavior>);
return factory.CreateChannel();
}

还要记得相应地处理客户端 channel 。如果您使用 IoC,容器可能可以为您处理(例如,Autofac 可以)。

关于c# - 自定义终结点行为未在具有服务引用的 WCF 客户端中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15401738/

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