ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 自定义端点行为未在带有服务引用的WCF客户端中使用

2019-06-29 17:54:11  阅读:146  来源: 互联网

标签:c soap wcf soap-client wcf-endpoint


我有一个问题,我不太确定它是如何开始的.我相当确定它之前工作正常,但不记得做出任何改变.

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

我公开了一个使用HTTP头认证的API.我在我的解决方案中使用此API的操作.为了避免样板代码,我使用CustomClientMessageInspector和CustomCredentialBehavior创建了一个我想初始化服务的ClientFactory,后者负责将标题添加到消息中.

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

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

CustomEndpointBehavior:

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?

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

编辑我接受了卡洛斯的建议(在评论中)并简化了呼叫,并使用了以下调用,而不是有效.我很高兴它的工作原理,但是,我想知道原始代码中的问题所在,所以每次我需要使用服务引用时都不必调用样板代码.

以下代码有效:

        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可以).

标签:c,soap,wcf,soap-client,wcf-endpoint
来源: https://codeday.me/bug/20190629/1328394.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有