.NET Core调用WCF的最佳实践

现在.NET Core貌似很火,与其他.NET开发者交流不说上几句.NET Core都感觉自己落伍了一样。但是冷静背后我们要也看到.NET Core目前还有太多不足,别的不多说,与自家的服务框架WCF集成起来就不咋地,从最初不支持,到现在有个笨笨咔咔的Web Service Reference Provider,生成的代理类简直不堪入目,还特别的慢。所以本人本着为将来框架的兼容性做准备,就着手研究了下能不能不通过代理类访问WCF,好在微软开源了一部分WCF代码。

WCF的开发者一定很熟悉,WCF的所有配置都是可以通过代码和配置文件两种方式,而大多数开发者都会选择配置文件,但是从.NET Core开始,微软干掉了Web/App.config,不知道别人怎么样,反正我是非常之不习惯。干掉Web/App.config的后果,就是开源支持.NET Core的那部分Client Side没有配置文件的支持,翻看源码后发现,只要是读取配置文件的地方,都是这样的代码 —— PlatformNotSupported。

protected void InitializeEndpoint(string configurationName, EndpointAddress address)

{

            _serviceEndpoint = this.CreateDescription();


            ServiceEndpoint serviceEndpointFromConfig = null;


            // Project N and K do not support System.Configuration, but this method is part of Windows Store contract.

            // The configurationName==null path occurs in normal use.

            if (configurationName != null)

            {

                throw ExceptionHelper.PlatformNotSupported();

                // serviceEndpointFromConfig = ConfigLoader.LookupEndpoint(configurationName, address, this.serviceEndpoint.Contract);

       }

}

但是好在微软又推出了System.Configuration.ConfigurationManager的NuGet包,所以本人仿照WCF原生的配置文件,自己实现一套配置,经过两个晚上的战斗,已经成功。好了,废话不多说,上代码了。

先看看最终的效果是什么样的,WCF服务端的代码结构如下:

640?wx_fmt=png

采用标准的WCF分层方式,用控制台做宿主,其中IAppService项目版本为.NET Standard 2.0,每个终结点同时使用BasicHttpBinding与NetTcpBinding双重绑定,配置文件如下:

<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <!--WCF配置-->

  <system.serviceModel>

    <!--WCF服务配置,手动增加service节点-->

    <services>

      <!--产品服务配置-->

      <service behaviorConfiguration="DefaultBehavior" name="WCF.AppService.Implements.ProductService">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8098/Hosts/ProductService.svc" />

            <add baseAddress="net.tcp://localhost:8099/Hosts/ProductService.svc" />

          </baseAddresses>

        </host>

        <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="WCF.IAppService.Interfaces.IProductService" />

        <endpoint binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WCF.IAppService.Interfaces.IProductService" />

      </service>

      <!--订单服务配置-->

      <service behaviorConfiguration="DefaultBehavior" name="WCF.AppService.Implements.OrderService">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8098/Hosts/OrderService.svc" />

            <add baseAddress="net.tcp://localhost:8099/Hosts/OrderService.svc" />

          </baseAddresses>

        </host>

        <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="WCF.IAppService.Interfaces.IOrderService" />

        <endpoint binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WCF.IAppService.Interfaces.IOrderService" />

      </service>

      <!--集成服务配置-->

      <service behaviorConfiguration="DefaultBehavior" name="WCF.AppService.Implements.IntegrationService">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8098/Hosts/IntegrationService.svc" />

            <add baseAddress="net.tcp://localhost:8099/Hosts/IntegrationService.svc" />

          </baseAddresses>

        </host>

        <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="WCF.IAppService.Interfaces.IIntegrationService" />

        <endpoint binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WCF.IAppService.Interfaces.IIntegrationService" />

      </service>

    </services>

    <!--WCF行为配置,配置好无需修改-->

    <behaviors>

      <serviceBehaviors>

        <behavior name="DefaultBehavior">

          <!--是否允许get请求访问-->

          <serviceMetadata httpGetEnabled="true" />

          <!--允许从请求消息头中检索元数据地址信息-->

          <useRequestHeadersForMetadataAddress />

          <!--是否显示异常信息-->

          <serviceDebug includeExceptionDetailInFaults="true" />

          <!--最大序列化的对象个数-->

          <dataContractSerializer maxItemsInObjectGraph="2147483647" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

    <!--WCF绑定配置,配置好无需修改-->

    <bindings>

      <netTcpBinding>

        <binding name="tcpBinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" />

      </netTcpBinding>

      <basicHttpBinding>

        <binding name="basicBinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" />

      </basicHttpBinding>

    </bindings>

    <!--WCF多宿主绑定配置-->

    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />

  </system.serviceModel>

