neontapir
neontapir

Reputation: 4736

Why is the response content in this streaming service example empty?

I could really use some help understanding why this unit test is failing. I suspect it's due to the way I'm handling the streams. I have a number of other tests that successfully use this self-hosting server setup, but they all read services that return primitives like strings.

Here's the test in question:

using System.Net.Http;
using System.Threading;
using System.Web.Http.SelfHost;
using AttributeRouting.Web.Http.SelfHost;
using NUnit.Framework;

[TestFixture]
public class StreamControllerTests 
{
    [Test]
    public void Can_get_simple_streaming_service_to_respond()
    {
        using (var config = new HttpSelfHostConfiguration("http://in-memory"))
        {
            config.Routes.MapHttpAttributeRoutes();
            using (var server = new HttpSelfHostServer(config))
            {
                // I get the same behavior if I use HttpClient
                using (var client = new HttpMessageInvoker(server))
                {
                    using (var request = new HttpRequestMessage(HttpMethod.Get, "http://in-memory/stream/notepad"))
                    {
                        using (HttpResponseMessage response = client.SendAsync(request, CancellationToken.None).Result)
                        {
                            Assert.IsNotNull(response.Content);
                            // FAILS, content length is 0
                            Assert.Greater(response.Content.Headers.ContentLength, 0); 
                        }
                    }
                }
            }
        }

And here is the controller that feeds the test:

using System;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using AttributeRouting.Web.Mvc;
using MyUnitTests.Properties;

[GET("stream/notepad")]
public HttpResponseMessage StreamAnImageFromResources()
{
    var imageStream = new MemoryStream(); // closed when stream content is read
    Resources.a_jpeg_in_resources.Save(imageStream, ImageFormat.Jpeg);
    try
    {                               
        HttpResponseMessage response = Request.CreateResponse();
        // at this point, imageStream contains about 120K bytes
        response.Content = new StreamContent(imageStream); 
        return response;            
    }
    catch (Exception e)
    {
        return Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, e);
    }
}

Upvotes: 2

Views: 1264

Answers (1)

Darrel Miller
Darrel Miller

Reputation: 142044

I don't see anything really wrong but your test is more complicated than it needs to be.

Try this,

[Test]
public void Can_get_simple_streaming_service_to_respond2()
{
    var config = new HttpConfiguration();
    config.Routes.MapHttpAttributeRoutes();
    var server = new HttpServer(config);

    var client = new HttpClient(server);

    var request = new HttpRequestMessage(HttpMethod.Get, "http://in-memory/stream/notepad");

    HttpResponseMessage response = client.SendAsync(request, CancellationToken.None).Result;

    Assert.IsNotNull(response.Content);
    // FAILS, content length is 0
    Assert.Greater(response.Content.Headers.ContentLength, 0);
}

EDIT: In the comments, Darrel gave me the true answer, which I'm moving to the answer body for visibility:

Check the position of your image stream after doing Save. You need to reset it back to 0 before passing to StreamContent. Also, you might want to consider doing GetManifestResourceStream instead, it will save copying the bytes into managed memory.

Upvotes: 2

Related Questions