Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question, C# generated client: Is there a way to stream large json's? #4236

Open
byte3 opened this issue Nov 19, 2022 · 2 comments
Open

Question, C# generated client: Is there a way to stream large json's? #4236

byte3 opened this issue Nov 19, 2022 · 2 comments

Comments

@byte3
Copy link

byte3 commented Nov 19, 2022

I want to send a large json through a nswag generated csharp client.

My problem is with the generated code:

var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(model, _settings.Value);
var content_ = new System.Net.Http.StringContent(json_);

Serializing model into a json string essentialy doubles the memory consumption.

I would like to serialze the json into a stream and use StreamContent instead of StringContent.
Like it is explained here: https://johnthiriet.com/efficient-post-calls/

Is there a way to generate a client that way?
By looking at the source code it does not seem possible. But maybe is missed something.

@dittodhole
Copy link

dittodhole commented Jan 14, 2023

I have the same question, since I migrated one of our clients to a swagger definition and generating the client with NSwag - actually, one API even has a bulk-insert endpoint (there could be additional optimization done on providing the stream in chunks).

I've actually found an interesting part here (operation.HasBinaryBodyParameter):

{% if operation.HasBinaryBodyParameter -%}
{% if operation.ContentParameter.HasBinaryBodyWithMultipleMimeTypes -%}
var content_ = new System.Net.Http.StreamContent({{ operation.ContentParameter.VariableName }}.Data);
content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse({{ operation.ContentParameter.VariableName }}.ContentType);
{% else -%}
var content_ = new System.Net.Http.StreamContent({{ operation.ContentParameter.VariableName }});
content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("{{ operation.Consumes }}");
{% endif -%}

The default branch is this here:

{% else -%}
var json_ = {% if UseSystemTextJson %}System.Text.Json.JsonSerializer.Serialize{% else %}Newtonsoft.Json.JsonConvert.SerializeObject{% endif %}({{ operation.ContentParameter.VariableName }}, {% if SerializeTypeInformation %}typeof({{ operation.ContentParameter.Type }}), {% endif %}{% if UseRequestAndResponseSerializationSettings %}_requestSettings{% else %}_settings{% endif %}.Value);
var content_ = new System.Net.Http.StringContent(json_);
content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("{{ operation.Consumes }}");

But could also be this here (operation.HasPlainTextBodyParameter):

{% elsif operation.HasPlainTextBodyParameter -%}
var content_ = new System.Net.Http.StringContent({{ operation.ContentParameter.VariableName }});
content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("{{ operation.Consumes }}");

Some idea how to declare the operation body binary somehow?

Best

@gklittlejohn
Copy link

I managed to do this by using a custom Client.Class.liquid template (setting templateDirectory in the .nswag) and using a custom content that writes to the request stream directly. Obviously this is not idea using a custom template.

System.Net.Http.Json looks like it takes this same approach but I'm not sure if there are any issues with this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants