dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.35k stars 9.99k forks source link

[Question] Proper way of writing a JSON response in middleware using HttpContext.Response? #19891

Closed kikaragyozov closed 4 years ago

kikaragyozov commented 4 years ago
public static async Task WriteJsonResponseAsync(this HttpContext context, JsonOptions options, int statusCode, object jsonObject)
{
    // Serialize using the settings provided
    using MemoryStream stream = new MemoryStream();
    await JsonSerializer.SerializeAsync(stream, jsonObject, typeof(SomeGenericType), options.JsonSerializerOptions);
    ReadOnlyMemory<byte> readOnlyMemory = new ReadOnlyMemory<byte>(stream.ToArray());

    // Set the status code
    context.Response.StatusCode = statusCode;

    // Set the content type
    context.Response.ContentType = "application/json; charset=utf-8";

    // Write the content
    await context.Response.Body.WriteAsync(readOnlyMemory);
    await context.Response.Body.FlushAsync();
}

Is the above the correct way to do it for UTF8 json content? The JsonOptions passed are the default ones used in an ASP.NET Core 3.1 application.

Alternatively, from IdentityServer's library, do we just do the following:

public static async Task WriteJsonAsync(this HttpResponse response, string json, string contentType = null)
{
    response.ContentType = (contentType ?? "application/json; charset=UTF-8");
    await response.WriteAsync(json);
    await response.Body.FlushAsync();
}

I'm not sure which is the more correct way, and which yields the same performance as when ASP.NET Core itself does the heavy lifting (serialization).

How is it being done there? Is it using streams like here, or something else entirely? My goal is to do the same heavy-lifting ASP.NET Core 3.1 originally does for serialization of objects.

Thank you.

davidfowl commented 4 years ago

The latter will scale better as content gets larger as you can avoid buffering the entire object in memory first.

kikaragyozov commented 4 years ago

@davidfowl Thank you for answering! Is it okay then to use JsonSerializer.Serialize(Object, Type, JsonSerializerOptions) to avoid all of the above streams and what-not in order to create my json string? I'm not sure if that's done in an utf-8 way. The only method that seems to do utf-8 json conversion requires usage of streams?

davidfowl commented 4 years ago

Everything on the JSONSerializer is Utf8 only.