长时间的潜伏者,这里的第一次海报。 我几天来一直在努力解决这个问题,并希望得到任何提示。 我在下面分解了这个问题。
我想要实现的目标:
我想设置一个JSON WCF Web服务,但我想使用JSON.net序列化程序而不是WCF附带的序列化程序。为什么?因为我发现使用WCF附带的序列化会增加集合(我将在下面展示一个我的意思的例子)。该服务的最终消费者将成为一个JavaScript客户端,因此我不希望客户端做更多的麻烦来浏览JSON。
我想出了一个我想要的简单示例,并着手尝试使其在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%所以我找到并关注这篇文章以适应我的目标: http://www.codeproject.com/Articles/105273/Create-RESTful-WCF-Service-API-Step-By-Step-Guide#
尝试取1:
在上面的帖子之后,我能够设置一个WCF服务(下面列出的代码),它完成了我想要的但是生成的JSON输出有点臃肿,如下所示。
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响应中汤中的头发是在对“payLoad”的JSON响应中将Dictionary对象映射出来的方式。它是一个对象数组,而我期待一个JSON对象没有这个“Key”,“Value”业务。不是我想要的。关闭,但在客户端处理相当挑剔。没有人喜欢臃肿和不必要的工作,所以请大家注意这一点。
更多地寻找解决方案我读了一些SO帖子,暗示这里发生的事情是该服务正在使用内置的串行器 并且不会以任何其他方式序列化“字典”。需要一些额外的工作才能以我期望的格式获得它。 所以,我想,如何使用另一个序列化器? 按照这个想法,我在这里发现了这个坏孩子:http://james.newtonking.com/projects/json-net.aspx
这导致我的第二次尝试。
尝试2:
将JSON.NET序列化程序下载并导入到我的小项目中,我将以下文件更改为这样(将 whoareyou 方法的返回类型更改为 string ):< / p>
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, string>
{
{"userFullName", "Paul The Octopus"},
{"userLevel", "Administrator"}
};
WhoAreYouResponse whoAreYouResponse = new WhoAreYouResponse
{
errorCode = 0,
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",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "json/whoareyou?username={username}")]
string whoareyou(string username);
}
}
当调用该服务时,我得到了这个回复:
"{
\"errorCode\":0,
\"payLoad\":{
\"userFullName\":\"Paul The Octopus\",
\"userLevel\":\"Administrator\"}
}"
赢家!这就是我想要的和期望的......但是。把卡车放回去。整个JSON对象用双引号括起来!? 嗯。这是一个包含JSON对象的字符串。我把头发从汤里拿出来,现在一只苍蝇飞进了它!
片刻之后,很明显(我认为)正在发生的事情是JSON.NET序列化程序像魅力一样工作,在字符串中吐出一个JSON对象,然后通过WCF序列化器和基本上是字符串化的。所以我在返回中看到的是一个JSON字符串。很近!事实上,我的方法 whoareyou 表示它返回一个字符串,所以几乎是我的错。
所以,我的问题是,如何让这个问题孩子停止这种双序列化业务?我找不到我的 whoareyou 方法的返回类型,就像JSON对象一样。 有没有办法告诉WCF使用JSON.NET序列化器,或者某种类似的解决方案?
指针非常感谢。
答案 0 :(得分:6)
据我所知,您正在从头开始创建服务,并且对REST服务的实现方式没有任何限制。然后我建议你使用ASP.NET WebApi
不要使用传统的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)它可以用更难的方式完成。