using System;
using System.Collections.Generic;
using System.Globalization;
+using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.ServiceModel;
using System.ServiceModel.Channels;
-using System.ServiceModel.Dispatcher;
+using System.ServiceModel.Description;
using System.ServiceModel.Web;
using System.Text;
using System.Xml;
using XmlObjectSerializer = System.Object;
#endif
-namespace System.ServiceModel.Description
+namespace System.ServiceModel.Dispatcher
{
internal abstract class WebMessageFormatter
{
get { return template; }
}
- protected WebContentFormat ToContentFormat (WebMessageFormat src)
+ protected WebContentFormat ToContentFormat (WebMessageFormat src, object result)
{
+ if (result is Stream)
+ return WebContentFormat.Raw;
switch (src) {
case WebMessageFormat.Xml:
return WebContentFormat.Xml;
// FIXME: set hp.SuppressEntityBody for some cases.
ret.Properties.Add (HttpRequestMessageProperty.Name, hp);
- var wp = new WebBodyFormatMessageProperty (ToContentFormat (Info.IsRequestFormatSetExplicitly ? Info.RequestFormat : Behavior.DefaultOutgoingRequestFormat));
+ var wp = new WebBodyFormatMessageProperty (ToContentFormat (Info.IsRequestFormatSetExplicitly ? Info.RequestFormat : Behavior.DefaultOutgoingRequestFormat, null));
ret.Properties.Add (WebBodyFormatMessageProperty.Name, wp);
return ret;
internal class WrappedBodyWriter : BodyWriter
{
- public WrappedBodyWriter (object value, XmlObjectSerializer serializer, string name, string ns, bool json)
+ public WrappedBodyWriter (object value, XmlObjectSerializer serializer, string name, string ns, WebContentFormat fmt)
: base (true)
{
this.name = name;
this.ns = ns;
this.value = value;
this.serializer = serializer;
- this.is_json = json;
+ this.fmt = fmt;
}
- bool is_json;
+ WebContentFormat fmt;
string name, ns;
object value;
XmlObjectSerializer serializer;
#if !NET_2_1
protected override BodyWriter OnCreateBufferedCopy (int maxBufferSize)
{
- return new WrappedBodyWriter (value, serializer, name, ns, is_json);
+ return new WrappedBodyWriter (value, serializer, name, ns, fmt);
}
#endif
protected override void OnWriteBodyContents (XmlDictionaryWriter writer)
{
- if (is_json)
+ switch (fmt) {
+ case WebContentFormat.Raw:
+ WriteRawContents (writer);
+ break;
+ case WebContentFormat.Json:
WriteJsonBodyContents (writer);
- else
+ break;
+ case WebContentFormat.Xml:
WriteXmlBodyContents (writer);
+ break;
+ }
+ }
+
+ void WriteRawContents (XmlDictionaryWriter writer)
+ {
+ throw new NotSupportedException ("Some unsupported sequence of writing operation occured. It is likely a missing feature.");
}
void WriteJsonBodyContents (XmlDictionaryWriter writer)
Message SerializeReplyCore (MessageVersion messageVersion, object [] parameters, object result)
{
- if (parameters == null)
- throw new ArgumentNullException ("parameters");
+ // parameters could be null.
+ // result could be null. For Raw output, it becomes no output.
+
CheckMessageVersion (messageVersion);
MessageDescription md = GetMessageDescription (MessageDirection.Output);
break;
}
- bool json = msgfmt == WebMessageFormat.Json;
- Message ret = Message.CreateMessage (MessageVersion.None, null, new WrappedBodyWriter (result, serializer, name, ns, json));
+ var contentFormat = ToContentFormat (msgfmt, result);
+ Message ret = contentFormat == WebContentFormat.Raw ? new RawMessage ((Stream) result) : Message.CreateMessage (MessageVersion.None, null, new WrappedBodyWriter (result, serializer, name, ns, contentFormat));
// Message properties
hp.Headers ["Content-Type"] = mediaType + "; charset=utf-8";
// apply user-customized HTTP results via WebOperationContext.
- WebOperationContext.Current.OutgoingResponse.Apply (hp);
+ if (WebOperationContext.Current != null) // this formatter must be available outside ServiceHost.
+ WebOperationContext.Current.OutgoingResponse.Apply (hp);
// FIXME: fill some properties if required.
ret.Properties.Add (HttpResponseMessageProperty.Name, hp);
- var wp = new WebBodyFormatMessageProperty (ToContentFormat (msgfmt));
+ var wp = new WebBodyFormatMessageProperty (contentFormat);
ret.Properties.Add (WebBodyFormatMessageProperty.Name, wp);
return ret;
}
}
#endif
+
+ internal class RawMessage : Message
+ {
+ public RawMessage (Stream stream)
+ {
+ this.Stream = stream;
+ headers = new MessageHeaders (MessageVersion.None);
+ properties = new MessageProperties ();
+ }
+
+ public override MessageVersion Version {
+ get { return MessageVersion.None; }
+ }
+
+ MessageHeaders headers;
+
+ public override MessageHeaders Headers {
+ get { return headers; }
+ }
+
+ MessageProperties properties;
+
+ public override MessageProperties Properties {
+ get { return properties; }
+ }
+
+ public Stream Stream { get; private set; }
+
+ protected override void OnWriteBodyContents (XmlDictionaryWriter writer)
+ {
+ throw new NotSupportedException ();
+ }
+ }
}
}
using System;
+using System.IO;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
OperationDescription od = cd.Operations[0];
Assert.IsTrue (od.Behaviors.Contains (typeof (WebGetAttribute)), "Operation is recognized as WebGet");
}
+
+ [Test]
+ public void MessageFormatterSupportsRaw ()
+ {
+ var ms = new MemoryStream ();
+ var bytes = new byte [] {0, 1, 2, 0xFF};
+ ms.Write (bytes, 0, bytes.Length);
+ ms.Position = 0;
+ var cd = ContractDescription.GetContract (typeof (ITestService));
+ var od = cd.Operations [0];
+ var se = new ServiceEndpoint (cd, new WebHttpBinding (), new EndpointAddress ("http://localhost:37564/"));
+ var formatter = new WebHttpBehaviorExt ().DoGetReplyDispatchFormatter (od, se);
+
+ var msg = formatter.SerializeReply (MessageVersion.None, null, ms);
+ var wp = msg.Properties ["WebBodyFormatMessageProperty"] as WebBodyFormatMessageProperty;
+ Assert.IsNotNull (wp, "#1");
+ Assert.AreEqual (WebContentFormat.Raw, wp.Format, "#2");
+
+ var wmebe = new WebMessageEncodingBindingElement ();
+ var wme = wmebe.CreateMessageEncoderFactory ().Encoder;
+ var ms2 = new MemoryStream ();
+ wme.WriteMessage (msg, ms2);
+ Assert.AreEqual (bytes, ms2.ToArray (), "#3");
+ }
+ }
+
+ [ServiceContract]
+ public interface ITestService
+ {
+ [OperationContract]
+ Stream Receive (Stream input);
}
}