Skip to content

Unexpected breaking change in .NET 7 #81506

@slovely

Description

@slovely

Description

The StringContent constructor:

public StringContent(string content, Encoding? encoding, string mediaType)

has changed behaviour from .NET6 to .NET7. We had a particular code-path that ended up passing null into this constructor for the mediaType, which worked as expected in .NET6 and set the mime type to "text/plain". In .NET7 the same call throws ArgumentException.

The fix for this would be changing StringContent (lines 47-48) from:

public StringContent(string content, Encoding? encoding, string mediaType)
            : this(content, encoding, new MediaTypeHeaderValue(mediaType, (encoding ?? DefaultStringEncoding).WebName))

to:

public StringContent(string content, Encoding? encoding, string mediaType)
            : this(content, encoding, new MediaTypeHeaderValue(mediaType ?? DefaultMediaType, (encoding ?? DefaultStringEncoding).WebName))

(https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Http/src/System/Net/Http/StringContent.cs#L47)

Reproduction Steps

Create a unit test project, targeting both .NET6 and 7:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFrameworks>net6.0;net7.0</TargetFrameworks>
        <Nullable>enable</Nullable>

        <IsPackable>false</IsPackable>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0"/>
        <PackageReference Include="NUnit" Version="3.13.2"/>
        <PackageReference Include="NUnit3TestAdapter" Version="4.0.0"/>
    </ItemGroup>

</Project>

And add the following test:

public class Tests
{
    [Test]
    public void Test1()
    {
        string mimeType = null;
        var sc = new StringContent("Hello world!", Encoding.Default, mimeType);
        
        Assert.AreEqual(sc.Headers.ContentType.MediaType, "text/plain");
    }
}

From the CLI run dotnet test. The unit test passes for .NET6, but throws an error in .NET7:
image

Expected behavior

The behaviour on .NET6 and 7

Actual behavior

The .NET7 version throws an exception:

A total of 1 test files matched the specified pattern.
  Failed Test1 [28 ms]
  Error Message:
   System.ArgumentException : The value cannot be null or empty. (Parameter 'mediaType')
  Stack Trace:
     at System.Net.Http.Headers.MediaTypeHeaderValue.CheckMediaTypeFormat(String mediaType, String parameterName)
   at System.Net.Http.StringContent..ctor(String content, Encoding encoding, String mediaType)
   at StringContentChange.Tests.Test1() in C:\projects\git\StringContentChange\StringContentChange\UnitTest1.cs:line 13
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)

Regression?

Yes, works in .NET6

Known Workarounds

Call the constructor that only takes string content, Encoding encoding parameters.

Configuration

.NET SDK:
 Version:   7.0.102
 Commit:    4bbdd14480

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19045
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\7.0.102\

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions