您的位置:首页 > 其它

构建一个简单的WCF应用

2013-04-13 09:43 579 查看
本应用的功能虽然简单,但它具有一个完整的WCF应用的基本结构。应用实现一个简单的计算服务来提供基本的加、减、乘、除运算。

1、构建整个解决方案

创建一个空白的解决方案WcfServices,并添加如下项目:

(1)Service.Interface:用于定义服务契约(Service Contract)的类库项目,引用WCF的核心程序集System.ServiceModel.dll。

(2)Service:用于定义服务类型的类库项目。由于服务类型需要实现定义在Service.Interface中的相应的契约接口,因此该项目具有Service.Interface项目引用。

(3)Hosting:作为服务寄主的控制台应用。该项目同时引用Service.Interface、Service项目和System.ServiceModel.dll程序集。

(4)Client:一个控制台应用模拟服务的客户端,该项目引用System.ServiceModel.dll程序集。

2、创建服务契约

在Service.Interface项目中创建ICalculator.cs接口类。

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

namespace Service.Interface
{
[ServiceContract]
public interface ICalculator
{
[OperationContract]
double Add(double x, double y);

[OperationContract]
double Subtract(double x, double y);

[OperationContract]
double Multiply(double x, double y);

[OperationContract]
double Divide(double x, double y);
}
}


3、创建服务



在Service项目中创建CalculatorService.cs类,并实现ICalculator接口

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

namespace Service
{
public class CalculatorService:ICalculator
{
public double Add(double x, double y)
{
return x + y;
}

public double Subtract(double x, double y)
{
return x - y;
}

public double Multiply(double x, double y)
{
return x * y;
}

public double Divide(double x, double y)
{
return x / y;
}
}
}


4、通过自我寄宿的方式寄宿服务

WCF服务需要依存一个运行着的宿主进程,服务寄宿就是为服务指定一个宿主的过程。

在Hosting项目中创建MyServiceHost.cs类,这里分别以:代码编写、读取XML服务配置的形式创建寄宿服务。

4.1 通过代码编写创建服务程序

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using Service;
using Service.Interface;

namespace Hosting
{
/// <summary>
/// 服务寄宿类
/// </summary>
public class MyServiceHost : IDisposable
{
public ServiceHost myHost;    //服务
private const string serviceAddressUrl = "http://127.0.0.1:3721/CalculatorService";    //服务地址
private const string serviceMetadataUrl = "http://127.0.0.1:3721/CalculatorService/metadata";    //元数据发布的源地址

/// <summary>
/// 初始化
/// </summary>
public MyServiceHost()
{
ConstructSericeHost();
}

/// <summary>
/// 创建服务通过代码方式
/// </summary>
public void ConstructSericeHost()
{
//1、初始化ServiceHost对象
myHost = new ServiceHost(typeof(CalculatorService));

//2、添加一个终结点(终结点由:地址、绑定、契约组成)
Uri address = new Uri(serviceAddressUrl);    //地址
Binding binding = new BasicHttpBinding();    //绑定
Type serviceType = typeof(ICalculator);      //契约
myHost.AddServiceEndpoint(serviceType, binding, address);

//3、添加元数据发布行为
if (myHost.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
{
ServiceMetadataBehavior metadataBehavior = new ServiceMetadataBehavior();
metadataBehavior.HttpGetEnabled = true;
metadataBehavior.HttpGetUrl = new Uri(serviceMetadataUrl);
myHost.Description.Behaviors.Add(metadataBehavior);
}
}

/// <summary>
/// 打开服务
/// </summary>
public void Open()
{
Console.WriteLine("开始启动服务...");
myHost.Open();
Console.WriteLine("服务已启动...");
}

/// <summary>
/// 关闭服务
/// </summary>
public void Dispose()
{
if (myHost != null)
{
(myHost as IDisposable).Dispose();
Console.WriteLine("服务已关闭...");
}
}
}
}

4.2 通过读取XML服务配置创建服务程序

4.2.1 编写App.config配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Service.CalculatorService"
behaviorConfiguration="metadataBehavior">
<endpoint address="http://127.0.0.1:3721/CalculatorService"
binding="basicHttpBinding"
contract="Service.Interface.ICalculator"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="metadataBehavior">
<serviceMetadata httpGetEnabled="true"
httpGetUrl="http://127.0.0.1:3721/CalculatorService/metadata"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>


4.2.2 修改MyServiceHost.cs类中的方法

如果采用读取XML配置的形式,服务寄宿代码将会得到极大的精简。

/// <summary>
/// 创建服务通过读取XML方式
/// </summary>
public void ConstructSericeHost()
{
//初始化ServiceHost对象
myHost = new ServiceHost(typeof(CalculatorService));
}


4.3 运行服务

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using Service;
using Service.Interface;

namespace Hosting
{
class Program
{
static void Main(string[] args)
{
try
{
//由于MySerivceHost实现了IDisposable接口,所以使用using
using (MyServiceHost host = new MyServiceHost())
{
host.Open();
Console.Read();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.Read();
}
}
}
}


5、创建客户端调试服务

5.1 导出服务代理相关代码和相应的配置

服务被成功寄宿后,服务端便开始了服务调用请求的监听。借助代码生成工具(SvcUtil.exe)自动生成服务调用的服务代理相关代码和相应的配置。

(1)获取服务代理相关代码(CalculatorService.cs)

//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本:2.0.50727.4984
//
//     对此文件的更改可能会导致不正确的行为,并且如果
//     重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ICalculator")]
public interface ICalculator
{

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ICalculator/Add", ReplyAction="http://tempuri.org/ICalculator/AddResponse")]
double Add(double x, double y);

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ICalculator/Subtract", ReplyAction="http://tempuri.org/ICalculator/SubtractResponse")]
double Subtract(double x, double y);

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ICalculator/Multiply", ReplyAction="http://tempuri.org/ICalculator/MultiplyResponse")]
double Multiply(double x, double y);

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ICalculator/Divide", ReplyAction="http://tempuri.org/ICalculator/DivideResponse")]
double Divide(double x, double y);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface ICalculatorChannel : ICalculator, System.ServiceModel.IClientChannel
{
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class CalculatorClient : System.ServiceModel.ClientBase<ICalculator>, ICalculator
{

public CalculatorClient()
{
}

public CalculatorClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}

public CalculatorClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}

public CalculatorClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}

public CalculatorClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}

public double Add(double x, double y)
{
return base.Channel.Add(x, y);
}

public double Subtract(double x, double y)
{
return base.Channel.Subtract(x, y);
}

public double Multiply(double x, double y)
{
return base.Channel.Multiply(x, y);
}

public double Divide(double x, double y)
{
return base.Channel.Divide(x, y);
}
}
(2)获取相应的配置(App.config)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ICalculator" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://127.0.0.1:3721/CalculatorService" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ICalculator" contract="ICalculator"
name="BasicHttpBinding_ICalculator" />
</client>
</system.serviceModel>
</configuration>


