Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set one ProducesResponseType typeof for several HttpStatusCodes

I am setting the ProducesResponseType so as to have it documented with Swagger.

If the response is succesful (OK => 200), then it produces a IEnumerable.

[ProducesResponseType(typeof(IEnumerable<MyModel>), 200)]

But when I get an exception, I catch it, and then generate an object of my custom APIError class. When I populate the object, I can set different HttpStatusCodes, but in the end, what I want is to be able to set that ProducesResponseType is my APIError class for all the remaining HttpStatusCodes. I mean, I can get BadRequest, ServerInternalError, Forbidden, etc, but all are going to have the same response type (ApiError). Is there any way to set this line of code for all the error http codes? Or do I need to set it one by one?

[ProducesResponseType(typeof(ApiError), ???)]

Final result should look like this:

[ProducesResponseType(typeof(IEnumerable<MyModel>), 200)]
[ProducesResponseType(typeof(ApiError), AllFailureHttpCodes)]
like image 483
Andres Avatar asked Apr 01 '17 06:04

Andres


1 Answers

I fear that's not possible, at least not per action.

The IApiResponseMetadataProvider (see here) only has a single int StatusCode { get; } property defined and it's used for both ProducesAttribute and ProducesResponseTypeAttribute.

However, in your special case you may be able to register it as a global filter though, since the error result should be same on all actions no matter if it's GET, POST, PUT or DELETE.

services.AddMvc(options =>
{
    options.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(typeof(ApiError), 400));
    options.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(typeof(ApiError), 401));
    options.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(typeof(ApiError), 409));
});

These should then be applied to every action in your MVC/WebAPI application.

Word of warning

However, personally I find this usage wrong, because it would signal that every of your method can handle these type of errors. For example 409 is specifically for conflict, in a WebAPI you use it, when there is an error with updating an resource i.e. when using optimistic concurrency, the record was changed by another user and, hence the version of the record was changed and update failed.

Adding these to every method is just wrong. You should only add a status code if your action really handles this status code. For example, 409 is only suitable with PUT and POST Methods. Where 404 may be suitable for GET and PUT (update), but less suitable for POST (inserts).

This is especially bad, when you use tools such as Swagger to generate Api Docs, then you will just get a wrong documentation. You should look at ProducesResponseType as form of documentation and as such, shouldn't use a too generic approach for it.

Update: ASP.NET Core 2.2

With ASP.NET Core 2.2 the Swagger API support was greatly improved, this also includes convention based response type and codes.

It already comes with a good set of default conventions, but you can also override it and provide your own convention methods.

like image 82
Tseng Avatar answered Sep 29 '22 21:09

Tseng