I'm using Swashbuckle (6.1.1) in a .Net 5.0 Web API. I'm still learning, but I'd like to implement a class where certain properties only are valid when 'reading' with a GET
, and other properties when 'writing' with a POST
. According to the OpenAPI spec:
You can use the readOnly and writeOnly keywords to mark specific properties as read-only or write-only. This is useful, for example, when GET returns more properties than used in POST – you can use the same schema in both GET and POST and mark the extra properties as readOnly. readOnly properties are included in responses but not in requests, and writeOnly properties may be sent in requests but not in responses.
This is exactly what I want to achieve. However, I'm struggling to get Swashbuckle to generate the OpenAPI spec with the readOnly
and writeOnly
keyworks.
For example:
public class testDetails
{
public string commonProperty { get; set; }
public string readOnlyProperty { get; set; }
public string writeOnlyProperty { get; set; }
}
[ProducesResponseType(StatusCodes.Status200OK)]
[HttpGet("Get")]
public IActionResult Get([FromQuery] testDetails details)
{
Debug.WriteLine($"commonProperty is {details.commonProperty}");
Debug.WriteLine($"readOnlyProperty is {details.readOnlyProperty}");
Debug.WriteLine($"writeOnlyProperty is {details.writeOnlyProperty}");
return Ok();
}
I'd like readOnlyProperty
to be tagged as readOnly
, and writeOnlyProperty
to be tagged as writeOnly
in the generated swagger.json
.
In effect, writeOnlyProperty
shouldn't appear as a property for any GET
(but would appear for a POST
/PUT
), and conversely readOnlyProperty
should be available for a GET
but not a POST
.
I've tried adding a System.ComponentModel
[ReadOnly
] attribute, but with no effect. I've also tried changing the accessors to
public class testDetails
{
public string commonProperty { get; set; }
public string readOnlyProperty { get; internal set; }
public string writeOnlyProperty { internal get; set; }
}
... but this just ends up hiding the properties completely. None of this affects the actual operation of the code, but I'd still like properties to only be writable where they need to be, and read-only otherwise - exactly as the OpenAPI spec describes. Is there a way to do this, without creating separate "read and write classes"?
You can annotate read-only and write-only properties with SwaggerSchemaAttribute from the package Swashbuckle.AspNetCore.Annotations
. This will allow you to generate OpenAPI spec with the readOnly
and writeOnly
keywords and also hide properties from Swagger UI.
Follow these steps:
Install-Package Swashbuckle.AspNetCore.Annotations
ConfigureServices
method of Startup.cs
, enable annotations within in the Swagger config block:services.AddSwaggerGen(c =>
{
...
c.EnableAnnotations();
});
public class TestDetails
{
public string CommonProperty { get; set; }
[SwaggerSchema(ReadOnly = true)]
public string ReadOnlyProperty { get; set; }
[SwaggerSchema(WriteOnly = true)]
public string WriteOnlyProperty { get; set; }
}
Your controller may look like:
[ApiController]
[Route("[controller]")]
public class DataController : ControllerBase
{
private TestDetails testDetails = new TestDetails()
{
CommonProperty = "Common prop value",
ReadOnlyProperty = "ReadOnly prop value",
WriteOnlyProperty = "WriteOnly prop value"
};
public DataController()
{
}
[HttpGet]
[ProducesResponseType(typeof(TestDetails), (int) HttpStatusCode.OK)]
public IActionResult Get()
{
return Ok(testDetails);
}
[HttpPost]
[ProducesResponseType((int)HttpStatusCode.OK)]
public IActionResult Post([FromBody] TestDetails details)
{
return Ok();
}
}