使用JSON.Net的WCF RESTful Web服务:避免双序列化
很长一段时间,这里有第一次海报.
我几天来一直在努力解决这个问题,并希望得到任何提示. 我在下面分解了这个问题. 我想要实现的目标: 我想出了一个我想要的简单示例,并着手尝试使其在C#中运行.我必须承认在很长一段时间内没有使用.NET,这可能导致我的缓慢.无论如何,我对它有耐心等待. 所以,我想要一个接受用户名的服务,并返回一个带有用户信息的JSON对象. http://someHostName/whoareyou?username=paul 并让服务回应: { "errorCode": 0,"payLoad" : { "userFullName": "Paul The Octopus","userLevel" : "Administrator" } } 我可以轻松地在JavaScript或PHP中使用上述响应的JSON对象,并且对自己感觉非常好. 经过一些谷歌搜索后,我发现了一些帖子,建议在.NET Framework 4中使用WCF很容易.我刚刚在一个课程上做了一些WCF,但很久以前就忘记了它的99%,所以我找到并关注了这篇文章适应我的目标: 尝试1: RestServiceImpl.svc.cs文件 using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using Newtonsoft.Json; using System.Collections.Specialized; //Based on this psot: http://www.codeproject.com/Articles/105273/Create-RESTful-WCF-Service-API-Step-By-Step-Guide namespace RestService { public class RestServiceImpl : IRestServiceImpl { #region IRestService Members public WhoAreYouResponse whoareyou(string username) { var payLoad = new Dictionary<string,string> { {"userFullName","Paul The Octopus"},{"userLevel","Administrator"} }; WhoAreYouResponse whoAreYouResponse = new WhoAreYouResponse { errorCode = 0,payLoad = payLoad }; return whoAreYouResponse; } #endregion } //Helper bits to be used in service implementation public class WhoAreYouResponse { public int errorCode { get; set; } public Dictionary<string,string> payLoad { get; set; } } } IRestServiceImpl.cs文件 using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; namespace RestService { [ServiceContract] public interface IRestServiceImpl { [OperationContract] [WebInvoke(Method = "GET",ResponseFormat = WebMessageFormat.Json,BodyStyle = WebMessageBodyStyle.Bare,UriTemplate = "json/whoareyou?username={username}")] WhoAreYouResponse whoareyou(string username); } } Web.config文件 <?xml version="1.0"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <system.serviceModel> <services> <service name="RestService.RestServiceImpl" behaviorConfiguration="ServiceBehavior"> <endpoint address="" binding="webHttpBinding" contract="RestService.IRestServiceImpl" behaviorConfiguration="web"> </endpoint> </service> </services> <behaviors> <serviceBehaviors> <behavior name="ServiceBehavior"> <!-- To avoid disclosing metadata information,set the value below to false and remove the metadata endpoint above before deployment --> <serviceMetadata httpGetEnabled="true"/> <!-- To receive exception details in faults for debugging purposes,set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="web"> <webHttp/> </behavior> </endpointBehaviors> </behaviors> <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> </system.serviceModel> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/> </system.webServer> </configuration> *通过这样的浏览器调用服务的结果http://192.168.0.84/TestRestService/RestServiceImpl.svc/json/whoareyou?username=paul* { "errorCode":0,"payLoad" : [ {"Key":"userFullName","Value":"Paul The Octopus"},{"Key":"userLevel","Value":"Administrator"} ] } JSON响应中汤中的头发是在JSON响应中将Dictionary对象映射到“payLoad”的方式.它是一个对象数组,而我期待一个JSON对象没有这个“Key”,“Value”业务.不是我想要的.关闭,但在客户端处理相当挑剔.没有人喜欢臃肿和不必要的工作,所以请大家注意这一点. 为解决方案做了一些拖延我读了一些SO帖子,暗示这里发生的事情是该服务正在使用内置的串行器 这导致我的第二次尝试. 尝试2: RestServiceImpl.svc.cs using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using Newtonsoft.Json; using System.Collections.Specialized; //Based on this psot: http://www.codeproject.com/Articles/105273/Create-RESTful-WCF-Service-API-Step-By-Step-Guide namespace RestService { public class RestServiceImpl : IRestServiceImpl { #region IRestService Members public string whoareyou(string username) { var payLoad = new Dictionary<string,payLoad = payLoad }; return JsonConvert.SerializeObject(whoAreYouResponse); } #endregion } //Helper bits to be used in service implementation public class WhoAreYouResponse { public int errorCode { get; set; } public Dictionary<string,string> payLoad { get; set; } } } IRestServiceImpl.cs using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; namespace RestService { [ServiceContract] public interface IRestServiceImpl { [OperationContract] [WebInvoke(Method = "GET",UriTemplate = "json/whoareyou?username={username}")] string whoareyou(string username); } } 当服务被调用时,我得到了这个回复: "{ "errorCode":0,"payLoad":{ "userFullName":"Paul The Octopus","userLevel":"Administrator"} }" 优胜者!这就是我想要和期待的……但是.把卡车放回去.整个JSON对象用双引号括起来!? 经过一段时间的努力之后,很明显(我认为)发生的事情是,JSON.NET序列化程序的工作方式就像一个魅力,在字符串中吐出一个JSON对象,然后通过WCF序列化程序进行处理,实际上是字符串化.所以我在返回中看到的是一个JSON字符串.很近!事实上,我的方法whoareyou说它返回一个字符串,所以我的错. 所以,我的问题是,如何让这个问题孩子停止这种双序列化业务?我找不到我的whoareyou方法的返回类型,就像JSON对象一样. 指针非常赞赏.
据我所知,您正在从头开始创建服务,并且对REST服务的实现方式没有任何限制.然后我建议你使用ASP.NET WebApi
http://www.asp.net/web-api 不要使用传统的Web服务技术,因为在新版本中已经为您完成了许多样板代码. 使用web api,您可以轻松替换或添加任何序列化器/格式化程序.如何做到如下文所述: http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization 我遇到过您已经描述的序列化问题,并通过这种方法解决了这些问题.根据我对旧Web服务技术的经验(WCF 3.5 Rest Starter Kit,Wcf 4 REST)它可以用更难的方式完成. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |