(转载)如何创建restful wcf

  • 原文:http://www.cnblogs.com/wuhong/archive/2011/01/13/1934492.html
  • REST

          表述性状态转移(Representational State Transfer,REST),不是一种标准,而是一种软件架构风格。

          基于REST的服务与基于SOAP的服务相比,性能、效率和易用性上都更高,而SOAP协议非常的复杂和不透明。REST受到越来越多的Web服务供应商欢迎。目前大部分供应商,如yahoogoogleAmazon等都提供REST风格的服务。

    •   REST的主要原则是:

       1.网络上的所有事物都可被抽象为资源;

       2.每个资源都有一个唯一的资源标识符URI;

       3.使用标准方法操作资源;

       4.所有的操作都是无状态的;

       5.通过缓存来提高性能。

        

          REST是基于Http协议的,任何对资源的操作行为都是通过Http协议来实现。Http把对一个资源的操作限制在4个方法以内:GET、POST、PUTDELETE,这正是对资源CRUD操作的实现。

          REST的资源表述形式可以是XMLHTMLJSON,或者其他任意的形式,这取决于服务提供商和消费服务的用户。

           

          但是REST不是万能的。操作无状态也会带来巨大的安全问题,如何授权和验证用户?如果要求每次请求都包含完整的身份和验证信息,又如何避免信息泄漏?复杂的功能挑战架构的易用性,这就需要在性能与功能间权衡,究竟该用REST还是SOAP。

        

    • WebHttpBinding

            WebHttpBinding允许开发人员通过 HTTP 请求(这些请求使用“Plain old XML”(POX) 样式消息,而不是使用基于 SOAP 的消息)来公开 Web 服务,可以很便利的实现REST

            与其他绑定不同的是:必须使用WebHttpBehavior对服务的终结点进行配置。还要求使用WebGetAttributeWebInvokeAttribute属性将各个服务操作映射到 URI,同时定义调用和返回结果的消息格式。

             

    • 服务契约

            先定义服务契约。

            这里提供两个方法,分别采用GETPOST方式访问。

            我们可以看到,与普通WCF服务契约不同的是,需要额外用WebGet或者WebInvoke指定REST访问的方式。另外还要指定消息包装样式和消息格式,默认的消息请求和响应格式为XML,若选择JSON需要显式声明。 
             UriTemplate用来将方法映射到具体的Uri上,但如果不指定映射,将映射到默认的Uri。比如采用Get访问的GetUser方法,默认映射是:/GetUser?Name={Name}&Position={Position}。
    IContract
     1 namespace Rest.Contract
     2 {
     3     [DataContractFormat]
     4     [ServiceContract]
     5     public interface ITest
     6     {
     7         //[WebGet(UriTemplate = "/User/Get/{Name}/{Position}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
     8          [WebGet(UriTemplate = "/User/Get/{Name}/{Position}", BodyStyle = WebMessageBodyStyle.Bare)]
     9         [OperationContract]
    10         List<User> GetUser(string Name, string Position);
    11 
    12         //[WebInvoke(Method = "POST", UriTemplate = "/User/Create", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
    13          [WebInvoke(Method = "POST", UriTemplate = "/User/Create", BodyStyle = WebMessageBodyStyle.Bare)]
    14         [OperationContract]
    15         Result CreateUser(User u);
    16     }
    17 
    18     [DataContract(Namespace = "http://rest-server/datacontract/user")]
    19     public class User
    20     {
    21         [DataMember]
    22         public long ID { get; set; }
    23 
    24         [DataMember] 
    25         public string Name { get; set; }
    26 
    27         [DataMember]
    28         public int  Sex { get; set; }
    29 
    30         [DataMember]
    31         public string Position { get; set; }
    32 
    33         [DataMember]
    34         public string Email { get; set; }
    35     }
    36 
    37     [DataContract(Namespace = "http://rest-server/datacontract/result")]
    38     public class Result
    39     {
    40         [DataMember]
    41         public string Value { get; set; }
    42     }
    43 
    44 }
    45  

    • 服务端

            这里最简单的实现GetUserCreateUser两个方法的逻辑,关注点不在这里。

    namespace Rest.Service
     2 {
     3     public class Test : ITest
     4     {
     5         /// <summary>
     6         /// GET
     7         /// </summary>
     8         /// <param name="Name"></param>
     9         /// <param name="Position"></param>
    10         /// <returns></returns>
    11          public List<User> GetUser(string Name, string Position)
    12         {
    13             List<User> userList = List.Where(u => u.Name == Name && u.Position == Position).ToList();
    14 
    15             return userList;
    16         }
    17 
    18         /// <summary>
    19         /// POST
    20         /// </summary>
    21         /// <param name="u"></param>
    22         /// <returns></returns>
    23          public Result CreateUser(User u)
    24         {
    25             Result result = new Result();
    26             
    27             if (!List.Any(user => user.ID == u.ID))
    28                 List.Add(u);
    29 
    30             result.Value = u.ID.ToString();
    31 
    32             return result;
    33         }
    34 
    35         /// <summary>
    36         /// 测试数据
    37         /// </summary>
    38          private static List<User> List
    39         {
    40             get
    41             {
    42                 List<User> list = new List<User>{
    43                     new User{
    44                         ID = 19735,
    45                         Name = "wuhong",
    46                         Sex = 1,
    47                         Position = "engineer",
    48                         Email = "star_2345@qq.com"
    49                     }
    50                 };
    51 
    52                 return list;
    53             }
    54         }
    55     }
    56 }
    57  

       服务端的配置文件中只有一个特别处,必须使用WebHttpBehavior对服务的终结点进行配置。

    Web.Config
     1   <system.serviceModel>
     2     <bindings>
     3       <webHttpBinding>
     4         <binding name="webBinding">
     5         </binding>
     6       </webHttpBinding>
     7     </bindings>
     8     <services>
     9       <service name="Rest.Service.Test" behaviorConfiguration="testServiceBehavior">
    10         <endpoint address="" behaviorConfiguration="webBehavior" 
    11                   binding="webHttpBinding" bindingConfiguration="webBinding" contract="Wuhong.Rest.Contract.ITest">
    12         </endpoint>
    13       </service>
    14     </services>
    15     <behaviors>
    16       <endpointBehaviors>
    17         <behavior name="webBehavior">
    18           <!--这里必须设置-->
    19           <webHttp />
    20         </behavior>
    21       </endpointBehaviors>
    22       <serviceBehaviors>
    23         <behavior name="testServiceBehavior">
    24         </behavior>
    25       </serviceBehaviors>
    26     </behaviors>
    27   </system.serviceModel>
    28  

    • 客户端

           为了强调REST的通用性,客户端不用WCF的形式调用服务,而是用另外两种通用的方式:

           一是用C#编程直接HTTP访问,消息格式我们选XML

             二是用jquery实现GETPOST访问,消息格式我们选JSON。

       

             先实现C#方式,我们封装一个Client类,实现HTTP的GET和POST方式。

    Client类
     1 namespace Rest.Client
     2 {
     3     public class RestClient
     4     {
     5         /// <summary>
     6         /// 构造函数
     7         /// </summary>
     8         /// <param name="baseUrl"></param>
     9          public RestClient(string baseUri)
    10         {
    11             this.BaseUri = baseUri;
    12         }
    13 
    14         /// <summary>
    15         /// 基地址
    16         /// </summary>
    17          private string BaseUri;
    18 
    19         /// <summary>
    20         /// Post调用
    21         /// </summary>
    22         /// <param name="data"></param>
    23         /// <param name="uri"></param>
    24         /// <returns></returns>
    25          public string Post(string data, string uri)
    26         {
    27             //Web访问对象
    28              string serviceUrl = string.Format("{0}/{1}", this.BaseUri, uri);
    29             HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(serviceUrl);
    30 
    31             //转成网络流
    32              byte[] buf = UnicodeEncoding.UTF8.GetBytes(data);
    33 
    34             //设置
    35              myRequest.Method = "POST";
    36             myRequest.ContentLength = buf.Length;
    37             myRequest.ContentType = "text/html";
    38 
    39             // 发送请求
    40              Stream newStream = myRequest.GetRequestStream();
    41             newStream.Write(buf, 0, buf.Length);
    42             newStream.Close();
    43 
    44             // 获得接口返回值
    45              HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
    46             StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
    47 
    48             string ReturnXml = HttpUtility.HtmlDecode(reader.ReadToEnd());
    49 
    50             reader.Close();
    51             myResponse.Close();
    52 
    53             return ReturnXml;
    54         }
    55 
    56         /// <summary>
    57         /// Get调用
    58         /// </summary>
    59         /// <param name="uri"></param>
    60         /// <returns></returns>
    61          public string Get(string uri)
    62         {
    63             //Web访问对象
    64              string serviceUrl = string.Format("{0}/{1}", this.BaseUri, uri);
    65             HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(serviceUrl);
    66 
    67             // 获得接口返回值
    68              HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
    69             StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
    70 
    71             string ReturnXml = HttpUtility.UrlDecode(reader.ReadToEnd());
    72 
    73             reader.Close();
    74             myResponse.Close();
    75 
    76             return ReturnXml;
    77         }
    78 
    79     }
    80 }
    81  

    下面是主函数,按顺序调用两个接口,并显示返回值。需要注意XML约定的命名空间:

    Client Main函数
     1 namespace Rest.Client
     2 {
     3     class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             //初始化
     8              RestClient client = new RestClient(ClientConfiguration.ServiceUrl);
     9 
    10             //Get
    11              string uriGet = string.Format("User/Get/{0}/{1}", "wuhong", "engineer");
    12             string retGet = client.Get(uriGet);
    13 
    14             Console.WriteLine(retGet);
    15 
    16             //Post
    17              string uriPost = "User/Create";
    18             string data = "<User xmlns=\"http://rest-server/datacontract/user\"><ID>19735</ID><Name>wuhong</Name><Sex>1</Sex><Position>engineer</Position><Email>star_2345@qq.com</Email></User>";
    19  
    20             string retPost = client.Post(data, uriPost);
    21 
    22             Console.WriteLine(retPost);
    23 
    24             Console.ReadLine();
    25         }
    26     }
    27 
    28 }
    29  

    •  结果:

    • 接下来实现javascript方式。

            这里采用jquery访问REST服务,为了javascript操作数据的便利,消息格式选择JSON,可以忽略数据契约的命名空间。不过需要服务契约做一点修改,显式指定请求或响应消息的格式,例如: 

    1 [WebInvoke(Method = "POST", UriTemplate = "User/Create", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]

    Html 代码: 
    js client代码
     1 <html>
     2     <head>
     3         <script src="jquery-1.3.2.min.js" type="text/javascript"></script>
     4         <script type="text/javascript">
     5             function HttpGet() {
     6                 $.get( http://doxt-wuhong/Wuhong.Rest.Web/TestService.svc/User/Get/wuhong/engineer ,
     7                 function(data) {
     8                     $("#TextGet").val(data);
     9                 });
    10             }
    11             function HttpPost() {
    12                 var str = "{ \"Email\": \"star_2345@qq.com\", \"ID\": 19735, \"Name\": \"wuhong\", \"Position\": \"engineer\", \"Sex\": 1 }";
    13                 $.ajax({
    14                     type: "POST",
    15                     contentType: "application/json",
    16                     url:  http://doxt-wuhong/Wuhong.Rest.Web/TestService.svc/User/Create,
    17                     data: str,
    18                     success: function(data) {
    19                         $("#TextPost").val(data);
    20                     }
    21                 });
    22             }
    23         </script>
    24         <style type="text/css">
    25             #TextGet
    26             {
    27                 width: 700px;
    28             }
    29             #TextPost
    30             {
    31                 width: 700px;
    32             }
    33         </style>
    34     </head>
    35     <body>
    36         <input id="ButtonGet" type="button" value="GET" οnclick="HttpGet()" />
    37         <input id="TextGet" type="text" />
    38         <p/>    
    39         <input id="ButtonPost" type="button" value="POST" οnclick="HttpPost()" />
    40         <input id="TextPost" type="text" />
    41     </body>
    42  </html>
    43  

    •    结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值