zoukankan      html  css  js  c++  java
  • [转]十五天精通WCF——第十三天 用WCF来玩Rest

      

            在我们玩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中模拟测试如下。

     1    class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             Run();
     6         }
     7 
     8 
     9         /// <summary> 
    10         /// 报告系统错误 
    11         /// </summary> 
    12         /// <param name="ex"></param> 
    13         /// <returns></returns> 
    14         public static void Run()
    15         {
    16             HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://127.0.0.1:1920/HomeService/Add");
    17             Encoding encoding = Encoding.UTF8;
    18 
    19             string param = new JavaScriptSerializer().Serialize(new { ID = "10", Name = "hxc", SNS = "001" });
    20             byte[] bs = Encoding.ASCII.GetBytes(param);
    21 
    22             string responseData = String.Empty;
    23             req.Method = "POST";
    24             req.ContentType = "application/json";
    25             req.ContentLength = bs.Length;
    26             using (Stream reqStream = req.GetRequestStream())
    27             {
    28                 reqStream.Write(bs, 0, bs.Length);
    29                 reqStream.Close();
    30             }
    31             using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
    32             {
    33                 using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
    34                 {
    35                     responseData = reader.ReadToEnd().ToString();
    36                 }
    37             }
    38         }
    39     }
    View Code

    好了,大概就说这么多了,如果说你不嫌麻烦,你可以用WCF Rest,还有就是不要忘了很多的默认配置,如果你觉得太繁琐,

    可以用用asp.net web api。

  • 相关阅读:
    iis 部署网站常见问题
    提高你开发效率的十五个Visual Studio 2010使用技巧
    SQL SERVER 错误代码 0x534
    SQL Server2005修改计算机名后不能发布订阅
    Fedora桌面系统Idea中的部分中文无法显示解决
    最近去滴滴面试的一道题:斐波拉契数列非递归实现
    二叉查找树之红黑树
    二叉查找树之AVL树
    二叉查找树
    再看SpringMVC通过一个DispatcherServlet处理Servlet
  • 原文地址:https://www.cnblogs.com/go-jzg/p/6281888.html
Copyright © 2011-2022 走看看