From: Atsushi Eno Date: Wed, 14 Jul 2010 08:43:31 +0000 (-0000) Subject: 2010-07-14 Atsushi Enomoto X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=74ec2c95efc7e4ea59c382e07584c8bfe8a934a7;p=mono.git 2010-07-14 Atsushi Enomoto * WebMessageFormatter.cs : add support for Raw format. * WebMessageEncoder.cs : support Raw message. Fixed bug #619542. * WebHttpBehaviorTest.cs : add test for bug #619542 (not sure if it works on mono; run-test is broken in trunk. Verified under .NET). svn path=/trunk/mcs/; revision=160341 --- diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/ChangeLog b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/ChangeLog index b6cdce47747..53703ef5c1a 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/ChangeLog +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/ChangeLog @@ -1,3 +1,7 @@ +2010-07-14 Atsushi Enomoto + + * WebMessageEncoder.cs : support Raw message. Fixed bug #619542. + 2010-06-22 Atsushi Enomoto * WebMessageEncodingBindingElement.cs : return MessageVersion in diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncoder.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncoder.cs index 45ce9448b9d..700ea9fab75 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncoder.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Channels/WebMessageEncoder.cs @@ -30,6 +30,7 @@ using System.IO; using System.Net.Mime; using System.Runtime.Serialization.Json; using System.ServiceModel; +using System.ServiceModel.Dispatcher; using System.Text; using System.Xml; @@ -177,7 +178,16 @@ namespace System.ServiceModel.Channels message.WriteMessage (w); break; case WebContentFormat.Raw: - throw new NotImplementedException (); + var rmsg = (WebMessageFormatter.RawMessage) message; + var src = rmsg.Stream; + if (src == null) // null output + break; + + int len = 0; + byte [] buffer = new byte [4096]; + while ((len = src.Read (buffer, 0, buffer.Length)) > 0) + stream.Write (buffer, 0, len); + break; case WebContentFormat.Default: throw new SystemException ("INTERNAL ERROR: cannot determine content format"); } diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/ChangeLog b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/ChangeLog index 96e6faa96f8..0110de19f4d 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/ChangeLog +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/ChangeLog @@ -1,3 +1,7 @@ +2010-07-14 Atsushi Enomoto + + * WebMessageFormatter.cs : add support for Raw format. + 2010-07-06 Atsushi Enomoto * WebMessageFormatter.cs : add NET_2_1 profile build. diff --git a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebMessageFormatter.cs b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebMessageFormatter.cs index 485e875832c..7d3180da0e7 100644 --- a/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebMessageFormatter.cs +++ b/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebMessageFormatter.cs @@ -28,12 +28,13 @@ 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; @@ -42,7 +43,7 @@ using System.Xml; using XmlObjectSerializer = System.Object; #endif -namespace System.ServiceModel.Description +namespace System.ServiceModel.Dispatcher { internal abstract class WebMessageFormatter { @@ -125,8 +126,10 @@ namespace System.ServiceModel.Description 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; @@ -287,7 +290,7 @@ namespace System.ServiceModel.Description // 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; @@ -336,17 +339,17 @@ namespace System.ServiceModel.Description 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; @@ -354,16 +357,28 @@ namespace System.ServiceModel.Description #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) @@ -419,8 +434,9 @@ namespace System.ServiceModel.Description 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); @@ -455,8 +471,8 @@ namespace System.ServiceModel.Description 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 @@ -465,12 +481,13 @@ namespace System.ServiceModel.Description 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; @@ -504,5 +521,38 @@ namespace System.ServiceModel.Description } } #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 (); + } + } } } diff --git a/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Description/ChangeLog b/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Description/ChangeLog index ba7c2d280d6..6c2a20b9bfa 100644 --- a/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Description/ChangeLog +++ b/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Description/ChangeLog @@ -1,3 +1,8 @@ +2010-07-14 Atsushi Enomoto + + * WebHttpBehaviorTest.cs : add test for bug #619542 (not sure if it + works on mono; run-test is broken in trunk. Verified under .NET). + 2009-10-08 Atsushi Enomoto * WebScriptEnablingBehaviorTest.cs : new test. diff --git a/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Description/WebHttpBehaviorTest.cs b/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Description/WebHttpBehaviorTest.cs index d7ebd9a8858..009ba909588 100644 --- a/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Description/WebHttpBehaviorTest.cs +++ b/mcs/class/System.ServiceModel.Web/Test/System.ServiceModel.Description/WebHttpBehaviorTest.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Channels; @@ -188,5 +189,36 @@ namespace MonoTests.System.ServiceModel.Description 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); } }