Skip to content

ToCloudEventInternalAsync fails when using ContentMode.Binary in SystemTextJson and NewtonsoftJson #221

@squanbeck

Description

@squanbeck

Following this sample of code from the guide,

sdk-csharp/docs/guide.md

Lines 293 to 303 in 3ce4aa0

public class GameResult
{
[JsonProperty("playerId")]
public string PlayerId { get; set; }
[JsonProperty("gameId")]
public string GameId { get; set; }
[JsonProperty("score")]
public int Score { get; set; }
}

sdk-csharp/docs/guide.md

Lines 314 to 334 in 3ce4aa0

var result = new GameResult
{
PlayerId = "player1",
GameId = "game1",
Score = 200
};
var cloudEvent = new CloudEvent
{
Id = "result-1",
Type = "game.played.v1",
Source = new Uri("/game", UriKind.Relative),
Time = DateTimeOffset.UtcNow,
DataContentType = "application/json",
Data = result
};
var formatter = new JsonEventFormatter();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
Content = cloudEvent.ToHttpContent(ContentMode.Binary, formatter)
};

sdk-csharp/docs/guide.md

Lines 366 to 368 in 3ce4aa0

CloudEventFormatter formatter = new JsonEventFormatter<GameResult>();
CloudEvent cloudEvent = await request.ToCloudEventAsync(formatter);
GameResult result = (GameResult) cloudEvent.Data;

I end up with this error (line 151):

if (HasCloudEventsContentType(content))
{
var stream = await content.ReadAsStreamAsync().ConfigureAwait(false);
return await formatter.DecodeStructuredModeMessageAsync(stream, MimeUtilities.ToContentType(content.Headers.ContentType), extensionAttributes).ConfigureAwait(false);
}
else
{
string? versionId = headers.Contains(HttpUtilities.SpecVersionHttpHeader)
? headers.GetValues(HttpUtilities.SpecVersionHttpHeader).First()
: null;
if (versionId is null)
{
throw new ArgumentException($"Request does not represent a CloudEvent. It has neither a {HttpUtilities.SpecVersionHttpHeader} header, nor a suitable content type.", nameof(paramName));
}

When I looked further into it, it seems that the variable, "headers", is empty when using ContentMode.Binary. This is the case when using both SystemTextJson and NewtonsoftJson (likely when using the other packages as well, but these are the only ones I tested). However, I did notice that "content.headers" does contain the ce-specversion. Now, I am unsure if I am reading the CloudEvents specification correctly, but I think that this is in conformance, based off of my understanding that in binary mode, the event data need not be in the HTTP headers themselves, but rather in the message (in this case, the "content") metadata.

https://github.com/cloudevents/spec/blob/604fef3eea26801d1249bd7ee796e947d38cb5a1/cloudevents/spec.md?plain=1#L125-L134

If my understanding is accurate, does an extra check for "content.headers" containing ce-specversion need to exist here, somewhere around line 147?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions