wcf 服务创建,配置,测试

时间:2021-08-14 16:16:32

一.WCF创建:

常规的创建WCF服务是通过SOAP传输的,很多网站开发人员想放弃使用XML而使用JSON,这个时候可以参照:http://www.cnblogs.com/zhili/p/WCFRestService.html?utm_source=tuicool&utm_medium=referral

WCF 3.5中对Rest服务做了支持。WCF在System.ServiceModel.Web组件中新增了ResT编程,Rest编程有两个主要的新属性: WebGetAttribute 和 WebInvokeAttribute ,还有一个URI模板机制,帮助你声明每种方法响应使用的URI和动词。.NET Framework还提供了一个新的绑定(WebHttpBinding)和新的行为(WebHttpBehavior),此外,还提供了WebServiceHost和WebServiceHostFactory类来对Rest服务进行支持。

以前我们都是把WCF服务抽象为操作的概念,而Rest最早是由Roy Thomas Fielding 在他的博士论文( “体系结构风格和基于网络软件体系的设计 ”)中提出的。Rest服务是将服务抽象为资源,每个资源都有一个唯一的统一资源标识符(URI),我们不再是通过调用操作的方式与服务进行交互了,而是通过HTTP标准动词(GET、POST、PUT和DELETE)的统一接口来完成。总之一句话概括,Rest服务换了一种思维方式,把服务也当成一种资源,通过Get、Post、Put和Delete这些HTTP动词来进行交互。这样,问题就来了,Rest服务具有什么好处呢?即我们为什么要去关注Rest和实现它呢?

Rest优势就在于其使用极其简单,Rest服务要求很少的编码工作量,可以减少很多不必要的工作。Rest服务主要有以下优点:

  • 无需引入SOAP消息传输层,轻量级和高效率的HTTP格式可直接被应用。
  • 可以轻易地在任何编程语言中实现,尤其是在JS中。使用SOAP的服务与JS交互非常繁琐,而使用Rest服务与JS交互非常简单。
  • 可以不使用任何编程语言就能访问服务,而只需要使用Web浏览器即可。
  • 更好的性能和缓存支持。使用Rest服务可以改善响应时间和改善用户体验。
  • 可扩展性和无状态性。Rest服务基于HTTP协议,每个请求都是独立的,一旦被调用,服务器不保留任何会话,这样可以更具响应性,通过减少通讯状态的维护工作来提供服务的可扩展性。

Rest和SOAP比较:

REST目前只基于HTTP和HTTPS协议,而SOAP可支持任何传输协议,包括HTTP/HTTPS、TCP、SMTP等协议。另外Rest服务除了能使用XML作为数据承载外,还有JSON,RSS和 ATOM 形式。

Rest与SOAP对应的比较如下所示:

  1. SOAP是一种工业标准,面对的应用需求时RPC(远程过程调用),而Rest面对的应用需求是分布式Web系统。
  2. Rest服务强调数据,请求和响应消息都是数据的封装,而SOAP服务更强调接口,SOAP消息封装的是过程调用。Rest是面向资源的,而SOAP是面向接口的。
  3. Rest架构下,HTTP是承载协议,也是应用协议,而SOAP架构下,HTTP只是承载协议,SOAP才是应用协议。

那在什么情况下使用Rest,什么情况下使用SOAP呢?这要看具体的实际情况。具体应用场景如下所示:

  • 远程调用用SOAP。如果服务是作为一种功能提供,客户端调用服务是为了执行一个功能,用SOAP,比如常见的需求是认证授权。而数据服务用Rest。
  • 要更多的考虑非功能需求时使用SOAP,如需考虑安全、传输和协议等需求的情况下。
  • 低带宽、客户端的处理能力受限的场合可以考虑使用Rest。如在PDA或手机上消费服务。

第一步:创建Rest服务接口和实现。

[ServiceContract(Namespace ="http://www.cnblogs.com/zhili/")]//也可以不加直接通过服务url作为地址
public interface IEmployees
{
// 契约操作不再使用操作契约的方式来标识,而是使用WebGetAttribute特性来标识,从而表明该服务是Rest服务
//[OperationContract]//Rest可以不适用OperactionContract标识
[WebGet(UriTemplate = "all")]
//[WebGet(UriTemplate = "all", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
IEnumerable<Employee> GetAll(); [WebGet(UriTemplate = "{id}")]
////[WebGet(UriTemplate = "MySplit/{id}", Method = "POST" ,ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
Employee Get(string id); [WebInvoke(UriTemplate="/", Method="PUT")]
void Create(Employee employee); [WebInvoke(UriTemplate = "/", Method = "POST")]
void Update(Employee employee); [WebInvoke(UriTemplate = "/", Method = "DELETE")]
void Delete(string id);
}
//[Serializable],如果不是使用SOAP协议,可以不加
[DataContract(Namespace = "http://www.cnblogs.com.zhili/")]
public class Employee
{
//注意:对外访问的数据属性必须保证其get和set都是public,不然,数据传输不了的
[DataMember]
public string Id { get; set; } [DataMember]
public string Name { get; set; } [DataMember]
public string Department { get; set; }
}

