WCF 寄宿方式 代码,配置文件

可以通过代码或者配置文件寄宿WCF服务,在使用过程中的一些心得,记录一下,方便后续查阅。

预备知识,几个地址的作用

1、 behavior.HttpGetUrl  定义元数据的地址,如果不定义基地址,则必须定义HttpGetUrl ,是The absolute or relative location of the metadata.

2、baseAddresses 服务的地址,因为元数据(metadata)是属于一个host的,并不属于一个endpoint。此基地址就是客户端添加服务引用的地址,

所以baseAddress解决了Where to locate the WCF Service?

如果定义endpoint daaress="",则endpoint daaress就等于baseAddresses

3、终结点endpoint address ,用于和客户端通信,服务端与客户端endpoint的address必须严格对应。

4、在这三个地址中如果没有定义基地址则另外两个地址HttpGetUrl,endpoint address必须都不能为空

5、如果定义了baseaddress,则另外两个地址均可为空。此时endpoint address就是baseaddress定义的url

如服务端终结点配置为:

<endpoint address="http://127.0.0.1:8882/DBServer" binding="wsHttpBinding"  contract="IContract.IContract" />

即服务端定义address为"http://127.0.0.1:8882/DBServer" ,那么客户端的终结点address也必须为"http://127.0.0.1:8882/DBServer" 才可以建立通讯。

当我们Host一个WCF Service的时候,我们必须给他定义一个或多个Endpoint,然后service通过这个定义的Endpoint进行监听来自Client端的请求。当我们的Application需要调用这个Service的时候,因为Client 和Service是通过Endpoint的进行通信的, 所以我们必须为我们的Application定义Client端的Endpoint。只有当Client的Endpoint和Service端某个Endpoint相互匹配(Service端可以为一个Service定义多个Endpoint),Client端的请求才能被Service端监听到。也就是说,我们只有在Client具有一个与Service端完全匹配的Endpoint,我们才能调用这个Service。而这种匹配是比较严格的,比如从匹配Address方面,Client端和Service端的Endpoint Address不仅仅在URI上要完全匹配Service, 他们的Headers也需要相互匹配。对于Binding, 一般地,Client需要有一个与Service端完全一样的Binding,他们之间才能通信。

4、如果定义了基地址,则endpoint address可以设为空,这样所有endpoint的address就是基地址所定义的url

以下是一个建立wcf服务及调用的例子

1、新建一个控制台项目,添加以下程序集引用

using System.ServiceModel;
using System.ServiceModel.Web;

2、添加类IContract,只是为了演示,Contract和Service都建在一个项目里面了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace IContract //注意:如果命名空间为WCFHost,则在采用配置文件寄宿服务的时候会不认配置文件,不知道为什么
{
    [ServiceContract]
    public interface IContract
    {
        [OperationContract]
        [WebInvoke(UriTemplate = "Add/{x}/{y}")]
        double Add(double x, double y);

    }

}

 3、添加类DBService

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DBService  //注意:如果命名空间为WCFHost,则在采用配置文件寄宿服务的时候会不认配置文件,不知道为什么
{
    public class DBService:IContract.IContract
    {
        public double Add(double x, double y)
        {
            return x+y;
        }
    }
}

4、使用代码方式配置服务并开启服务,三个地址都进行了定义

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace WCFHost
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //Uri uri = new Uri("http://127.0.0.1:8881/DBServer"); //和下面一句等价
                Uri uri = new Uri("http://localhost:8881/DBServer");

                using (ServiceHost host = new ServiceHost(typeof(DBService.DBService), uri))
                {
                    //定义元数据发布方式,此处  通过在服务所在的URL后加“?wsdl”的方式公布WSDL,可直接通过HTTP访问得到。
                    System.ServiceModel.Description.ServiceMetadataBehavior behavior = new System.ServiceModel.Description.ServiceMetadataBehavior();
                    behavior.HttpGetEnabled = true;
                    //此句也可不要,HttpGetUrl定义元数据的url
                    behavior.HttpGetUrl = new Uri("http://localhost:8882/DBService");
                    host.Description.Behaviors.Add(behavior);

                    Uri endpointAddress =new Uri("http://127.0.0.1:8883/DBServer");

                    //添加终结点
                    host.AddServiceEndpoint(typeof(IContract.IContract), new WSHttpBinding(), endpointAddress);

                    ////定义终结点地址(如果定义了baseadress,终结点地址也可为空)
                    //host.AddServiceEndpoint(typeof(IContract.IContract), new WSHttpBinding(), "");

                    host.Opened += host_Opened;
                    host.Open();
                    Console.ReadLine();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        static void host_Opened(object sender, EventArgs e)
        {
            Console.WriteLine("DBService opened successful");
        }
    }
} 