</configuration>

运行测试没问题,服务端不多说,重点是客户端,因为IAppService是.NET Standard 2.0的类库版本,所以.NET Core客户端是可以正常引用的,新建.NET Core控制台,并引用上述IAppService项目。

客户端项目结构如下:

640?wx_fmt=png

客户端配置文件如下:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <configSections>

    <!--WCF配置节点-->

    <section name="system.serviceModel" type="System.ServiceModel.ServiceModelSection, System.ServiceModel.Toolkits" />

  </configSections>


  <!--WCF配置-->

  <system.serviceModel>

    <!--WCF客户端配置,手动增加endpoint节点-->

    <client>

      <!--商品服务契约配置-->

      <endpoint address="net.tcp://localhost:8099/Hosts/ProductService.svc" binding="netTcpBinding" contract="WCF.IAppService.Interfaces.IProductService" name="WCF.IAppService.Interfaces.IProductService">

        <headerProvider type="WCF.Core.Client.HeaderProviders.MyHeaderProvider" assembly="WCF.Core.Client"/>

      </endpoint>

      <!--订单服务契约配置-->

      <endpoint address="net.tcp://localhost:8099/Hosts/OrderService.svc" binding="netTcpBinding" contract="WCF.IAppService.Interfaces.IOrderService" name="WCF.IAppService.Interfaces.IOrderService" />

      <!--集成服务契约配置-->

      <endpoint address="net.tcp://localhost:8099/Hosts/IntegrationService.svc" binding="netTcpBinding" contract="WCF.IAppService.Interfaces.IIntegrationService" name="WCF.IAppService.Interfaces.IIntegrationService" />

    </client>

  </system.serviceModel>

</configuration>

Main方法中代码如下:

class Program

    {

        static void Main(string[] args)

        {

            //初始化容器

            IContainer container = InitContainer();


            //调用

            IProductService productService = container.Resolve<IProductService>();

            string products = productService.GetProducts();


            Console.WriteLine(products);


            container.Dispose();

            Console.ReadKey();

        }


        static IContainer InitContainer()

        {

            ContainerBuilder builder = new ContainerBuilder();

            Assembly wcfInterfaceAssembly = Assembly.Load("WCF.IAppService");


            //获取WCF接口类型集

            IEnumerable<Type> types = wcfInterfaceAssembly.GetTypes().Where(type => type.IsInterface);


            //获取服务代理泛型类型

            Type proxyGenericType = typeof(ServiceProxy<>);


            //注册WCF接口

            foreach (Type type in types)

            {

                Type proxyType = proxyGenericType.MakeGenericType(type);

                PropertyInfo propChannel = proxyType.GetProperty(ServiceProxy.ChannelPropertyName, type);


                builder.RegisterType(proxyType).OnRelease(proxy => ((IDisposable)proxy).Dispose());

                builder.Register(container => propChannel.GetValue(container.Resolve(proxyType))).

                    As(type).

                    OnRelease(channel => channel.CloseChannel());

            }


            return builder.Build();

        }

    }

启动运行结果如下:

640?wx_fmt=png

怎么样?是不是觉得很清爽?如果你有兴趣,可以到我的Git看全部源码,地址如下:

https://gitee.com/lishilei0523/WCF-DotNetCore

