wcf datetime json format

wcf 内置的json序列化工具,有时需要替换,或者特殊情况的处理,需要修改。

我也遇到了Dto属性类型是datetime,json的反序列化 和 序列号不友好。

这是国外网站的一个方案:Replacing WCF DataContractJsonSerializer with Newtonsoft JsonSerializer

不过时间格式还不是我想要的,他是发布在GitHub上,于是简单修改了时间格式,使更符合国情。

需要引用新写的库  WcfNewtonsoftJsonSerializer ,然后配置文件配置好。

关键配置部分:behaviorExtensions、endpointBehaviors、webHttpBinding

 1   <system.serviceModel>
 2 
 3     <extensions>
 4       <behaviorExtensions>
 5         <add name="newtonsoftJsonBehavior" type="WcfNewtonsoftJsonSerializer.NewtonsoftJsonBehaviorExtension, WcfNewtonsoftJsonSerializer" />
 6       </behaviorExtensions>
 7     </extensions>
 8     
 9     <behaviors>
10       <endpointBehaviors>
11         <behavior name="restEndPointBehavior">
12           <webHttp helpEnabled="true" />
13           <newtonsoftJsonBehavior />
14         </behavior>
15       </endpointBehaviors>
16       
17       <serviceBehaviors>
18         <behavior name="restServiceBehavior">
19           <serviceMetadata httpGetEnabled="true"/>
20           <serviceDebug includeExceptionDetailInFaults="true"  httpHelpPageEnabled="true"/>
21         </behavior>
22       </serviceBehaviors>
23     </behaviors>
24     <bindings>
25       <webHttpBinding>
26         <binding name="restWebHttpBinding" 
27                  contentTypeMapper="WcfNewtonsoftJsonSerializer.NewtonsoftJsonContentTypeMapper, WcfNewtonsoftJsonSerializer" 
28                  allowCookies="false" 
29                  bypassProxyOnLocal="false" 
30                  hostNameComparisonMode="StrongWildcard" 
31                  maxBufferPoolSize="524288" 
32                  maxBufferSize="2147483647" 
33                  closeTimeout="00:01:00" 
34                  openTimeout="00:01:00" 
35                  receiveTimeout="00:02:00" 
36                  sendTimeout="00:02:00" 
37                  maxReceivedMessageSize="2147483647" 
38                  transferMode="Buffered">
39           <security mode="None">
40             <transport clientCredentialType="None" />
41           </security>
42           <readerQuotas maxArrayLength="2147483647" 
43                         maxBytesPerRead="2147483647" 
44                         maxDepth="2147483647" 
45                         maxNameTableCharCount="2147483647" 
46                         maxStringContentLength="2147483647" />
47         </binding>
48       </webHttpBinding>
49     </bindings>
50     
51     <services>
52       <service name="WcfService1.Service1" behaviorConfiguration="restServiceBehavior">
53         <endpoint address="" 
54                   contract="WcfService1.IService1" 
55                   binding="webHttpBinding" 
56                   bindingConfiguration="restWebHttpBinding" 
57                   behaviorConfiguration="restEndPointBehavior" />
58         <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
59       </service>
60     </services>
61     
62   </system.serviceModel>

以下是WcfNewtonsoftJsonSerializer项目的关键代码:

  1     public class NewtonsoftJsonBehavior : WebHttpBehavior
  2     {
  3         public override void Validate( ServiceEndpoint endpoint )
  4         {
  5             base.Validate( endpoint );
  6 
  7             var elements = endpoint.Binding.CreateBindingElements();
  8             var webEncoder = elements.Find<WebMessageEncodingBindingElement>();
  9             if ( webEncoder == null )
 10             {
 11                 throw new InvalidOperationException( "This behavior must be used in an endpoint with the WebHttpBinding (or a custom binding with the WebMessageEncodingBindingElement)." );
 12             }
 13 
 14             foreach ( var operation in endpoint.Contract.Operations )
 15             {
 16                 ValidateOperation( operation );
 17             }
 18         }
 19 
 20         protected override IDispatchMessageFormatter GetRequestDispatchFormatter( OperationDescription operationDescription, ServiceEndpoint endpoint )
 21         {
 22             if ( IsGetOperation( operationDescription ) )
 23             {
 24                 // no change for GET operations
 25                 return base.GetRequestDispatchFormatter( operationDescription, endpoint );
 26             }
 27 
 28             if ( operationDescription.Messages[0].Body.Parts.Count == 0 )
 29             {
 30                 // nothing in the body, still use the default
 31                 return base.GetRequestDispatchFormatter( operationDescription, endpoint );
 32             }
 33 
 34             return new NewtonsoftJsonDispatchFormatter( operationDescription, true );
 35         }
 36 
 37         protected override IDispatchMessageFormatter GetReplyDispatchFormatter( OperationDescription operationDescription, ServiceEndpoint endpoint )
 38         {
 39             if ( operationDescription.Messages.Count == 1 || operationDescription.Messages[1].Body.ReturnValue.Type == typeof( void ) )
 40             {
 41                 return base.GetReplyDispatchFormatter( operationDescription, endpoint );
 42             }
 43             else
 44             {
 45                 return new NewtonsoftJsonDispatchFormatter( operationDescription, false );
 46             }
 47         }
 48 
 49         private void ValidateOperation( OperationDescription operation )
 50         {
 51             if ( operation.Messages.Count > 1 )
 52             {
 53                 if ( operation.Messages[1].Body.Parts.Count > 0 )
 54                 {
 55                     throw new InvalidOperationException( "Operations cannot have out/ref parameters." );
 56                 }
 57             }
 58 
 59             var bodyStyle = GetBodyStyle( operation );
 60             var inputParameterCount = operation.Messages[0].Body.Parts.Count;
 61             if ( !IsGetOperation( operation ) )
 62             {
 63                 var wrappedRequest = bodyStyle == WebMessageBodyStyle.Wrapped || bodyStyle == WebMessageBodyStyle.WrappedRequest;
 64                 if ( inputParameterCount == 1 && wrappedRequest )
 65                 {
 66                     throw new InvalidOperationException( "Wrapped body style for single parameters not implemented in this behavior." );
 67                 }
 68             }
 69 
 70             var wrappedResponse = bodyStyle == WebMessageBodyStyle.Wrapped || bodyStyle == WebMessageBodyStyle.WrappedResponse;
 71             var isVoidReturn = operation.Messages.Count == 1 || operation.Messages[1].Body.ReturnValue.Type == typeof( void );
 72             if ( !isVoidReturn && wrappedResponse )
 73             {
 74                 throw new InvalidOperationException( "Wrapped response not implemented in this behavior." );
 75             }
 76         }
 77 
 78         private WebMessageBodyStyle GetBodyStyle( OperationDescription operation )
 79         {
 80             var wga = operation.Behaviors.Find<WebGetAttribute>();
 81             if ( wga != null )
 82             {
 83                 return wga.BodyStyle;
 84             }
 85 
 86             var wia = operation.Behaviors.Find<WebInvokeAttribute>();
 87             if ( wia != null )
 88             {
 89                 return wia.BodyStyle;
 90             }
 91 
 92             return DefaultBodyStyle;
 93         }
 94 
 95         private bool IsGetOperation( OperationDescription operation )
 96         {
 97             var wga = operation.Behaviors.Find<WebGetAttribute>();
 98             if ( wga != null )
 99             {
100                 return true;
101             }
102 
103             var wia = operation.Behaviors.Find<WebInvokeAttribute>();
104             if ( wia != null )
105             {
106                 return wia.Method == "HEAD";
107             }
108 
109             return false;
110         }
111     }
 1     public class NewtonsoftJsonBehaviorExtension : BehaviorExtensionElement
 2     {
 3         public override Type BehaviorType
 4         {
 5             get { return typeof ( NewtonsoftJsonBehavior ); }
 6         }
 7 
 8         protected override object CreateBehavior()
 9         {
10             return new NewtonsoftJsonBehavior();
11         }
12     }
1     public class NewtonsoftJsonContentTypeMapper : WebContentTypeMapper
2     {
3         public override WebContentFormat GetMessageFormatForContentType( string contentType )
4         {
5             return WebContentFormat.Raw;
6         }
7     }
  1     public class NewtonsoftJsonDispatchFormatter : IDispatchMessageFormatter
  2     {
  3         private readonly OperationDescription _operation;
  4         private readonly Dictionary<string, int> _parameterNames;
  5 
  6         public NewtonsoftJsonDispatchFormatter( OperationDescription operation, bool isRequest )
  7         {
  8             _operation = operation;
  9             if ( isRequest )
 10             {
 11                 var operationParameterCount = operation.Messages[0].Body.Parts.Count;
 12                 if ( operationParameterCount > 1 )
 13                 {
 14                     _parameterNames = new Dictionary<string, int>();
 15                     for ( var i = 0; i < operationParameterCount; i++ )
 16                     {
 17                         _parameterNames.Add( operation.Messages[0].Body.Parts[i].Name, i );
 18                     }
 19                 }
 20             }
 21         }
 22 
 23         public void DeserializeRequest( Message message, object[] parameters )
 24         {
 25             object bodyFormatProperty;
 26             if ( !message.Properties.TryGetValue( WebBodyFormatMessageProperty.Name, out bodyFormatProperty ) ||
 27                  ( bodyFormatProperty as WebBodyFormatMessageProperty ).Format != WebContentFormat.Raw )
 28             {
 29                 throw new InvalidOperationException( "Incoming messages must have a body format of Raw. Is a ContentTypeMapper set on the WebHttpBinding?" );
 30             }
 31 
 32             var bodyReader = message.GetReaderAtBodyContents();
 33             bodyReader.ReadStartElement( "Binary" );
 34             var rawBody = bodyReader.ReadContentAsBase64();
 35             var ms = new MemoryStream( rawBody );
 36 
 37             var sr = new StreamReader( ms );
 38             var serializer = new Newtonsoft.Json.JsonSerializer();
 39             if ( parameters.Length == 1 )
 40             {
 41                 // single parameter, assuming bare
 42                 parameters[0] = serializer.Deserialize( sr, _operation.Messages[0].Body.Parts[0].Type );
 43             }
 44             else
 45             {
 46                 // multiple parameter, needs to be wrapped
 47                 Newtonsoft.Json.JsonReader reader = new Newtonsoft.Json.JsonTextReader( sr );
 48                 reader.Read();
 49                 if ( reader.TokenType != Newtonsoft.Json.JsonToken.StartObject )
 50                 {
 51                     throw new InvalidOperationException( "Input needs to be wrapped in an object" );
 52                 }
 53 
 54                 reader.Read();
 55                 while ( reader.TokenType == Newtonsoft.Json.JsonToken.PropertyName )
 56                 {
 57                     var parameterName = reader.Value as string;
 58                     reader.Read();
 59                     if ( _parameterNames.ContainsKey( parameterName ) )
 60                     {
 61                         var parameterIndex = _parameterNames[parameterName];
 62                         parameters[parameterIndex] = serializer.Deserialize( reader, _operation.Messages[0].Body.Parts[parameterIndex].Type );
 63                     }
 64                     else
 65                     {
 66                         reader.Skip();
 67                     }
 68 
 69                     reader.Read();
 70                 }
 71 
 72                 reader.Close();
 73             }
 74 
 75             sr.Close();
 76             ms.Close();
 77         }
 78 
 79         public Message SerializeReply( MessageVersion messageVersion, object[] parameters, object result )
 80         {
 81             byte[] body;
 82             var serializer = new Newtonsoft.Json.JsonSerializer();
 83             serializer.Converters.Add( new IsoDateTimeConverter() {DateTimeFormat = "yyyy-MM-dd HH:mm:ss", DateTimeStyles = DateTimeStyles.None} );
 84 
 85             using ( var ms = new MemoryStream() )
 86             {
 87                 using ( var sw = new StreamWriter( ms, Encoding.UTF8 ) )
 88                 {
 89                     using ( Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter( sw ) )
 90                     {
 91                         //writer.Formatting = Newtonsoft.Json.Formatting.Indented;
 92                         serializer.Serialize( writer, result );
 93                         sw.Flush();
 94                         body = ms.ToArray();
 95                     }
 96                 }
 97             }
 98 
 99             var replyMessage = Message.CreateMessage( messageVersion, _operation.Messages[1].Action, new RawBodyWriter( body ) );
100             replyMessage.Properties.Add( WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty( WebContentFormat.Raw ) );
101             var respProp = new HttpResponseMessageProperty();
102             respProp.Headers[HttpResponseHeader.ContentType] = "application/json";
103             replyMessage.Properties.Add( HttpResponseMessageProperty.Name, respProp );
104             return replyMessage;
105         }
106     }
 1     public class RawBodyWriter : BodyWriter
 2     {
 3         private readonly byte[] _content;
 4 
 5         public RawBodyWriter( byte[] content )
 6             : base( true )
 7         {
 8             _content = content;
 9         }
10 
11         protected override void OnWriteBodyContents( XmlDictionaryWriter writer )
12         {
13             writer.WriteStartElement( "Binary" );
14             writer.WriteBase64( _content, 0, _content.Length );
15             writer.WriteEndElement();
16         }
17     }

猜你喜欢

转载自www.cnblogs.com/jonney-wang/p/9655926.html
WCF