OpenApi does not set readOnly: true for get-only properties
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
Get-only properties are not marked as "readOnly: true".
I assume set-only properties as well not marked as "writeOnly: true".
See "Steps to reproduce" for more information and examples.
### Expected Behavior
In object schema (for POST endpoints):
\- and -
In operation schema (for GET endpoints with FromQuery dto object):
Get-only properties should not be writable, set-only properties should not be readable.
Get-only property should not generate input fields in SwaggerUI for query params.
Get-only property should not be part of json in SwaggerUI for body params.
Set-only property should not be shown in responses.
### Steps To Reproduce
```csharp
public record PaginatedRequest(
string? Sorting = "Id",
int PageNumber = 1,
int PageSize = 50
)
{
public int Skip => (PageNumber - 1) * PageSize;
public int Take => PageSize;
}
```
For endpoint that accepts this record as body parameter:
```csharp
[HttpPost("search")]
public async Task GetAllPost(
[FromBody] GetAllBlogsPaginatedRequest request,
CancellationToken cancellationToken = default) { ... }
```
Result is:
```json
{
"components": {
"schemas": {
"GetAllBlogsPaginatedRequest": {
"type": "object",
"properties": {
// ...
"skip": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"type": [
"integer",
"string"
],
"format": "int32"
},
"take": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"type": [
"integer",
"string"
],
"format": "int32"
}
}
}
}
}
}
```
For endpoint that accepts this record as query parameter:
```csharp
[HttpGet]
public async Task GetAll(
[FromQuery] GetAllBlogsPaginatedRequest request,
CancellationToken cancellationToken = default) { ... }
```
```json
{
"paths": {
"/Blogs": {
"get": {
"tags": [
"Blogs"
],
"operationId": "GetAll",
"parameters": [
// ...
{
"name": "Skip",
"in": "query",
"schema": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"type": [
"integer",
"string"
],
"format": "int32"
}
},
{
"name": "Take",
"in": "query",
"schema": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"type": [
"integer",
"string"
],
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "OK"
}
},
"security": [
{
"Bearer": []
},
{
"Client Credentials Keycloak": []
}
]
}
}
}
}
```
### Exceptions (if any)
None
### .NET Version
10.0.102
### Anything else?
``````
```csharp
builder.Services.AddOpenApi("v1",
api =>
{
api.AddDocumentTransformer(); // to add bearer auth
api.AddOperationTransformer(); // to use controler action name as operation id
});
```
Contributor guide
Assessment
This issue has not been assessed yet.