从上面代码可以看出,Rest服务不再使用OperactionContract的方式来标识操作了,此时在Rest架构下,每个操作都被当做一种资源对待,所以这里的操作使用了WebGetAttribute特性和WebInvokeAttribute来标识。下面具体看看契约的具体实现,即Rest服务的实现代码。实现服务的代码就不加了。

第二步:实现Rest服务宿主。这里还是使用控制台程序来作为宿主程序

namespace RestServiceHost
{
class Program
{
static void Main(string[] args)
{
// Rest服务使用WebServiceHost类来为服务提供宿主
using (WebServiceHost webHost = new WebServiceHost(typeof(EmployeesService)))
{
webHost.Opened += delegate
{
Console.WriteLine("Rest Employee Service 开启成功!");
}; webHost.Open();
Console.Read();
}
}
}
}

对应的配置文件内容如下所示:

<configuration>
<system.serviceModel>
<services>
<service name="WCFContractAndService.EmployeesService">
<!--这里Rest服务只能使用WebHttpBinding来作为绑定-->
<endpoint address="http://localhost:9003/employeeService"
binding="webHttpBinding" contract="RestContract.IEmployees"/>
</service>
</services>
</system.serviceModel>
</configuration>

第三步:实现Rest服务调用客户端。这里通过通道工厂的方式来创建代理对象的

namespace WCFClient
{
class Program
{
static void Main(string[] args)
{
using (ChannelFactory<IEmployees> channelFactory = new ChannelFactory<IEmployees>("employeeService"))
{
// 创建代理类
IEmployees proxy = channelFactory.CreateChannel(); Console.WriteLine("所有员工信息:"); // 通过代理类来对Rest服务进行操作
Array.ForEach<Employee>(proxy.GetAll().ToArray(), emp => Console.WriteLine(emp.ToString())); Console.WriteLine("\n添加一个新员工{0003}:");
proxy.Create(new Employee
{
Id = "", Name="李四", Department="财务部"
}); Array.ForEach<Employee>(proxy.GetAll().ToArray(), emp => Console.WriteLine(emp.ToString())); Console.WriteLine("\n修改员工(0003)信息:");
proxy.Update(new Employee
{
Id = "", Name="李四", Department = "销售部"
});
Array.ForEach<Employee>(proxy.GetAll().ToArray(), emp => Console.WriteLine(emp.ToString()));
Console.WriteLine("\n删除员工(0002)信息:");
proxy.Delete("");
Array.ForEach<Employee>(proxy.GetAll().ToArray(), emp => Console.WriteLine(emp.ToString())); Console.Read();
}
}
}
}

客户端对应的配置文件内容如下所示:

<configuration>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint name="employeeService" address="http://localhost:9003/employeeService" binding="webHttpBinding" behaviorConfiguration="webBehavior" contract="RestContract.IEmployees"> </endpoint>
</client>
</system.serviceModel>
</configuration>

二.WCF配置文件

配置也是WCF编程中的主要组成部分。在以往的.net应用程序中,我们会把DBConn和一些动态加载类及变量写在配置文件里。但WCF有所不同。他指定向客户端公开的服务,包括服务的地址、服务用于发送和接收消息的传输和消息编码,以及服务需要的安全类型等。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel> <!--配置服务和终结点开始-->
<services>
<service>
<endpoint></endpoint>
</service>
</services>
<!--配置服务和终结点结束--> <!--配置绑定开始-->
<bindings>
<netTcpBinding>
<binding>
</binding>
</netTcpBinding>
</bindings>
<!--配置绑定结束--> <!--配置行为开始-->
<behaviors>
<!--endpointBehaviors在Rest时候用,也可以不配置,可以加入一些自定义的,*发挥-->
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
</behavior>
</serviceBehaviors>
</behaviors>
<!--配置行为结束--> </system.serviceModel>
</configuration>

     Service配置节[必须有]:配置服务、接口和终结点。每个Service都会有以下两个属性。name:名称空间.类名[服务的具体实现类]。behaviorConfiguration:一个在behaviors节点中找到的名称。

  Binding配置节[可有可无]:配置绑定,如http,tcp等

  Behavior配置节[可有可无]:配置行为,如认证等。

//附一个各种自定义配置的,英文基本代表了各个意思
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding0" 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>

三.WCF测试:

调试:将Web.config中的 <webHttp /> 修改为 <webHttp helpEnabled="true" />,将可以在浏览器页面中列举出可用接口,并提供提交的数据样例。打开IE浏览器,在地址栏输入:http://localhost:3000/MyService.svc/help 即可。

1) 使用微软VisualStuio的wcf测试客户端(\Common7\IDE\WcfTestClient.exe):

wcf 服务创建,配置,测试

双击接口方法名,输入参数,测试。

2) 借用chrome扩展工具PostMan测试(Rest方式,也可以直接在地址栏输入地址)

wcf 服务创建,配置,测试