Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TestServer ignores stream position passed through StreamContent #33780

Closed
afkos opened this issue Jun 23, 2021 · 3 comments
Closed

TestServer ignores stream position passed through StreamContent #33780

afkos opened this issue Jun 23, 2021 · 3 comments
Labels
area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions ✔️ Resolution: Won't Fix Resolved because we decided not to change the behavior reported in this issue. Status: Resolved

Comments

@afkos
Copy link

afkos commented Jun 23, 2021

Describe the bug

When using TestServer, HttpClient sends the whole stream from the start, the actual position in the stream is ignored.
Test below shows passing stream with length = 3 and position = 1
I expect that only 2 bytes would be passed to the controller
The same problem with FileStream and with any stream that support Seek operation.

To Reproduce

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace TestProject1
{
    public class UnitTest1
    { 
        [Fact]
        public async void Test1()
        {
            var server = new TestServer(new WebHostBuilder().UseStartup<Startup>());

            using var client = server.CreateClient();

            using var mem = new MemoryStream(new byte[] { 1, 2, 3 });

            // set stream offset 
            mem.Position = 1;

            using var msg = new HttpRequestMessage(HttpMethod.Put, "Upload") { Content = new StreamContent(mem) };
            using var resp = await client.SendAsync(msg);
            
            var actualLength = await resp.EnsureSuccessStatusCode().Content.ReadAsStringAsync();

            Assert.Equal("2", actualLength);
        }
    }

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseRouting();
            app.UseEndpoints(endpoints => endpoints.MapControllers());
        }
    }

    [ApiController]
    [Route("[controller]")]
    public class UploadController : ControllerBase
    {
        [HttpPut]
        public async Task<IActionResult> Upload()
        {
            using var mem = new MemoryStream();
            await Request.Body.CopyToAsync(mem);
            return Content(mem.Length.ToString());
        }
    }
}

Further technical details

  • ASP.NET Core version - 5.0.7
  • Microsoft.AspNetCore.Mvc.Testing 5.0.7
  • Microsoft Visual Studio Community 2019 Version 16.10.2
  • The output of dotnet --info:
Пакет SDK для .NET (отражающий любой global.json):
 Version:   5.0.301
 Commit:    ef17233f86

Среда выполнения:
 OS Name:     Windows
 OS Version:  10.0.19043
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\5.0.301\

Host (useful for support):
  Version: 5.0.7
  Commit:  556582d964

.NET SDKs installed:
  3.1.405 [C:\Program Files\dotnet\sdk]
  5.0.100 [C:\Program Files\dotnet\sdk]
  5.0.102 [C:\Program Files\dotnet\sdk]
  5.0.202 [C:\Program Files\dotnet\sdk]
  5.0.301 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.11 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
@BrennanConroy
Copy link
Member

BrennanConroy commented Jun 23, 2021

Triage: This behavior has been here since the beginning and would be a major breaking change if we changed it. We wont be making any changes here.

As a workaround you can copy the partial stream to a new MemoryStream.

@BrennanConroy BrennanConroy added the ✔️ Resolution: Won't Fix Resolved because we decided not to change the behavior reported in this issue. label Jun 23, 2021
@ghost ghost added the Status: Resolved label Jun 23, 2021
@afkos
Copy link
Author

afkos commented Jun 24, 2021

The behavior is different for TestServer and a real server.
It took a lot of time to investigate, that the problem is not with our code.

Maybe it's better to document the difference.

@BrennanConroy
Copy link
Member

Filed dotnet/AspNetCore.Docs#22618 for docs

@ghost ghost locked as resolved and limited conversation to collaborators Jul 28, 2021
@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Aug 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions ✔️ Resolution: Won't Fix Resolved because we decided not to change the behavior reported in this issue. Status: Resolved
Projects
None yet
Development

No branches or pull requests

4 participants