Open GoogleCodeExporter opened 9 years ago
This is an new feature request, not a defect. Anyway, to quote that msdn
document:
http://msdn.microsoft.com/en-us/library/bb412204.aspx
"Extending WebHttpBehavior
WebHttpBehavior is extensible by using a number of virtual methods:
GetOperationSelector, GetReplyClientFormatter, GetRequestClientFormatter,
GetReplyDispatchFormatter, and GetRequestDispatchFormatter. Developers can
derive a
class from WebHttpBehavior and override these methods to customize the default
behavior."
I'm not sure what the difference is between IClientMessageFormatter and
IDispatchMessageFormatter yet, but I imagine a ProtoMessageFormatter could
implement
one of those, then a WebProtoBehavior could override a couple of the
WebHttpBehavior
methods and provide it.
Original comment by cameron.taggart
on 5 May 2009 at 2:09
OK, it was IDispatchMessageFormatter that did the trick. Replies as Protocol
Buffers
are working with this code:
public class WebProtoBehavior : WebHttpBehavior
{
protected override IDispatchMessageFormatter
GetReplyDispatchFormatter(OperationDescription operationDescription,
ServiceEndpoint
endpoint)
{
return new ProtoDispatchMessageFormatter();
}
}
public class ProtoDispatchMessageFormatter : IDispatchMessageFormatter
{
public void DeserializeRequest(Message message, object[] parameters)
{
throw new NotImplementedException();
}
public Message SerializeReply(MessageVersion messageVersion, object[]
parameters, object result)
{
var contentType = "application/x-protobuf";
var format = WebContentFormat.Raw;
var type = result.GetType();
// from ProtoOperationBehavior.cs
var serializer = (XmlObjectSerializer)typeof(XmlProtoSerializer<>)
.MakeGenericType(type)
.GetConstructor(Type.EmptyTypes)
.Invoke(null);
WebOperationContext.Current.OutgoingResponse.ContentType = contentType;
OperationContext.Current.OutgoingMessageProperties.Add(
WebBodyFormatMessageProperty.Name, new
WebBodyFormatMessageProperty(format));
return Message.CreateMessage(MessageVersion.None, null, result,
serializer);
}
}
// had to comment out WriteStartElement, so did the same for WriteEndElement
class XmlProtoSerializer<T> : XmlObjectSerializer
{
public override void WriteEndObject(System.Xml.XmlDictionaryWriter writer)
{
//writer.WriteEndElement();
}
public override void WriteStartObject(System.Xml.XmlDictionaryWriter writer,
object graph)
{
//writer.WriteStartElement(PROTO_ELEMENT); // Exception
}
...
Original comment by cameron.taggart
on 7 May 2009 at 2:27
That looks really promising; any example usage? Is it just a case of decorating
methods/the interface/? with the behaviour? And if so, at client? server?
(basically, I'd love to put a unit test together and commit it)
Your input is hugely appreciated,
Marc
Original comment by marc.gravell
on 7 May 2009 at 7:03
I was able to get a WCF REST Service reply with Protocol Buffers (PB). I was
*not*
able to get a WCF REST client able to deserialze the reply. I tried multiple
ways
and this is an en excpetion where I feel I was close, but haven't figured out
how to
resolve this:
System.Runtime.Serialization.SerializationException was unhandled
Message="There was an error checking start element of object of type
Company.License. The data at the root level is invalid. Line 1, position 1."
Source="mscorlib"
StackTrace:
Server stack trace:
at
System.Runtime.Serialization.XmlObjectSerializer.IsStartObjectHandleExceptions(X
mlRea
derDelegator reader)
at
System.Runtime.Serialization.DataContractSerializer.IsStartObject(XmlDictionaryR
eader
reader)
at
System.ServiceModel.Dispatcher.SingleBodyParameterMessageFormatter.ReadObject(Me
ssage
message)
at
System.ServiceModel.Dispatcher.SingleBodyParameterMessageFormatter.DeserializeRe
ply(M
essage message, Object[] parameters)
at
System.ServiceModel.Dispatcher.DemultiplexingClientMessageFormatter.DeserializeR
eply(
Message message, Object[] parameters)
at
System.ServiceModel.Dispatcher.CompositeClientFormatter.DeserializeReply(Message
message, Object[] parameters)
at System.ServiceModel.Dispatcher.ProxyOperationRuntime.AfterReply(ProxyRpc&
rpc)
at
System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime
operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean
oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan
timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean
oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at
System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessag
e
methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage
reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
msgData, Int32 type)
Original comment by cameron.taggart
on 13 May 2009 at 8:29
[deleted comment]
I took a completely different approach and implemented a MessageEncoder that
begins
like this:
namespace ProtoBuf.ServiceModel.Web
{
public class ProtoMessageEncoder : MessageEncoder
{
I just got it working on the server side and the client side looks possible.
Another
approach may be to implement a custom DataContractSerializer, then wire it up
like
so:
http://tinyurl.com/rbwzl3
Original comment by cameron.taggart
on 16 May 2009 at 3:16
Interesting; anything concrete?
Original comment by marc.gravell
on 16 May 2009 at 8:46
I am probably going to give up for now on getting the WCF client working. I'm
getting quite frustrated with the WCF API, even with 3 books on hand. I posted
a
message here where I got stuck:
http://tinyurl.com/p22wvc
I got the WCF services serving protocol buffers with two different
implementations.
They work, but both must create MemoryStream buffers, which doesn't feel right.
WCF
is extremely XML centric.
Original comment by cameron.taggart
on 19 May 2009 at 2:05
I feel for your frustration. I hugely appreciate all the time you've spent
trying to
crack this; it must be painful that it (WCF) refuses to play the game...
It sounds like you've done a lot more digging in this area than I have, so I
can't
offer any sensible input - but really: thanks again for trying.
Regards,
Marc
Original comment by marc.gravell
on 19 May 2009 at 7:28
Marc, Cameron
Have you made any progress on this front.
I am currently using Damian Mehers approach to send back XML and JSON.
I need to add protobuf to that mix.
http://damianblog.com/2008/10/31/wcf-rest-dynamic-response/
if a working version of public
class WebProtoBehavior : WebHttpBehavior exist I think I can take it the rest
of the
way.
Herb
Original comment by ghst...@gmail.com
on 26 Aug 2009 at 9:48
Ok, so I don't know where Cameron got stuck, but I followed his lead and got it
all
to work end to end.
1) sync down r269
2) add the 3 files I have attached here
(ProtoDispatchMessageFormatter.cs,WebProtoBehavior.cs,
XmlProtoSerializerForRest.cs). This is all from camerons stuff.
3) I was enhanced Damian Mehers to also return protobuf stuff
http://damianblog.com/2008/10/31/wcf-rest-dynamic-response/
4) I wrote a test forms application that requests a protobuf response and
deserializes it correctly.
Original comment by ghst...@gmail.com
on 28 Aug 2009 at 5:46
Attachments:
Cool - interesting progress. This simply isn't something I've had chance to
progress,
so thanks.
Original comment by marc.gravell
on 28 Aug 2009 at 9:42
Original issue reported on code.google.com by
cameron.taggart
on 5 May 2009 at 1:41