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之旅》博文系列匯總
總結
以上是生活随笔為你收集整理的WCF学习之三, 寄宿方式 代码,配置文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 便携式土壤取样钻用于土壤剖面采样和土壤原
- 下一篇: The 12 Months of the