Ps:因为微软公开的WCF类库本身就不完善,所以我也没法提供全部的功能,本人所作调用方式目前支持BasicHttpBinding和NetTcpBinding,并且包含消息头支持。如果你觉得代码对你有帮助,麻烦点个Star,不胜感激。

欢迎进入我的码云 https://gitee.com/lishilei0523


原文地址:http://www.cnblogs.com/lishilei0523/p/8886483.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321501.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

4、表单提交和验证

1、启用/禁用表单module sbt启动应用时默认就启用了表单&#xff0c;也可以在build.sbt中添加启用libraryDependencies javaForms&#xff0c;想要移除表单时使用PlayMinimalJava 插件 2、play接收表单数据 play.data中的类可用于处理HTTP表单数据提交和验证&#xff0c;操…

【贪心】最佳浏览路线问题

最佳浏览路线问题最佳浏览路线问题最佳浏览路线问题 题目描述 某旅游区的街道成网格状&#xff08;见图&#xff09;&#xff0c;其中东西向的街道都是旅游街&#xff0c;南北向的街道都是林荫道。由于游客众多&#xff0c;旅游街被规定为单行道。游客在旅游街上只能从西向东…

Ooui:在浏览器中运行.NET应用

在过去数年中&#xff0c;桌面应用开发人员一直处境艰难&#xff0c;因为人们的主要关注点聚焦于Web和移动应用。由于Microsoft未来Windows平台的计划未定&#xff0c;并且UWP应用也没有突破性进展&#xff0c;因此技术落伍的责任也不应由.NET开发人员来承担。当前迫切需要解决…

5、play中的json数据处理

1、play中的json库 Play使用Jackson JSON库将对象转换为JSON和JSON之间的对象。play的操作使用JsonNode类型&#xff0c;play.libs.json包中有操作json数据的方法 2、java对象和json数据 将java对象转成play中的JsonNode类型&#xff1a; 将JsonNode格式的数据解析到java对象…

农行基于TFS工具的敏捷转型实践

““春天工程”项目组是应用开发二部最早采用敏捷模式的项目组&#xff0c;项目组在项目推进过程中使用Scrum框架&#xff0c;结合“看板站会”形式&#xff0c;积极探索项目推进新措施。结合TFS工具逐步实现了电子工具与物理看板的有机融合&#xff0c;并在过程管理、版本管理…

6、XML数据处理

1、处理xml请求 两种方式&#xff0c;一是直接将请求体数据转成Document对象&#xff1a; 二是定义自己的解析格式将请求体进行解析&#xff1a; 2、返回xml格式数据响应 设置响应头格式为application/xml类型

.NET Core:新的快速开发平台

.NET Core 今年已经发布了 2.0 版本了。技术雷达最近将 .NET Core 从“评估”移到了“试用”阶段&#xff0c;意味着运用这项技术的风险在不断减小。本文将简要介绍基于 .NET Core 的快速开发的方式。.NET Core 产生于 2014年&#xff0c;是一个不折不扣的新开发平台。SmallTal…

7、play中的文件上传

1、基本的文件上传处理 将form的类型设置成multipart/form-data&#xff0c;请求的方式必须是POST类型&#xff0c;实例如下&#xff1a; 请求发到controller&#xff0c;controller中处理&#xff1a; public Result upload() {MultipartFormData<TemporaryFile> bod…

分布式高性能消息处理中心HPMessageCenter

HPMessageCenter高性能消息分发中心。用户只需写好restful接口&#xff0c;在portal里面配置消息的处理地址&#xff0c;消息消费者就会自动访问相关接口&#xff0c;完成消息任务。&#xff08;其实HPMessageCenter有两个版本&#xff0c;这次开源的是第二个版本。在第一个版本…

8、play框架中持久层操作

1、使用jdbc连接数据库 1、1 简介 JDBC是一个阻塞操作&#xff0c;它将导致线程等待&#xff0c;直接使用JDBC进行查询将导致性能降低 1、2 配置数据源 play提供了一个用于管理JDBC连接池的插件&#xff0c;可以根据需要配置任意多个数据库&#xff0c;想要使用此插件&…

