Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Fully Expand Models in ApiExplorer #2378

Closed
rynowak opened this issue Apr 13, 2015 · 4 comments
Closed

Fully Expand Models in ApiExplorer #2378

rynowak opened this issue Apr 13, 2015 · 4 comments

Comments

@rynowak
Copy link
Member

rynowak commented Apr 13, 2015

This is feedback from @domaindrivendev:

    [HttpGet("addresses/validate")
    public bool ValidateAddress([FromQuery] Address address)

Today we'd describe address as a single parameter, despite the fact that it maps to different query string keys (address.zipcode, address.state, etc...). The feedback is that Swashbuckle (and other consumers) would always want this data to be broken down as much as possible (today it's as brief as possible).

We should either break this down fully (by property) or break down the first level (by property).

We'd of course apply cycle-breaking, and terminate on any type with a type-converter from string.

@danroth27 danroth27 added this to the 6.0.0-beta5 milestone Apr 14, 2015
@domaindrivendev
Copy link

Awesome - this will really simplify things in Swashbuckle!

You should have a quick read over this issue if you get a chance. It's related to the way in which I implemented a workaround for lack of the above up to this point.

domaindrivendev/Swashbuckle.WebApi#285

@rynowak
Copy link
Member Author

rynowak commented Apr 24, 2015

@domaindrivendev

In that case, what we recommend for the app developer is that you use the attributes to specify precisely what you mean.

Due to compat with MVC's ability to handle form posts, model binding always tries first to use the parameter name as a prefix and then again with the empty string as a prefix.

So for the example in the bug:

public User GetUserWithComplexParameters(
    [FromQuery] GetUserRequest getUserRequest,
    [FromQuery] GetUserAdditionalRequest getUserAdditionalRequest)

public class GetUserRequest
{
    public string AdditionalField { get; set; }
}

public class GetUserAdditionalRequest
{
    public string AdditionalField { get; set; }
}

There are three equally valid ways to set AdditionalField to a distinct value on both models.

?getUserRequest.AdditionalField=foo&AdditionalField=bar
?AdditionalField=foo&getUserAdditionalRequest.AdditionalField=bar
?getUserRequest.AdditionalField=foo&getUserAdditionalRequest.AdditionalField=bar

This is great for MVC/browser scenarios, but for an API it's better to be precise. Many users don't realize that all of these are valid, and the risk is that an innocent-looking refactor will break existing clients.

For that reason we recommend that you be explict when defining an API about the behavior re:prefixes

public User GetUserWithComplexParameters(
    [FromQuery(Name = "")] GetUserRequest getUserRequest,
    [FromQuery(Name = "getUserAdditionalRequest")] GetUserAdditionalRequest getUserAdditionalRequest)

@rynowak
Copy link
Member Author

rynowak commented Apr 24, 2015

I'm not 100% sure that this guidance is relevant for a WebAPI 2 user, but this case is something we definitely want to support precision on in the next release.

rynowak added a commit that referenced this issue May 5, 2015
This change dramatically simplifies the parameter discovery logic in
DefaultApiDescriptionProvider. Instead of surfacing POCO objects as
parameters, we now fully expand every model.

The rationale is that we want to show every key/value that can be set by
the user and not force consumers of ApiDescription to do that themselves.

Tests are cleaned up to match the new behavior.
@rynowak rynowak closed this as completed in 0f6b233 May 8, 2015
@rynowak
Copy link
Member Author

rynowak commented May 8, 2015

0f6b233

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants