具有服务参考的 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 客户端中未使用自定义终结点行为 的相关文章

  • System.MissingMethodException:找不到方法?

    以前工作的 ASP NET WebForms 应用程序现在抛出此错误 System MissingMethodException 找不到方法 The DoThis方法位于同一个类上 它应该可以工作 我有一个这样的通用处理程序 public
  • Ruby 解释器嵌入到 C 代码中

    我只是尝试书中的一个简单例子 我有一个 sum rb 文件 class Summer def sum max raise Invalid maximum max if max lt 0 max max max 2 end end 还有一个
  • 获取光标相对于控件的位置 - C#

    我想获取鼠标相对于鼠标指针所在控件的位置 这意味着当我将光标置于控件的起点 左上角 时 它应该给出 0 0 我正在使用以下代码 private void panel1 MouseMove object sender MouseEventAr
  • 将 Visual Studio 2012 C++ 单元测试项目链接到 exe 会导致访问冲突

    我从现有的整体 exe 本机 Visual Studio 2012 项目开始 我想添加一个本机单元测试项目 根据http msdn microsoft com en us library hh419385 aspx objectRef ht
  • 堆栈独立的C/C++蓝牙API?

    我想知道是否有适用于 Windows XP Vista 7 x86 和 x64 的堆栈独立 C C 蓝牙 api 我的目标是创建连接并通过蓝牙发送 接收一些时间关键的数据 我的研究给了我以下选择以及这项任务的缺点 用于蓝牙的 Windows
  • 模拟 EF core dbcontext 和 dbset

    我正在使用 ASP NET Core 2 2 EF Core 和 MOQ 当我运行测试时 我收到此错误 消息 System NotSupportedException 非虚拟 可在 VB 中重写 成员上的设置无效 x gt x Movies
  • WCF 版本控制枚举

    我开始编写一些需要向前兼容和版本控制的 WCF 数据协定 我一直在阅读 MSDN 文章here http msdn microsoft com en us library ms733832 aspx 并且想知道是否有人对有关枚举的第 14
  • 如何在 asp .net mvc 2 中对不直接属于我的模型的对象使用 DisplayFor()?

    我确信我在这里遗漏了一些非常简单的东西 我创建了一个自定义日期时间显示模板 使用以下方法时效果很好 但是 我遇到了这样的情况 在部分控件内 我在 for 循环中迭代模型中的对象 我想要一个 DateTime 属性来使用显示模板 但我不知道如
  • string.empty 和 string[0] == '\0' 之间的区别

    假设我们有一个字符串 std string str some value is assigned 有什么区别str empty and str 0 0 C 11 及更高版本 string variable 0 如果字符串为空 则需要返回空字
  • 混合 VS2012 平台工具集

    我们正在从 VS2005 切换到 VS2012 update 2 我们正在构建大量 主要是控制台 本机 C 无 MFC ATL 可执行文件 它们使用几个常见的静态链接库 这些可执行文件主要在 Win7 计算机上运行 但有些也部署在较旧的 X
  • 如何在单独的类库中管理客户端上下文对象?

    我正在尝试创建一个库 类库 对于共享点 它将拥有所有共享点 dll 来与共享点服务器交互上传文件 文档并创建文档库和文档集 现在这个库可以被使用客户端 例如 Web 应用程序 asp net webform 或 mvc 或控制台应用程序或
  • MSBuild 将动态生成的文件复制为项目依赖项的一部分

    我有一个自定义 msbuild 任务 它正在生成一些输出文件到 ProjectA 的输出目录 TargetDir 当前的代码是这样的
  • 从 Linq 的列表中选择多个字段

    在 ASP NET C 中 我有一个结构 public struct Data public int item1 public int item2 public int category id public string category
  • 将 libpng 链接到 android 原生项目

    我在尝试在本机 Android 项目中加载 libpng 时遇到问题 编译器似乎无法识别 libpng 函数 但可以识别类型 如 png byte 它可以正常编译类型 但如果我添加函数 则会抛出错误 这是编译输出 Windows 7 cmd
  • CS0246 找不到类型或命名空间名称“ErrorViewModel”(您是否缺少 using 指令或程序集引用?)

    我收到 CS0246 错误代码 我正在做一个 MVC net core 项目 我正在将 Razor 合并到我的 C 代码中 我在进行构建时收到此错误 我在最后一行收到错误 有人能帮我解决这个问题吗 global Microsoft AspN
  • “sizeof”对不完整类型列表结构 C 的无效应用

    我正在尝试实现一种处理页面错误的替换算法 因此 我尝试使用 malloc 创建一个循环链表 但出现以下错误 无效的应用程序sizeof to incomplete typepageInMemory 以下是代码 typedef struct
  • g++4.9 不支持 std::align

    在学习对齐问题等时 我意识到我的 g 4 9 macports OS X 实现不支持std align 如果我尝试编译 使用 std c 11 此示例代码来自http www cplusplus com reference memory a
  • Python 中的 C 指针算术

    我正在尝试将一个简单的 C 程序转换为 Python 但由于我对 C 和 Python 都一无所知 这对我来说很困难 我被 C 指针困住了 有一个函数采用 unsigned long int 指针并将其值添加到 while 循环中的某些变量
  • 为什么没有参数的函数(与实际函数定义相比)可以编译?

    我刚刚看到某人的 C 代码 我很困惑为什么要编译它 有两点我不明白 The 函数原型与实际函数定义相比没有参数 中的参数函数定义没有类型 include
  • MsBuild 在 Visual Studio Online 上找不到恢复的 NuGet 包

    我尝试构建一个存储在 Visual Studio Online 上的外部 GIT 存储库中的解决方案 它有以下步骤 1 Git 恢复 有效 2 NuGet 恢复 有效 3 构建 不起作用 查看日志时我的第一个猜测是 MsBuild 没有查找

随机推荐