DBCHM-最简单、实用的数据库表列批注维护工具

DBCHM支持SqlServer/MySql/Oracle/PostgreSQL/Sqlite等数据库的表列批注维护管理。DBCHM有以下几个功能表&#xff0c;列的批注可以编辑保存到数据库。表&#xff0c;列的批注支持通过pdm文件导入的方式进行更新到数据库。基于数据库中的表列结构(列ID/列名/数据类型/长度/精度…

浅谈Log4net在项目中如何记录日志

一 引入背景在软件开发周期中&#xff0c;无论是开发中&#xff0c;或是测试中&#xff0c;或是上线后&#xff0c;选择合适的工具监控程序的运行状态至关重要&#xff0c;只有如此&#xff0c;才能更好地排查程序问题和检测程序性能问题等。本篇文章主要与大家分享&#xf…

9、play中缓存的使用

1、简介 对于存储在缓存中的任何数据&#xff0c;都需要放置一个再生策略&#xff0c;以防数据丢失。这一理念是play基本原则之一。对于进程内缓存&#xff0c;Caffeine 通常是最佳选择。如果需要分布式缓存&#xff0c;play提供了Memcached和Redis的第三方插件。 2、添加缓存…

10、使用ws调用Rest api

目录 1、简介 2、添加WS配置 3、发送请求 4、处理请求 5、常用模式和用例 6、自定义BodyReadables和BodyWritables 6、独立WS 7、访问AsyncHttpClient 8、配置WS 1、简介 有时我们想从一个play应用程序中调用其他HTTP服务。Play提供了WS库来进行异步HTTP方法调用。 …

拥抱开源,Office 365 开发迎来新时代

前言作为全球最大的开放源代码托管平台&#xff0c;Github在上周迎来了它的十岁生日。自从2008年正式上线以来&#xff0c;Github上面汇聚了数以千万计的开发人员和各种项目&#xff0c;它几乎成为了开源的代名词和风向标&#xff0c;各大软件巨头都纷纷支持&#xff0c;在广大…

11、OAuth和OpenID服务

1、OAuth 1、1 简介 OAuth是发布受保护数据并与之交互的简单方法。对于人们来说&#xff0c;这也是一种更安全的访问方式。例如&#xff0c;它可以用来访问你的用户在Twitter上的数据。Play仅提供对OAuth 1.0的支持。 1、2 基本工作原理 在build.sbt中添加配置&#xff1a;…

求凸函数极值 CSF迭代法(雾)

简介 本算法用来求解凸函数极值点的问题&#xff0c;由我在写ACM习题时想到&#xff0c;在网上并未找到这样的算法&#xff0c;拿出来给大家分享一下&#xff0c;如果网上没有的话&#xff0c;我决定给它起名叫做 CSF迭代法&#xff0c;如果这个算法早已经存在&#xff0c;那就…

12、play整合Akka

1、简介 Akka使用actor模型来提高抽象级别&#xff0c;并提供一个更好的平台来构建正确的并发和可扩展的应用程序。在容错方面&#xff0c;它采用了“Let it crash”的模式&#xff0c;这种模式在电信行业获得了巨大成功&#xff0c;用于构建永不停止的自我修复系统应用程序。…

ASP.NET Core 添加统一模型验证处理机制

一.前言模型验证自ASP.NET MVC便有提供&#xff0c;我们可以在Model(DTO)的属性上加上数据注解&#xff08;Data Annotations&#xff09;特性&#xff0c;在进入Action之前便会根据数据注解&#xff0c;来验证输入的数据是否合法&#xff0c;下面介绍以下如何统一处理验证并返…

13、play中实现信息国际化

目录 1、指定应用使用的语言 2、语言配置文件 3、在Controller中使用 4、在模板中使用 5、改变当前请求的语言 6、格式化信息 1、指定应用使用的语言 在conf/application.conf中进行配置&#xff1a; 这些语言标记将用于创建play.i18n.Lang实例。要访问应用程序支持的语…