具有服务参考的 WCF 客户端中未使用自定义终结点行为

2023-12-21

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

首先,请不要过多关注设置,除非它直接影响其无法正常工作的原因。我并不是在寻求批评,而是在寻找导致它不起作用的原因。

我正在公开一个使用 HTTP 标头身份验证的 API。我在我的解决方案中使用此 API 的操作。为了避免样板代码,我创建了一个客户工厂我想使用一个来初始化服务自定义客户端消息检查器 and a 自定义凭证行为它负责将标头添加到消息中。

这个想法是,当我需要使用服务时,代码将类似于以下内容:

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));
    }
}

IClientMessageInspector:

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?

EDIT为了展示我所看到的内容,这里是调用服务操作之前的监视窗口的屏幕截图。它显示了使用所有正确值初始化的我的自定义凭据行为。

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

以下代码有效:

        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 });

知道为什么最初的代码不起作用,而这个却起作用吗?


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

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

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

factory.Endpoint.Behaviors.Add()将为您提供添加行为的方式。 然后创建您刚刚调用的实际服务factory.CreateChannel()它返回一个T.

总结来说:

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有服务参考的 WCF 客户端中未使用自定义终结点行为 的相关文章

随机推荐