5、使用配置文件配置服务并开启服务,作用同4

5.1 添加配置文件,配置文件中定义了三个address,基地址(服务地址),元数据地址、与客户端的通讯地址

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:8881/DBServer"></serviceMetadata>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <!--注意此处name必须与第三步服务的命名空间一致-->
      <service behaviorConfiguration="metadataBehavior" name="DBService.DBService">
        <endpoint address="http://127.0.0.1:8882/DBServer" binding="wsHttpBinding"  contract="IContract.IContract" />
        <host>
          <baseAddresses>
            <add baseAddress="http://127.0.0.1:8883/DBServer"/>
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
</configuration>

5.2 开启服务

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace WCFHost
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                ServiceHost host1 = new ServiceHost(typeof(DBService.DBService));
                host1.Opened += host_Opened;
                host1.Open();
                Console.ReadLine();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        static void host_Opened(object sender, EventArgs e)
        {
            Console.WriteLine("DBService opened successful");
        }
    }
}

6、在浏览器中打开服务地址:http://127.0.0.1:8883/DBServer,如下图

打开元数据地址:http://127.0.0.1:8881/DBServer,如下图

客户端添加服务,使用服务地址或者元数据地址均可找到服务。

而终结点地址:http://127.0.0.1:8882/DBServer,无法打开,

7、在客户端调用服务时,定义终结点address必须服务定义的终结点address匹配,如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace WCFClient
{
    class Program
    {
        static void Main(string[] args)
        {
            WSHttpBinding binding = new WSHttpBinding();
            EndpointAddress address = new EndpointAddress(new Uri("http://127.0.0.1:8882/DBServer"));
            ServiceReference1.ContractClient client = new ServiceReference1.ContractClient(binding, address);
            double i = client.Add(1, 2);
            Console.WriteLine(i);
            Console.ReadLine();
        }
    }
}

8、只定义baseAddress,不定义其他两个address

8.1 配置文件定义

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <!--注意此处name必须与第三步服务的命名空间一致-->
      <service behaviorConfiguration="metadataBehavior" name="DBService.DBService">
        <endpoint address="" binding="wsHttpBinding"  contract="IContract.IContract" />
        <host>
          <baseAddresses>
            <add baseAddress="http://127.0.0.1:8883/DBServer"/>
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
</configuration>

  开启服务

                ServiceHost host1 = new ServiceHost(typeof(DBService.DBService));
                host1.Opened += host_Opened;
                host1.Open();
                Console.ReadLine();

  

8.2 代码定义并开启服务

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace WCFHost
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //Uri uri = new Uri("http://127.0.0.1:8881/DBServer"); //和下面一句等价
                Uri uri = new Uri("http://localhost:8881/DBServer");

                using (ServiceHost host = new ServiceHost(typeof(DBService.DBService), uri))
                {
                    //定义元数据发布方式,此处  通过在服务所在的URL后加“?wsdl”的方式公布WSDL,可直接通过HTTP访问得到。
                    System.ServiceModel.Description.ServiceMetadataBehavior behavior = new System.ServiceModel.Description.ServiceMetadataBehavior();
                    behavior.HttpGetEnabled = true;
                    host.Description.Behaviors.Add(behavior);

                    host.AddServiceEndpoint(typeof(IContract.IContract), new WSHttpBinding(), "");

                    host.Opened += host_Opened;
                    host.Open();
                    Console.ReadLine();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        static void host_Opened(object sender, EventArgs e)
        {
            Console.WriteLine("DBService opened successful");
        }
    }
}

  8.3 客户端,直接添加服务引用会自动生成配置文件,然后调用

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IContract" />
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8881/DBServer" binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_IContract" contract="ServiceReference1.IContract"
                name="WSHttpBinding_IContract" />
        </client>
    </system.serviceModel>
</configuration>

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace WCFClient
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceReference1.ContractClient client = new ServiceReference1.ContractClient();

            double i = client.Add(1, 2);
            Console.WriteLine(i);
            Console.ReadLine();

        }
    }
}

  8.4 也可不用配置文件,通过代码直接调用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace WCFClient
{
    class Program
    {
        static void Main(string[] args)
        {

            WSHttpBinding binding = new WSHttpBinding();
            EndpointAddress address = new EndpointAddress(new Uri("http://127.0.0.1:8881/DBServer"));
            ServiceReference1.ContractClient client = new ServiceReference1.ContractClient(binding, address);
            client.Endpoint.Binding = binding;

            double i = client.Add(1, 2);
            Console.WriteLine(i);
            Console.ReadLine();

        }
    }
}

  9、比较WCF发布元数据的两种方式,不管哪种方式ServiceMetadata节点必须存在。

