原文:http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/wcf-extensibility-message-formatters.aspx
在编写Rest形式的WCF的时候,如果消息格式设置为Json,则默认是使用DataContractJsonSerializer这个类来做Json转换的;
关于这个类,地球人都知道他做json的时候是非常不友好的,不光是要设一堆的knowtype,而且对于DataTable,居然会返回xml形式,
对于Dictionary,使用冗余形式的{“Key”:"XXX","Value":"YYY"}
而不是大家都喜闻乐见的{“XXX”:“YYY”}这种形式,不光丑,还占地方
可能这种缺点连国外的牛人都看不下去了,所以,就有了原文这篇文章
这个牛人做的是编程方式绑定的自定义behavior,而我原来的WCF是windows 服务形式的,而且用的是config配置,所以为了备忘,特记录以下过程:
- 把他上传的代码包下载下来:
- 把他代码包中的NewtonsoftJson*.cs和RawBodyWriter.cs下载到自己的项目中(放在同一个文件夹中,命名空间也相同)
- 把他的Program.cs中定义的MyRawMapper这个类也放在同样的包中
- 把NewtonsoftJsonBehavior.cs中的108~112行注释掉,因为这一行他不允许使用uriTemplate,而我要使用uriTemplate来定制自己的服务uri,否则uri只能和方法名相同:
如我的服务是这样定义的://string uriTemplate = this.GetUriTemplate(operation); //if (uriTemplate != null) //{ // throw new InvalidOperationException("UriTemplate support not implemented in this behavior."); //}
其中UriTemplate = "Sql",表明我的服务Uri是“Sql”而不是“GetData”,这样更具有灵活性[WebInvoke(Method="POST",BodyStyle=WebMessageBodyStyle.Bare, UriTemplate = "Sql",RequestFormat=WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] SqlResult GetData(string sql);
- 在同样的包中增加一个类:
public class NewtonJsonBehaviorExtensionElement : BehaviorExtensionElement { public override Type BehaviorType { get { return typeof(NewtonsoftJsonBehavior); } } protected override object CreateBehavior() { return new NewtonsoftJsonBehavior(); } }
- 修改配置文件:
- 增加行为扩展:
<extensions> <behaviorExtensions> <add name="newtonsoftJsonBehavior" type="<命名空间>.NewtonJsonBehaviorExtensionElement,<程序集>"/> </behaviorExtensions> </extensions> </system.serviceModel>
- 给此服务绑定的上添加RawMapper:
<webHttpBinding> <binding name="XXX" contentTypeMapper="<命名空间>.JsonRawMapper,<程序集>">
- 给此服务绑定的终结点上添加自定的json扩展:
<endpointBehaviors> <behavior name="WebBehavior"> <webHttp helpEnabled="true" faultExceptionEnabled="true" defaultBodyStyle="Bare"/> <newtonsoftJsonBehavior /> </behavior>
- 增加行为扩展:
这样以后就可以使用我们大家都喜欢的newtonjson来序列化反序列化json了:
如果需要把时间日期格式定义成成yyyy-MM-dd HH:mm:ss的格式(newton是格式化成yyyy-MM-ddTHH:mm:ssT)的,则可以修改NewtonsoftJsonDispatchFormatter.cs的代码:DeserializeRequest方法中的:
Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer() {
DateFormatString = "yyyy-MM-dd HH:mm:ss"
};
SerializeReply方法中的:
using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw) { DateFormatString ="yyyy-MM-dd HH:mm:ss"})
{
同时,可以在正式环境中把SerializeReply方法中的如下这样注释掉,以减少传输数据大小:
//writer.Formatting = Newtonsoft.Json.Formatting.Indented;
这种配置方式没有找到可以在config文件中直接配置json输出格式和日期时间格式的方法,貌似WCF自定义行为扩展是不支持自定义属性的xml配置的,如果可以的话
能配置成
<newtonsoftJsonBehavior JsonFormatter="None" DateTimeFormatter="yyyy-MM-dd HH:mm:ss"/>
就完美了,可惜解析的时候就过不去
此文相关的代码现在已经传到oschina上了
http://git.oschina.net/juncos/REST4SqlServer
这是一个https的Windows服务,用于通过此REST服务执行sql语句
在App.config中需要指定https绑定的证书,和服务URL(现在为XXX.xxx.xxx.xx)
此证书可以自己通过Openssl或者.net的mkcert自己制作