WCF入门学习(4)

前言

上一篇的学习中碰到一个问题,用地址http://localhost:8080/mex 访问元数据的时候一直提示400 bad request 错误,因为时间太晚了,查了好几遍代码,也没有发现问题。刚刚又试验了一下,解决方案分两步

①用管理员方式运行vs,

② 将

<serviceMetadata httpGetEnabled="true" />
改成
<serviceMetadata httpGetEnabled="true" httpGetUrl="mex"/>

也就是 我们给他指定一个httpGetUrl,至于为什么这么做,是参考的serviceMetadata

最后,要说关于mex endpoint的作用,通俗的来讲就是只要客户端访问这个地址,他就可以知道关于这个WCF服务一些说明介绍。

第四集 WCF service implementing multiple service contracts

假设有这样的场景,有个公司需要通过http 给外网提供一个公共服务,同时又需要通过tcp协议给公司防火墙内的内容用户提供另一个服务,并且,还不想写多个WCF服务。

所以这一集主要两点,

  • 在一个WCF服务中实现两个contract
  • 通过endpoint配置对外界提供这两个服务 contract

关于如何搭建一个WCF服务,可以参考上一篇,这集只讲一些其他的重点。

首先是新建一个类库,然后添加一个WCF服务项,取名CompanyService。然后打开ICompanyService.cs,删除里面原先的ICompanyService接口,添加如下两个接口。

    [ServiceContract]
    public interface ICompanyPublicService
    {
        [OperationContract]
        string GetPublicInformation();
    }

    [ServiceContract]
    public interface ICompanyConfidentialService
    {
        [OperationContract]
        string GetConfidentialInformation();
    }
解释一下,我们定义了两个合约,一个是公用PublicService ,一个是机密的ConfidentialService,里面分别有各自的GetInformation方法。
然后打开CompanyService.cs 文件,修改里面的CompanyService 类为如下内容:
    public class CompanyService : ICompanyPublicService, ICompanyConfidentialService
    {
        public string GetConfidentialInformation()
        {
            return "这是机密内网的服务";
        }

        public string GetPublicInformation()
        {
            return "这是外网的公共服务";
        }
    }

解释一下,我们的服务名称依旧没有改变,还是CompanyService,但是他实现了上面定义的两个有ServiceContract特性的契约接口。

类定义完毕,然后是配置文件部分。关于整体的配置文件,请看上一篇,下面是完整代码。

  <system.serviceModel>
    <services>
      <service name="Part4.CompanyService" behaviorConfiguration="mexBehavior">
        <endpoint address="CompanyService" binding="basicHttpBinding" contract="Part4.ICompanyPublicService"></endpoint>
        <endpoint address="CompanyService" binding="netTcpBinding" contract="Part4.ICompanyConfidentialService"></endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/"/>
            <add baseAddress="net.tcp://localhost:8090/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors >
        <behavior name="mexBehavior">
          <serviceMetadata httpGetEnabled="true" httpGetUrl="mex"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

因为自己也是初学者,所以在手写的时候还是会碰到一些问题。比如 service节点 的name 属性,表示服务的名字,内容是实现接口的带命名空间的类名;而endpoint里面的contract的名字是定义的时候的带命名空间的接口名字。同时,为了让客户端可以通过添加服务引用的方式来调用,不要忘记了mex endpoint ,以及serviceMetadata元素。

然后新建一个控制台程序,用来托管这个服务。关于如何创建,依旧查看上一篇。启动服务。

完成之后编写客户端代码来调用。

我们新建一个Asp.net 的空网站,然后添加服务引用:

可以看到,CompanyService里面包含了两个服务。点击确定,查看一下网站的web.config 文件。

    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_ICompanyPublicService" />
            </basicHttpBinding>
            <netTcpBinding>
                <binding name="NetTcpBinding_ICompanyConfidentialService" />
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8080/CompanyService" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_ICompanyPublicService"
                contract="CompanyService.ICompanyPublicService" name="BasicHttpBinding_ICompanyPublicService" />
            <endpoint address="net.tcp://localhost:8090/CompanyService" binding="netTcpBinding"
                bindingConfiguration="NetTcpBinding_ICompanyConfidentialService"
                contract="CompanyService.ICompanyConfidentialService" name="NetTcpBinding_ICompanyConfidentialService">
                <identity>
                    <userPrincipalName value="LOUSAIBIAO\Sheldon" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>

这些都是自动生成的代码,用来配合我们客户端的调用。

然后给网站添加一个新页面,拖两个button ,两个label (你们都懂得)大致就这个效果。

编写两个button的点击事件。

    protected void Button1_Click(object sender, EventArgs e)
    {
        //因为有多个endpoint ,所以要指定名字
         var client = new CompanyPublicServiceClient("BasicHttpBinding_ICompanyPublicService");
        Label1.Text = client.GetPublicInformation();
    }
    protected void Button2_Click(object sender, EventArgs e)
    {
        var client = new CompanyConfidentialServiceClient("NetTcpBinding_ICompanyConfidentialService");
        Label2.Text = client.GetConfidentialInformation();
    }

调试运行该网站,并点击按钮,得到如下结果。

至此,实现方面的介绍完毕,有一点要说明的,因为我们是在vs上本机调试,说以,两个button都能获取的数据,但如果是过防火墙的外网来访问,在没有给控制面板中的防火墙添加额外的入站出站规则的时候,GetConfidential 方法是无效的。

介绍完毕,Thank you。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我和PYTHON有个约会

Django来敲门~第一部分【6.2 HTML视图模板】

天下难事必作於易。天下大事必作於细。是以圣人终不为大,故能成其大 ——老子《道德经》

20920
来自专栏零基础使用Django2.0.1打造在线教育网站

利用Flask搭建微电影视频网站(三):前端首页搭建

努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

91310
来自专栏王小雷

Ubuntu16.04安装后开发环境配置和常用软件安装

Ubuntu16.04安装后1.安装常用软件搜狗输入法+编辑器Atom+浏览器Chome+视频播放器vlc+图像编辑器GIMP Image Editor安装+视...

40350
来自专栏魏艾斯博客www.vpsss.net

导入 Avada 模板时出现 php time limit 和 php max input vars 提示怎么办?

网友导入 Avada 模板的时候出现下图这个问题,之前很多网友都遇到过类似问题,好多人用的宝塔面板,在后台能找到修改的可视化界面,而如果是主机商提供的面板就没这...

37120
来自专栏企鹅号快讯

小程序的APPID到底有什么用?小程序问答#3

hello大家好,今天小柳又来给大家解答在小程序的使用过程中,最常出现的问题及疑惑。 Q1 问 小程序的 AppID 是什么东西?有什么用? 答 想要获得 Ap...

44400
来自专栏Linux驱动

23.QT记事本

源码下载地址: https://download.csdn.net/download/qq_37997682/10453294

15130
来自专栏大数据钻研

HTML meta标签总结与属性使用介绍

之前学习前端中,对meta标签的了解仅仅只是这一句。 <metacharset="UTF-8"> 但是打开任意的网站,其head标签内都有一列的meta标签。比...

34560
来自专栏云计算教程系列

如何在Windows 10上安装Ruby并设置本地编程环境

Ruby是一种动态编程语言,可用于编写从简单脚本到游戏和Web应用程序的任何内容。它于1993年首次在日本发布,但在2005年作为服务器端Web开发的语言获得了...

41600
来自专栏Crossin的编程教室

Python 与 Excel 不得不说的事

数据处理是 Python 的一大应用场景,而 Excel 则是最流行的数据处理软件。因此用 Python 进行数据相关的工作时,难免要和 Excel 打交道。 ...

37460
来自专栏前端说吧

Compass(更新中。。。)

26360

扫码关注云+社区

领取腾讯云代金券