ASP.NET MVC Controller cannot return HttpResponseMessage correctly with streamed content

12,050

Solution 1

Thanks to Phil I got it to work by having the MVC controller return FileStreamResult.

Here is the code

    public ActionResult GetDataAsJsonStream()
    {
        object returnObj = new
        {
            Name = "Alice",
            Age = 23,
            Pets = new List<string> { "Fido", "Polly", "Spot" }
        };

        var stream = new MemoryStream().SerializeJson(returnObj);
        stream.Position = 0;

        return File(stream, "application/json");
    }

UPDATE

A better way to do this is to write directly to the response stream without creating a memory stream

    public ActionResult GetJsonStreamWrittenToResponseStream()
    {
        object returnObj = new
        {
            Name = "Alice",
            Age = 23,
            Pets = new List<string> { "Fido", "Polly", "Spot" }
        };

        Response.ContentType = "application/json";
        Response.OutputStream.SerializeJson(returnObj);

        return new EmptyResult();
    }

Solution 2

Perhaps try returning an ActionResult from your MVC method instead.

public ActionResult GetDataAsJsonStream() {}

In order to return a stream, you'll likely have to use FileStreamResult. What would be even easier is just returning a JsonResult.

public ActionResult GetDataAsJson()
{
    object returnObj = new
    {
        Name = "Alice",
        Age = 23,
        Pets = new List<string> { "Fido", "Polly", "Spot" }
    };

    return Json(returnObj, JsonRequestBehavior.AllowGet);
}

This is pseudo code but the concept should be sound.

Share:
12,050
superfly71
Author by

superfly71

Updated on June 04, 2022

Comments

  • superfly71
    superfly71 over 1 year

    Just as the title says I am not getting the MVC Controller to return HttpResponseMessage correctly.

        [HttpGet]
        [AllowAnonymous]
        public HttpResponseMessage GetDataAsJsonStream()
        {
            object returnObj = new
            {
                Name = "Alice",
                Age = 23,
                Pets = new List<string> { "Fido", "Polly", "Spot" }
            };
    
            var response = Request.CreateResponse(HttpStatusCode.OK);
            var stream = new MemoryStream().SerializeJson(returnObj);
            stream.Position = 0;
            response.Content = new StreamContent(stream);
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    
            return response;
        }
    

    This is what I got using MVC Controller:

    Incorrect result

    It works fine when using WebApi ApiController

    Correct result

    Correct me if I'm wrong I think the problem is MVC is serializing HttpResponseMessage instead of returning it.

    By the way I am using MVC 5.

    Thanks in advance.

    EDIT I would like to have the flexibility to write to the response stream directly when returning large datasets.

  • superfly71
    superfly71 over 7 years
    Thanks Phil. I am aware of the Json() controller method. What I am concerned is when returning large datasets. Json() will first serialize into Json objects in memory before writing it out to the response stream. I like to write to the stream directly so it won't eat up memory.
  • Phil Cooper
    Phil Cooper over 7 years
    @superfly71 if that's the case and it's probably something you should have mentioned in your question, you could probably use FileStreamResult with a contentType of 'application/json'.
  • Phil Cooper
    Phil Cooper over 7 years
    @superfly71 nice :) that will definitely give some context around this when someone stumbles upon this question in the not so distant future.