Table of Contents

Class ValidationArgValue

Namespace
Trellis
Assembly
Trellis.Core.dll

The value of a single entry in the Args carried by a FieldViolation or RuleViolation.

[JsonConverter(typeof(ValidationArgValueJsonConverter))]
public abstract record ValidationArgValue : IEquatable<ValidationArgValue>
Inheritance
ValidationArgValue
Implements
Derived
Inherited Members
Extension Methods

Examples

ValidationArgs.Of("maxLength", 50)                     // {"maxLength": 50}
ValidationArgs.Of("min", 0, "max", 255)                // {"min": 0, "max": 255}
ValidationArgs.Of("allowed", ValidationArgValue.ListOf("red", "green"))

Remarks

This is a closed union — ValidationArgValue.Text, ValidationArgValue.Number, ValidationArgValue.Bool, or ValidationArgValue.List — and the constructor is private so it stays closed. A client can therefore switch over it exhaustively, and the JSON shape of an arg is knowable from the type alone rather than from whatever a producer happened to pass.

The cases are JSON's self-describing values: its three scalars, plus a list of them. JSON's other two constructs are deliberately absent. null would give a dictionary two spellings of the same thing, since an arg with no value is an arg that is simply not there. An object would mean a client needs a schema per reason code to know what it is looking at, which gives up the property that makes this union worth having — that the shape follows from the type — and turns args into an open-ended payload, which is a poor thing to echo back to a caller.

The predecessor of this type was string, which forced every operand onto the wire quoted: a length bound arrived as "maxLength": "50", and a client that wanted to compare it against a length had to parse it back out, guessing at the format. Modelling the number as a number removes the guess — "maxLength": 50 — while keeping the property that made string attractive in the first place, which is that no producer-side culture can leak into the payload. ValidationArgValue.Number holds a decimal and is written by System.Text.Json invariantly, so a German server and an American one emit the same bytes.

Args are still operands, not an echo of the caller's input. Never put the rejected value itself in here — a rejected password or token would then be reflected back in an error response and into whatever logs that response.

Methods

ListFrom(IEnumerable<ValidationArgValue>)

Builds a ValidationArgValue.List from a sequence.

public static ValidationArgValue ListFrom(IEnumerable<ValidationArgValue> items)

Parameters

items IEnumerable<ValidationArgValue>

The list members, in order.

Returns

ValidationArgValue

ListOf(params ValidationArgValue[])

Builds a ValidationArgValue.List from the supplied items.

public static ValidationArgValue ListOf(params ValidationArgValue[] items)

Parameters

items ValidationArgValue[]

The list members, in order. May be empty.

Returns

ValidationArgValue

Operators

implicit operator ValidationArgValue(bool)

Wraps a boolean as ValidationArgValue.Bool.

public static implicit operator ValidationArgValue(bool value)

Parameters

value bool

The flag.

Returns

ValidationArgValue

implicit operator ValidationArgValue(decimal)

Wraps a decimal as ValidationArgValue.Number.

public static implicit operator ValidationArgValue(decimal value)

Parameters

value decimal

The number.

Returns

ValidationArgValue

implicit operator ValidationArgValue(int)

Wraps an integer as ValidationArgValue.Number.

public static implicit operator ValidationArgValue(int value)

Parameters

value int

The number.

Returns

ValidationArgValue

implicit operator ValidationArgValue(long)

Wraps a long as ValidationArgValue.Number.

public static implicit operator ValidationArgValue(long value)

Parameters

value long

The number.

Returns

ValidationArgValue

implicit operator ValidationArgValue(string)

Wraps a string as ValidationArgValue.Text.

public static implicit operator ValidationArgValue(string value)

Parameters

value string

The text.

Returns

ValidationArgValue