元数据描述服务的细节,导出以及发布元数据,都是由一个服务中的ServiceMetadataBehavior实现的。

必须为服务配置ServiceMetadata行为,即配置节点,才能为发布元数据,才能再使用httpGetEnabled=true或者httpGetEnabled=false发布元数据。

<serviceBehaviors>

<behavior name="metadataBehavior">
      <serviceMetadata  />
   </behavior>
</serviceBehaviors>

9.1 WSDL,此方式通过在服务的URL后加“?wsdl”的方式公布WSDL,可直接通过HTTP访问。

   设置httpGetEnabled="true" 发布元数据(图片见上面步骤6),设置为false不发布元数据。以下为设置为false的情况:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <!--<serviceMetadata httpGetEnabled="true" />-->    <!--设置为true公布元数据,服务可以开启,客户端也可以访问服务-->
          <serviceMetadata httpGetEnabled="false" />  <!--设置为false不公布元数据,服务可以开启,但是客户端无法访问服务-->
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <!--注意此处name必须与第三步服务的命名空间一致-->
      <service behaviorConfiguration="metadataBehavior" name="DBService.DBService">
        <endpoint address="" binding="wsHttpBinding"  contract="IContract.IContract" />
        <host>
          <baseAddresses>
            <add baseAddress="http://127.0.0.1:8883/DBServer"/>
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
</configuration>

设置为false的情况:

  

9.2 MEX:此方式以一般的终结点方式公布,支持各种协议:http、tcp、NamedPipe

注意:以终结点的方式公开的元数据,无法通过浏览器查看元数据内容

添加mex终结点发布元数据,此时httpGetEnabled设置为true和false均可访问服务,只是元数据发布方式不同。

有mex终结点,httpGetEnabled="true",此时服务可以开启,客户端也可以访问服务,元数据以wsdl方式发布。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <serviceMetadata httpGetEnabled="true" />  <!--设置true,则以wsdl方式发布-->
          <!--<serviceMetadata httpGetEnabled="false" />-->  <!--设置false,则以mex方式发布-->
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <!--注意此处name必须与第三步服务的命名空间一致-->
      <service behaviorConfiguration="metadataBehavior" name="DBService.DBService">
        <endpoint address="" binding="wsHttpBinding"  contract="IContract.IContract" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://127.0.0.1:8883/DBServer"/>
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
</configuration>

  

有mex终结点,httpGetEnabled="false",此时服务可以开启,客户端也可以访问服务,元数据以mex方式发布。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <!--<serviceMetadata httpGetEnabled="true" />-->  <!--设置true,则以wsdl方式发布-->
          <serviceMetadata httpGetEnabled="false" />  <!--设置false,则以mex方式发布-->
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <!--注意此处name必须与第三步服务的命名空间一致-->
      <service behaviorConfiguration="metadataBehavior" name="DBService.DBService">
        <endpoint address="" binding="wsHttpBinding"  contract="IContract.IContract" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://127.0.0.1:8883/DBServer"/>
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
</configuration>

  

例子的源代码

 参考:

我的WCF之旅(2):Endpoint Overview

WCF公开服务元数据方式

整理一下思路,探讨WCF(二)

WCF元数据发布的2种方式:httpGetEnabled与mex

WCF 第五章 导出并发布元数据(服务行为)

如何:使用代码发布服务的元数据

《我的WCF之旅》博文系列汇总

时间: 2024-10-17 09:56:11

WCF 寄宿方式 代码,配置文件的相关文章

WCF寄宿方式

WCF开发框架形成之旅---WCF的几种寄宿方式 WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便.高效提供服务调用.本文分别对这几种方式进行详细介绍并开发例子进行说明,以求大家对WCF寄宿的方式进行全面的认识和了解. 1. WCF服务的IIS服务寄宿 我在我前面几篇WCF开发框架的介绍文章中,介绍过了WCF常用的一种寄宿方式,IIS服务寄宿.这种寄宿方式是最为方便的方式,而且由于服务只需要

[转]WCF的几种寄宿方式

