[Request] Add support for arbitrary models in custom actions
@xuzhg is already working on this.
Since Feb 27, 2023.
- Dominant language
- C#
- Stars
- 505
- Forks
- 186
- PR merge metrics
- No merged PRs in 30d
Description
Custom functions today are very cumbersome to use: they require the use of parameters that are bound to a custom dictionary-like structure, ODataActionParameters. The consumer then needs to read the parameters from this object to use them.
This goes against standard MVC model binding which allows (and recommends) binding your parameters directly into a strongly typed model object that represent them.
I think adding native support in OData to bind the body of the action to an actual custom model (like MVC does) would make the framework vastly easier to use.
From the docs: https://learn.microsoft.com/en-us/odata/webapi-8/fundamentals/actions-functions#bound-action-1
Instead of:
[HttpPost("odata/Books({key})/Rate")]
public IActionResult Rate([FromODataUri] string key, ODataActionParameters parameters)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
int rating = (int)parameters["rating"];
if (rating < 0)
{
return BadRequest();
}
return Ok(new BookRating() { BookID = key, Rating = rating });
}
We'd do:
public class RatingViewModel
{
public int Rating { get; set; }
}
[HttpPost("odata/Books({key})/Rate")]
public IActionResult Rate([FromODataUri] string key, RatingViewModel ratingViewModel)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
if (ratingViewModel.Rating < 0)
{
return BadRequest();
}
return Ok(new BookRating() { BookID = key, Rating = ratingViewModel.Rating });
}
This would naturally also open the door for standard validation using DataAnnotations or FluentValidation, making it much more seamless when coming from a normal MVC route.
When specifying the EDM for the function, I'm not entirely sure what would need to be done there, but maybe something that would generate the required EDM automatically based on the complex type could be achieved?
builder.EntityType<Book>()
.Action("rate")
.Parameter<RatingViewModel>("ratingViewModel");
The Parameter method could identify that the type is not a primitive type, and apply the rules as needed (either transparently transform it into multiple Parameter<primitiveType> calls for each property, or just support this natively at the EDM level as well.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.