I'm in the middle of converting an ASP.NET Core 6 API app to be a Minimal API app. Now that ASP.NET Core 8 supports [FromForm] for object binding, I decided to take the plunge, but I'm running into trouble.
Specifically I'm having a hard time getting value objects bound. In my case these are strongly typed ids using Andrew Lock's StronglyTypedId. When I added a TryParse static method to the value object, as mentioned here, it successfully bound when using [FromRoute], but I can't get it to bind to the property of an object, even though the TryParse should still apply.
Here's the object I'm trying to bind using [FromForm]:
public sealed class Command :
IRequest<IResult> {
[MaxLength(254), EmailAddress]
public string? Email { get; init; }
[Required]
public ContactId Id { get; init; }//<-- The property not binding...
[Required, MaxLength(byte.MaxValue)]
public string Name { get; init; } = null!;
[Range(1000000000, 9999999999)]
public long? Phone { get; init; }
}
And here's the value object for the ContactId property:
[StronglyTypedId(StronglyTypedIdBackingType.Int, StronglyTypedIdConverter.EfCoreValueConverter | StronglyTypedIdConverter.SystemTextJson | StronglyTypedIdConverter.TypeConverter)]
public partial struct ContactId {
public static ContactId Parse(
int? value) => value.HasValue
? new ContactId(value.Value)
: throw new ArgumentNullException(nameof(value));
public static ContactId Parse(
ReadOnlySpan<char> value) => int.TryParse(value, out var intValue)
? new ContactId(intValue)
: throw new ArgumentNullException(nameof(value));
public static bool TryParse(
string value,
out ContactId id) {
if (!int.TryParse(value, out var intValue)) {
ArgumentNullException.ThrowIfNull(value, nameof(value));
}
id = new ContactId(intValue);
return true;
}
public sealed class EfCoreValueGenerator :
ValueGenerator<ContactId> {
public override ContactId Next(
EntityEntry entry) => new(Random.Shared.Next() * -1);
public override bool GeneratesTemporaryValues => true;
}
}
What should I do to resolve this?
ContactId?