Skip to content

Property or indexer 'IOpenApiMediaType.Example' cannot be assigned to -- it is read only #2618

@AdaskoTheBeAsT

Description

@AdaskoTheBeAsT

Describe the bug
When I am using new Microsoft.OpenApi I receive

Property or indexer 'IOpenApiMediaType.Example' cannot be assigned to -- it is read only
obj\Debug\net10.0\Microsoft.AspNetCore.OpenApi.SourceGenerators\Microsoft.AspNetCore.OpenApi.SourceGenerators.XmlCommentGenerator\OpenApiXmlCommentSupport.generated.cs	503	

OpenApi File To Reproduce
Add the OpenApi file you're using or a link to it as well as the steps to reproduce the current behavior.

Expected behavior
It should work without problems

Screenshots/Code Snippets

Image

taken from autogenerated OpenApiXmlCommentSupport.generated.cs

[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=10.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "10.0.0.0")]
file class XmlCommentOperationTransformer : IOpenApiOperationTransformer
{
    public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransformerContext context, CancellationToken cancellationToken)
    {
        var methodInfo = context.Description.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor
            ? controllerActionDescriptor.MethodInfo
            : context.Description.ActionDescriptor.EndpointMetadata.OfType<MethodInfo>().SingleOrDefault();

        if (methodInfo is null)
        {
            return Task.CompletedTask;
        }
        if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(methodInfo.CreateDocumentationId()), out var methodComment))
        {
            if (methodComment.Summary is { } summary)
            {
                operation.Summary = summary;
            }
            if (methodComment.Description is { } description)
            {
                operation.Description = description;
            }
            if (methodComment.Remarks is { } remarks)
            {
                operation.Description = remarks;
            }
            if (methodComment.Parameters is { Count: > 0})
            {
                foreach (var parameterComment in methodComment.Parameters)
                {
                    var parameterInfo = methodInfo.GetParameters().SingleOrDefault(info => info.Name == parameterComment.Name);
                    var operationParameter = operation.Parameters?.SingleOrDefault(parameter => parameter.Name == parameterComment.Name);
                    if (operationParameter is not null)
                    {
                        var targetOperationParameter = UnwrapOpenApiParameter(operationParameter);
                        targetOperationParameter.Description = parameterComment.Description;
                        if (parameterComment.Example is { } jsonString)
                        {
                            targetOperationParameter.Example = jsonString.Parse();
                        }
                        targetOperationParameter.Deprecated = parameterComment.Deprecated;
                    }
                    else
                    {
                        var requestBody = operation.RequestBody;
                        if (requestBody is not null)
                        {
                            requestBody.Description = parameterComment.Description;
                            if (parameterComment.Example is { } jsonString)
                            {
                                var content = requestBody?.Content?.Values;
                                if (content is null)
                                {
                                    continue;
                                }
                                foreach (var mediaType in content)
                                {
                                    // here is error
                                    mediaType.Example = jsonString.Parse();
                                }
                            }
                        }
                    }
                }
            }
            // Applies `<returns>` on XML comments for operation with single response value.
            if (methodComment.Returns is { } returns && operation.Responses is { Count: 1 })
            {
                var response = operation.Responses.First();
                response.Value.Description = returns;
            }
            // Applies `<response>` on XML comments for operation with multiple response values.
            if (methodComment.Responses is { Count: > 0} && operation.Responses is { Count: > 0 })
            {
                foreach (var response in operation.Responses)
                {
                    var responseComment = methodComment.Responses.SingleOrDefault(xmlResponse => xmlResponse.Code == response.Key);
                    if (responseComment is not null)
                    {
                        response.Value.Description = responseComment.Description;
                    }
                }
            }
        }
        foreach (var parameterDescription in context.Description.ParameterDescriptions)
        {
            var metadata = parameterDescription.ModelMetadata;
            if (metadata.MetadataKind == ModelMetadataKind.Property
                && metadata.ContainerType is { } containerType
                && metadata.PropertyName is { } propertyName)
            {
                var propertyDocId = DocumentationCommentIdHelper.CreateDocumentationId(containerType, propertyName);
                if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyDocId), out var propertyComment))
                {
                    var parameter = operation.Parameters?.SingleOrDefault(p => p.Name == metadata.Name);
                    var description = propertyComment.Summary;
                    if (!string.IsNullOrEmpty(description) && !string.IsNullOrEmpty(propertyComment.Value))
                    {
                        description = $"{description}\n{propertyComment.Value}";
                    }
                    else if (string.IsNullOrEmpty(description))
                    {
                        description = propertyComment.Value;
                    }
                    if (parameter is null)
                    {
                        if (operation.RequestBody is not null)
                        {
                            operation.RequestBody.Description = description;
                            if (propertyComment.Examples?.FirstOrDefault() is { } jsonString)
                            {
                                var content = operation.RequestBody.Content?.Values;
                                if (content is null)
                                {
                                    continue;
                                }
                                var parsedExample = jsonString.Parse();
                                foreach (var mediaType in content)
                                {
                                    // here is error
                                    mediaType.Example = parsedExample;
                                }
                            }
                        }
                        continue;
                    }
                    var targetOperationParameter = UnwrapOpenApiParameter(parameter);
                    if (targetOperationParameter is not null)
                    {
                        targetOperationParameter.Description = description;
                        if (propertyComment.Examples?.FirstOrDefault() is { } jsonString)
                        {
                            targetOperationParameter.Example = jsonString.Parse();
                        }
                    }
                }
            }
        }

        return Task.CompletedTask;
    }

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions