2 // WebMessageEncoder.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System
.Net
.Mime
;
31 using System
.Runtime
.Serialization
.Json
;
32 using System
.ServiceModel
;
36 namespace System
.ServiceModel
.Channels
38 internal class WebMessageEncoder
: MessageEncoder
40 internal const string ScriptPropertyName
= "618BC2B0-38AA-21A3-DB4A-404FC87B9B11"; // randomly generated
42 WebMessageEncodingBindingElement source
;
44 public WebMessageEncoder (WebMessageEncodingBindingElement source
)
49 public override string ContentType
{
51 get { return MediaType; }
53 get { return MediaType + "; charset=" + source.WriteEncoding.HeaderName; }
57 // FIXME: find out how it can be customized.
58 public override string MediaType
{
59 get { return "application/xml"; }
62 public override MessageVersion MessageVersion
{
63 get { return MessageVersion.None; }
66 public override Message
ReadMessage (ArraySegment
<byte> buffer
, BufferManager bufferManager
, string contentType
)
68 throw new NotImplementedException ();
71 public override Message
ReadMessage (Stream stream
, int maxSizeOfHeaders
, string contentType
)
74 throw new ArgumentNullException ("stream");
75 if (contentType
== null)
76 throw new ArgumentNullException ("contentType");
78 Encoding enc
= Encoding
.UTF8
;
79 ContentType ct
= new ContentType (contentType
);
80 if (ct
.CharSet
!= null)
81 enc
= Encoding
.GetEncoding (ct
.CharSet
);
83 WebContentFormat fmt
= WebContentFormat
.Xml
;
84 if (source
.ContentTypeMapper
!= null)
85 fmt
= source
.ContentTypeMapper
.GetMessageFormatForContentType (contentType
);
87 switch (ct
.MediaType
) {
88 case "application/json":
89 fmt
= WebContentFormat
.Json
;
91 case "application/xml":
92 fmt
= WebContentFormat
.Xml
;
94 case "application/octet-stream":
95 fmt
= WebContentFormat
.Raw
;
101 WebBodyFormatMessageProperty wp
= null;
103 case WebContentFormat
.Xml
:
104 // FIXME: is it safe/unsafe/required to keep XmlReader open?
105 msg
= Message
.CreateMessage (MessageVersion
.None
, null, XmlReader
.Create (new StreamReader (stream
, enc
)));
106 wp
= new WebBodyFormatMessageProperty (WebContentFormat
.Xml
);
108 case WebContentFormat
.Json
:
109 // FIXME: is it safe/unsafe/required to keep XmlReader open?
111 msg
= Message
.CreateMessage (MessageVersion
.None
, null, JsonReaderWriterFactory
.CreateJsonReader (stream
, source
.ReaderQuotas
));
113 msg
= Message
.CreateMessage (MessageVersion
.None
, null, JsonReaderWriterFactory
.CreateJsonReader (stream
, enc
, source
.ReaderQuotas
, null));
115 wp
= new WebBodyFormatMessageProperty (WebContentFormat
.Json
);
117 case WebContentFormat
.Raw
:
118 throw new NotImplementedException ();
120 throw new SystemException ("INTERNAL ERROR: cannot determine content format");
123 msg
.Properties
.Add (WebBodyFormatMessageProperty
.Name
, wp
);
127 WebContentFormat
GetContentFormat (Message message
)
129 string name
= WebBodyFormatMessageProperty
.Name
;
130 if (message
.Properties
.ContainsKey (name
))
131 return ((WebBodyFormatMessageProperty
) message
.Properties
[name
]).Format
;
134 case "application/xml":
136 return WebContentFormat
.Xml
;
137 case "application/json":
139 return WebContentFormat
.Json
;
140 case "application/octet-stream":
141 return WebContentFormat
.Raw
;
143 return WebContentFormat
.Default
;
147 public override void WriteMessage (Message message
, Stream stream
)
150 throw new ArgumentNullException ("message");
152 // Handle /js and /jsdebug as the special cases.
153 var script
= message
.Properties
[ScriptPropertyName
] as string;
154 if (script
!= null) {
155 var bytes
= source
.WriteEncoding
.GetBytes (script
);
156 stream
.Write (bytes
, 0, bytes
.Length
);
160 if (!MessageVersion
.Equals (message
.Version
))
161 throw new ProtocolException (String
.Format ("MessageVersion {0} is not supported", message
.Version
));
163 throw new ArgumentNullException ("stream");
165 switch (GetContentFormat (message
)) {
166 case WebContentFormat
.Xml
:
168 using (XmlWriter w
= XmlDictionaryWriter
.CreateDictionaryWriter (XmlWriter
.Create (new StreamWriter (stream
, source
.WriteEncoding
))))
169 message
.WriteMessage (w
);
171 using (XmlWriter w
= XmlDictionaryWriter
.CreateTextWriter (stream
, source
.WriteEncoding
))
172 message
.WriteMessage (w
);
175 case WebContentFormat
.Json
:
176 using (XmlWriter w
= JsonReaderWriterFactory
.CreateJsonWriter (stream
, source
.WriteEncoding
))
177 message
.WriteMessage (w
);
179 case WebContentFormat
.Raw
:
180 throw new NotImplementedException ();
181 case WebContentFormat
.Default
:
182 throw new SystemException ("INTERNAL ERROR: cannot determine content format");
186 public override ArraySegment
<byte> WriteMessage (Message message
, int maxMessageSize
, BufferManager bufferManager
,
189 throw new NotImplementedException ();