Using ASP.NET Core 2.2 I have the following ApiController action:
[ApiController]
public class PostController : Controller {
[HttpGet("posts/{postId:int:min(1)}")]
public async Task<IActionResult> GetByPostId([FromQuery]GetByPostIdRequest request {
}
}
Where GetByPostIdRequest is the following:
public class GetByPostIdRequest {
[FromRoute]
public Int32 PostId {聽get; set; }
public String LanguageCode { get; set; }
public IncludeExpression Include { get; set; }
}
The only way all parameters get values are:
FromQuery in action so I there is no Unsupported Media Type errorFromRoute inside the Request class to bind the PostId.Isn't there another way to do this?
Possible Solution
A suggestion could be to allow multiple attributes for one model ([FromRoute, FromQuery]):
[HttpGet("posts/{postId:int:min(1)}")]
public async Task<IActionResult> GetByPostId([FromRoute, FromQuery]GetByPostIdRequest request) {
}
}
Try something like that:
[HttpGet("posts/{postId:int:min(1)}")]
public async Task<IActionResult> GetByPostId([FromRoute] int postId, [FromQuery]GetByPostIdRequest request)
{
request.PostId = postId;
}
I would recommend @mateusvbf's suggestion Alternatively you could use the ModelBinderAttribute to indicate that the parameter isn't being deserialized from body. Outside of that, changing the binding source to a different one half way through an object graph isn't something we would support.
@mateusvbf Sure, that works but imagine a situation where I am using FluentValidation to validate GetByPostIdRequest and during validation of GetByPostIdRequest I need to know postId.
Consider I am not doing manual validation but automatic validation and adding errors to Model State.
Then things get a little bit tricky ... am I wrong?
Alternatively you could use the
ModelBinderAttributeto indicate that the parameter isn't being deserialized from body.
You mean using a custom model binder for GetByPostIdRequest object?
I added ModelBinder attribute to GetByPostIdRequest and I got the 415 error.
[HttpGet("posts/{postId:int:min(1)}")]
public async Task<IActionResult> GetByPostId([ModelBinder]GetByPostIdRequest request) {
request.PostId = postId;
}
Not sure what you meant ... Could you clarify?
Just decorating a parameter with the ModelBinder attributes tells MVC that it needs to be model bound and values can come from either Query, Form or Route.
I still don't understand why there is no support for Body/Route/Query out of the box. Having to have multiple arguments on the action is such a hack. ModelBinder doesn't work for a non-form payload.
The possible solution provided by the OP would also enable scenarios like the one I described in my issue #13492. Unfortunately though they closed it as something they don't plan to support :(
Thank you for contacting us. Due to no activity on this issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.