2017-01-02 9 views
2

クライアントから送信された要求を圧縮します。私は、Q/Aは検出されませんでしたServiceStackクライアント圧縮

ServiceStack - How To Compress Requests From Client

をしかし、このコードを使用したとき、私は内容が「{」とない「\ u001F ...」で始まる必要があり、サーバからSerializationExceptionを取得します

この解決方法はまだ有効ですか、またはクライアント要求ペイロードを圧縮する別の方法がありますか?


更新1:ここにFiddlerからの出力があります。リクエスト:

POST http://xxxxxx:8104/entries HTTP/1.1 
Accept: application/json 
User-Agent: ServiceStack .NET Client 4,51 
Accept-Encoding: gzip,deflate 
Content-Encoding: gzip 
Content-Type: application/json 
Host: xxxxxx:8104 
Content-Length: 187 
Expect: 100-continue 

[binary data not shown here] 

と応答:

HTTP/1.1 400 Bad Request 
Transfer-Encoding: chunked 
Content-Type: application/json; charset=utf-8 
Server: Microsoft-HTTPAPI/2.0 
Date: Tue, 03 Jan 2017 07:22:57 GMT 

427 
{"ResponseStatus":{"ErrorCode":"SerializationException","Message":"Could not deserialize 'application/json' request using Namespace.NameOfDto'\nError: System.Runtime.Serialization.SerializationException: Type definitions should start with a '{', expecting serialized type 'NameOfDto', got string starting with: \u001F \b\u0000\u0000\u0000\u0000\u0000\u0004\u00005 \n @\u0010 e 1 P W :h\u001D :D M'YЙ \u001D B| F 7 \r\n at ServiceStack.Text.Common.DeserializeTypeRefJson.StringToType(TypeConfig typeConfig, String strType, EmptyCtorDelegate ctorFn, Dictionary`2 typeAccessorMap)\r\n at ServiceStack.Text.Common.DeserializeType`1.<>c__DisplayClass1_0.<GetParseMethod>b__1(String value)\r\n at ServiceStack.Text.JsonSerializer.DeserializeFromString(String value, Type type)\r\n at ServiceStack.Text.JsonSerializer.DeserializeFromStream(Type type, Stream stream)\r\n at ServiceStack.Serialization.JsonDataContractSerializer.DeserializeFromStream(Type type, S 
27e 
tream stream)\r\n at ServiceStack.Host.Handlers.ServiceStackHandlerBase.CreateContentTypeRequest(IRequest httpReq, Type requestType, String contentType)","StackTrace":" at ServiceStack.Host.Handlers.ServiceStackHandlerBase.CreateContentTypeRequest(IRequest httpReq, Type requestType, String contentType)\r\n at ServiceStack.Host.RestHandler.CreateRequest(IRequest httpReq, IRestPath restPath, Dictionary`2 requestParams)\r\n at ServiceStack.Host.RestHandler.CreateRequest(IRequest httpReq, IRestPath restPath)\r\n at ServiceStack.Host.RestHandler.ProcessRequestAsync(IRequest httpReq, IResponse httpRes, String operationName)"}} 
0 

クライアント:

public class GzipJsonServiceClient : JsonServiceClient 
{ 
    public GzipJsonServiceClient() 
    { 
     SetRequestFilter(); 
    } 

    public GzipJsonServiceClient(string baseUri) 
     : base(baseUri) 
    { 
     SetRequestFilter(); 
    } 

    public override void SerializeToStream(IRequest requestContext, object request, Stream stream) 
    { 
     using (var gzipStream = new GZipStream(stream, CompressionMode.Compress)) 
     { 
      base.SerializeToStream(requestContext, request, gzipStream); 
      gzipStream.Close(); 
     } 
    } 

    private void SetRequestFilter() 
    { 
     RequestFilter = req => 
     { 
      if (req.Method.HasRequestBody()) 
      { 
       req.Headers.Add(HttpRequestHeader.ContentEncoding, CompressionTypes.GZip); 
      } 
     }; 
    } 
} 

リクエストコード:

サービス側は、Visual Studioテンプレートからである
var client = new GzipJsonServiceClient(uri) { Timeout = TimeSpan.FromSeconds(10) }; 
var request = new NameOfDto(); 
client.Post(request); 

、ホスティングServiceStack Windows内のサービスサービス。私はNewtonsoft JSONのnugetを使用して、私の問題を解決する方法を考え出し、

public void Post(NameOfDto request) 
{ 
    var appHost = (AppHost)HostContext.AppHost; 
    ... 
} 
+0

質問を更新して、使用しているコードと生のHTTPリクエスト/レスポンスヘッダーをFiddlerのようなものを使って表示できますか? – mythz

答えて

1

サポート:

public static class GZipRequestStreamParser 
{ 
    public static T ParseRequestStream<T>(Stream requestStream) 
    { 
     using (var gzipStream = new GZipStream(requestStream, CompressionMode.Decompress)) 
     using (var reader = new StreamReader(gzipStream)) 
     { 
      var serializedObject = reader.ReadToEnd(); 
      var deserializedObject = JsonConvert.DeserializeObject<T>(serializedObject); 
      return deserializedObject; 
     } 
    } 
} 

は、最後にエンドポイントを更新しました+ Deflate圧縮がServiceStack HttpListener ServerとすべてのC#サービスクライアントに追加されましたthis commitにあります。

これは、あなたが新しいRequestCompressionTypeプロパティでクライアントの要求を送信することができます、例えば:

var client = new JsonServiceClient(baseUrl) 
{ 
    RequestCompressionType = CompressionTypes.GZip, 
}; 

var response = client.Post(new NameOfDto { ... }); 

この機能は、v4.5.5から入手可能です+それは今available on MyGetです。

+0

問題があります...ユニットテストで、Helloのクラスに "public List Dummy {get; set;}"を追加して文字列を入力すると、HelloServiceのAnyメソッドでnullとして到着します。何か案は? –

+0

@MartinAこの質問を更新するか、reproに十分なコードを付けて新しい質問をしてください – mythz

+0

ここにフォローアップの質問を追加しました:http://stackoverflow.com/questions/41466387/servicestack-client-compression-fails-with-generic-リスト –

0

OK:それは達していない1つの方法で、かなりバニラです。私がDTOを変更する必要のないServiceStackの「すぐに使える」ソリューションがあれば好きですが、

私は私のDTOにIRequiresRequestStreamインタフェースを追加しました:その後

[Route("/entries", "POST")] 
public class NameOfDto : IRequiresRequestStream 
{ 
    [ApiMember(IsRequired = true)] 
    public string OneOfManyProperties { get; set; } 

    public Stream RequestStream { get; set; } 
} 

は、新しいクラスを作成します。クライアントにGzipため

public void Post(NameOfDto request) 
{ 
    request = GZipRequestStreamParser.ParseRequestStream<NameOfDto>(request.RequestStream); 

    var appHost = (AppHost)HostContext.AppHost; 

    // work with request object! 
}