复习WCF(4)----- 承载服务
承载服务:
可以在IIS中承载,也可以在托管的应用程序中(自承载,自己承载自己),也可以在windows进程激活服务(WAS)中承载。(话说我现在也不知道WAS是啥,有空去了解下,但是可以知道它比IIS多支持一些协议)
一.IIS中承载
note:IIS5.1和IIS6.0仅限于HTTP通信,IIS7.0可以承载TCP/IP的协议还有命名管道以及MSMQ
如果要在IIS中承载,得安装和注册IIS和WCF以及WCF Http激活组件
IIS和WCF都很容易了,IIS就是在打开或关闭Windows功能里勾选安装,WCF在你装完VS2010就有了
WCF Http激活组件的话 也是在打开或关闭Windows功能里勾选安装 如图所示

接下来用一个内联例子演示 也就是直接在服务文件里面写上服务代码(.svc文件)
项目工程:

service.svc:
<%@ ServiceHost Language="c#" Debug="true" Service="Microsoft.ServiceModel.Samples.CalculatorService" %>
using System;
using System.ServiceModel;
namespace Microsoft.ServiceModel.Samples
{
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Subtract(double n1, double n2);
[OperationContract]
double Multiply(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
}
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2)
{
return n1 + n2;
}
public double Subtract(double n1, double n2)
{
return n1 - n2;
}
public double Multiply(double n1, double n2)
{
return n1 * n2;
}
public double Divide(double n1, double n2)
{
return n1 / n2;
}
}
}
这个例子其实和第二篇文章的例子差不多,分别就是加减乘除然后把结果返回给调用方 很简单
大家注意 因为如果在新建项里选择WCF服务,他生成的文件是有两个,还有一个IService1.cs的接口文件, 我不喜欢这样子 如图:

所以我一般建立svc文件,都是直接右键项目,选择新建项,然后选择文本文件 只是在名字那里写成了xxx.svc
当在svc里写代码的时候 刚写不会有只能提示,等你写完一个using System;之后,就会有智能提示了
web.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<!-- This endpoint is exposed at the base address provided by host: http://localhost/servicemodelsamples/service.svc -->
<endpoint address=""
binding="wsHttpBinding"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
<!-- the mex endpoint is exposed at http://localhost/servicemodelsamples/service.svc/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
大家可以在IIS管理器的"处理程序映射"中看到.svc ,如果没有看到.svc,那就证明开始的WCF Http组件激活是失败的

至此,服务已经完成(服务和配置文件),现在来将他部署到IIS上
部署上去也是非常简单的 就像我们部署asp.net应用程序一样 为了更加详细我就把所有步骤都传上来:



大功告成 现在来测试一下这个服务是否OK,测试方式就是在网页的URL上输入服务的网址
这个网址和平常的asp.net网址没什么区别,比如我的就是http://localhost/ServiceModelSamples/service.svc
你也可以在IIS管理器中选中刚才复制进去的service.svc文件,右键点击选择浏览,也会自动从浏览器中打开
如果没有问题 会出现这个画面:

大家可以看到第一行是 svcutil.exe http://teddy-pc/ServiceModelSamples/service.svc?wsdl
我们可以使用他来生成客户端的代理类和配置文件(当然,也可以在VS工程右键添加服务引用来生成) 现在 打开vs2010的命令提示工具

svcutil.exe:生成的命令 (如果对此命令好奇,可以直接敲此命令不加任何参数回车,他会展示出所有的参数和注释)
/out:cs代码生成路径 (例子中我放在了C盘根目录)
/config:配置文件生成路径 (例子中我放在了C盘根目录)
http://localhost/ServiceModelSamples/service.svc 开始部署在IIS中服务的路径


生成成功
现在我们来使用这个代理类 用控制台程序示例
将生成的文件copy到控制台程序里(这里可能会报错,因为客户端默认不会添加ServiceModel这个程序集,请手动添加)

