aaronR
aaronR

Reputation: 1567

Describing Dynamic Response Types For REST API

I use a standard APIResponse Object Interface for all of my REST APIs.

public interface IAPIResponse
{
    IAPIError Error { get; set; }        
    IEnumerable<dynamic> Results { get; set; }
    void AddResult(string groupName, object data);

}

Here is how I use the standard APIResponse object.

public async Task<IActionResult> Get()
{
        try
        {
           var response = new UsersGetResponse {
                   Users = await _someService.GetAll()};

            _apiResponse.AddResult("UsersGetResponse", response );

            return new ObjectResult(_apiResponse);
        }
        catch (Exception ex)
        {
            _apiResponse.Error = new APIError(ex.Message, 500);
            return new ObjectResult(_apiResponse);
        }            
}  

The call to _someSerice.GetAll() returns a list of the following User Objects.

public interface IUser
{

    string Id { get; set; }
    bool IsAdmin { get; }
    string Name { get; set; }
    string Email { get; set; }
}

Which is an attribute of the parent class UsersGetResponse

public class UsersGetResponse
{
     public IList<User> Users { get; set;}
}

This will produce the following JSON.

{
"error": null,    
"results": [
{
  "UsersGetResponse": {

    "Users": [
      {
        "id": 171161,
        "isAdmin" : true,
        "name": "Dave Smith",
        "email": "[email protected]"
      },
      {
        "id": 171162,
        "isAdmin" : false,
        "name": "Jane Doe",
        "email": "[email protected]"            
      }
    ]
  }
}
]
}

If I use the ProducedResponseType annotation like so.

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

I only get the following Example JSON in swagger.

{
  "error": {
    "message": "string",
    "number": 0
  },    
  "results": [
  {}
  ]
}

I'm trying to see if there is a way to properly communicate to the consumers of my API that I have a standard APIResponse Object with Dynamic results that have specific Objects like UsersGetResponse.

Upvotes: 0

Views: 4328

Answers (2)

user7886649
user7886649

Reputation: 391

Without fully understanding the scope of what you are trying to do, I will not be able to give you a complete solution. However, with the info that you have provided, this is what you should do:

public sealed class APIResponse<T>
{
    IAPIError Error { get; set; }        
    T Results { get; set; }
}

public async Task<IActionResult> Get()
{
    var response = new ApiResponse<<IEnumerable<User>>>();
    try
    {
        var data = await _someService.GetAll();
        response.Result = data;

        return Ok(response);//returns 200 status code
    }
    catch (Exception ex)
    {
        response.Error = new APIError(ex.Message, 500);
        return BadRequrest(response);
    }            
}  

You can then annotate like this:

[ProducesResponseType(typeof(APIResponse<IEnumerable<User>>), StatusCodes.Status200OK)]

Hope this helps.

Upvotes: 1

user7886649
user7886649

Reputation: 391

This is because you are using dynamic type. Swagger does not recognize any "properties" on that type. If you use a concrete type or an interface instead, swagger will show you the properties on that object.

Upvotes: 0

Related Questions