1. 什么是REST?
Rest的全称是Representational State Transfer, 普通的WCF使用SOAP,而使用REST构建的WCF服务
使用其他数据传输方式,例如JSON
Rest的四种操作:
- GET - Requests a specific representation of a resource
- PUT - Creates or updates a resource with the supplied representation
- DELETE - Deletes the specified resource
- POST - Submits data to be processed by the identified resource
2. 什么情况下使用REST?
- Less overhead (no SOAP envelope to wrap every call in)
- Less duplication (HTTP already represents operations like
DELETE
,PUT
,GET
, etc. that have to otherwise be represented in a SOAP envelope). - More standardized - HTTP operations are well understood and operate consistently. Some SOAP implementations can get finicky.
- More human readable and testable (harder to test SOAP with just a browser).
- Don't need to use XML (well, you kind of don't have to for SOAP either but it hardly makes sense since you're already doing parsing of the envelope).
- Libraries have made SOAP (kind of) easy. But you are abstracting away a lot of redundancy underneath as I have noted. Yes, in theory, SOAP can go over other transports so as to avoid riding atop a layer doing similar things, but in reality just about all SOAP work you'll ever do is over HTTP.
3. 简单的例子
1) 首先,制作服务契约的接口
IHelloService
using System.ServiceModel;
using System.ServiceModel.Web;
namespace Perseus.WCF.REST.Contract.Service
{
[ServiceContract]
public interface IHelloService
{
[OperationContract]
[WebInvoke(Method = " GET ",
ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = " xml/{name}/{age} ")]
string HelloXml( string name, string age);
[OperationContract]
[WebInvoke(Method = " GET ",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = " json/{name}/{age} ")]
string HelloJson( string name, string age);
}
}
using System.ServiceModel.Web;
namespace Perseus.WCF.REST.Contract.Service
{
[ServiceContract]
public interface IHelloService
{
[OperationContract]
[WebInvoke(Method = " GET ",
ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = " xml/{name}/{age} ")]
string HelloXml( string name, string age);
[OperationContract]
[WebInvoke(Method = " GET ",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = " json/{name}/{age} ")]
string HelloJson( string name, string age);
}
}
2) 然后, 新建一个WCF服务项目,在项目中添加WCF服务文件svc
HelloService.svc
using Perseus.WCF.REST.Contract.Service;
namespace Perseus.WCF.REST.Service
{
public class HelloService : IHelloService
{
public string HelloXml( string name, string age)
{
return " Hello " + name + " "
+ " Your Age: " + age;
}
public string HelloJson( string name, string age)
{
return " Hello " + name + " "
+ " Your Age: " + age;
}
}
}
namespace Perseus.WCF.REST.Service
{
public class HelloService : IHelloService
{
public string HelloXml( string name, string age)
{
return " Hello " + name + " "
+ " Your Age: " + age;
}
public string HelloJson( string name, string age)
{
return " Hello " + name + " "
+ " Your Age: " + age;
}
}
}
3) 配置文件
<?
xml version="1.0"
?>
< configuration >
< connectionStrings >
< add name ="NorthwindConnectionString" connectionString ="Data Source=localhost;Initial Catalog=Northwind;Integrated Security=True" providerName ="System.Data.SqlClient" />
</ connectionStrings >
< system.web >
< compilation debug ="true" targetFramework ="4.0" />
</ system.web >
< system.serviceModel >
< services >
< service name ="Perseus.WCF.REST.Service.HelloService" behaviorConfiguration ="ServiceBehaviour" >
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
< endpoint address ="" binding ="webHttpBinding" contract ="Perseus.WCF.REST.Contract.Service.IHelloService" behaviorConfiguration ="web" >
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
</ endpoint >
</ service >
</ services >
< behaviors >
< endpointBehaviors >
< behavior name ="web" >
< webHttp />
</ behavior >
</ endpointBehaviors >
< serviceBehaviors >
< behavior name ="ServiceBehaviour" >
< serviceMetadata httpGetEnabled ="true" />
< serviceDebug includeExceptionDetailInFaults ="false" />
</ behavior >
< behavior name ="" >
< serviceMetadata httpGetEnabled ="true" />
< serviceDebug includeExceptionDetailInFaults ="false" />
</ behavior >
</ serviceBehaviors >
</ behaviors >
< serviceHostingEnvironment multipleSiteBindingsEnabled ="true" />
</ system.serviceModel >
< system.webServer >
< modules runAllManagedModulesForAllRequests ="true" />
</ system.webServer >
</ configuration >
< configuration >
< connectionStrings >
< add name ="NorthwindConnectionString" connectionString ="Data Source=localhost;Initial Catalog=Northwind;Integrated Security=True" providerName ="System.Data.SqlClient" />
</ connectionStrings >
< system.web >
< compilation debug ="true" targetFramework ="4.0" />
</ system.web >
< system.serviceModel >
< services >
< service name ="Perseus.WCF.REST.Service.HelloService" behaviorConfiguration ="ServiceBehaviour" >
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
< endpoint address ="" binding ="webHttpBinding" contract ="Perseus.WCF.REST.Contract.Service.IHelloService" behaviorConfiguration ="web" >
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
</ endpoint >
</ service >
</ services >
< behaviors >
< endpointBehaviors >
< behavior name ="web" >
< webHttp />
</ behavior >
</ endpointBehaviors >
< serviceBehaviors >
< behavior name ="ServiceBehaviour" >
< serviceMetadata httpGetEnabled ="true" />
< serviceDebug includeExceptionDetailInFaults ="false" />
</ behavior >
< behavior name ="" >
< serviceMetadata httpGetEnabled ="true" />
< serviceDebug includeExceptionDetailInFaults ="false" />
</ behavior >
</ serviceBehaviors >
</ behaviors >
< serviceHostingEnvironment multipleSiteBindingsEnabled ="true" />
</ system.serviceModel >
< system.webServer >
< modules runAllManagedModulesForAllRequests ="true" />
</ system.webServer >
</ configuration >
4) 地址栏调试
http://localhost:7695/HelloService.svc/xml/david/30
返回结果:
<
HelloXmlResponse
xmlns
="http://tempuri.org/"
>
< HelloXmlResult >Hello david Your Age: 30 </ HelloXmlResult >
</ HelloXmlResponse >
< HelloXmlResult >Hello david Your Age: 30 </ HelloXmlResult >
</ HelloXmlResponse >
http://localhost:7695/HelloService.svc/json/david/30
返回结果:
{"HelloJsonResult":"Hello david Your Age: 30"}
5) 编写客户端调用代码
HelloRestTest
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;
using Perseus.WCF.REST.Contract.Service;
namespace Perseus.WCF.Client
{
class HelloRestTest : ITestCase
{
public void Run()
{
Console.Write( " Please Input Your Name: ");
string name = Console.ReadLine();
Console.Write( " Please Input Your Age: ");
string age = Console.ReadLine();
string url = " http://localhost:7695/HelloService.svc ";
using (WebChannelFactory<IHelloService> wcf
= new WebChannelFactory<IHelloService>( new Uri(url)))
{
var channel = wcf.CreateChannel();
IClientChannel clientchanel = channel as IClientChannel;
string result = channel.HelloJson(name, age);
Console.WriteLine(result);
}
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;
using Perseus.WCF.REST.Contract.Service;
namespace Perseus.WCF.Client
{
class HelloRestTest : ITestCase
{
public void Run()
{
Console.Write( " Please Input Your Name: ");
string name = Console.ReadLine();
Console.Write( " Please Input Your Age: ");
string age = Console.ReadLine();
string url = " http://localhost:7695/HelloService.svc ";
using (WebChannelFactory<IHelloService> wcf
= new WebChannelFactory<IHelloService>( new Uri(url)))
{
var channel = wcf.CreateChannel();
IClientChannel clientchanel = channel as IClientChannel;
string result = channel.HelloJson(name, age);
Console.WriteLine(result);
}
}
}
}
运行结果:
Hello david Your Age: 30