本文将通过一个简单的实例,介绍如何创建一个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 会有我的微信号,如果有问题你也可以在那找到我;当然不感兴趣无视此信息;