using System.Runtime.Serialization;
public class FriendlyUrlValidationException : Exception
public FriendlyUrlValidationException()
public FriendlyUrlValidationException(string message) : base(message)
public FriendlyUrlValidationException(string message, Exception inner) : base(message, inner)
protected FriendlyUrlValidationException(
StreamingContext context) : base(info, context)
public class FriendlyUrlJsonConverter : JsonConverter
public override bool CanConvert(Type objectType)
return objectType == typeof(FriendlyUrl);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
return new FriendlyUrl((string)reader.Value);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
writer.WriteValue(((FriendlyUrl)value).ToString());
[JsonConverter(typeof(FriendlyUrlJsonConverter))]
public class FriendlyUrl : IEquatable<FriendlyUrl>, IConvertible
_friendlyUrl = string.Empty;
public FriendlyUrl(string value)
public static implicit operator FriendlyUrl(string friendlyUrlValue)
return new FriendlyUrl { _friendlyUrl = friendlyUrlValue };
public static implicit operator string(FriendlyUrl furl)
return furl._friendlyUrl;
public override string ToString()
private string _friendlyUrl;
public bool Equals(FriendlyUrl other)
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return string.Equals(_friendlyUrl, other._friendlyUrl, StringComparison.InvariantCultureIgnoreCase);
public override bool Equals(object obj)
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj is string stringValue) return string.Equals(_friendlyUrl, stringValue, StringComparison.InvariantCultureIgnoreCase);
if (obj.GetType() != GetType()) return false;
return Equals((FriendlyUrl) obj);
public override int GetHashCode()
return _friendlyUrl != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(_friendlyUrl) : 0;
public static bool operator ==(FriendlyUrl left, FriendlyUrl right)
return Equals(left, right);
public static bool operator !=(FriendlyUrl left, FriendlyUrl right)
return !Equals(left, right);
TypeCode IConvertible.GetTypeCode()
return _friendlyUrl.GetTypeCode();
bool IConvertible.ToBoolean(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToBoolean(provider);
byte IConvertible.ToByte(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToByte(provider);
char IConvertible.ToChar(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToChar(provider);
DateTime IConvertible.ToDateTime(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToDateTime(provider);
decimal IConvertible.ToDecimal(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToDecimal(provider);
double IConvertible.ToDouble(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToDouble(provider);
short IConvertible.ToInt16(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToInt16(provider);
int IConvertible.ToInt32(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToInt32(provider);
long IConvertible.ToInt64(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToInt64(provider);
sbyte IConvertible.ToSByte(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToSByte(provider);
float IConvertible.ToSingle(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToSingle(provider);
string IConvertible.ToString(IFormatProvider provider)
return _friendlyUrl.ToString(provider);
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
if (conversionType == typeof(FriendlyUrl))
return ((IConvertible) _friendlyUrl).ToType(conversionType, provider);
ushort IConvertible.ToUInt16(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToUInt16(provider);
uint IConvertible.ToUInt32(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToUInt32(provider);
ulong IConvertible.ToUInt64(IFormatProvider provider)
return ((IConvertible) _friendlyUrl).ToUInt64(provider);
public static void Test()
FriendlyUrl friendlyUrl = "some-friendly-url-1";
string friendlyUrlJson = JsonConvert.SerializeObject(friendlyUrl);
Assert.AreEqual($"\"{friendlyUrl}\"", friendlyUrlJson);
FriendlyUrl deserialized = JsonConvert.DeserializeObject<FriendlyUrl>(friendlyUrlJson);
Assert.AreEqual(friendlyUrl, deserialized);
Console.WriteLine("Success");
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Assembly.GetName().Name, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.Location.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];