Swashbuckle.AspNetCore.Filters icon indicating copy to clipboard operation
Swashbuckle.AspNetCore.Filters copied to clipboard

Facility to disable automatic annotation for examples

Open RonakThakkar opened this issue 5 years ago • 12 comments

I have come across a case where I created a custom response example which is derived from
MyExample : IExamplesProvider and then GetExamples have a specific message returned.

Now I want this to be applied to only specific response code, but because of automatic annotation, it gets applied to all actions that have return type set to string.

RonakThakkar avatar Nov 25 '19 13:11 RonakThakkar

Hmm, you've come up with a use case I hadn't considered.

I would say that in general it's a bad practice to return a plain old string in an API response. I usually have unique DTOs for each of my requests and responses.

e.g. instead of returning "Order submitted" consider returning

{
  "message": "Order submitted"
}

The reason I say this is, if you ever needed to extend the response by adding a new property, e.g.

{
  "id": 123,
  "message": "Order submitted"
}

Then it is not a breaking change - consumers of your API that know about "message" can keep reading it and don't need to change.

mattfrear avatar Nov 25 '19 22:11 mattfrear

I don't know if this is related for request examples as well, but I just came across a problem where I have, say, an HTTP POST controller action with the following signature:

        [HttpPost]
        [SwaggerRequestExample(typeof(MyCustomInput), typeof(MyCustomInputExample))]
        public async Task<IActionResult> Post([FromBody] MyCustomInput myCustomInput)

Expected behaviour would be that it activates the MyCustomInputExample implementation, which it actually does. But, if I have an implementation of IExamplesProvider that uses type string, it will activate that one afterwards, and override the examples return value from the IExamplesProvider I expected to be used.

I can agree it's probably bad practice to return a string, which is an easy fix for me. However, it's still quite confusing behaviour that can take quite a bit of time to debug.

CodingBeagle avatar Dec 11 '19 12:12 CodingBeagle

Hmm, there is logic in place such that if a [SwaggerRequestExamples] attribute present, then the automatic annotation won't be applied. It sounds like that logic is not working correctly, which is a bug.

@CodingBeagle which version of Swashbuckle.AspNetCore.Filters are you using?

mattfrear avatar Dec 11 '19 20:12 mattfrear

@mattfrear I am using version 5.0.0-rc8 :)

CodingBeagle avatar Dec 12 '19 09:12 CodingBeagle

@mattfrear I realise this issue is quite old but I am having a related problem. I am upgrading from 4.3.1 to 5.1.1 and have an issue related to this. I have two end points - one decorated with:

[ProducesResponseType(typeof(LinkedResponse), StatusCodes.Status200OK)]
[SwaggerResponseExample(StatusCodes.Status200OK, typeof(GetResponseExample))]

and the other decorated with:

[ProducesResponseType(typeof(LinkedResponse), StatusCodes.Status200OK)]

In 4.3.1, the former comes with an example, the latter does not as expected, but now I get the same example (GetResponseExample) for both. I suspect the automatic annotation of examples is kicking in here which is why I am now getting the example in the second case. Is there a way to either disable the automatic annotation completely, going back to 4.3.1 behaviour, or some attribute I could apply to the second case to explicitly NOT generate an example for it? The former is my preferred route.

As an experiment I tried adding an example to the second case that simply returned null and that worked but it seems counter-intuitive to add an example to not add an example if you see what I mean.

thanks

freeranger avatar Jun 24 '20 12:06 freeranger

I suspect the automatic annotation of examples is kicking in here which is why I am now getting the example in the second case. Is there a way to either disable the automatic annotation completely, going back to 4.3.1 behaviour, or some attribute I could apply to the second case to explicitly NOT generate an example for it? The former is my preferred route.

As an experiment I tried adding an example to the second case that simply returned null and that worked but it seems counter-intuitive to add an example to not add an example if you see what I mean.

Hi @freeranger . You've found the workaround I was going to suggest, so well done :-)

I've added a new extension method for you to register the required services for examples but without automatic annotations.

Instead of services.AddSwaggerExamplesFromAssemblyOf<YourExample>();

call services.AddSwaggerExamples();

This will be in the next release, possibly quite soon.

mattfrear avatar Jun 25 '20 09:06 mattfrear

Wow, great service - thanks @mattfrear !

freeranger avatar Jun 25 '20 09:06 freeranger

Released https://www.nuget.org/packages/Swashbuckle.AspNetCore.Filters/5.1.2

mattfrear avatar Jun 25 '20 10:06 mattfrear

Doesn't work for me. services.AddSwaggerExamples(); hides all examples for all status codes

tyskodima avatar Jul 05 '21 13:07 tyskodima

Doesn't work for me. services.AddSwaggerExamples(); hides all examples for all status codes

It's been a while since I looked at this, but I think if you use services.AddSwaggerExamples() then you have to explicitly add [SwaggerRequestExample] and [SwaggerResponseExample] to all of your controller actions.

mattfrear avatar Jul 06 '21 08:07 mattfrear

@mattfrear I've created a simple project: https://github.com/tyskodima/TestResponseExamples

if I use AddSwaggerExamples, then there are no examples for any actions image

if I use AddSwaggerExamplesFromAssemblies, examples are added to all actions. But I need it only for action1 image

tyskodima avatar Jul 06 '21 18:07 tyskodima

Thanks for providing a simple project to reproduce the error. It looks like it's not working any more.

mattfrear avatar Jul 07 '21 06:07 mattfrear