Stream endpoint change after 4.5.8

Hi there. I have just migrated from version 4.5.8 to 4.5.14.

I’ve noticed (from broken tests) a breaking change in an endpoint that we serve images from.
I think the bytes coming back from it are somehow different than they used to be in v 4.5.8.
My service looks like this:

        [AddHeader(ContentType = MimeTypes.ImagePng)]
        public Stream Get(GetPngPic body)
        {
            ...serve up an image stream from storage
        }

On the client I am doing this:

    var bytes = "https://localhost/api/images/1234.png".GetBytesFromUrl();
    var stream = new MemoryStream(bytes);
    var image = (Bitmap)Image.FromStream(stream);

that last line is throwing an exception now: System.ArgumentException: Parameter is not valid.

Has anything changed between 4.5.8 and 4.5.14 that would affect this?

It’s impossible to tell what change made between v4.5.8 released on 2017-03-29 and 4.5.14 released 2017-09-06 is the cause for some random Exception. There’s even less chance to identify it without its full StackTrace showing what’s throwing the Exception.

Like any issues, check to see if it’s been resolved with the latest version, if it’s still an issue, include a stand-alone repro I can run locally to repro the issue and I’ll investigate and identify what the issue is.

Yep fair call.
Sorry, we are not yet up to date with 5.x yet.

OK, here is a simple repro: https://www.dropbox.com/s/rqc9ny62pyeeqjb/ServiceStackBug.zip?dl=0

You can see that the service returns an image in a stream endpoint.
It works in 4.5.8, 4.5.10 and 4.5.12, but at 4.5.14 it breaks.

I do see some changes noted in the Release Notes for 4.5.14 but nothing clues in me to what has changed.

UPDATE: I noticed that it works again in 5.0.2, (but still broken in 4.5.14 and 5.0.0)

So, it would be really helpful if I could identify what code I need to use as a patch in my code at version 4.5.14 temporarily to make it work, until we can upgrade past 5.0.2.
Do you guys know?

I thought the difference would be in ServiceStack.Text between 5.0.0 and 5.0.2, since GetBytesFromUrl() is in HttpUtils which is in ServiceStack.Text.
But not seeing much change there that could be related, except the addition to PclExport stuff.

Is that where the fix is?

Sorry, I dont know this codebase well enough to know where to look.

If I add this test to the mix, that uses HttpClient I think I can conclude that the problem is not in the client, but in the server code? correct?


        [TestMethod]
        public async Task WhenGetPicWithHttpClient_ThenReturnsPic()
        {
            var url = _baseUrl
                .CombineWith(new GetPng().ToGetUrl());

            var client = new HttpClient();
            var stream = await client.GetStreamAsync(url);

            //BUG: When version 4.5.14
            //BUG: This line throws: System.ArgumentException: Parameter is not valid.
            var image = (Bitmap) Image.FromStream(stream); 

            Assert.AreEqual(48, image.Width);
            Assert.AreEqual(48, image.Height);
        }

Could this have been the fix?

If it is, what do you think I can do in v 4.5.14 to workaround it?

(4.5.14 is the last version before moving to 5.X which I cannot do at the moment)

If you’re returning a Stream you can reset it in your Service:

stream.Position = 0;
return stream;

Or adding a Global Response Filter that does it:

GlobalRequestFilters.Add((req, res, dto) => {
    if (dto is Stream stream && stream.CanSeek)
    {
        stream.Position = 0;
    }
});

Yep, sweet! that works as a neat workaround for 4.5.14. thanks

p.s. the filter would be:

            GlobalResponseFilters.Add((req, res, dto) =>
            {
                var stream = dto as Stream;
                if (stream != null && stream.CanSeek)
                {
                    stream.Position = 0;
                }
            });

That’s only if you’re using an old version of C#.

I have to ask @mythz, don’t shoot the messenger!

Is there any chance your team would do a 4.5.15 fix to include this fix.
To support those that
(a) may have this bug, but don’t know it yet (i.e. they had no tests to detect it yet, and have code out in the wild with this introduced bug),
(b) stuck on 4.X and cant go to 5.X yet, because of size of migration work?

No, all fixes are forward only, made to the current version. You can customize your own fork at the version of the source code release.

But I can’t imagine upgrading to v5 would require that much effort.