Rather than hard-coding the expected form field names for a DTO, is it possible for them to be dynamic / determined at run time?
Background: I'm implementing a webhook which will be called with form-url-encoded data (the shape of the data the webhook will be invoked with is out of my control).
Currently the signature of my controller actions look something like below:
public async Task<IActionResult> PerformSomeAction([FromForm]SomeWebhookRequestDto request)
The DTO is for the most part has a bunch of properties like below:
[ModelBinder(Name = "some_property")]
[BindRequired]
public string SomeProperty { get; set; }
where the form-field name is known to be "some_property" in advance (will never change)
However for some properties, I'll want to determine the form field name at runtime:
[ModelBinder(Name = "field[xxx]")]
[BindRequired]
public DateTime? AnotherProperty { get; set; }
Note that xxx will be replaced by a number (will change according to information in the URL).
Note that I'd rather avoid implementing custom model binders if I can - it seems I should just be able to hook in a IValueProvider - I've had a go at doing that (added a IValueProviderFactory, registered at position 0) - but it seems that [FromForm] is greedy and so my IValueProvider(Factory) never gets a chance.
To clarify some points:
- The requests all have the same intent (they're all a request asking my API to do a single specific thing)
- The requests all have the same semantic shape (let's say there are 10 fields, all 10 must be populated with valid data for that field - dates where dates are supposed to go, strings where strings are supposed to go). The meaning of the field-values are consistent too.
- For the fields with names that must be determined at runtime, the field name will be something like "field[132]" or "field[130]". The names of those fields will depend on information provided in the URL - my API will perform a look-up to determine what the final names should be.
- There could be a very large number of these configurations so setting up separate endpoints for each is not feasible.
- While the above is somewhat of a nightmare, short of refusing to work on the gig it is out of my control