如何重写 WCF 客户端以使用 ChannelFactory 而不是服务引用

发布于 2024-10-27 11:18:54 字数 2951 浏览 2 评论 0原文

我有一个使用 Web 服务软件工厂 创建的 WCF 服务。我所有传入的请求和返回的响应都作为消息契约实现。我一直通过在 VS 中添加服务引用来访问该服务,效果很好。然而,我现在被告知这不是标准的公司方式,我需要使用基于 System.ServiceModel.ChannelFactory 的内部 WCF 代理帮助程序类来调用该服务。

我以前从未使用过 ChannelFactory,并且正在努力找出重写客户端访问的最佳方法。服务契约由服务工厂生成,我需要向代理帮助器类提供服务接口。这是服务合同的一部分 - 服务上总共有大约 25 个操作:

namespace CAEWCFService.ServiceContracts
{
  /// <summary>
  /// Service Contract Class - CAEServiceContract
  /// </summary>
  [WCF::ServiceContract(Namespace = "urn:CAEServiceServiceContracts", Name = "CAEServiceContract", SessionMode = WCF::SessionMode.Allowed, ProtectionLevel = ProtectionLevel.None )]
  public partial interface ICAEServiceContract 
  {
    [WCF::OperationContract(IsTerminating = false, IsInitiating = true, IsOneWay = false, AsyncPattern = false, Action = "GetAllIncomes", ProtectionLevel = ProtectionLevel.None)]
    CAEService.MessageContracts.GetAllIncomesReponse GetIncomeRecords(CAEService.MessageContracts.GetAllIncomesRequest request);

    [WCF::OperationContract(IsTerminating = false, IsInitiating = true, IsOneWay = false, AsyncPattern = false, Action = "urn:CAEServiceServiceContracts.CAEServiceContract.GetSecurityRecords", ProtectionLevel = ProtectionLevel.None)]
    CAEService.MessageContracts.GetAllSecuritiesResponse GetSecurityRecords(CAEService.MessageContracts.GetAllSecuritiesRequest request);

    //... the rest
  }
}

这是来自客户端调用 GetIncomeRecords 操作的调用:

CAEServiceContractClient client = new CAEServiceContractClient();    

IncomeSearchItem item = new IncomeSearchItem()
{
    aCode = aCode.Text,
    bCode = bCode.Text,
    sCode = sCode.Text,
    secDesc = tbSecurityName.Text,
    status = statusValue != 0 ? statusValue : 0,
    fromDate = fromDate,
    toDate = toDate,
    IncomeID = 0,
    userBank = userBank,
    userId = userId,
    currentRate = currentSourceVal != 0 ? currentSourceVal : 0,
    dateConfirmed = ddDate.SelectedValue,
    pageIndex = pageIdx,
    pageSize = recordsPerPage
};

GetAllIncomesReponse response = new GetAllIncomesReponse();

try
{
    response = client.GetIncomeRecords(item);
    totalRecords = response.TotalRecords;

    incomelist.DataSource = response.IncomeItemColl;
    incomelist.DataBind();

    //.. the rest
}

这是来自另一个项目的一些示例代码,展示了如何使用代理帮助程序。我的服务的问题在于,它期望并返回消息契约,而示例则传入原始类型并返回原始类型或数据集:

public static class ServiceHelper
{
  /// <summary>
  /// Services the verification.
  /// </summary>
  /// <param name="user">The user.</param>
  /// <returns></returns>
  public static string ServiceVerification(string user)
  {
    return WCFProxyHelper<IFCAServices>.Use(client =>
      client.ServiceVerification(user));
  } 
}

那么最快/最简单的方法是什么?如何使 ChannelFactory 知道我的 IncomeSearchItem 以及我需要传递给服务的其他几个对象?我可以/应该使用 svcutil 生成所有对象并在 ChannelFactory 中使用它吗?

I have a WCF service created using the web service software factory. All my incoming requests and returned responses are implemented as message contracts. I had been accessing the service by adding a service reference in VS which worked fine. However I've now been told that this isn't the standard company way and that I need to call the service using an in-house WCF proxy helper class based on the System.ServiceModel.ChannelFactory.

I've never used the ChannelFactory before and I'm struggling to figure out the best way to re-write the client access. The service contract is generated by the service factory and I need to provide the service interface to the proxy helper class. Here's part of the service contract - there's about 25 operations in total on the service:

namespace CAEWCFService.ServiceContracts
{
  /// <summary>
  /// Service Contract Class - CAEServiceContract
  /// </summary>
  [WCF::ServiceContract(Namespace = "urn:CAEServiceServiceContracts", Name = "CAEServiceContract", SessionMode = WCF::SessionMode.Allowed, ProtectionLevel = ProtectionLevel.None )]
  public partial interface ICAEServiceContract 
  {
    [WCF::OperationContract(IsTerminating = false, IsInitiating = true, IsOneWay = false, AsyncPattern = false, Action = "GetAllIncomes", ProtectionLevel = ProtectionLevel.None)]
    CAEService.MessageContracts.GetAllIncomesReponse GetIncomeRecords(CAEService.MessageContracts.GetAllIncomesRequest request);

