简体   繁体   中英

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": "Dave.Smith@gmail.com"
      },
      {
        "id": 171162,
        "isAdmin" : false,
        "name": "Jane Doe",
        "email": "Jane.Doe@gmail.com"            
      }
    ]
  }
}
]
}

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM