Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I accurately represent the dto that will be returned to a REST call with Swagger? #72

Open
sw-bbrown opened this issue Sep 24, 2018 · 2 comments

Comments

@sw-bbrown
Copy link

Hello,

We're trying to do these two things in an Asp.Net core Api:

  • leverage the halcyon package to add _links to our Dto models as our flavor of HAL.
  • leverage NSwag to generate swagger documentation of what the api looks like, including what the models look like.

We have Dto models similar to this:

public class FooDto
{
  public int Id {get; set;}
  public string Value {get; set}
}

Which when returned out of the API have a self link added by creating a new Halcyon.HAL.HALResponse , which looks like this (sorry for adding comments to json but i wanted to be clear):

// run-time json
{
  "Id": 1,
  "Value": "some value",
  "_links": {
    "self": {
      "href": "/foo/1"
    }
  }
}

The Problem
But when we instruct NSwag about the Dto with an attribute on the controller like this [SwaggerResponse(HttpStatusCode.OK, typeof(FooDto))]
The swagger page does not include the "_links" field in the representation of the return model.

// swagger documentation json
{
  "Id": "int",
  "Value": "string"
  // Links section should be here
}

If we give Swagger the HALResponse type: [SwaggerResponse(HttpStatusCode.OK, typeof(HALResponse))], the swagger page simply displays a json model with "model" and "config" sections and no other content.

I've search around the web without finding a solution that still uses the Halcyon.HAL.HALResponse. I did see that issue #56 mentioned Swagger but it didn't seem to touch on this issue except in one un-responded-to comment on the bottom.

I can see a way to get swagger the correct model- add the _links property to the Dtos, but that means throwing out Halcyon, so I wanted to check here first.

The Issue:
How can we register a type such that NSwag/Swagger will properly document the model that will be returned from the API when returning something like this:

            return this.HAL(fooModel, new Link[] {
                new Link("self", "/api/foo/{id}")
            });
@macux
Copy link

macux commented Nov 30, 2018

Would like a solution to this too, however it'll need some kind of customisation of NSwag rather than halcyon given that NSwag will use either the Produces[ResponseType]Attribute(s) or SwaggerResponseAttribute with a type to determine what the response is.

As you've seen there is no type that contains both your actual response and the HAL info and there's no way of constructing that type automatically given, for example, an embedded object receives its name from a string at runtime.

The solution would be to write a custom ContractResolver which NSwag supports (or possibly a JsonConverter). You would then map your return type to the HAL based on your own conventions, e.g. for a simple object perhaps you'd only add a _self link whereas for any IEnumerable you'd add _self/first/prev/next/last and maybe a count. For an embedded IEnumerable you'd also need an extra bit of jiggery pockery to get the name of the collection, which could be done with a Description attribute on the base DTO type that's in the IEnumerable. A few hoops to jump through but suspect it's all possible, you'd certainly end up with an opinionated ContractResolver but suspect that would work OK.

Feel free to post your solution here when you've written it! 😉

@macux
Copy link

macux commented Dec 3, 2018

FWIW I've got this working in a simple API, result was though that dropping halycon was the simplest thing to do and adding a couple of dto base classes (one for simple objects and another for collections). Currently I've got a custom contract resolver that just renames the embedded property on the collection dto to the actual collection name but I may change this at some point to just inherit from the base dto classes if the HAL gets more complex.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants