5

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

わかりました、サービスは稼働しています。mobile/help があります。mobile/some-data で GET を発行し、XML と JSON の両方で応答を取得できます

application/xml は XML を返し、application/json は JSON を返します。

クライアントが application/x-protobufs を設定し、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

2番目のリンクは私が必要としているものですが、うまくいきません。理由はわかりませんが、どの名前空間が存在するのかわかりませんMediaTypeProcessor.NET4で動作させることはできませんか?

web.config を介した protobuf-net の構成に関するさまざまな散在する情報により、さまざまなエラーが発生し、そのようにする必要があるかどうかわかりません。コードのみのソリューションが必要です。

編集:

私が調査したことから、私の悪いMediaFormatter点は、現在のバージョンの WCF にはないようです。すべての protobuf クライアントに対して個別の URL を作成するのが最善でしょうか? このようにして、Stream を受け取り、Stream を返すことができます。すべてのシリアル化ロジックを手動で処理します。これ以上の作業はありませんが、実際のデータをより適切に制御できるようになります。

4

1 に答える 1

3

最初に行うことは、NuGetを介してMicrosoft.AspNet.WebApi( "Microsoft ASP.NET Web APIコアライブラリ(RC)")と( "Microsoft ASP.NET Web APIクライアントライブラリ(RC)")を追加することです。Microsoft.AspNet.WebApi.Client

これは最も有望なウォークスルーのように見えます:http://byterot.blogspot.co.uk/2012/04/aspnet-web-api-series-part-5.html

MediaTypeFormatterにありますSystem.Net.Http.Formatting

のところ、動作させるための時間がありませんが、おそらく次の方法でフォーマッターを追加できます。

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

次のような完全にテストされていない実装の例を使用します。

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

私はWebAPIについてほとんど何も知らないので、うまく機能させることができたら教えてください。サポートされているラッパーをダウンロード可能なバイナリとして非常に喜んで追加しますが、機能するまでそれを行うことはできません; p

于 2012-07-20T13:41:51.507 に答える