转自:https://www.cnblogs.com/huangxincheng/p/4669120.html
在我们玩wcf的时候,都会潜意识的觉得wcf就是通过soap协议交换消息的,并且可以在basic,tcp,msmq等等绑定中任意切换,
牛逼的一塌糊涂,但是呢,如果说哪一天wcf不再使用soap协议,而是采用json格式的字符串,是不是有一点颠覆你对wcf的认识的???
从传统意义上说,wcf是非常重量级的,很明白的一个例子就是太多太多的配置,尤其是Behavior的配置,而且behavior对wcf来说又是重
中之重,它对wcf的扩展和性能又是最重要的,可恨的是wcf在binding,behavior,contract之中的配置又是非常非常的保守,可以说用
wcf来玩分布式,这些默认配置是完全做不到的,就比如说basicbinding的基类HttpBindingBase。
抱怨的话我也不说了,可能微软也觉得这个问题是个不小的问题,然后就有了轻量级的 asp.net web api,你可以看到它和wcf比起来精
简多了,也许让我们这些码农更加的专注于业务吧,既然wcf带了这玩意,我也得必须约谈一下。
一:UriTemplate
要说rest,还得先说UriTemplate,因为wcf用UriTemplate来做rest中的uri模板匹配,然后用WebInvoke这个OperationBehavior
插入到wcf的心脏中,说的玄乎一点,这个就有点像mvc中的路由匹配机制,下面我举个例子:
1. 用UriTemplate来告知可以监视的完整Url
从下面的图中,可以看到三个元素:服务地址,模板,入参(这里面的”1“),这三个元素组合在一起,就构成了完整的remote url,
然后这个完整的url就是我模板(/User/{id})监视的对象。
2. 通过UriTemplate来解析url中的参数。
既然可以构建url,那当然可以解析url啦,对吧,下面这张图可以很清晰的告知你,当外来的url=http://127.0.1:1920/HomeService
/User/1过来的时候应该被哪个uriTemplate所接收。
正是因为UriTemplate具有这样的url构建和解析能力,所以wcf就把UriTemplate作为WebInvoke和WebGet这两个属性的参数来动态
解析外来的url,然后根据这个url分配到具体的服务方法上,下面我们具体看一看。
二:WebGet,WebInvoke的使用
刚才也说了,WebGet和WebInvoke正是用了UriTemplate,才具有了路由转向的功能,还有就是默认返回的是xml,这里就用json
值作为服务返回的格式
1 [ServiceContract]
2 public interface IHomeService
3 {
4 [OperationContract]
5 [WebGet(UriTemplate = "Get/{id}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
6 Student Get(string id);
7
8 [OperationContract]
9 [WebInvoke(Method = "POST", UriTemplate = "Add", RequestFormat = WebMessageFormat.Json,
10 ResponseFormat = WebMessageFormat.Json)]
11 string Add(Student stu);
12 }
对了,Rest推荐使用Http协议中的Get,Post,Delete,Put来作为CURD的状态机制,然后就是你如果看懂了UriTemplate,那你现在应
该知道这个Template在监视什么类型的url。做完了上面的coding,下面我们需要在webconfig中通过behavior来指定启动“web编程模型”,
就比如下面这样。
1 <?xml version="1.0" encoding="utf-8"?>
2 <configuration>
3
4 <system.diagnostics>
5 <sources>
6 <source name="System.ServiceModel" switchValue="ActivityTracing">
7 <listeners>
8 <add name="mylisteners" type="System.Diagnostics.XmlWriterTraceListener" initializeData="E:\1.txt" />
9 </listeners>
10 </source>
11 <source name="System.ServiceModel.MessageLogging" switchValue="ActivityTracing">
12 <listeners>
13 <add name="messagelogging" type="System.Diagnostics.XmlWriterTraceListener" initializeData="E:\2.txt"/>
14 </listeners>
15 </source>
16 </sources>
17 <trace autoflush="true"/>
18 </system.diagnostics>
19
20 <system.serviceModel>
21
22 <diagnostics>
23 <messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtTransportLevel="true" />
24 </diagnostics>
25
26 <behaviors>
27 <serviceBehaviors>
28 <behavior>
29 <serviceMetadata httpGetEnabled="true" />
30 <serviceDebug includeExceptionDetailInFaults="true" />
31 </behavior>
32 </serviceBehaviors>
33 <endpointBehaviors>
34 <behavior name="webbehavior">
35 <webHttp />
36 </behavior>
37 </endpointBehaviors>
38 </behaviors>
39
40 <services>
41 <service name="MyService.HomeService">
42 <endpoint address="HomeService" binding="webHttpBinding" behaviorConfiguration="webbehavior"
43 contract="MyService.IHomeService">
44 <identity>
45 <dns value="localhost" />
46 </identity>
47 </endpoint>
48 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
49 <host>
50 <baseAddresses>
51 <add baseAddress="http://127.0.0.1:1920" />
52 </baseAddresses>
53 </host>
54 </service>
55 </services>
56
57 </system.serviceModel>
58
59 </configuration>
其实呢?也就是代码中的WebHttpBehavior类
好了,我现在服务地址也出来了:http://127.0.0.1:1920 ,然后服务方法的template也指定了。只要http.sys监控到了template
匹配的url,服务方法就会被执行,比如我现在在浏览器里面输入:http://127.0.0.1:1920/HomeService/Get/1 来测试下Get操作。
可以看到,get方法成功了,也正确的匹配了我的服务方法Get。
1 public class HomeService : IHomeService
2 {
3 public Student Get(string id)
4 {
5 return new Student() { ID = Convert.ToInt32(id), Name = "hxc", SNS = "001" };
6 }
7
8 public string Add(Student stu)
9 {
10 return "hello";
11 }
12 }
然后我们看看Add方法,我在HttpWebRequest中模拟测试如下。
View Code
好了,大概就说这么多了,如果说你不嫌麻烦,你可以用WCF Rest,还有就是不要忘了很多的默认配置,如果你觉得太繁琐,
可以用用asp.net web api。