Aspnetcore: Support multiple FromRoute and FromQuery per Object

Created on 3 May 2019  路  8Comments  路  Source: dotnet/aspnetcore

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:

  1. Have FromQuery in action so I there is no Unsupported Media Type error
  2. Have FromRoute 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) {
    }

}
area-mvc question

All 8 comments

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 ModelBinderAttribute to 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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

davidfowl picture davidfowl  路  126Comments

mkArtakMSFT picture mkArtakMSFT  路  89Comments

oliverjanik picture oliverjanik  路  91Comments

natemcmaster picture natemcmaster  路  213Comments

danroth27 picture danroth27  路  79Comments