2
votes

I am part of a large C# API project, and we are having issues with clients being confused due to unneeded properties showing in our Swagger documentation (we are using Swashbuckle to generate it)

In its simplest form, it comes down to this:

  • We have a simple class with just an ID and a Description property.

  • On the POST, we don't require the ID to be sent (will be auto generated). But on GET, and other verbs, the ID is required to be returned/sent

We would love to use the exact same model for all these endpoints (for simplicity), but exclude the ID from the POST request documentation

It would be great if it was excluded by endpoint, not by Verb - as I am sure we will run into some scenario where it is not Verb specific.

1
Sounds like you solved one problem only to create another. Perhaps you should distinct message contracts per operation. Its the model that should be canonical, not operation arguments - Micky
Does Swashbuckle have a way to mark a property as readOnly? This scenario is exactly what readOnly is for. - Helen
@Helen Yes Swashbuckle does have support for readOnly: github.com/domaindrivendev/Swashbuckle/blob/master/… - Helder Sepulveda
Zyth21, look into IDocumentFilter you can modify your resulting schema.json with that, you can add the readOnly property @Helen suggested, or just add good examples to each action - Helder Sepulveda

1 Answers

-1
votes

I usually use completely separate models as I usually follow the CQRS pattern so what I'm querying in a GET doesn't often look close to when I'm sending in a command via POST or PUT but I guess you could do something like this:

public class AddUpdateAddressType
{
    [Required]
    [StringLength(50, MinimumLength = 2)]
    public string Name { get; set; }

    public string Description { get; set; }
}

public class AddressType : AddUpdateAddressType {

    [JsonProperty(Order = -10)]
    public int Id { get; set; }

    [JsonProperty(Order = 98)]
    [DataType(DataType.DateTime)]
    public DateTime CreatedOn { get; set; }

    [JsonProperty(Order = 99)]
    [DataType(DataType.DateTime)]
    public DateTime ModifiedOn { get; set; }

}

Then in your controller actions the GET method is decorated with

    [HttpGet("{id:int}")]
    public async Task<IActionResult> Get(int id)
    {
         // fetch and return AddressType
    }

and your POST (or PUT) methods could look something like this

    [HttpPost]
    public async Task<IActionResult> Add(AddAddressType addressType)
    {
        // save AddressType and return whatever
    }

Hope this helps.