dotnet-sdk icon indicating copy to clipboard operation
dotnet-sdk copied to clipboard

Issue with HTTP call formatting in DaprClient

Open Hsuwen opened this issue 3 years ago • 2 comments

I am using DaprClient for HTTP calls. I'm having an issue with the format of the response when getting the string of the response via a get request.

My RPC (my-app):

[HttpGet] public IActionResult Test() { return Ok("my string text"); }

DaprClient Invoke 1:

string str = await daprClient.InvokeMethodAsync<string>(HttpMethod.Get, "my-app", "test"); I got "Dapr.Client.InvocationException" exception: An exception occurred while invoking method: my-app on app-id: test. And the InnerException "System.Text.Json.JsonException": \u00270xE6\u0027 is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.

DaprClient Invoke 2:

Next, I tried a more low-level call: var req = daprClient.CreateInvokeMethodRequest(HttpMethod.Get, "my-app", "test"); var res = await daprClient.InvokeMethodWithResponseAsync(req); return Ok(new { a = res.StatusCode, b = await res.Content.ReadAsStringAsync(), }); Then I got the result: { "a": 200, "b": "my string text" } It can be seen that it responds in "text/plain" format. If it is "application/json", the value of b will be "\"my string text\"".

Summarize:

I looked at the source code for "CreateInvokeMethodRequest" in "DaprClientGrpc.cs" and none of the HTTP calls explicitly specify "Accept" (eg: application/json). However, JSON serialization is declared in the annotation of the generic method. So not specifying the Accept header, is it "incomplete"? In the case of "my-app", it responds in "text/plain" format by default, which makes JSON formatting impossible.

Hsuwen avatar Sep 22 '22 02:09 Hsuwen

I think the comment in the source code mentions "The type of the data that will be JSON deserialized from the response body" is ambiguous, which would mean that the SDK internally defines the "JSON" format and then doesn't actually specify "Accept" .

Please confirm.

Hsuwen avatar Sep 22 '22 02:09 Hsuwen

I don't believe we specify any content headers, though you could yourself by providing an appropriate httpclient/factory to the client construction.

InvokeMethodAsync<TResponse>() does try and deserialize whatever the response is into the given object. Since you aren't passing an object back, but rather a raw string, the serialization fails.

halspang avatar Sep 23 '22 19:09 halspang