Support optional properties with defaults in ATS input DTOs
- Dominant language
- C#
- Stars
- 6.3k
- Forks
- 991
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 196
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
ATS currently projects some semantically optional C# DTO properties as required generated-language properties.
The issue is visible in #19008's `AzureSandboxOptions`:
```csharp
[AspireDto]
public sealed class AzureSandboxOptions
{
public AzureSandboxTier Tier { get; set; } = AzureSandboxTier.Medium;
public AzureSandboxEndpointOptions[]? Endpoints { get; set; }
}
```
The generated ATS surface emits both without `?`:
```text
Endpoints: AzureSandboxEndpointOptions[]
Tier: AzureSandboxTier
```
As a result, a TypeScript caller that only wants lifecycle configuration cannot write:
```typescript
await api.publishAsAzureSandbox(group, {
autoSuspendEnabled: true,
autoSuspendInterval: 300_000
});
```
It must also supply unrelated dummy/default values such as `tier` and `endpoints`, even though the C# API defaults `Tier` and permits `Endpoints` to be null.
`AtsCapabilityScanner.IsOptionalDtoProperty` currently treats a writable property as required unless it is a nullable value type or cannot be written after initialization. Nullable reference-type metadata and property initializer defaults are not sufficient to mark it optional.
### Expected Behavior
Generated-language input DTOs should represent properties with meaningful C# defaults or nullable input semantics as optional without breaking mutable C# configuration overloads.
Design and implement an explicit, predictable mechanism. Possibilities include:
- an ATS-specific optional-property attribute/default metadata,
- an immutable ATS adapter DTO with `init` properties mapped into the mutable C# options type,
- or a carefully scoped scanner enhancement that respects nullable reference metadata/defaults.
Do not broadly mark every writable reference property optional without compatibility analysis. Add scanner/code-generator tests and a TypeScript runtime fixture that omits both `tier` and `endpoints` while configuring lifecycle fields.
### Steps To Reproduce
1. Generate the TypeScript SDK for `Aspire.Hosting.Azure.Sandboxes` from #19008.
2. Call `publishAsAzureSandbox` with only `autoSuspendEnabled` and `autoSuspendInterval`.
3. TypeScript reports that `tier` and `endpoints` are missing.
4. The equivalent C# options object compiles and uses its defaults.
### Exceptions (if any)
N/A
### Aspire doctor output
N/A
### Anything else?
Follow-up from #19008. The Sandbox APIs are experimental, so an adapter can still be introduced without stabilizing the current generated shape.
Contributor guide
Research direction
Start with AtsCapabilityScanner.IsOptionalDtoProperty and trace how nullable metadata and property defaults affect generated input DTOs. Review the scanner and code-generator tests, then add the TypeScript runtime fixture that omits tier and endpoints; done means the lifecycle-only call type-checks and runtime behavior preserves C# defaults and nullable semantics without broadly weakening required properties.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, typescript
- Domain
- api, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100