为REST形式的WCF使用newtonsoftJson转换器

原文: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配置,所以为了备忘,特记录以下过程:


  1. 把他上传的代码包下载下来:
  2. 把他代码包中的NewtonsoftJson*.cs和RawBodyWriter.cs下载到自己的项目中(放在同一个文件夹中,命名空间也相同)
  3. 把他的Program.cs中定义的MyRawMapper这个类也放在同样的包中
  4. 把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.");
                //}
    如我的服务是这样定义的:
            [WebInvoke(Method="POST",BodyStyle=WebMessageBodyStyle.Bare, UriTemplate = "Sql",RequestFormat=WebMessageFormat.Json,  ResponseFormat = WebMessageFormat.Json)]
            SqlResult GetData(string sql);
    其中UriTemplate = "Sql",表明我的服务Uri是“Sql”而不是“GetData”,这样更具有灵活性
  5. 在同样的包中增加一个类:
        public class NewtonJsonBehaviorExtensionElement : BehaviorExtensionElement
        {
    
            public override Type BehaviorType
            {
                get { return typeof(NewtonsoftJsonBehavior); }
            }
    
            protected override object CreateBehavior()
            {
                return new NewtonsoftJsonBehavior();
            }
        }
  6. 修改配置文件:
    1. 增加行为扩展:
      
      
        
          
        
      
        
    2. 给此服务绑定的上添加RawMapper:
            
              

    3. 给此服务绑定的终结点上添加自定的json扩展:
          
            
              
                
                
              
              

这样以后就可以使用我们大家都喜欢的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配置的,如果可以的话

能配置成

就完美了,可惜解析的时候就过不去


此文相关的代码现在已经传到oschina上了

http://git.oschina.net/juncos/REST4SqlServer

这是一个https的Windows服务,用于通过此REST服务执行sql语句

在App.config中需要指定https绑定的证书,和服务URL(现在为XXX.xxx.xxx.xx)

此证书可以自己通过Openssl或者.net的mkcert自己制作



你可能感兴趣的:(MS)