Adding protobuf-net to my WCF Rest service
.net, protobuf-net, protocol-buffers, rest, wcf
Solution
The first thing to do is to add `Microsoft.AspNet.WebApi` ("Microsoft ASP.NET Web API Core Libraries (RC)") and `Microsoft.AspNet.WebApi.Client` ("Microsoft ASP.NET Web API Client Libraries (RC)") via NuGet.
This looks like the most promising walk-through: http://byterot.blogspot.co.uk/2012/04/aspnet-web-api-series-part-5.html
`MediaTypeFormatter` is in `System.Net.Http.Formatting`
I haven't got time right now to try and get it working, but you can PRESUMABLY add the formatter via:
GlobalConfiguration.Configuration.Formatters.Add(
new ProtobufMediaTypeFormatter(RuntimeTypeModel.Default));
With an example COMPLETELY UNTESTED implementation of something like:
public class ProtobufMediaTypeFormatter : MediaTypeFormatter
{
private readonly TypeModel model;
public override bool CanReadType(Type type)
{
return model.IsDefined(type);
}
public override bool CanWriteType(Type type)
{
return model.IsDefined(type);
}
public ProtobufMediaTypeFormatter() : this(null) {}
public ProtobufMediaTypeFormatter(TypeModel model) : base()
{
this.model = model ?? RuntimeTypeModel.Default;
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/protobuf"));
}
public override System.Threading.Tasks.Task<object> ReadFromStreamAsync(Type type, System.IO.Stream stream, HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
{
// write as sync for now
var taskSource = new TaskCompletionSource<object>();
try
{
taskSource.SetResult(model.Deserialize(stream, null, type));
} catch (Exception ex)
{
taskSource.SetException(ex);
}
return taskSource.Task;
}
public override System.Threading.Tasks.Task WriteToStreamAsync(Type type, object value, System.IO.Stream stream, HttpContentHeaders contentHeaders, System.Net.TransportContext transportContext)
{
// write as sync for now
var taskSource = new TaskCompletionSource<object>();
try
{
model.Serialize(stream, value);
taskSource.SetResult(null);
}
catch (Exception ex)
{
taskSource.SetException(ex);
}
return taskSource.Task;
}
}
I know virtually nothing about Web API, so please let me know if you manage to get it working for you. I will quite happily add a supported wrapper as a downloadable binary, but I can't do that until it works ;p
Problem
Is there any canonical straight way of enabling protobuf-net serialization on .NET 4 WCF? I tried to simplify code to the point where it can be easy to build on: Here is my service code: ``` [ServiceContract] [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class MobileServiceV2 { [WebGet(UriTemplate = "/some-data")] [Description("returns test data")] public MyResponse GetSomeData() { return new MyResponse { SomeData = "Test string here" }; } } [DataContract] public class MyResponse { [DataMember(Order = 1)] public string SomeData { get; set; } } ``` I'm activating this service route in `Application_OnStart` (Global.asax) like so: ``` RouteTable.Routes.Add(new ServiceRoute("mobile", new MyServiceHostFactory(), typeof(MobileServiceV2))); ``` I use `MyServiceHostFactory` to manage services with MEF, but that's irrelevant. Configuration of my service is all default, the only additional stuff in Web.Config is here: ``` <system.serviceModel> <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> <standardEndpoints> <webHttpEndpoint> <standardEndpoint helpEnabled="true" maxReceivedMessageSize="5242880" defaultOutgoingResponseFormat="Json" automaticFormatSelectionEnabled="true"> <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> </standardEndpoint> </webHttpEndpoint> </standardEndpoints> </system.serviceModel> ``` Ok, service alive and running. There is mobile/help, I can issue GET on mobile/some-data and getting response in both XML and JSON application/xml returns XML, application/json returns JSON What do I need to do so clients can set application/x-protobufs and get their response encoded using protobuf-net? I'm reading whole day and getting more and more confused... Here is what I found so far and nothing seems to give straight solution: http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/ http://weblogs.thinktecture.com/cweyer/2010/12/using-jsonnet-as-a-default-serializer-in-wcf-httpwebrest-vnext.html Second link is kind of what I need, but it doesnt work for me. Don't know why but I can't figure out which namespace `MediaTypeProcessor` lives in and just can't make it work in .NET4 ? Various scattered info about configuring protobuf-net via web.config give me different errors and I'm just not sure I need to go that way. I'd rather have code-only solution. EDIT: From what I researched - my bad, `MediaFormatter` seem to NOT be in current version of WCF. I wonder if creating separate URL for all protobuf clients will be best? This way I can receive Stream and return Stream. Handler all serializing logic manually. Little more work but I will have better control over actual data.