| File: System\Net\Http\StringContent.cs | Web Access |
| Project: src\runtime\src\libraries\System.Net.Http\src\System.Net.Http.csproj (System.Net.Http) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.IO; using System.Net.Http.Headers; using System.Text; using System.Threading; using System.Threading.Tasks; namespace System.Net.Http { /// <summary>Provides HTTP content based on a string.</summary> public class StringContent : ByteArrayContent { /// <summary>The media type to use when none is specified.</summary> private const string DefaultMediaType = "text/plain"; /// <summary>Creates a new instance of the <see cref="StringContent"/> class.</summary> /// <param name="content">The content used to initialize the <see cref="StringContent"/>.</param> /// <remarks>The media type for the <see cref="StringContent"/> created defaults to text/plain.</remarks> public StringContent(string content) : this(content, DefaultStringEncoding, DefaultMediaType) { } /// <summary>Creates a new instance of the <see cref="StringContent"/> class.</summary> /// <param name="content">The content used to initialize the <see cref="StringContent"/>.</param> /// <param name="mediaType">The media type to use for the content.</param> public StringContent(string content, MediaTypeHeaderValue? mediaType) : this(content, DefaultStringEncoding, mediaType) { } /// <summary>Creates a new instance of the <see cref="StringContent"/> class.</summary> /// <param name="content">The content used to initialize the <see cref="StringContent"/>.</param> /// <param name="encoding">The encoding to use for the content.</param> /// <remarks>The media type for the <see cref="StringContent"/> created defaults to text/plain.</remarks> public StringContent(string content, Encoding? encoding) : this(content, encoding, DefaultMediaType) { } /// <summary>Creates a new instance of the <see cref="StringContent"/> class.</summary> /// <param name="content">The content used to initialize the <see cref="StringContent"/>.</param> /// <param name="encoding">The encoding to use for the content.</param> /// <param name="mediaType">The media type to use for the content.</param> public StringContent(string content, Encoding? encoding, string? mediaType) : base(GetContentByteArray(content, encoding)) { Debug.Assert(DefaultStringEncoding.WebName == "utf-8"); encoding ??= DefaultStringEncoding; mediaType ??= DefaultMediaType; // Avoid allocating MediaTypeHeaderValue and related objects for common media types. if (ReferenceEquals(encoding, DefaultStringEncoding)) { string? knownValue = mediaType switch { "text/plain" => "text/plain; charset=utf-8", "application/json" => "application/json; charset=utf-8", _ => null }; if (knownValue is not null) { Headers.TryAddWithoutValidation(KnownHeaders.ContentType.Descriptor, knownValue); return; } } Headers.ContentType = new MediaTypeHeaderValue(mediaType, encoding.WebName); } /// <summary>Creates a new instance of the <see cref="StringContent"/> class.</summary> /// <param name="content">The content used to initialize the <see cref="StringContent"/>.</param> /// <param name="encoding">The encoding to use for the content.</param> /// <param name="mediaType">The media type to use for the content.</param> public StringContent(string content, Encoding? encoding, MediaTypeHeaderValue? mediaType) : base(GetContentByteArray(content, encoding)) { Headers.ContentType = mediaType; } /// <summary>Serialize the string into a byte-array using encoding information provided by the caller (if any).</summary> /// <param name="content">The content used to initialize the <see cref="StringContent"/>.</param> /// <param name="encoding">The encoding to use for the content.</param> /// <returns>The serialized byte array.</returns> private static byte[] GetContentByteArray(string content, Encoding? encoding) { ArgumentNullException.ThrowIfNull(content); // In this case we treat 'null' strings differently from string.Empty in order to be consistent with our // other *Content constructors: 'null' throws, empty values are allowed. return (encoding ?? DefaultStringEncoding).GetBytes(content); } /// <summary>Serialize and write the byte array provided in the constructor to an HTTP content stream as an asynchronous operation.</summary> /// <param name="stream">The target stream.</param> /// <param name="context">Information about the transport, like channel binding token. This parameter may be <see langword="null" />.</param> /// <param name="cancellationToken">The cancellation token to cancel the operation.</param> /// <returns>The task object representing the asynchronous operation.</returns> protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cancellationToken) => // Only skip the original protected virtual SerializeToStreamAsync if this // isn't a derived type that may have overridden the behavior. GetType() == typeof(StringContent) ? SerializeToStreamAsyncCore(stream, cancellationToken) : base.SerializeToStreamAsync(stream, context, cancellationToken); internal override Stream? TryCreateContentReadStream() => GetType() == typeof(StringContent) ? CreateMemoryStreamForByteArray() : // type check ensures we use possible derived type's CreateContentReadStreamAsync override null; } }