    [WCF::OperationContract(IsTerminating = false, IsInitiating = true, IsOneWay = false, AsyncPattern = false, Action = "urn:CAEServiceServiceContracts.CAEServiceContract.GetSecurityRecords", ProtectionLevel = ProtectionLevel.None)]
    CAEService.MessageContracts.GetAllSecuritiesResponse GetSecurityRecords(CAEService.MessageContracts.GetAllSecuritiesRequest request);

    //... the rest
  }
}

And here's the call from the client side calling the GetIncomeRecords operation:

CAEServiceContractClient client = new CAEServiceContractClient();    

IncomeSearchItem item = new IncomeSearchItem()
{
    aCode = aCode.Text,
    bCode = bCode.Text,
    sCode = sCode.Text,
    secDesc = tbSecurityName.Text,
    status = statusValue != 0 ? statusValue : 0,
    fromDate = fromDate,
    toDate = toDate,
    IncomeID = 0,
    userBank = userBank,
    userId = userId,
    currentRate = currentSourceVal != 0 ? currentSourceVal : 0,
    dateConfirmed = ddDate.SelectedValue,
    pageIndex = pageIdx,
    pageSize = recordsPerPage
};

GetAllIncomesReponse response = new GetAllIncomesReponse();

try
{
    response = client.GetIncomeRecords(item);
    totalRecords = response.TotalRecords;

    incomelist.DataSource = response.IncomeItemColl;
    incomelist.DataBind();

    //.. the rest
}

Here's some sample code from another project showing how to use the proxy helper. The problem with my service is that it expects and returns message contracts whereas the sample one passes in primitive types and returns primitives or datasets:

public static class ServiceHelper
{
  /// <summary>
  /// Services the verification.
  /// </summary>
  /// <param name="user">The user.</param>
  /// <returns></returns>
  public static string ServiceVerification(string user)
  {
    return WCFProxyHelper<IFCAServices>.Use(client =>
      client.ServiceVerification(user));
  } 
}

So what's the quickest / easiest way to do this? How do I make the ChannelFactory aware of my IncomeSearchItem and several other objects that I need to pass to the service? Can / should I use svcutil to generate all the objects and use that in the ChannelFactory?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

耶耶耶 2024-11-03 11:18:54

您是说“公司方式”是使用服务助手,并且它在内部创建基于 ChannelFactory 的代理 - 或者,您是否想长期创建自己的代理类。这对你有用吗? ServiceHelper 上的扩展方法可以让您继续使用公司方式,但不需要更改 ServiceHelper 来了解您的请求/响应消息或它们包含的任何内容。

using CAEService;
using CAEService.MessageContracts;

public static class ServiceHelperExtensions
{
    public static GetAllIncomesReponse GetIncomeRecords(this ServiceHelper, GetAllIncomesRequest request)
    {
        return WCFProxyHelper<ICAEServiceContract>.Use(client =>
            client.GetAllIncomes(request));
    }
}

然后在客户端代码中,您可以将其替换

 response = client.GetIncomeRecords(item);

为:

response = ServiceHelper.GetIncomeRecords(item);

我认为您还必须使用 SVCUTIL.exe 命令来生成代理类,然后编辑结果,删除代理并仅保留请求/响应类和他们的支持类型。或者,如果您已经在 VS 中完成了“添加服务引用”,则可以单击解决方案资源管理器中的“显示所有文件”选项并深入查看服务引用。这些文件之一包含生成的服务代理及其支持类型,全部位于一个文件中。

Are you saying that the "Company Way" is to use the service helper, and that it internally creates a proxy based on ChannelFactory - or, do you want to create your own proxy class the long way. Would this work for you? An extension method on ServiceHelper would let you stay using the company way, but would not require the ServiceHelper to be changed to know about your request/response messages or anything they contain.

using CAEService;
using CAEService.MessageContracts;

public static class ServiceHelperExtensions
{
    public static GetAllIncomesReponse GetIncomeRecords(this ServiceHelper, GetAllIncomesRequest request)
    {
        return WCFProxyHelper<ICAEServiceContract>.Use(client =>
            client.GetAllIncomes(request));
    }
}

Then in client code, you would replace this:

 response = client.GetIncomeRecords(item);

with this:

response = ServiceHelper.GetIncomeRecords(item);

I think you will also have to use the SVCUTIL.exe command to generate a proxy class, and then edit the result stripping out the proxy and leaving only the request/response classes and their supporting types. Alternatively, if you have already done "Add Service Reference" in VS, you can click the "Show All Files" option in solution explorer and drill into the service reference. One of those files contains the generated service proxy and its supporting types, all in one file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文