From 6a1af9e99089c1ca591aada8f2345fd259733a08 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 9 May 2023 14:29:34 -0400 Subject: [PATCH] Add ArgumentException.ThrowIfNullOrWhiteSpace --- .../Net/WebSockets/WebSocketValidate.cs | 5 +--- .../src/Resources/Strings.resx | 3 -- .../DataAnnotations/Schema/ColumnAttribute.cs | 12 ++------ .../Schema/ForeignKeyAttribute.cs | 6 +--- .../Schema/InversePropertyAttribute.cs | 6 +--- .../DataAnnotations/Schema/TableAttribute.cs | 12 ++------ .../src/Resources/Strings.resx | 3 -- .../Http/Headers/AuthenticationHeaderValue.cs | 2 +- .../Http/Headers/CacheControlHeaderValue.cs | 2 +- .../Headers/ContentDispositionHeaderValue.cs | 12 ++++---- .../Http/Headers/ContentRangeHeaderValue.cs | 2 +- .../Net/Http/Headers/EntityTagHeaderValue.cs | 6 ++-- .../Net/Http/Headers/HeaderUtilities.cs | 22 +++++--------- .../System/Net/Http/Headers/HttpHeaders.cs | 5 +--- .../Net/Http/Headers/MediaTypeHeaderValue.cs | 12 ++++---- .../Net/Http/Headers/NameValueHeaderValue.cs | 2 +- .../Net/Http/Headers/ProductHeaderValue.cs | 4 +-- .../Http/Headers/ProductInfoHeaderValue.cs | 2 +- .../Net/Http/Headers/RangeHeaderValue.cs | 2 +- .../Headers/StringWithQualityHeaderValue.cs | 4 +-- .../Http/Headers/TransferCodingHeaderValue.cs | 2 +- .../System/Net/Http/Headers/ViaHeaderValue.cs | 11 +++---- .../Net/Http/Headers/WarningHeaderValue.cs | 9 ++---- .../src/System/Net/Http/HttpMethod.cs | 5 +--- .../src/System/Net/Http/MultipartContent.cs | 10 ++----- .../Net/Http/MultipartFormDataContent.cs | 17 ++--------- .../src/Resources/Strings.resx | 3 -- .../src/Resources/Strings.resx | 3 -- .../src/Resources/Strings.resx | 3 -- .../src/Resources/Strings.resx | 3 ++ .../src/System/ArgumentException.cs | 20 +++++++++++++ .../System.Runtime/ref/System.Runtime.cs | 1 + .../tests/System/ArgumentExceptionTests.cs | 30 +++++++++++++++++++ 33 files changed, 105 insertions(+), 136 deletions(-) diff --git a/src/libraries/Common/src/System/Net/WebSockets/WebSocketValidate.cs b/src/libraries/Common/src/System/Net/WebSockets/WebSocketValidate.cs index dafe325c8c07b8..7c97c082d26f89 100644 --- a/src/libraries/Common/src/System/Net/WebSockets/WebSocketValidate.cs +++ b/src/libraries/Common/src/System/Net/WebSockets/WebSocketValidate.cs @@ -58,10 +58,7 @@ internal static void ThrowIfInvalidState(WebSocketState currentState, bool isDis internal static void ValidateSubprotocol(string subProtocol) { - if (string.IsNullOrWhiteSpace(subProtocol)) - { - throw new ArgumentException(SR.net_WebSockets_InvalidEmptySubProtocol, nameof(subProtocol)); - } + ArgumentException.ThrowIfNullOrWhiteSpace(subProtocol); int indexOfInvalidChar = subProtocol.AsSpan().IndexOfAnyExcept(s_validSubprotocolChars); if (indexOfInvalidChar >= 0) diff --git a/src/libraries/System.ComponentModel.Annotations/src/Resources/Strings.resx b/src/libraries/System.ComponentModel.Annotations/src/Resources/Strings.resx index 0cac133cb27bf4..71307a5f361cf7 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/Resources/Strings.resx +++ b/src/libraries/System.ComponentModel.Annotations/src/Resources/Strings.resx @@ -60,9 +60,6 @@ The {0} field does not equal any of the values specified in AllowedValuesAttribute. - - The argument '{0}' cannot be null, empty or contain only whitespace. - The associated metadata type for type '{0}' contains the following unknown properties or fields: {1}. Please make sure that the names of these members match the names of the properties on the main type. diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/ColumnAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/ColumnAttribute.cs index 66a112ef8b45d7..c71b1c13431f75 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/ColumnAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/ColumnAttribute.cs @@ -28,11 +28,7 @@ public ColumnAttribute() /// The name of the column the property is mapped to. public ColumnAttribute(string name) { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentException(SR.Format(SR.ArgumentIsNullOrWhitespace, nameof(name)), nameof(name)); - } - + ArgumentException.ThrowIfNullOrWhiteSpace(name); Name = name; } @@ -64,11 +60,7 @@ public string? TypeName get => _typeName; set { - if (string.IsNullOrWhiteSpace(value)) - { - throw new ArgumentException(SR.Format(SR.ArgumentIsNullOrWhitespace, nameof(value)), nameof(value)); - } - + ArgumentException.ThrowIfNullOrWhiteSpace(value); _typeName = value; } } diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/ForeignKeyAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/ForeignKeyAttribute.cs index a93bc6e328ef84..f640f5f597bfb8 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/ForeignKeyAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/ForeignKeyAttribute.cs @@ -23,11 +23,7 @@ public class ForeignKeyAttribute : Attribute /// public ForeignKeyAttribute(string name) { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentException(SR.Format(SR.ArgumentIsNullOrWhitespace, nameof(name)), nameof(name)); - } - + ArgumentException.ThrowIfNullOrWhiteSpace(name); Name = name; } diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/InversePropertyAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/InversePropertyAttribute.cs index c6d78bdd71365d..4f2b3ceec6f078 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/InversePropertyAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/InversePropertyAttribute.cs @@ -17,11 +17,7 @@ public class InversePropertyAttribute : Attribute /// The navigation property representing the other end of the same relationship. public InversePropertyAttribute(string property) { - if (string.IsNullOrWhiteSpace(property)) - { - throw new ArgumentException(SR.Format(SR.ArgumentIsNullOrWhitespace, nameof(property)), nameof(property)); - } - + ArgumentException.ThrowIfNullOrWhiteSpace(property); Property = property; } diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/TableAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/TableAttribute.cs index 489bf85830c827..19f00eb5fc1a6e 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/TableAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/TableAttribute.cs @@ -20,11 +20,7 @@ public class TableAttribute : Attribute /// The name of the table the class is mapped to. public TableAttribute(string name) { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentException(SR.Format(SR.ArgumentIsNullOrWhitespace, nameof(name)), nameof(name)); - } - + ArgumentException.ThrowIfNullOrWhiteSpace(name); Name = name; } @@ -42,11 +38,7 @@ public string? Schema get => _schema; set { - if (string.IsNullOrWhiteSpace(value)) - { - throw new ArgumentException(SR.Format(SR.ArgumentIsNullOrWhitespace, nameof(value)), nameof(value)); - } - + ArgumentException.ThrowIfNullOrWhiteSpace(value); _schema = value; } } diff --git a/src/libraries/System.Net.Http/src/Resources/Strings.resx b/src/libraries/System.Net.Http/src/Resources/Strings.resx index 8cd19984d7216b..b89c5a6c1c9b78 100644 --- a/src/libraries/System.Net.Http/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Http/src/Resources/Strings.resx @@ -180,9 +180,6 @@ The content's stream has already been retrieved via async ReadAsStreamAsync and cannot be subsequently accessed synchronously. - - The value cannot be null or empty. - The request message was already sent. Cannot send the same request message multiple times. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/AuthenticationHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/AuthenticationHeaderValue.cs index fedc31077e9e75..930cb8f8408587 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/AuthenticationHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/AuthenticationHeaderValue.cs @@ -37,7 +37,7 @@ public AuthenticationHeaderValue(string scheme) public AuthenticationHeaderValue(string scheme, string? parameter) { - HeaderUtilities.CheckValidToken(scheme, nameof(scheme)); + HeaderUtilities.CheckValidToken(scheme); HttpHeaders.CheckContainsNewLine(parameter); _scheme = scheme; _parameter = parameter; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/CacheControlHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/CacheControlHeaderValue.cs index 3067cc68689b46..c72e1965e14386 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/CacheControlHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/CacheControlHeaderValue.cs @@ -594,7 +594,7 @@ object ICloneable.Clone() private sealed class TokenObjectCollection : ObjectCollection { - public override void Validate(string item) => HeaderUtilities.CheckValidToken(item, nameof(item)); + public override void Validate(string item) => HeaderUtilities.CheckValidToken(item); public int GetHashCode(StringComparer comparer) { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ContentDispositionHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ContentDispositionHeaderValue.cs index 02cc4b3289caf5..05f731954469e3 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ContentDispositionHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ContentDispositionHeaderValue.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Runtime.CompilerServices; using System.Text; namespace System.Net.Http.Headers @@ -34,7 +35,7 @@ public string DispositionType get { return _dispositionType; } set { - CheckDispositionTypeFormat(value, nameof(value)); + CheckDispositionTypeFormat(value); _dispositionType = value; } } @@ -139,7 +140,7 @@ protected ContentDispositionHeaderValue(ContentDispositionHeaderValue source) public ContentDispositionHeaderValue(string dispositionType) { - CheckDispositionTypeFormat(dispositionType, nameof(dispositionType)); + CheckDispositionTypeFormat(dispositionType); _dispositionType = dispositionType; } @@ -270,12 +271,9 @@ private static int GetDispositionTypeExpressionLength(string input, int startInd return typeLength; } - private static void CheckDispositionTypeFormat(string dispositionType, string parameterName) + private static void CheckDispositionTypeFormat(string dispositionType, [CallerArgumentExpression(nameof(dispositionType))] string? parameterName = null) { - if (string.IsNullOrEmpty(dispositionType)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, parameterName); - } + ArgumentException.ThrowIfNullOrWhiteSpace(dispositionType, parameterName); // When adding values using strongly typed objects, no leading/trailing LWS (whitespace) are allowed. int dispositionTypeLength = GetDispositionTypeExpressionLength(dispositionType, 0, out string? tempDispositionType); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ContentRangeHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ContentRangeHeaderValue.cs index aa08f5e507e035..5c463972d60dd4 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ContentRangeHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ContentRangeHeaderValue.cs @@ -19,7 +19,7 @@ public string Unit get { return _unit; } set { - HeaderUtilities.CheckValidToken(value, nameof(value)); + HeaderUtilities.CheckValidToken(value); _unit = value; } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/EntityTagHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/EntityTagHeaderValue.cs index fb1e2614686484..d6177a2555a567 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/EntityTagHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/EntityTagHeaderValue.cs @@ -35,10 +35,8 @@ public EntityTagHeaderValue(string tag) public EntityTagHeaderValue(string tag, bool isWeak) { - if (string.IsNullOrEmpty(tag)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, nameof(tag)); - } + ArgumentException.ThrowIfNullOrWhiteSpace(tag); + int length; if ((HttpRuleParser.GetQuotedStringLength(tag, 0, out length) != HttpParseResult.Parsed) || (length != tag.Length)) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HeaderUtilities.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HeaderUtilities.cs index 20730990ce9a42..1a40f471418c41 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HeaderUtilities.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HeaderUtilities.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; +using System.Runtime.CompilerServices; using System.Text; namespace System.Net.Http.Headers @@ -139,12 +140,9 @@ private static void AddHexEscaped(byte c, ref ValueStringBuilder destination) return null; } - internal static void CheckValidToken(string value, string parameterName) + internal static void CheckValidToken(string value, [CallerArgumentExpression(nameof(value))] string? parameterName = null) { - if (string.IsNullOrEmpty(value)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, parameterName); - } + ArgumentException.ThrowIfNullOrWhiteSpace(value, parameterName); if (HttpRuleParser.GetTokenLength(value, 0) != value.Length) { @@ -152,12 +150,9 @@ internal static void CheckValidToken(string value, string parameterName) } } - internal static void CheckValidComment(string value, string parameterName) + internal static void CheckValidComment(string value, [CallerArgumentExpression(nameof(value))] string? parameterName = null) { - if (string.IsNullOrEmpty(value)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, parameterName); - } + ArgumentException.ThrowIfNullOrWhiteSpace(value, parameterName); int length; if ((HttpRuleParser.GetCommentLength(value, 0, out length) != HttpParseResult.Parsed) || @@ -167,12 +162,9 @@ internal static void CheckValidComment(string value, string parameterName) } } - internal static void CheckValidQuotedString(string value, string parameterName) + internal static void CheckValidQuotedString(string value, [CallerArgumentExpression(nameof(value))] string? parameterName = null) { - if (string.IsNullOrEmpty(value)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, parameterName); - } + ArgumentException.ThrowIfNullOrWhiteSpace(value, parameterName); int length; if ((HttpRuleParser.GetQuotedStringLength(value, 0, out length) != HttpParseResult.Parsed) || diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs index aa984ff86e41be..090f195fae23e2 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs @@ -1027,10 +1027,7 @@ private static void ParseAndAddValue(HeaderDescriptor descriptor, HeaderStoreIte private HeaderDescriptor GetHeaderDescriptor(string name) { - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, nameof(name)); - } + ArgumentException.ThrowIfNullOrWhiteSpace(name); if (!HeaderDescriptor.TryGet(name, out HeaderDescriptor descriptor)) { 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 d87029e3b93365..130c8bdd198927 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 @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Text; using static System.HexConverter; @@ -68,7 +69,7 @@ public string? MediaType get { return _mediaType; } set { - CheckMediaTypeFormat(value, nameof(value)); + CheckMediaTypeFormat(value); _mediaType = value; } } @@ -100,7 +101,7 @@ public MediaTypeHeaderValue(string mediaType) /// The value to use for the character set. public MediaTypeHeaderValue(string mediaType, string? charSet) { - CheckMediaTypeFormat(mediaType, nameof(mediaType)); + CheckMediaTypeFormat(mediaType); _mediaType = mediaType; if (!string.IsNullOrEmpty(charSet)) @@ -272,12 +273,9 @@ private static int GetMediaTypeExpressionLength(string input, int startIndex, ou return mediaTypeLength; } - private static void CheckMediaTypeFormat(string mediaType, string parameterName) + private static void CheckMediaTypeFormat(string mediaType, [CallerArgumentExpression(nameof(mediaType))] string? parameterName = null) { - if (string.IsNullOrEmpty(mediaType)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, parameterName); - } + ArgumentException.ThrowIfNullOrWhiteSpace(mediaType, parameterName); // When adding values using strongly typed objects, no leading/trailing LWS (whitespace) are allowed. // Also no LWS between type and subtype are allowed. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/NameValueHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/NameValueHeaderValue.cs index 56c9fb1ba4eb86..6920a881828fcc 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/NameValueHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/NameValueHeaderValue.cs @@ -345,7 +345,7 @@ internal static int GetValueLength(string input, int startIndex) private static void CheckNameValueFormat(string name, string? value) { - HeaderUtilities.CheckValidToken(name, nameof(name)); + HeaderUtilities.CheckValidToken(name); CheckValueFormat(value); } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ProductHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ProductHeaderValue.cs index efdf5f7d39d56a..846f435a099b97 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ProductHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ProductHeaderValue.cs @@ -29,11 +29,11 @@ public ProductHeaderValue(string name) public ProductHeaderValue(string name, string? version) { - HeaderUtilities.CheckValidToken(name, nameof(name)); + HeaderUtilities.CheckValidToken(name); if (!string.IsNullOrEmpty(version)) { - HeaderUtilities.CheckValidToken(version, nameof(version)); + HeaderUtilities.CheckValidToken(version); _version = version; } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ProductInfoHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ProductInfoHeaderValue.cs index 6ed9717836ad6a..1d877bb053a176 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ProductInfoHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ProductInfoHeaderValue.cs @@ -29,7 +29,7 @@ public ProductInfoHeaderValue(ProductHeaderValue product) public ProductInfoHeaderValue(string comment) { - HeaderUtilities.CheckValidComment(comment, nameof(comment)); + HeaderUtilities.CheckValidComment(comment); _comment = comment; } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/RangeHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/RangeHeaderValue.cs index cc7b3259120cf0..85bfdd0ec5c769 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/RangeHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/RangeHeaderValue.cs @@ -19,7 +19,7 @@ public string Unit get { return _unit; } set { - HeaderUtilities.CheckValidToken(value, nameof(value)); + HeaderUtilities.CheckValidToken(value); _unit = value; } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/StringWithQualityHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/StringWithQualityHeaderValue.cs index d7da89b5cb0bb8..bf7dc4f2dd3d5b 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/StringWithQualityHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/StringWithQualityHeaderValue.cs @@ -20,7 +20,7 @@ public class StringWithQualityHeaderValue : ICloneable public StringWithQualityHeaderValue(string value) { - HeaderUtilities.CheckValidToken(value, nameof(value)); + HeaderUtilities.CheckValidToken(value); _value = value; _quality = NotSetSentinel; @@ -28,7 +28,7 @@ public StringWithQualityHeaderValue(string value) public StringWithQualityHeaderValue(string value, double quality) { - HeaderUtilities.CheckValidToken(value, nameof(value)); + HeaderUtilities.CheckValidToken(value); ArgumentOutOfRangeException.ThrowIfNegative(quality); ArgumentOutOfRangeException.ThrowIfGreaterThan(quality, 1.0); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/TransferCodingHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/TransferCodingHeaderValue.cs index 67b2b30fd601d0..db30cd036f56fd 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/TransferCodingHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/TransferCodingHeaderValue.cs @@ -33,7 +33,7 @@ protected TransferCodingHeaderValue(TransferCodingHeaderValue source) public TransferCodingHeaderValue(string value) { - HeaderUtilities.CheckValidToken(value, nameof(value)); + HeaderUtilities.CheckValidToken(value); _value = value; } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ViaHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ViaHeaderValue.cs index 65fd928a001bb5..fc9a64e7bc7345 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ViaHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ViaHeaderValue.cs @@ -47,18 +47,18 @@ public ViaHeaderValue(string protocolVersion, string receivedBy, string? protoco public ViaHeaderValue(string protocolVersion, string receivedBy, string? protocolName, string? comment) { - HeaderUtilities.CheckValidToken(protocolVersion, nameof(protocolVersion)); + HeaderUtilities.CheckValidToken(protocolVersion); CheckReceivedBy(receivedBy); if (!string.IsNullOrEmpty(protocolName)) { - HeaderUtilities.CheckValidToken(protocolName, nameof(protocolName)); + HeaderUtilities.CheckValidToken(protocolName); _protocolName = protocolName; } if (!string.IsNullOrEmpty(comment)) { - HeaderUtilities.CheckValidComment(comment, nameof(comment)); + HeaderUtilities.CheckValidComment(comment); _comment = comment; } @@ -275,10 +275,7 @@ object ICloneable.Clone() private static void CheckReceivedBy(string receivedBy) { - if (string.IsNullOrEmpty(receivedBy)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, nameof(receivedBy)); - } + ArgumentException.ThrowIfNullOrWhiteSpace(receivedBy); // 'receivedBy' can either be a host or a token. Since a token is a valid host, we only verify if the value // is a valid host.; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/WarningHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/WarningHeaderValue.cs index 586c0b68fc549b..9501eac5f5f5df 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/WarningHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/WarningHeaderValue.cs @@ -28,7 +28,7 @@ public WarningHeaderValue(int code, string agent, string text) { CheckCode(code); CheckAgent(agent); - HeaderUtilities.CheckValidQuotedString(text, nameof(text)); + HeaderUtilities.CheckValidQuotedString(text); _code = code; _agent = agent; @@ -39,7 +39,7 @@ public WarningHeaderValue(int code, string agent, string text, DateTimeOffset da { CheckCode(code); CheckAgent(agent); - HeaderUtilities.CheckValidQuotedString(text, nameof(text)); + HeaderUtilities.CheckValidQuotedString(text); _code = code; _agent = agent; @@ -282,10 +282,7 @@ private static void CheckCode(int code) private static void CheckAgent(string agent) { - if (string.IsNullOrEmpty(agent)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, nameof(agent)); - } + ArgumentException.ThrowIfNullOrWhiteSpace(agent); // 'receivedBy' can either be a host or a token. Since a token is a valid host, we only verify if the value // is a valid host. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpMethod.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpMethod.cs index cda7a9f228a028..045d85fb97cd8c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpMethod.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpMethod.cs @@ -78,10 +78,7 @@ public string Method public HttpMethod(string method) { - if (string.IsNullOrEmpty(method)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, nameof(method)); - } + ArgumentException.ThrowIfNullOrWhiteSpace(method); if (!HttpRuleParser.IsToken(method)) { throw new FormatException(SR.net_http_httpmethod_format_error); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/MultipartContent.cs b/src/libraries/System.Net.Http/src/System/Net/Http/MultipartContent.cs index 3f249987f08a96..961de333e1d6fa 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/MultipartContent.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/MultipartContent.cs @@ -43,10 +43,7 @@ public MultipartContent(string subtype) public MultipartContent(string subtype, string boundary) { - if (string.IsNullOrWhiteSpace(subtype)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, nameof(subtype)); - } + ArgumentException.ThrowIfNullOrWhiteSpace(subtype); ValidateBoundary(boundary); _boundary = boundary; @@ -68,10 +65,7 @@ private static void ValidateBoundary(string boundary) { // NameValueHeaderValue is too restrictive for boundary. // Instead validate it ourselves and then quote it. - if (string.IsNullOrWhiteSpace(boundary)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, nameof(boundary)); - } + ArgumentException.ThrowIfNullOrWhiteSpace(boundary); // RFC 2046 Section 5.1.1 // boundary := 0*69 bcharsnospace diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/MultipartFormDataContent.cs b/src/libraries/System.Net.Http/src/System/Net/Http/MultipartFormDataContent.cs index 7eba9d8aee7660..e09b64e79bb009 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/MultipartFormDataContent.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/MultipartFormDataContent.cs @@ -35,11 +35,7 @@ public override void Add(HttpContent content) public void Add(HttpContent content, string name) { ArgumentNullException.ThrowIfNull(content); - - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, nameof(name)); - } + ArgumentException.ThrowIfNullOrWhiteSpace(name); AddInternal(content, name, null); } @@ -47,15 +43,8 @@ public void Add(HttpContent content, string name) public void Add(HttpContent content, string name, string fileName) { ArgumentNullException.ThrowIfNull(content); - - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, nameof(name)); - } - if (string.IsNullOrWhiteSpace(fileName)) - { - throw new ArgumentException(SR.net_http_argument_empty_string, nameof(fileName)); - } + ArgumentException.ThrowIfNullOrWhiteSpace(name); + ArgumentException.ThrowIfNullOrWhiteSpace(fileName); AddInternal(content, name, fileName); } diff --git a/src/libraries/System.Net.HttpListener/src/Resources/Strings.resx b/src/libraries/System.Net.HttpListener/src/Resources/Strings.resx index 6bd8e2b8aa767d..9e7e8bfa17c853 100644 --- a/src/libraries/System.Net.HttpListener/src/Resources/Strings.resx +++ b/src/libraries/System.Net.HttpListener/src/Resources/Strings.resx @@ -302,9 +302,6 @@ The {0} operation was called on an incoming request with WebSocket version '{1}', expected '{2}'. - - Empty string is not a valid subprotocol value. Please use \"null\" to specify no value. - The WebSocket protocol '{0}' is invalid because it contains the invalid character '{1}'. diff --git a/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx b/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx index e3d5079aafc0bc..81ae9dc7e21e47 100644 --- a/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx +++ b/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx @@ -93,9 +93,6 @@ The WebSocket protocol '{0}' is invalid because it contains the invalid character '{1}'. - - Empty string is not a valid subprotocol value. Please use \"null\" to specify no value. - The close status description '{0}' is invalid. When using close status code '{1}' the description must be null. diff --git a/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx b/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx index 24f8e00b44f217..1b7857f0021605 100644 --- a/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx +++ b/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx @@ -90,9 +90,6 @@ The argument must be a value greater than {0}. - - Empty string is not a valid subprotocol value. Please use \"null\" to specify no value. - The WebSocket protocol '{0}' is invalid because it contains the invalid character '{1}'. diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index da4412098aa6fe..9244fede0601e1 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -3869,6 +3869,9 @@ The value cannot be an empty string. + + The value cannot be an empty string or composed entirely of whitespace. + FrameworkName is invalid. diff --git a/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs b/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs index e9b41c5af3e8a7..5265a299b62c9b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs @@ -118,11 +118,31 @@ public static void ThrowIfNullOrEmpty([NotNull] string? argument, [CallerArgumen } } + /// Throws an exception if is null, empty, or consists only of white-space characters. + /// The string argument to validate. + /// The name of the parameter with which corresponds. + /// is null. + /// is empty or consists only of white-space characters. + public static void ThrowIfNullOrWhiteSpace([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) + { + if (string.IsNullOrWhiteSpace(argument)) + { + ThrowNullOrWhiteSpaceException(argument, paramName); + } + } + [DoesNotReturn] private static void ThrowNullOrEmptyException(string? argument, string? paramName) { ArgumentNullException.ThrowIfNull(argument, paramName); throw new ArgumentException(SR.Argument_EmptyString, paramName); } + + [DoesNotReturn] + private static void ThrowNullOrWhiteSpaceException(string? argument, string? paramName) + { + ArgumentNullException.ThrowIfNull(argument, paramName); + throw new ArgumentException(SR.Argument_EmptyOrWhiteSpaceString, paramName); + } } } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index f5a8ae284b7229..5362c12fcb659e 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -292,6 +292,7 @@ public ArgumentException(string? message, string? paramName, System.Exception? i [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public static void ThrowIfNullOrEmpty([System.Diagnostics.CodeAnalysis.NotNullAttribute] string? argument, [System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? paramName = null) { throw null; } + public static void ThrowIfNullOrWhiteSpace([System.Diagnostics.CodeAnalysis.NotNullAttribute] string? argument, [System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? paramName = null) { throw null; } } public partial class ArgumentNullException : System.ArgumentException { diff --git a/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs b/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs index d2d9804912e944..4535eb38c68a46 100644 --- a/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArgumentExceptionTests.cs @@ -87,5 +87,35 @@ public static void ThrowIfNullOrEmpty_UsesArgumentExpression_ParameterNameMatche someString = "abc"; ArgumentException.ThrowIfNullOrEmpty(someString); } + + [Fact] + public static void ThrowIfNullOrWhiteSpace_ThrowsForInvalidInput() + { + AssertExtensions.Throws(null, () => ArgumentException.ThrowIfNullOrWhiteSpace(null, null)); + AssertExtensions.Throws("something", () => ArgumentException.ThrowIfNullOrWhiteSpace(null, "something")); + + AssertExtensions.Throws(null, () => ArgumentException.ThrowIfNullOrWhiteSpace("", null)); + AssertExtensions.Throws("something", () => ArgumentException.ThrowIfNullOrWhiteSpace("", "something")); + + string allWhitespace = "\u0009\u000A\u000B\u000C\u000D\u0020\u0085\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000"; + AssertExtensions.Throws("something", () => ArgumentException.ThrowIfNullOrWhiteSpace(" ", "something")); + AssertExtensions.Throws("something", () => ArgumentException.ThrowIfNullOrWhiteSpace(allWhitespace, "something")); + ArgumentException.ThrowIfNullOrWhiteSpace("a" + allWhitespace, "something"); + ArgumentException.ThrowIfNullOrWhiteSpace(allWhitespace + "a", "something"); + ArgumentException.ThrowIfNullOrWhiteSpace(allWhitespace.Substring(0, 5) + "a" + allWhitespace.Substring(5), "something"); + } + + [Fact] + public static void ThrowIfNullOrWhiteSpace_UsesArgumentExpression_ParameterNameMatches() + { + string someString = null; + AssertExtensions.Throws(nameof(someString), () => ArgumentException.ThrowIfNullOrWhiteSpace(someString)); + + someString = ""; + AssertExtensions.Throws(nameof(someString), () => ArgumentException.ThrowIfNullOrWhiteSpace(someString)); + + someString = " "; + AssertExtensions.Throws(nameof(someString), () => ArgumentException.ThrowIfNullOrWhiteSpace(someString)); + } } }