本文將通過一個簡單的實例,介紹如何創建一個Rest服務接口,以及通過JQUERY去對它進行調用;主要采取兩種方式分別為Get跟Post;其中將通過Post提交簡單類型(Sring)以及復雜類型(自定義實現UserModel)與Rest服務進行交互;
一 Rest服務創建
其中Web客戶端(ClintWeb)不對其它層的引用,只通過Rest部署后的服務進行效互;
1:實體層(Model)
using System.Runtime.Serialization; namespace Model { [DataContract] public class UserModel { [DataMember] public int ID { get; set; } [DataMember] public string UserName { get; set; } [DataMember] public string PassWord { get; set; } [DataMember] public int Age { get; set; } public override string ToString() { return string.Format("ID:{0};姓名: {1};年齡:{2};密碼:{3}",ID, UserName, Age, PassWord); } } }
此處要注意[DataContract],[DataMember]在命名空間using System.Runtime.Serialization下面;
2:接口層(IServiceInterface)
using System.ServiceModel.Web; using System.ServiceModel; using Model; namespace IServiceInterface { [ServiceContract] public interface IUser { [WebGet(UriTemplate = "/{ID}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] UserModel GetUserFromID(string ID); [WebGet(UriTemplate = "All", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)] List<UserModel> GetAllUser(); [WebInvoke(UriTemplate = "/User/UserName", Method = "POST", RequestFormat = WebMessageFormat.Json,ResponseFormat=WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)] String GetUserName(string Name); [WebInvoke(UriTemplate = "/User/Post", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)] string UpdateUser(UserModel model); } }
3:邏輯層(ServiceBll)
using IServiceInterface; using Model; namespace ServiceBll { public class UserBll:IUser { public static List<UserModel> GetUserList() { List<UserModel> list = new List<UserModel>() { new UserModel(){ID=1,UserName="踏浪帥",PassWord="123456",Age=27}, new UserModel(){ID=2,UserName="wujunyang",PassWord="345678",Age=30}, new UserModel(){ID=3,UserName="cnblogs",PassWord="987654",Age=33} }; return list; } public UserModel GetUserFromID(string ID) { UserModel item = GetUserList().Where(a => a.ID == int.Parse(ID)).SingleOrDefault(); if (item != null) { return item; } else { return new UserModel(); } } public List<UserModel> GetAllUser() { return GetUserList(); } public string UpdateUser(UserModel model) { return model.ToString(); } public String GetUserName(string Name) { return "您好:" + Name; } } }
后面創建的客戶端傳參數要跟上面各個方法的參數相同,比如:Name,model等
4:Rest服務(RestService)
此處新建一個文本文件把它修改成.svc格式,在其里面寫入:
<%@ ServiceHost Language="C#" Debug="true" Service="ServiceBll.UserBll" %>
web.config文件內容:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="webHttp"> <webHttp helpEnabled="true"/> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior name="MapConfigBehavior"> <!-- 為避免泄漏元數據信息,請在部署前將以下值設置為 false 並刪除上面的元數據終結點 --> <serviceMetadata httpGetEnabled="true"/> <!-- 要接收故障異常詳細信息以進行調試,請將以下值設置為 true。在部署前設置為 false 以避免泄漏異常信息 --> <serviceDebug includeExceptionDetailInFaults="true"/> <dataContractSerializer maxItemsInObjectGraph="2147483647"/> </behavior> </serviceBehaviors> </behaviors> <bindings> <webHttpBinding> <binding name="webHttpBindConfig" receiveTimeout="00:30:00" sendTimeout="00:30:00" maxReceivedMessageSize="104857600"> <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"/> <security mode="None"></security> </binding> </webHttpBinding> </bindings> <services> <service name="ServiceBll.UserBll" behaviorConfiguration="MapConfigBehavior"> <endpoint binding="webHttpBinding" contract="IServiceInterface.IUser" bindingConfiguration="webHttpBindConfig" behaviorConfiguration="webHttp"/> </service> </services> </system.serviceModel> </configuration>
通過上面的代碼我們便簡單完成一個Rest服務的創建,接着我們把它發布在IIS里面;進一步可以為客戶端進行調用做准備;
二 客戶端Web調用服務
客戶端主要運用JQUERY的Ajax進行服務調用;
1:通過Get方式進行調用返回單個實例的JSON:
$.ajax({ type: "get", contentType: "application/json; charset=utf-8", url: "http://localhost:8089/WcfRestService.svc/1", success: function (userInfo) { alert("用戶名:" + userInfo.UserName + " 密碼:" + userInfo.PassWord + " 年齡:" + userInfo.Age); }, error: function (error) { alert("出錯:" + error.responseText); } });
運行效果:
2:通過Get方式進行調用返回列表實例的JSON
$.ajax({ type: "get", contentType: "application/json; charset=utf-8", url: "http://localhost:8089/WcfRestService.svc/All", success: function (userlist) { $.each(userlist.GetAllUserResult, function (item, value) { alert(value.ID + "|" + value.UserName + "|" + value.PassWord + "|" + value.Age); }) } });
運行效果:
![]() |
![]() |
![]() |
其中要注意要從結果userlist.GetAllUserResult進行循環,我們可以能過IE的F12進行查看,不難發現是跟我們接口服務名稱有關的 對應接口名稱+Result 此處我們的定義接口名稱為GetAllUser
3:通過Post方式進行簡單類型的交互
var UserMsg = { 'Name': '踏浪帥' }; var UserMessage = JSON2.stringify(UserMsg); $.ajax({ type: "POST", contentType: "application/json", url: "http://localhost:8089/WcfRestService.svc/User/UserName", data: UserMessage, dataType: "json", crossDomain: false, success: function (userNameInfo) { alert(userNameInfo); }, error: function (error) { alert(error.responseText); } });
運行效果:
其中要注意var UserMsg = { 'Name': '踏浪帥' }; "Name"必需要跟Rest服務接口的參數是一樣;JSON2.stringify(UserMsg)則是把它轉化成JSON格式,其定義在json2.js里;
4:通過Post方式進行復雜類型(自定義實體)的交互
var UserMsg = { 'model': { 'ID': '6', 'UserName': '踏浪帥', 'PassWord': '123456', 'Age': '27'} }; var UserMessage = JSON2.stringify(UserMsg); $.ajax({ type: "POST", contentType: "application/json", url: "http://localhost:8089/WcfRestService.svc/User/Post", data: UserMessage, dataType: "json", crossDomain: false, success: function (userNameInfo) { alert(userNameInfo); }, error: function (error) { alert(error.responseText); } });
運行效果:
其中要注意交互實體的書寫方式,其中model是我們Rest服務接口定義的參數,其它則是實體的名稱和對應的值,都是以字符串格式;特別要注意接口服務中采用Post的BodyStyle= WebMessageBodyStyle.WrappedRequest;這個問題困惑好幾天,最后發現把它設置成BodyStyle = WebMessageBodyStyle.Bare;服務接口就一直交互失敗;
三 理論知識
1:接口服務中的WebMessageBodyStyle枚舉,首先我們先看一下它幾個值
// 一個指定是否包裝參數和返回值的枚舉。 public enum WebMessageBodyStyle { // 摘要: 不包裝請求和響應。 Bare = 0, // 摘要:包裝請求和響應。 Wrapped = 1, // 摘要:包裝請求,但不包裝響應。 WrappedRequest = 2, // 摘要:包裝響應,但不包裝請求。 WrappedResponse = 3, }
先前一直Post交互失敗,就是因為對枚舉了解不夠,導致一直查找不出錯誤的所在地方;這邊引用一下蔣老師的文章來說明幾個的區別:請求消息和回復消息分別是對操作方法輸入參數和返回值(輸出參數和引用參數)的封裝,WebMessageBodyStyle中的Bare表示請求消息和回復消息的主體部分僅僅包含針對輸入參數和返回值(輸出參數和引用參數)序列化后的內容,而Wrapped則會在外面包裝一個基於當前操作的“封套”。枚舉項WrappedRequest和WrappedResponse用於單獨針對請求消息和回復消息的主體進行封裝。WebGetAttribute與WebInvokeAttribute的屬性BodyStyle的默認值為Bare。如果該屬性被設置成WrappedRequest,則回復消息主體依然采用Bare風格;
如果該屬性被設置成WrappedResponse,則請求消息主體依然采用Bare風格。布爾類型的只讀屬性IsBodyStyleSetExplicitly表示是否針對屬性BodyStyle進行了顯示設置。在使用POST操作時,在客戶端與服務端交互過程中,需要指定WebMessageBodyStyle;在GET操作時,不論格式,可以不必指定。
四 工具運用
在上面創建的服務中定義Get及Post方式進行調用服務,其實我們也可以通過Fiddler來模擬交互;
1:選擇Get方式,並把服務的地址寫入,然后Execute
選擇運行完的Web會話,在"嗅探"->"TextView",可以看到調用服務返回的內容
2:選擇Post方式,並把服務的地址寫入,在Request Headers寫入"Content-Type:application/json" 在RequestBody寫入要傳遞給服務的參數和值
執行后返回的結果如下:
復雜類型的Post方式
執行后返回的結果如下:
如果,您認為閱讀這篇博客讓您有些收獲,不妨點擊一下右下角的【推薦】按鈕,若有不足歡迎指正。 因為,我的寫作熱情也離不開您的肯定支持。
感謝您的閱讀(源代碼下載)
最近有個妹子弄的一個關於擴大眼界跟內含的訂閱號,每天都會更新一些深度內容,在這里如果你感興趣也可以關注一下(嘿對美女跟知識感興趣),當然可以關注后輸入:github 會有我的微信號,如果有問題你也可以在那找到我;當然不感興趣無視此信息;