转自:WCF开发框架形成之旅---WCF的几种寄宿方式 WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便.高效提供服务调用.本文分别对这几种方式进行详细介绍并开发例子进行说明,以求大家对WCF寄宿的方式进行全面的认识和了解. 1. WCF服务的IIS服务寄宿 我在我前面几篇WCF开发框架的介绍文章中,介绍过了WCF常用的一种寄宿方式,IIS服务寄宿.这种寄宿方式是最为方便的方式,而且由于服务

微软 WCF的几种寄宿方式,寄宿IIS、寄宿winform、寄宿控制台、寄宿Windows服务

WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便.高效提供服务调用.本文分别对这几种方式进行详细介绍并开发例子进行说明,以求大家对WCF寄宿的方式进行全面的认识和了解. 1. WCF服务的IIS服务寄宿 我在我前面几篇WCF开发框架的介绍文章中,介绍过了WCF常用的一种寄宿方式,IIS服务寄宿.这种寄宿方式是最为方便的方式,而且由于服务只需要IIS运行就能自动运行起来,因此广为使用. 创建这

WCF引用方式之IIS方式寄宿服务

通过IIS方式寄宿服务 之前的例子是将控制台作为WCF的寄宿方式或者是直接添加契约项目的引用,然后通过配置或者是ChannelFactory的形式进行创建服务对象,其实在大多的开发中以IIS的形式创建WCF也是比较常见的.每一个Webservice都是具有一个asmx文本文件,客户端通过访问.asmx文件即可实现Webservice的调用.当然WCF和Webservice类似,每一个WCF服务都有一个对应的.svc文本文件.基于IIS服务寄宿要求的WCF服务都具有相应的.svc文件,.svc文件

将WCF寄宿在托管的Windows服务中

在我之前的一篇博客中我介绍了如何发布WCF服务并将该服务寄宿于IIS上,今天我再来介绍一种方式,就是将WCF服务寄宿在Windows服务中,这样做有什么好处呢?当然可以省去部署IIS等一系列的问题,能够让部署更加简单,当然WCF的寄宿方式一般分为以下四种方式,针对每一种方式我来简单介绍以下: 具体的寄宿方式详细信息请参考MSDN:https://msdn.microsoft.com/zh-cn/library/ms733109(v=vs.100).aspx 一.WCF服务寄宿方式: 1):寄宿在

WCF寄宿与IIS里时遇到的问题

[问题总结]WCF寄宿与IIS里时遇到的问题 最近在公司做了一个小的视频处理网站,由于视频处理,网站在不同的服务器上,所以处理视频的时候得在网站服务器上通过wcf请求视频处理服务器处理视频,并将结果返回.我在写好这个wcf服务后寄宿到IIS里时遇到了不少的问题,下面是问题的描述,以及解决的方法. 问题1: 由于我这里的wcf服务是采用“WSHttpBinding”的方式,即安全绑定模式,客户端在引用这个服务后所生成的终结点配置(endpoint )就变成了 <endpoint address=&qu

WCF寄宿(Host)之自我寄宿(Self-Hosting)简单实例【Windows应用程序宿主】

 前言: 以各种应用程序做自我寄宿的宿主原理方法大同小异,故:这儿直接上案例! 步骤一:创建服务契约和服务 1.新建解决方案:添加WCF服务库项目. 2.为了演示,我把自动生成的接口以及实现接口的类删除,自己添加一个WCF Service 3.撰写服务函数(同时,因为将原有的自动生成的接口与类删除了,故而需要将配置文件作相应的改动:) namespace wcfself02{ // NOTE: You can use the "Rename" command on the "

编写WCF服务时右击配置文件无“Edit WCF Configuration”(编辑 WCF 配置)远程的解决办法

原文:编写WCF服务时右击配置文件无“Edit WCF Configuration”远程的解决办法 今天在看<WCF揭秘>书中看到作者提出可以在一个WCF Host应用程序的App.Config文件上右击, 通过弹出的" Edit WCF Configuration”(编辑WCF配置)选项来利用GUI界面编辑WCF的配置信息. 但是我在尝试的时候并没有找到这个右键菜单,开始还以为作者弄错了,但又尝试了一会后便发现了窍门. 右键App.Config文件默认是没有" Edit

WCF学习之旅—WCF寄宿前的准备(八)

一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有"WCF 服务应用程序"和"WCF服务库". WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类协定的定义,可以直接看到运行的效果. WCF服务库,可以认为是一个包含WCF服务以及协定定义的类库.不能直接运行,你可以在其他项目里引用,在宿主里启用托管这个库,有点类似于我们在Web/windows项目中应用的类库.考虑WCF服务设计的时候,服务类的定义为单独的库,可以为其它