2

I was trying to implement a subclass of ActionResult that will stream big JSON objects from a REST API, I found this solution on stack overflow but it seems like it's an implementation for asp.net MVC.

public class JsonStreamingResult : ActionResult
{
    private IEnumerable itemsToSerialize;

    public JsonStreamingResult(IEnumerable itemsToSerialize)
    {
        this.itemsToSerialize = itemsToSerialize;
    }

    public override void ExecuteResult(ActionContext context)
    {
        var response = context.HttpContext.Response;
        response.ContentType = "application/json";
        response.ContentEncoding = Encoding.UTF8;

        JsonSerializer serializer = new JsonSerializer();

        using (StreamWriter sw = new StreamWriter(response.OutputStream))
        using (JsonTextWriter writer = new JsonTextWriter(sw))
        {
            writer.WriteStartArray();
            foreach (object item in itemsToSerialize)
            {
                JObject obj = JObject.FromObject(item, serializer);
                obj.WriteTo(writer);
                writer.Flush();
            }
            writer.WriteEndArray();
        }
    }
}

But when I was in the process of porting this to asp.net core MVC I found that the response class does not have ContentEncoding and OutputStream properties.

Please, can anyone provide the required changes to port this class to asp.net core?

Thanks in advance.

13
  • 2
    Are you sure you need that in the first place? When you call return Json(someObject) you get back a JsonResult object that eventually uses a JsonWriter to write to the response output stream. Have you tried returning your data in the normal way? Commented Apr 11, 2019 at 11:36
  • @PanagiotisKanavos Please see this question, I have the same issue : stackoverflow.com/questions/26269438/… Commented Apr 11, 2019 at 11:43
  • That question isn't about ASP.NET Core and the problem there was caused by the attempt to manually serialize the data. Do you have an actual problem? Have you tried using return Json()? I posted links to the source code that show that ASP.NET Core already writes to the output stream Commented Apr 11, 2019 at 11:49
  • 2
    How do you know? Did you time the entire action execution or the serialization parts? If the connection is slow, retrieving the data will take a lot of time. If loading the data is slow, the entire operation will take a lot of time no matter how the data is serialized. You'll have to profile your code, or at least debug it and see what's actually taking that long. Commented Apr 11, 2019 at 12:00
  • 1
    How about stop returning so much data at once? JSON is pretty verbose: not as verbose as XML, but that's not really saying much. Returning 20,000 JSON objects is going to take a while - no matter what you do. The correct approach here is to page the results. Return something like 100 at a time, and then allow the client to request the next "page" of 100 results when they actually want it. This is far more efficient anyways, as it would be rare that all 20,000 are actually needed. Commented Apr 11, 2019 at 17:36

1 Answer 1

3

OutputStream - in ASP.NET Core HttpResponse contains Body property to which you can write a response. ContentEncoding - set encoding for StreamWriter since you manually write result to the response stream. In ASP.NET MVC HttpResponse.ContentEncoding were only used when you called HttpResponse.Write methods.

public class JsonStreamingResult : ActionResult
{
    private IEnumerable itemsToSerialize;

    public JsonStreamingResult(IEnumerable itemsToSerialize)
    {
        this.itemsToSerialize = itemsToSerialize;
    }

    public override void ExecuteResult(ActionContext context)
    {
        var response = context.HttpContext.Response;
        response.ContentType = "application/json";

        JsonSerializer serializer = new JsonSerializer();

        using (StreamWriter sw = new StreamWriter(response.Body, Encoding.UTF8))
        using (JsonTextWriter writer = new JsonTextWriter(sw))
        {
            writer.WriteStartArray();
            foreach (object item in itemsToSerialize)
            {
                JObject obj = JObject.FromObject(item, serializer);
                obj.WriteTo(writer);
                writer.Flush();
            }
            writer.WriteEndArray();
        }
    }
}

Update

According to source code, JsonResultExecutor internally does exactly what I've described, only difference is it parses encoding from ContentType.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.