Given the below OData custom action. Is it possible to get a more refactor friendly binding of the action parameters?
Both magic strings has to be exactly the same: .Parameter<int>("Rating")
and (int)parameters["Rating"]
. Which is bound to break at some point in the future.
Config
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
// New code:
builder.Namespace = "ProductService";
builder.EntityType<Product>()
.Action("Rate")
.Parameter<int>("Rating");
Controller
[HttpPost]
public async Task<IHttpActionResult> Rate([FromODataUri] int key, ODataActionParameters parameters)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
int rating = (int)parameters["Rating"];
db.Ratings.Add(new ProductRating
{
ProductID = key,
Rating = rating
});
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateException e)
{
if (!ProductExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
Request
POST http://localhost/Products(1)/ProductService.Rate HTTP/1.1
Content-Type: application/json
Content-Length: 12
{"Rating":5}
I tried putting the parameter directly in the method. But I couldn't get it to work.
public async Task<IHttpActionResult> Rate([FromODataUri] int key, int rate)
According to How to pass an objet as a parameter to an OData Action using ASP.NET Web Api? it seems it's possible to use an Object
but I only have a primitive type as the parameter.
Please advice :)
I think you are talking about this issue https://github.com/OData/WebApi/issues/777
The ODataActionParameters make thing complicate when there is only one action parameter, we will try to have a workaround or design for this after breaking change 6.0 release.