然后给Main方法写上代码 来测试部署在IIS上的服务是否可行
class Program
{
static void Main(string[] args)
{
//代理类
CalculatorClient client = new CalculatorClient();
double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
value1 = 145.00D;
value2 = 76.54D;
result = client.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
value1 = 9.00D;
value2 = 81.25D;
result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
value1 = 22.00D;
value2 = 7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
client.Close();
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
}

好了 大功告成
二.在Windows进程激活服务(WAS) 中承载
和开始的IIS承载的步骤基本上一样,而且也是承载在IIS上,不同的是他可以支持Http和非Http协议(比如net.tcp)
这次我就不上图了 太麻烦 这文章也会显得很臃肿 具体步骤还是上面的例子 只是某些地方改下:
1.服务工程改为一个svc文件和cs文件,如service.cs和service.svc
svc文件就指定一下,<%@ ServiceHost Language="c#" Debug="true" Service="Microsoft.ServiceModel.Samples.CalculatorService" %>
cs文件就写上服务代码(服务协定和实现服务协定,也就是将上面的单个svc文件分为这两个文件)
配置文件的绑定改为netTcpBinding,当然netTcpBinding这个绑定模式还得设置一下 所以用bindingConfiguration指定下设置 这里上传个代码:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<!-- This endpoint is exposed at the base address provided by host: net.tcp://localhost/servicemodelsamples/service.svc -->
<endpoint binding="netTcpBinding" bindingConfiguration="PortSharingBinding"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
<!-- the mex endpoint is exposed at net.tcp://localhost/servicemodelsamples/service.svc/mex -->
<endpoint address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="PortSharingBinding" portSharingEnabled="true">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
2.重新生成项目,将生成的bin文件夹和svc和config,copy到IIS上添加的应用程序对应的目录下。
3.选择此应用程序 选择高级设置,然后将“已启用的协议”加上net.tcp(如果还要别的协议就用逗号分隔) 如图

4.在生成代理类的时候 命令提示行代码基本一样 唯一不同的是更改服务地址的协议
比如以前是http://teddy-pc/ServiceModelSamples/service.svc 那现在就是net.tcp://teddy-pc/ServiceModelSamples/service.svc
你生成的配置文件中的服务地址也会自动为net.tcp
然后还是一样测试使用
注意:

IIS承载需要勾选红框的第一个
而这个承载需要勾选红框的第二个 反正你都勾了就好了
三.在托管应用程序中承载(自承载)
服务可以承载于任何.net framework应用程序中,自承载服务是最灵活的宿主选项,因为此服务部署所需要的基础结构最少
代码演示:
上面的服务都是wcf项目下建立的,而这个自承载就用应用程序项目,用控制台程序示例 首先创建一个控制台程序

服务端program.cs:
// Copyright (c) Microsoft Corporation. All Rights Reserved.
using System;
using System.Configuration;
using System.ServiceModel;
namespace Microsoft.ServiceModel.Samples
{
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Subtract(double n1, double n2);
[OperationContract]
double Multiply(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
}
//在服务里里面做了些简单的输出 以方便我们看到服务运转的情况
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2)
{
double result = n1 + n2;
Console.WriteLine("服务端运行了!!加");
return result;
}
public double Subtract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("服务端运行了!!减");
return result;
}
public double Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("服务端运行了!!乘");
return result;
}
public double Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("服务端运行了!! 除");
return result;
}
//服务被“自承载”,就是从这里开始
public static void Main()
{
//通过ServiceHost进行自承载
using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService)))
{
//打开、侦听消息
serviceHost.Open();
//Open后就正常运转了
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
}
}
}
}
App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<!--需要指定基址,因为它是自承载的,别人来访问服务,肯定需要一个地址吧-->
<!--端口随便给,但是必须给,而且这个端口必须在计算机中已经打开,不然就访问不到-->
<!--不要搞混了,这不是IIS!!!!-->
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ServiceModelSamples11/service"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
打开8000端口:

现在这个自承载的服务就完成了
客户端和上面也一样 现在示例创建客户端
接下来我们下载元数据(也就是生成代理类)
在生成之前,你必须先把这个自承载的控制台程序先运行起来 不然就无法访问,所以请大家一定搞清楚,他并不是在IIS里~!!

运行起来后,你可以尝试将 http://localhost:8000/ServiceModelSamples11/service/mex输入在浏览器 但是没反应 所以更加确定它是和IIS无关的!!!
有人肯定会想为什么是http://localhost:8000/ServiceModelSamples11/service/mex 上面的例子不都是.svc结束吗
(因为上面都是将一个具体的服务文件xxx.svc承载在IIS里,而现在只是虚拟一下而已)
然后我们生成代理类,和上面一样用svcutil生成,但是注意 路径的最后面是/mex 其余的地方一模一样

后面的就一模一样了
将生成的文件copy到客户端,客户端还是那么几个方法,调用加减乘除,只是在调用的时候会输出结果
客户端Program.cs:
class Program
{
static void Main(string[] args)
{
CalculatorClient client = new CalculatorClient();
double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
value1 = 145.00D;
value2 = 76.54D;
result = client.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
value1 = 9.00D;
value2 = 81.25D;
result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
value1 = 22.00D;
value2 = 7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
client.Close();
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
}
然后可以测试了
因为不能在一个解决方案中同时运行两个程序,我们先把解决方案生成,然后将服务控制台程序设为启动项启动,然后在生成的客户端控制台程序目录双击运行

测试结果:

有兴趣的话,还可以在服务端的控制台程序代码里,设置一个断点自己研究研究
最后,我们来总结一下 承载方式有
1.IIS承载
2.在Windows进程激活服务(WAS) 中承载
3.在托管应用程序中承载(自承载
而1和2其实是差不多的,差不多的地方是都是通过IIS实现
但不同的地方是:虽然都是通过IIS,但IIS只是一个“入口”,最终会使用不同的辅助进程来完成承载
3的话呢,就更简单了,优点在与灵活

浙公网安备 33010602011771号