如何将 Json.Net 设置为 WCF REST 服务的默认序列化程序
Posted
技术标签:
【中文标题】如何将 Json.Net 设置为 WCF REST 服务的默认序列化程序【英文标题】:How to set Json.Net as the default serializer for WCF REST service 【发布时间】:2011-03-08 07:19:38 【问题描述】:是否可以在序列化/反序列化实体时覆盖默认的 WCF DataContractSerializer 行为并改用 JSON.NET?
我有以下处理城市实体的服务合同。出于设计原因,City 实体具有 IsReference=true,因此默认的 DataContractSerializer 会引发错误。
对于“GET”方法,我可以使用 JsonConvert.DeserializeObject 来处理这种情况,但使用“PUT、POST、DELETE”方法时,DataContractSerializer 具有优先权,并且由于无法序列化 IsReference 实体而抱怨失败。
我找到了这个Post 来实现 IOperationBehavior 并提供我自己的序列化器,但我不知道如何将 Json.NET 与它集成。我相信应该有更直接的方法来解决这个问题。
我将不胜感激有关此方案的任何帮助或指导,或对其他方法的建议。
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class CityService
[Description("Get all Cities")]
[WebGet(UriTemplate = "")]
public Message Cities()
[Description("Allows the details of a single City to be updated.")]
[WebInvoke(UriTemplate = "code", Method = "PUT")]
public Message UpdateCity(string code, City city)
非常感谢
霍萨姆
【问题讨论】:
对传入的请求做同样的事情怎么样?传入的请求是 json camelCase 并且需要在 C# PascalCase 类中序列化?请在此处查看我的帖子:***.com/questions/50884879/… 【参考方案1】:使用扩展编码器和序列化器(请参阅http://msdn.microsoft.com/en-us/library/ms733092.aspx)或其他扩展 WCF 的方法(如使用 DataContractSerializerOperationBehavior
)非常有趣,但对于您的特殊问题,有更简单的解决方法。
如果您已经使用 Message
类型返回结果并使用 WCF4,您可以执行以下操作:
public Message UpdateCity(string code, City city)
MyResponseDataClass message = CreateMyResponse();
// use JSON.NET to serialize the response data
string myResponseBody = JsonConvert.Serialize(message);
return WebOperationContext.Current.CreateTextResponse (myResponseBody,
"application/json; charset=utf-8",
Encoding.UTF8);
如果出现错误(如HttpStatusCode.Unauthorized
或HttpStatusCode.Conflict
)或其他需要设置HTTP状态码的情况(如HttpStatusCode.Created
),您可以继续使用WebOperationContext.Current.OutgoingResponse.StatusCode
。
作为替代方案,您还可以返回 Stream
(请参阅 http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-web.aspx 和 http://msdn.microsoft.com/en-us/library/ms732038.aspx)而不是 Message
以返回任何数据,而无需 Microsoft JSON 序列化程序进行额外的默认处理。对于 WCF4,您可以使用 CreateStreamResponse
(参见 http://msdn.microsoft.com/en-us/library/dd782273.aspx)而不是 CreateTextResponse
。如果您将使用此技术产生响应,请不要忘记在写入流后将流位置设置为 0。
【讨论】:
如何处理反序列化传入的 City 对象? @Christopher Stott:请参阅以“阅读消息”开头的 msdn.microsoft.com/en-us/library/ms734675.aspx。 从该链接看来,UpdateCity 必须采用 Message 参数才能使用 JSON.NET 进行反序列化。那是对的吗?有什么办法吗? 我知道它很旧,但解决了我的 TimeSpan 和 DateTime 格式问题。 @ramires.cabral:这是个好消息!顺便说一句,JSON.NET
(Newtonsoft.Json
) 的使用允许在转换过程中设置一些附加选项:JsonSerializerSettings 作为JsonConvert.SerializeObject
和Formatting.Indented
的第二/第三个参数。我个人最喜欢将ContractResolver
与new CamelCasePropertyNamesContractResolver()
和NullValueHandling
与NullValueHandling.Ignore
一起使用(参见here)【参考方案2】:
您是否有某些原因要专门使用 Json.NET 库。如果要返回 JSON,为什么不直接使用 WebGet 和 WebInvoke 属性中的 ResponseFormat 属性?
[WebGet(UriTemplate = "", ResponseFormat = WebMessageFormat.Json)]
在大多数情况下应该如此。您正在运行哪个版本的 WCF?您返回 Message 类型而不是实际类型的任何原因?
【讨论】:
这是 WCF4。在我的 web.config 中,我的在服务行为的服务 Web 配置中定义它:
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" />
<!--<enableWebScript />-->
</behavior>
</endpointBehaviors>
或在您的接口的操作合同中
[OperationContract]
[WebInvoke(Method = "GET",
UriTemplate = "/advertisements/app_id/access_token/genero/age",
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]
【讨论】:
以上是关于如何将 Json.Net 设置为 WCF REST 服务的默认序列化程序的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 中正确使用 WCF REST API 上的 Stream 将文件(图像/视频/等)上传到服务器?