-
-
Notifications
You must be signed in to change notification settings - Fork 227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question - is it possible to bind both FromQuery and Body object using this library #42
Comments
I have no idea if the below comment will be helpful or applicable to this library. I just started looking at it now. But with MediatR I did this and it would work. On the query/command/request itself you put the attributes on the properties themselves where it's coming from. At least back then, public class ResourceRequest : TRequest<TResponse>
{
[FromQuery]
public int ExternalTicketId { get; set; }
[FromBody]
public ResourceRequestBody Body { get; set; }
public class ResourceRequestBody
{
public int Id { get; set; }
public string Name { get; set; }
}
} Good luck, Again I have no idea if this works in this library. I'll add though, looking back... I'd probably just remove the stuff from the query/route in these cases and just put those parameters into the body/payload if you can. Because I was using AutoMapper, and some other tools to make things "easier" I had to deal with these two levels of stuff... when I could have, in this case, just put that ExternalTicketId into the payload body. |
I was about to ask the same question, or at least similar. There is a use case when I want to add a child to a parent with the request: Url: Body:
In a "normal" controller we'd define the endpoint:
We can't do this with Endpoints so I tried adding a wrapper class like above
and defining the endpoint thus:
This didn't work and failed to bind the properties. At a loss as to what to do now, I don't want to stop using Endpoints, but I feel that this is a very common pattern and should be supported.... is it? Am I doing something wrong? |
yeah I never solved this problem - which is unfortunate as I also really enjoy this library and pattern. I fallback to using the default controllers for now for these cases |
¿Could be this a possible solution?
Even with three
|
I had the same issue but after further exploration and fiddling around I realise that the Model Binding actually takes care of this. All that is needed is to create your Model Class and decorate your properties with the attributes you need. i.e. public class NewArticleRequest
{
[FromRoute(Name = "username")] public string Username { get; set; }
[FromRoute(Name ="category")] public string Category { get; set; }
[FromBody] public Article Article { get; set; }
[FromHeader (Name = "Content-Type")] public string ContentType { get; set; }
} Then you can make use of it in your End Point as follows [Route("/article")]
public class Post : BaseAsyncEndpoint
.WithRequest<NewArticleRequest>
.WithoutResponse
{
[HttpPost("{username}/{category}")]
[SwaggerOperation(
Summary = "Submit a new article",
Description = "Enables the submission of new articles",
OperationId = "B349A6C4-1198-4B53-B9BE-85232E06F16E",
Tags = new[] {"Article"})
]
public override Task<ActionResult> HandleAsync([FromRoute] NewArticleRequest request,
CancellationToken cancellationToken = new CancellationToken())
{
//// your implementation
}
} The only snag/issue/bug I seem to run into seems to be related only to the [FromRoute] is that it doesn't seem to bind those specific properties unless you explicity set the in the Another key point to remember is when making use of Model Binding on [FromRoute(Name = "username")] public string Username { get; set; } Also as in the case for the [FromHeader (Name = "Content-Type")] public string ContentType { get; set; } |
Can others confirm here if @garywoodfine 's approach works? If so I will be sure to get it added to the docs and will avoid adding additional complexity to the underlying package. If it doesn't work, please provide an example of what you're doing that doesn't work. Thanks! |
I've just spun up an API from scratch. Confirmed that this way does work. The important part is having the Endpoint
Models
Request POST http://localhost:5000/weather/5/stuff
I have closed PR #50 |
As an FYI this method confuses Swashbuckle - the generated UI will assume the request body is the parameter type and seemingly is ignorant of the property flag So to follow @matt-lethargic's example, whilst the API endpoint will be expecting the request body in the form of a {
"summary": "Bad weather"
} The swagger UI and document will describe it as: {
"day": "string",
"forecast": {
"summary": "string"
}
} There may well be an easy workaround - I only tried this out about 90mins ago and haven't been able to locate a solution in that time. I'm also pretty certain this is something for Swashbuckle to fix but thought others may find this useful to know. |
@Jestar342 have you reported this issue to Swashbuckle? I just faced same problem... |
I've documented this in the README. |
@Jestar342 and @fw2568 did you ever find a solution? I filed an issue here: domaindrivendev/Swashbuckle.AspNetCore#2346 |
Running AspNet Core 6: [Route("weather")]
public class WeatherForecastController : EndpointBaseAsync.WithRequest<CreateForecastRequest>.WithoutResult
{
[HttpPost("{day}/stuff")]
public override async Task<ActionResult> HandleAsync([FromRoute] CreateForecastRequest request, CancellationToken cancellationToken = new CancellationToken())
{
await Task.CompletedTask;
return Ok();
}
}
public record CreateForecastRequest
{
[FromRoute] // don't need to specify for capitalization [FromRoute(Name = "day")]
public string Day { get; set; }
[FromBody]
public ForecastModel Forecast { get; set; }
}
public record ForecastModel
{
public string Summary { get; set; }
} Renders in Swagger |
I recently published this which I'm experimenting with for this purpose as well: |
How do you combine Ardalis.RouteAndBodyModelBinding with ApiEndpoints? And one more question - is it possible to define request parameters' attributes ( |
It is possible to do this as I can't workout how based on the TRequest, TResponse definition. The below will obviously not compile.
Thanks
public class MyEndpoint : BaseEndpoint<PayloadBody, string>
...
[HttpPost("resource/{externalTicketId}")]
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))]
public override ActionResult Handle([FromQuery] string externalTicketId, PayloadBody payload)
{
....
The text was updated successfully, but these errors were encountered: