diff --git a/src/Microsoft.AspNetCore.Http.Abstractions/PathString.cs b/src/Microsoft.AspNetCore.Http.Abstractions/PathString.cs index b82d4442..2a5960b6 100644 --- a/src/Microsoft.AspNetCore.Http.Abstractions/PathString.cs +++ b/src/Microsoft.AspNetCore.Http.Abstractions/PathString.cs @@ -443,25 +443,35 @@ public override int GetHashCode() /// /// public static implicit operator PathString(string s) - { - return new PathString(s); - } + => ConvertFromString(s); /// /// Implicitly calls ToString(). /// /// public static implicit operator string(PathString path) - { - return path.ToString(); - } + => path.ToString(); + + internal static PathString ConvertFromString(string s) + => string.IsNullOrEmpty(s) ? new PathString(s) : FromUriComponent(s); } internal class PathStringConverter : TypeConverter { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + => sourceType == typeof(string) + ? true + : base.CanConvertFrom(context, sourceType); + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - return new PathString((string)value); - } + => value is string + ? PathString.ConvertFromString((string)value) + : base.ConvertFrom(context, culture, value); + + public override object ConvertTo(ITypeDescriptorContext context, + CultureInfo culture, object value, Type destinationType) + => destinationType == typeof(string) + ? value.ToString() + : base.ConvertTo(context, culture, value, destinationType); } } diff --git a/test/Microsoft.AspNetCore.Http.Abstractions.Tests/PathStringTests.cs b/test/Microsoft.AspNetCore.Http.Abstractions.Tests/PathStringTests.cs index 365a9de3..ad070afa 100644 --- a/test/Microsoft.AspNetCore.Http.Abstractions.Tests/PathStringTests.cs +++ b/test/Microsoft.AspNetCore.Http.Abstractions.Tests/PathStringTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -208,11 +208,27 @@ public void ToUriComponentEscapeCorrectly(string category, string input, string } [Fact] - public void PathStringConvertsFromString() + public void PathStringConvertsOnlyToAndFromString() { var converter = TypeDescriptor.GetConverter(typeof(PathString)); PathString result = (PathString)converter.ConvertFromInvariantString("/foo"); Assert.Equal("/foo", result.ToString()); + Assert.Equal("/foo", converter.ConvertTo(result, typeof(string))); + Assert.True(converter.CanConvertFrom(typeof(string))); + Assert.False(converter.CanConvertFrom(typeof(int))); + Assert.False(converter.CanConvertFrom(typeof(bool))); + Assert.True(converter.CanConvertTo(typeof(string))); + Assert.False(converter.CanConvertTo(typeof(int))); + Assert.False(converter.CanConvertTo(typeof(bool))); + } + + [Fact] + public void PathStringStaysEqualAfterAssignments() + { + PathString p1 = "/?"; + string s1 = p1; + PathString p2 = s1; + Assert.Equal(p1, p2); } } }