将protobuf-net添加到我的WCF Rest服务

时间:2012-07-20 03:03:10

标签: .net wcf rest protocol-buffers protobuf-net

是否有任何规范的直接方式在.NET 4 WCF上启用protobuf-net序列化?我试图简化代码,使其易于构建:

这是我的服务代码:

[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; }
}

我正在Application_OnStart(Global.asax)中激活此服务路线,如下所示:

RouteTable.Routes.Add(new ServiceRoute("mobile", new MyServiceHostFactory(), typeof(MobileServiceV2)));

我使用MyServiceHostFactory来管理MEF服务,但这无关紧要。

我的服务配置都是默认设置,Web.Config中唯一的附加内容就在这里:

<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>

好的,服务还活着。有移动/帮助,我可以在移动/某些数据上发出GET并在XML和JSON中获得响应

application / xml返回XML,application / json返回JSON

我需要做什么才能让客户端设置application / x-protobuf并使用protobuf-net编码响应?

我整天都在读书,越来越困惑......

这是我到目前为止所发现的,似乎没有什么能给出直接解决方案:

  1. http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/

  2. http://weblogs.thinktecture.com/cweyer/2010/12/using-jsonnet-as-a-default-serializer-in-wcf-httpwebrest-vnext.html

  3. 第二个链接是我需要的东西,但它对我不起作用。不知道为什么,但我无法弄清楚哪个命名空间MediaTypeProcessor存在并且无法使其在.NET4中运行?

    关于通过web.config配置protobuf-net的各种分散信息给了我不同的错误,我只是不确定我是否需要这样做。我宁愿使用纯代码解决方案。

    编辑:

    根据我的研究 - 我的不好,MediaFormatter似乎不在当前版本的WCF中。我想知道为所有protobuf客户创建单独的URL是否最好?这样我就可以收到Stream并返回Stream。处理程序所有手动序列化逻辑。更多的工作,但我将更好地控制实际数据。

1 个答案:

答案 0 :(得分:3)

要做的第一件事是添加Microsoft.AspNet.WebApi(“Microsoft ASP.NET Web API核心库(RC)”)和Microsoft.AspNet.WebApi.Client(“Microsoft ASP.NET Web API客户端库(RC)” “)通过NuGet。

这看起来是最有希望的演练:http://byterot.blogspot.co.uk/2012/04/aspnet-web-api-series-part-5.html

MediaTypeFormatter位于System.Net.Http.Formatting

我没有时间现在尝试让它正常工作,但你可以 PRESUMABLY 通过以下方式添加格式化程序:

GlobalConfiguration.Configuration.Formatters.Add(
    new ProtobufMediaTypeFormatter(RuntimeTypeModel.Default));

使用示例 COMPLETELY UNTESTED 实现类似的内容:

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;
    }
}

我对Web API几乎一无所知,所以如果你设法让它为你工作,请告诉我。我很乐意添加一个支持的包装器作为可下载的二进制文件,但在它工作之前我不能这样做; p