Skip to content

OpenApi DefaultValueAttribute on properties isn't considered on FromQuery model properties in controllers #61934

Open
@MoazAlkharfan

Description

@MoazAlkharfan

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

While having a default value on an object based model sent via query isn't being considered but on the method parameter directly is considered.

{
	"openapi": "3.0.1",
	"info": {
		"title": "DefaultValueAttributeReproduction | v1"
	},
	"paths": {
		"/test1": {
			"get": {
				"parameters": [
					{
						"name": "dto",
						"in": "query",
						"required": true,
						"schema": {
							"type": "object",
							"properties": {
								"testValue": {
									"type": "integer",
									"format": "int32",
									"default": 3
								}
							}
						}
					}
				]
			}
		},
		"/Test": {
			"get": {
				"parameters": [
					{
						"name": "TestValue1",
						"in": "query",
						"schema": {
							"type": "integer",
							"format": "int32"
						}
					},
					{
						"name": "TestValue2",
						"in": "query",
						"schema": {
							"type": "integer",
							"format": "int32"
						}
					},
					{
						"name": "TestValue3",
						"in": "query",
						"schema": {
							"type": "integer",
							"format": "int32",
							"default": -1
						}
					},
					{
						"name": "TestValue4",
						"in": "query",
						"schema": {
							"type": "integer",
							"format": "int32",
							"default": -1
						}
					}
				]
			}
		}
	}
}

Expected Behavior

Open Api doc should have the default value set

{
	"openapi": "3.0.1",
	"info": {
		"title": "DefaultValueAttributeReproduction | v1"
	},
	"paths": {
		"/test1": {
			"get": {
				"parameters": [
					{
						"name": "dto",
						"in": "query",
						"required": true,
						"schema": {
							"type": "object",
							"properties": {
								"testValue": {
									"type": "integer",
									"format": "int32",
									"default": 3
								}
							}
						}
					}
				]
			}
		},
		"/Test": {
			"get": {
				"parameters": [
					{
						"name": "TestValue1",
						"in": "query",
						"schema": {
							"type": "integer",
-							"format": "int32"
+							"format": "int32",
+							"default": 1
						}
					},
					{
						"name": "TestValue2",
						"in": "query",
						"schema": {
							"type": "integer",
-							"format": "int32"
+							"format": "int32",
+							"default": 2
						}
					},
					{
						"name": "TestValue3",
						"in": "query",
						"schema": {
							"type": "integer",
							"format": "int32",
-							"default": -1
+							"default": 3
						}
					},
					{
						"name": "TestValue4",
						"in": "query",
						"schema": {
							"type": "integer",
							"format": "int32",
-							"default": -1
+							"default": 4
						}
					}
				]
			}
		}
	}
}

Steps To Reproduce

Reporoduction code:

using Microsoft.AspNetCore.Mvc;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.MapControllers();

app.MapGet("test1", (
    [FromQuery] TestRequestFromMinimalDto dto) => "Hello World!");

app.Run();


public class TestRequestFromControllerDto
{
    [FromQuery]
    [DefaultValue(1)]
    public int TestValue1 { get; set; } = 1;

    [FromQuery]
    [DefaultValue(2)]
    public int TestValue2 { get; set; } = 2;
}

public class TestRequestFromControllerDto2
{
    [FromQuery]
    [DefaultValue(3)]
    public int TestValue3 { get; set; } = 3;

    [FromQuery]
    [DefaultValue(4)]
    public int TestValue4 { get; set; } = 4;
}

[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
    [HttpGet]
    public IActionResult Get([FromQuery] TestRequestFromControllerDto request, [FromQuery][DefaultValue(-1)] TestRequestFromControllerDto2 request2)
    {
        return Ok(new { request, request2 });
    }
}

public class TestRequestFromMinimalDto : IParsable<TestRequestFromMinimalDto>
{
    [DefaultValue(3)]
    public int TestValue { get; set; } = 3;

    public static TestRequestFromMinimalDto Parse(string s, IFormatProvider? provider)
    {
        return new TestRequestFromMinimalDto();
    }


    public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out TestRequestFromMinimalDto result)
    {
        result = new TestRequestFromMinimalDto();
        return true;
    }
}

Exceptions (if any)

No response

.NET Version

9.0.300

Anything else?

Framework: net9.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-openapi

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions