hal icon indicating copy to clipboard operation
hal copied to clipboard

Swagger UI response Type for HAL Resources

Open ceriomenco opened this issue 1 year ago • 2 comments

Problem statement:

When using swagger with [ProducesResponseType(typeof(MeetingRoom), StatusCodes.Status200OK)] The generated docs would produce a schema such as:

{
  "id": 0,
  "name": "string",
  "seats": 0
}

Where as in reality the response type is a wrapped HAL resource such as:

{
  "_links": {
    "self": {
      "href": string
    }
  },
  "id": number,
  "name": string,
  "seats": number
}

What approach would you suggest for integrating with swagger docs?

Couple of things come to my mind:

  1. Custom ActionAttribute aka ProducesHalResponseType(typeof(MeetingRoom), StatusCodes.Status200OK)] which would attempt describe it accordingly.
  2. Custom converters for serialization.

ceriomenco avatar Dec 20 '23 17:12 ceriomenco

Hi @ceriomenco , I may need some time to investigate this issue and provide a good solution. But I guess I should be able to handle this by customizing the serialization on the Swagger side. Will keep you posted once I found the solution asap. Thanks.

daxnet avatar Dec 24 '23 10:12 daxnet

Hi @ceriomenco, After some thinking I suppose the type used in the ProducesResponseType is a kind of schema type which would be dynamic in the HAL's use cases, however, that is not supported at the moment. Specifically, ProducesResponseType attribute requires a concrete type on its Type parameter, you must explicitly specify the type with the typeof expression. However, describing the schema of an array of MeetingRoom in a HAL response for example is quite dynamic (like the name of the array in the _embedded object is specific to meetingRooms in our case). Even though we can create a type dynamically at runtime by using reflection emit, it is not able to be used by ProducesResponseType attribute. But we have a workaround, take the MeetingRooms as an example, you can define the following set of schema classes and use the root one in the ProducesResponseType declaration:

public sealed class MeetingRoomResponseSchema
{
    public LinksSchema _links { get; set; }

    public PageSchema page { get; set; }

    public EmbeddedSchema _embedded { get; set; }
}

public class LinksSchema
{
    public LinkSchema _self { get; set; }

    public LinkSchema _first { get; set; }
}

public class LinkSchema
{
    public string href { get; set; }
}

public class PageSchema
{
    public int number { get; set; }

    public int size { get; set; }

    public int totalElements { get; set; }

    public int totalPages { get; set; }
}

public class MeetingRoomSchema : MeetingRoom
{
    public LinkSchema _self { get; set; }
}

public class EmbeddedSchema
{
    public MeetingRoomSchema[] meetingRooms { get; set; }
}

And then:

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

Generally, such kind of schema type is quite domain-specific and will not be part of the HAL library (But maybe adding the common ones like PageSchema, LinkSchema to the library could be an idea).

Thanks!

daxnet avatar Dec 24 '23 11:12 daxnet

Since there is no additional request on this topic, will close this ticket. If necessary, please create another one for tracking. Thanks.

daxnet avatar Jul 10 '24 00:07 daxnet