In the backend, when there are distributed demands, we often use 64-bit numeric types to represent field types. However, the frontend does not support numeric types longer than 16 bits, so when larger long and ulong values are transmitted to the backend, their accuracy has already been lost.
The solution is to convert ulong and long to strings and pass them to the backend.
public class TentantQueryDto
{
public ulong Id { get; set; }
}
This is a backend model where Id is a 64-bit number. We want to achieve automatic conversion from string to ulong when passed from the frontend, and automatic return of string to the frontend when ulong is sent from the backend.
First, we define two converters:
public class ULongToStringConverter : JsonConverter<ulong>
{
public override ulong Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string stringValue = reader.GetString();
if (string.IsNullOrWhiteSpace(stringValue)) return 0;
if (ulong.TryParse(stringValue, out var value)) return value;
return 0;
}
public override void Write(Utf8JsonWriter writer, ulong value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
public class StringToULongConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return reader.GetString();
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
ulong result = 0;
if (string.IsNullOrWhiteSpace(value))
result = 0;
if (ulong.TryParse(value, out var number))
result = number;
writer.WriteNumberValue(result);
}
}
These two converters are nothing special; they just convert between numeric values and strings.
Next, we define an attribute that tells us which fields should be used and how to automatically convert parameter types during JSON transmission between the frontend and backend:
/// <summary>
/// String and ulong converters
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property, AllowMultiple = false)]
public class ULongConverterAttribute : JsonConverterAttribute
{
public override JsonConverter CreateConverter(Type typeToConvert)
{
if (typeToConvert == typeof(ulong))
return new ULongToStringConverter();
if (typeToConvert == typeof(string))
return new StringToULongConverter();
return base.CreateConverter(typeToConvert);
}
}
Use this attribute on the fields that need to be converted:
public class TentantQueryDto
{
[ULongConverter]
public ulong Id { get; set; }
}
This way, we do not need to add conversion code separately, as ASP.NET Core will automatically invoke the converters during data transmission between the frontend and backend.
文章评论