在IIS中承载
WCF可以方便的通过IIS承载。此承载模型与ASP.NET和ASP.NET Web Service使用的模型类似。
可以在一下操作系统上的IIS版本上承载WCF
—— Windows XP SP2上的IIS 5.1
—— Windows Server 2003上的 IIS 6.0
—— Windows Vista(Windows 7)和Windows Server 2008 上的 IIS 7.0
IIS7
用Wndows进程激活服务(WAS:Windows process Activation Service)来允许通过HTTP之外的协议进行激活和网络通信。此环境适合开发通过WCF支持的任何网络协议(包括HTTP、net.tcp、net.pipe和net.msmq)进行通信的WCF服务。这是之前的IIS 5.1 6.0所做不到的。
IIS承载的好处:
1) 可以像处理其他任何类型的IIS应用程序(包括ASP.NET应用程序和ASMX)一样,部署和管理IIS中承载的WCF服务。
2) IIS提供进程激活、运行状况管理和回收功能以提高承载的应用程序的可靠性。
3) 像ASP.NET一样,ASP.NET中承载的WCF服务可以利用ASP.NET共享宿主模型。在此模型中,多个应用程序驻留在一个公共辅助进程中以提高服务器密度和可伸缩性。
4) IIS中承载的WCF服务于ASP.NET 2.0使用相同的动态编译模型,(也就是说可以使用内联代码来开发WCF服务,它在访问的时候编译并且运行)该模型简化了承载的服务的开发和部署。
5) 当决定在IIS中承载WCF服务时,一定要记住IIS 5.1和IIS 6.0 仅限于HTTP通信。只有IIS 7才支持WAS,WAS中就包含了NET.TCP、NET.PIPE和NET.MSMQ通信方式。
部署IIS承载的WCF服务
1. 请确保正确安装和注册IIS和WCF以及WCF HTTP激活组件。安装方式有一下两种:
第一种:在CMD(Windows 命令处理程序)里输入一下字符串后点回车安装:
第二种:控制面板\程序\程序和功能 里把一下HTTPActivation check上点确定安装。
Demo演示: 在IIS中承载WCF服务,并且在客户端应用程序中调用该WCF服务
这例子是使用内联代码来写的例子,就是直接在这个服务文件里写入我们的服务代码。
1) 新建一个WCF Service Application,然后删除IService1.cs和Service.svc.cs文件,在删除Service1.svc里的头文件的“CodeBehind="Service1.svc.cs" ,然后再下面添加以下WCF服务代码:
<%@ServiceHost language=c# Debug="true" Service="Microsoft.ServiceModel.Samples.CalculatorService" %>
// Copyright (c) Microsoft Corporation. All Rights Reserved.
using System;
using System.ServiceModel;
namespace Microsoft.ServiceModel.Samples
{
// Define a service contract.
[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);
}
// Service class which implements the service contract.
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;
}
}
}
2) 服务的配置文件如下:注意这里必须要有mex类型的address,只有有了元数据,才会在客户端生成相应的代理类。
<?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>
3)由于是内联代码,所以这里也不需要编译,直接把这两个文件拷贝到:C:\inetpub\wwwroot\servicemodelsamples 里。然后再IIS里“添加应用程序”:
4)设定应用程序参数:
5)最后可以在浏览器里输入该WCF地址(http://localhost/ServiceModelSamples/Service.svc)查看是否添加成功,注意我们的访问的Service.svc这个是由我们的文件名决定的,也就是拷贝到servicemodelsamoles文件夹里的.svc文件名决定的。这里由于使用的是HTTP协议来承载,所以要用HTTP://协议:
这里的 svcutil.exe 是指使用这个文件来得到当前服务的元数据。
有时候可能会出现错误信息:
Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceMode
这个时候需要用管理员权限打开CMD, 重新注册一下 asp.net 4.0:下面的是说客户端如何调用该WCF服务的例子。
6)通过该WCF页面告诉我们的元数据的方法(svcutil.exe http://eric-pc.tycofs.com/ServiceModelSamples/service.svc?wsdl),来测试一下,看看生成一个什么样的代码:
通过Svcutil.exe工具生成代理类调用:
1. 找到如下地址“C:\Windows\System32\cmd.exe”命令行工具,右键以管理员身份运行(WIN7系统下)。
2. 输入如下命令:“cd C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin”进入到svcuitl.exe工具所在的文件夹下。然后再输入一下代码生成代理类:
svcutil.exe /out:c:/ClientCode.cs /config:c:/app.config http://localhost/ServiceModelSamples/Service.svc
3.按回车进行生成客户端代理类,如果出现一下提示,则证明代理类生成成功:
利用svcutil这个命令行工具(该工具在:"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\SvcUtil.exe"里(WIN7系统)),
4. 可以到C盘根目录下看到生成的客户端代理类以及配置文件,这样就可以把代理类和配置文件使用到客户端项目中进行调用WCF服务使用了。
7)如果不适用svcutil这个命令其实也是可以生成代理类以及配置文件的,下面来讲一下如何在控制台应用程序中调用WCF服务(WCF服务部署在IIS上的情况)使用:
1. 新建一个控制台应用程序,然后再Service References里添加服务,添加服务的配置如下:
这里的Address里的WCF服务,是我们上面所部署在IIS上的WCF服务,点击GO即可搜到服务,然后双击添加到该控制台应用程序中。
2. 添加完WCF服务互,就可以在Main方法中调用该WCF方法了,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Video4.Demo1.ServiceReference1;
namespace Video4.Demo1
{
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);
Console.ReadKey();
}
}
}
源代码: http://download.csdn.net/detail/eric_k1m/6319093
在Windows进程激活服务(WAS)中承载
如果不只是使用HTTP协议的话(如使用NET.TCP/NET.PIPE等)的时候,必须使用WAS中承载WCF服务。
IIS 7.0的模型图:WAS与WWW Service提供ASP.NET应用程序和ASP.NET Web Servce服务是并列的。
所有去处理运行应用程序,是在辅助进程里进行。
Windows进程激活服务(WAS)管理辅助进程的激活和生存期,该辅助进程包含WCF服务的应用程序。
WAS进程模型通过移除对HTTP的依赖性使得HTTP服务器的IIS 6.0进程模型通用化。可以向HTTP一样来进行其他协议的部署。
允许WCF服务在宿主环境中同时使用HTTP和非HTTP协议(如NET.TCP),该宿主环境支持基于消息的激活并提供在给定计算机上承载大量应用程序的能力。
基于消息的应用程序激活和辅助进程应用程序会动态地启动和停止,以响应使用HTTP和非HTTP网络协议送达的传入工作项。
可靠的应用程序和辅助进程回收可以使应用程序保持良好的运行状态。
集中的应用程序配置和管理,可以使用IIS管理工具来部署WCF服务。
允许应用程序利用IIS进程模型,而无需完全IIS安装的部署需求量。如果我们只要WAS进程激活来承载WCF的话,IIS就可以使用很轻量级的,不需要HTTP等服务。
部署该服务步骤:
1)Windows进程激活服务(WAS)安装位置在:控制面板\程序\
2)然后使用APPCMD来把新的协议绑定到默认的网站上,或者是绑定到某一个应用程序上,让IIS支持我们所要的协议,也可以是用IIS管理工具可视化的修改:
3)创建一个具有要使用的网络协议绑定的WAS站点,或者向现有站点添加新协议绑定。
4)创建一个应用程序以承载服务,并使该应用程序可以使用所需的网络协定。
5)生成一个公开的非HTTP终结点的WCF服务。
DEMO2 Windows进程激活(WAS)承载WCF服务:
1)新建一个“WCF Service Application”类型的项目,删除自动生成的Iservice1和Service1文件,手动添加一个“WCF Service”类型的文件“Service.svc”,这里我们来做一个TCPIP协议的演示,这里我们使用了一个后端类,服务文件(service.svc)只是做了一个标记,这里的CalculatorServce就是后端类:
<%@ServiceHost language="c#" Debug="true" Service="Microsoft.ServiceModel.Samples.CalculatorService" %>
2)WCF服务接口和实现类和上面的DEMO是样的。在ICalculatorService.cs文件里输入:
namespace Video4.Demo2.TcpActivation
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ICalculatorService" in both code and config file together.
[ServiceContract(Namespace = "http://Video4.Demo2.TcpActivation")]
public interface ICalculatorService
{
[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);
}
}
在CalculatorService.svc.cs里输入:
namespace Video4.Demo2.TcpActivation
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "CalculatorService" in code, svc and config file together.
public class CalculatorService : ICalculatorService
{
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;
}
}
}
3)这里不一样的是Web.config配置文件,这个binding使用的"net.TcpBinding",对netTCP做属性的配置是在bindingConfiguration的PortSharingBinding里做设置。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="Video4.Demo2.TcpActivation.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="Video4.Demo2.TcpActivation.ICalculatorService"/>
<!-- 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>
4) 然后再去确定是否在Windows功能里选中打开了“Windows Communication Foundation Non-HTTP Activation”选项。这就是非HTTP激活的选项。
5)打开IIS管理器,一下里确认是否添加有了“net.tcp”等非HTTP选项的协定。只有勾选了上面的选项后,才能在这里看的到非HTTP协议。
并且在站点里,默认也不是不会打开非HTTP协议的,我们需要手动输入的在如下选项里添加NET.TPC协议。
6) 把项目building后生成的“bin文件夹”,以及CalculatorService.svc服务文件和web.config配置文件拷贝到应用程序目录(C:\inetpub\wwwroot\TestService)里。
7) 在IIS管理器里添加应用程序“TestService”,这里主要一定要在高级设置里添加上面所说的"net.tcp"协议。
8) 然后就可以打开IE来测试一下该服务部署是否成功,在IE里输入“http://localhost/TestService/CalculatorService.svc”访问服务,正常情况下是会打开回下界面,这里可以看到该服务的传输协协议是net.tcp的:
8) 同样的也可以按照DEMO1所讲的使用SVCUITL.exe的控制台程序生成客户端代理类。注意这里地址参数要用net.tcp协议的。还要注意移动要用管理员模式打开CMD.exe否则由于权限问题不会生成代理类及配置文件:
也可以在客户端的Service Reference里Add Service Reference的时候输入:net.tcp://10.47.142.55/testservice/calculatorservice.svc/mex 来自动找到该WCF服务:
9) 在该解决方案中添加一个控制台应用程序“Client”项目,然后把上面生成的WCF代理类TcpipClientCode.cs和配置文件App.config都添加到该项目中,并且引用“System.ServiceModel”和“System.Runtime.Serialization”用于序列化。然后再Main方法中调用WCF代理类的方法进行测试调用WCF服务的方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Client
{
class Program
{
static void Main(string[] args)
{
CalculatorServiceClient client = new CalculatorServiceClient();
double value1 = 1.00D;
double value2 = 2.00D;
double result = client.Add(value1 , value2);
Console.WriteLine(result);
Console.ReadKey();
}
}
}
源代码: http://download.csdn.net/detail/eric_k1m/6337989
在托管应用程序中承载(自承载)
服务可以承载于任何.NET Framework应用程序中。自承载服务是最灵活的宿主选项,因此次服务部署所需要的基础结构最少。但是,此服务也是最不可靠的宿主选项。
使用Windows控制台程序来制作WCF服务,因为安全级别低,这样翻遍我们进行调试测试。这种方法不需要IIS来承载WCF服务,也不需要其他的协议安全等设置。
DEMO3 自承载:
1) 这里的自承载是使用一个控制台应用程序来承载WCF服务,新建一个控制台应用程序,然后再该控制台程序里添加WCF服务代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace Video4.Demo3.SeltHost
{
[ServiceContract(Namespace = "http://Video4.Demo3.SeltHost")]
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("Received Add({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Subtract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("Received Subtract({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
}
class Program
{
static void Main(string[] args)
{
//ServiceHost类是通过自承载的一个服务类Create a ServiceHost for the CalculatorService type.
using(ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService)))
{
// Open the ServiceHost to create listeners and start listening for messages.
//打开WCF服务开始侦听WCF消息
serviceHost.Open();
Console.WriteLine("The Service is ready");
Console.WriteLine("Press [Enter] to terminate service");
Console.WriteLine();
Console.ReadLine();
}
}
}
}
2) 添加该WCF服务的配置文件(Application Configuration File类型的):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Video4.Demo3.SeltHost.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior">
<!--通过baseAddress来让客户端通过这个地址访问我们的服务-->
<host>
<baseAddresses>
<!--定义的地址是随意性的,端口也是随意性的,但是所指定的端口号必须要打开才行。通过Windows防火墙来查看是否打开-->
<add baseAddress="http://localhost:8000/SeltHost/CalculatorService"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="Video4.Demo3.SeltHost.ICalculator"/>
<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>
3) 确认是否打开了baseAddres里设定的端口,如果没打开则手动设置打开,如果关闭了windows防火墙的话可以忽略这项。
4) 这个时候运行该控制台程序还是会报错 "HTTP could not register URL",这是由于WIN7 权限问题导致的,还需要用”管理员身份“打开CMD.EXE后,在输入一下代码,打开权限:
C:\Windows\system32>netsh http add urlacl url=http://+:8000/SeltHost/CalculatorService user=TYCOFS\xkjin
该命令结构为: netsh http add urlacl url=http://+:8000/服务名 user=DOMAIN\UserName
打开后结构如下:
这个时候在运行该WCF控制台服务则可以正常运行了。
5) 添加一个客户端的调用WCF服务的控制台程序,添加app.config以及服务代理类。而且可以在WCF服务上设置断点,当客户端调用WCF服务的时候就会进入到断点,这就表明自承载有利于测试使用。(这里还没实现)
源代码 :http://download.csdn.net/detail/eric_k1m/6338381