< Summary

Information
Class: System.Net.Http.FormUrlEncodedContent
Assembly: System.Net.Http
File(s): D:\runner\runtime\src\libraries\System.Net.Http\src\System\Net\Http\FormUrlEncodedContent.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 53
Coverable lines: 53
Total lines: 99
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 16
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%110%
GetContentByteArray(...)0%440%
Encode(...)0%880%
SerializeToStreamAsync(...)0%220%
TryCreateContentReadStream()0%220%

File(s)

D:\runner\runtime\src\libraries\System.Net.Http\src\System\Net\Http\FormUrlEncodedContent.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections.Generic;
 5using System.IO;
 6using System.Net.Http.Headers;
 7using System.Text;
 8using System.Threading;
 9using System.Threading.Tasks;
 10
 11namespace System.Net.Http
 12{
 13    public class FormUrlEncodedContent : ByteArrayContent
 14    {
 15        public FormUrlEncodedContent(
 16            IEnumerable<KeyValuePair<
 17                #nullable disable
 18                string, string
 19                #nullable restore
 20            >> nameValueCollection)
 021            : base(GetContentByteArray(nameValueCollection))
 022        {
 023            Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
 024        }
 25
 26        private static byte[] GetContentByteArray(IEnumerable<KeyValuePair<string?, string?>> nameValueCollection)
 027        {
 028            ArgumentNullException.ThrowIfNull(nameValueCollection);
 29
 30            // Encode and concatenate data
 031            var builder = new ValueStringBuilder(stackalloc char[256]);
 32
 033            foreach (KeyValuePair<string?, string?> pair in nameValueCollection)
 034            {
 035                if (builder.Length > 0)
 036                {
 037                    builder.Append('&');
 038                }
 39
 040                Encode(ref builder, pair.Key);
 041                builder.Append('=');
 042                Encode(ref builder, pair.Value);
 043            }
 44
 45            // EscapeDataString will always return an ASCII string and DefaultHttpEncoding is Latin1,
 46            // so we know the output byte size will be the same as the builder length.
 047            byte[] bytes = new byte[builder.Length];
 048            HttpRuleParser.DefaultHttpEncoding.GetBytes(builder.AsSpan(), bytes);
 049            builder.Dispose();
 050            return bytes;
 051        }
 52
 53        private static void Encode(ref ValueStringBuilder builder, string? data)
 054        {
 055            if (!string.IsNullOrEmpty(data))
 056            {
 57                int charsWritten;
 058                while (!Uri.TryEscapeDataString(data, builder.RawChars.Slice(builder.Length), out charsWritten))
 059                {
 060                    builder.EnsureCapacity(builder.Capacity + 1);
 061                }
 62
 63                // Escape spaces as '+'.
 064                if (data.Contains(' '))
 065                {
 066                    ReadOnlySpan<char> escapedChars = builder.RawChars.Slice(builder.Length, charsWritten);
 67
 068                    while (true)
 069                    {
 070                        int indexOfEscapedSpace = escapedChars.IndexOf("%20", StringComparison.Ordinal);
 071                        if (indexOfEscapedSpace < 0)
 072                        {
 073                            builder.Append(escapedChars);
 074                            break;
 75                        }
 76
 077                        builder.Append(escapedChars.Slice(0, indexOfEscapedSpace));
 078                        builder.Append('+');
 079                        escapedChars = escapedChars.Slice(indexOfEscapedSpace + 3); // Skip "%20"
 080                    }
 081                }
 82                else
 083                {
 084                    builder.Length += charsWritten;
 085                }
 086            }
 087        }
 88
 89        protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cance
 90            // Only skip the original protected virtual SerializeToStreamAsync if this
 91            // isn't a derived type that may have overridden the behavior.
 092            GetType() == typeof(FormUrlEncodedContent) ? SerializeToStreamAsyncCore(stream, cancellationToken) :
 093            base.SerializeToStreamAsync(stream, context, cancellationToken);
 94
 95        internal override Stream? TryCreateContentReadStream() =>
 096            GetType() == typeof(FormUrlEncodedContent) ? CreateMemoryStreamForByteArray() : // type check ensures we use
 097            null;
 98    }
 99}