diff --git a/src/libraries/System.Net.Http/ref/System.Net.Http.cs b/src/libraries/System.Net.Http/ref/System.Net.Http.cs index 0f63c2badb27ba..c83776ff9bc456 100644 --- a/src/libraries/System.Net.Http/ref/System.Net.Http.cs +++ b/src/libraries/System.Net.Http/ref/System.Net.Http.cs @@ -437,8 +437,10 @@ protected override void SerializeToStream(System.IO.Stream stream, System.Net.Tr public partial class StringContent : System.Net.Http.ByteArrayContent { public StringContent(string content) : base (default(byte[])) { } + public StringContent(string content, System.Net.Http.Headers.MediaTypeHeaderValue mediaType) : base (default(byte[])) { } public StringContent(string content, System.Text.Encoding? encoding) : base (default(byte[])) { } - public StringContent(string content, System.Text.Encoding? encoding, string? mediaType) : base (default(byte[])) { } + public StringContent(string content, System.Text.Encoding? encoding, System.Net.Http.Headers.MediaTypeHeaderValue mediaType) : base (default(byte[])) { } + public StringContent(string content, System.Text.Encoding? encoding, string mediaType) : base (default(byte[])) { } protected override System.Threading.Tasks.Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext? context, System.Threading.CancellationToken cancellationToken) { throw null; } } } @@ -692,6 +694,7 @@ public partial class MediaTypeHeaderValue : System.ICloneable { protected MediaTypeHeaderValue(System.Net.Http.Headers.MediaTypeHeaderValue source) { } public MediaTypeHeaderValue(string mediaType) { } + public MediaTypeHeaderValue(string mediaType, string? charSet) { } public string? CharSet { get { throw null; } set { } } [System.Diagnostics.CodeAnalysis.DisallowNullAttribute] public string? MediaType { get { throw null; } set { } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderValue.cs index b4bc8da37ad27d..47855527860dca 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderValue.cs @@ -80,9 +80,19 @@ protected MediaTypeHeaderValue(MediaTypeHeaderValue source) } public MediaTypeHeaderValue(string mediaType) + : this(mediaType, charSet: null) + { + } + + public MediaTypeHeaderValue(string mediaType, string? charSet) { CheckMediaTypeFormat(mediaType, nameof(mediaType)); _mediaType = mediaType; + + if (!string.IsNullOrEmpty(charSet)) + { + CharSet = charSet; + } } public override string ToString() diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/StringContent.cs b/src/libraries/System.Net.Http/src/System/Net/Http/StringContent.cs index 05ec413dbdb533..3fcb4c7ce76e5d 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/StringContent.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/StringContent.cs @@ -14,23 +14,29 @@ public class StringContent : ByteArrayContent private const string DefaultMediaType = "text/plain"; public StringContent(string content) - : this(content, null, null) + : this(content, DefaultStringEncoding, DefaultMediaType) + { + } + + public StringContent(string content, MediaTypeHeaderValue mediaType) + : this(content, DefaultStringEncoding, mediaType) { } public StringContent(string content, Encoding? encoding) - : this(content, encoding, null) + : this(content, encoding, DefaultMediaType) { } - public StringContent(string content, Encoding? encoding, string? mediaType) - : base(GetContentByteArray(content, encoding)) + public StringContent(string content, Encoding? encoding, string mediaType) + : this(content, encoding, new MediaTypeHeaderValue(mediaType, (encoding ?? DefaultStringEncoding).WebName)) { - // Initialize the 'Content-Type' header with information provided by parameters. - MediaTypeHeaderValue headerValue = new MediaTypeHeaderValue((mediaType == null) ? DefaultMediaType : mediaType); - headerValue.CharSet = (encoding == null) ? HttpContent.DefaultStringEncoding.WebName : encoding.WebName; + } - Headers.ContentType = headerValue; + public StringContent(string content, Encoding? encoding, MediaTypeHeaderValue mediaType) + : base(GetContentByteArray(content, encoding)) + { + Headers.ContentType = mediaType; } // A StringContent is essentially a ByteArrayContent. We serialize the string into a byte-array in the diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/StringContentTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/StringContentTest.cs index 10a241bc79116d..73e33fde4fa9ba 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/StringContentTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/StringContentTest.cs @@ -70,5 +70,67 @@ public async Task Ctor_DefineNoEncoding_DefaultEncodingUsed() string roundTrip = new StreamReader(destination, defaultStringEncoding).ReadToEnd(); Assert.Equal(sourceString, roundTrip); } + + [Fact] + public async Task Ctor_UseCustomMediaTypeHeaderValue_SpecificEncoding() + { + // Use UTF-8 encoding to serialize a chinese string. + string sourceString = "\u4f1a\u5458\u670d\u52a1"; + + var mediaTypeHeaderValue = new Headers.MediaTypeHeaderValue("application/custom", Encoding.UTF8.WebName); + + var content = new StringContent(sourceString, Encoding.UTF8, mediaTypeHeaderValue); + + Assert.Equal("application/custom", content.Headers.ContentType.MediaType); + Assert.Equal("utf-8", content.Headers.ContentType.CharSet); + + var destination = new MemoryStream(12); + await content.CopyToAsync(destination); + + string destinationString = Encoding.UTF8.GetString(destination.ToArray(), 0, (int)destination.Length); + + Assert.Equal(sourceString, destinationString); + } + + [Fact] + public async Task Ctor_UseCustomMediaTypeHeaderValue() + { + // Use UTF-8 encoding to serialize a chinese string. + string sourceString = "\u4f1a\u5458\u670d\u52a1"; + + var mediaTypeHeaderValue = new Headers.MediaTypeHeaderValue("application/custom", Encoding.UTF8.WebName); + + var content = new StringContent(sourceString, mediaTypeHeaderValue); + + Assert.Equal("application/custom", content.Headers.ContentType.MediaType); + Assert.Equal("utf-8", content.Headers.ContentType.CharSet); + + var destination = new MemoryStream(12); + await content.CopyToAsync(destination); + + string destinationString = Encoding.UTF8.GetString(destination.ToArray(), 0, (int)destination.Length); + + Assert.Equal(sourceString, destinationString); + } + + [Fact] + public async Task Ctor_UseSpecificEncodingAndContentType() + { + // Use UTF-8 encoding to serialize a chinese string. + string sourceString = "\u4f1a\u5458\u670d\u52a1"; + string contentType = "application/custom"; + + var content = new StringContent(sourceString, Encoding.UTF8, contentType); + + Assert.Equal("application/custom", content.Headers.ContentType.MediaType); + Assert.Equal("utf-8", content.Headers.ContentType.CharSet); + + var destination = new MemoryStream(12); + await content.CopyToAsync(destination); + + string destinationString = Encoding.UTF8.GetString(destination.ToArray(), 0, (int)destination.Length); + + Assert.Equal(sourceString, destinationString); + } } }