ASP.NET Core Post Json Request Parameter Model Type Conversion

2021年7月12日 54点热度 0人点赞 1条评论
内容目录

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.

痴者工良

高级程序员劝退师

文章评论