5.1 通过代码创建客户端

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

namespace Client
{
class Program
{
static void Main(string[] args)
{
//使用代码设置信息
BasicHttpBinding bind = new BasicHttpBinding();
bind.Security.Mode = BasicHttpSecurityMode.None;
EndpointAddress edp = new EndpointAddress("http://127.0.0.1:3721/CalculatorService");
CalculatorClient client = new CalculatorClient(bind, edp);
double result = client.Add(3, 4);
client.Close();
Console.Write(result);
Console.Read();
}
}
}


5.2 通过读取配置方式创建客户端

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

namespace Client
{
class Program
{
static void Main(string[] args)
{
//使用读取配置方式创建客户端
CalculatorClient client = new CalculatorClient("BasicHttpBinding_ICalculator");
double result = client.Add(3, 7);
client.Close();
Console.Write(result);
Console.Read();
}
}
}

6、通过IIS寄宿服务

前面演示了将控制台应用作为服务寄主的自我寄宿方式,下面来演示如何将IIS作为服务的寄主。

6.1 创建Web应用

创建名为WcfService的web应用程序。

(1) 创建.svc文件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Service.Interface;

namespace WcfService
{
// 注意: 如果更改此处的类名 "CalculatorService",也必须更新 Web.config 中对 "CalculatorService" 的引用。
public class CalculatorService : ICalculator
{
public double Add(double x, double y)
{
return x + y;
}

public double Subtract(double x, double y)
{
return x - y;
}

public double Multiply(double x, double y)
{
return x * y;
}

public double Divide(double x, double y)
{
return x / y;
}
}
}
(2) 在Web.config中添加服务配置
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WcfService.CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="WcfService.CalculatorServiceBehavior"
name="WcfService.CalculatorService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration=""
contract="Service.Interface.ICalculator">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
</configuration>


(3)将网站部署到IIS

6.2 客户端调用服务

(1)导出服务代理相关代码和相应的配置

通过地址:svcutil.exe http://localhost:11477/CalculatorService.svc?wsdl,借助代码生成工具导出服务代理相关代码和相应的配置。
得到服务代理相关代码和相应的配置后,客户端的调用就与本文上述的调用方式是一样的。

(本文的实例参考于蒋金楠老师的《WCF全面解析》书中的例子)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: