diff --git a/src/OpenApi/gen/XmlCommentGenerator.Emitter.cs b/src/OpenApi/gen/XmlCommentGenerator.Emitter.cs
index b7bff6ff1282..2dd60e993cc9 100644
--- a/src/OpenApi/gen/XmlCommentGenerator.Emitter.cs
+++ b/src/OpenApi/gen/XmlCommentGenerator.Emitter.cs
@@ -444,7 +444,8 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
             foreach (var parameterDescription in context.Description.ParameterDescriptions)
             {
                 var metadata = parameterDescription.ModelMetadata;
-                if (metadata.MetadataKind == ModelMetadataKind.Property
+                if (metadata is not null
+                    && metadata.MetadataKind == ModelMetadataKind.Property
                     && metadata.ContainerType is { } containerType
                     && metadata.PropertyName is { } propertyName)
                 {
diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/OperationTests.Controllers.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/OperationTests.Controllers.cs
index 5e13b2a06f6b..ef26c9590ec3 100644
--- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/OperationTests.Controllers.cs
+++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/OperationTests.Controllers.cs
@@ -96,4 +96,49 @@ await SnapshotTestHelper.VerifyOpenApi(compilation, document =>
             Assert.Equal("The todo to insert into the database.", path3.RequestBody.Description);
         });
     }
+
+    [Fact]
+    public async Task SupportsRouteParametersFromControllers()
+    {
+        var source = """
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
+
+var builder = WebApplication.CreateBuilder();
+
+builder.Services
+    .AddControllers()
+    .AddApplicationPart(typeof(TestController).Assembly);
+builder.Services.AddOpenApi();
+
+var app = builder.Build();
+
+app.MapControllers();
+
+app.Run();
+
+[ApiController]
+[Route("[controller]")]
+public class TestController : ControllerBase
+{
+    /// The id of the user.
+    [HttpGet("{userId}")]
+    public string Get()
+    {
+        return "Hello, World!";
+    }
+}
+
+public partial class Program {}
+
+""";
+        var generator = new XmlCommentGenerator();
+        await SnapshotTestHelper.Verify(source, generator, out var compilation);
+        await SnapshotTestHelper.VerifyOpenApi(compilation, document =>
+        {
+            var path = document.Paths["/Test/{userId}"].Operations[HttpMethod.Get];
+            Assert.Equal("The id of the user.", path.Parameters[0].Description);
+        });
+    }
 }
diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AddOpenApiTests.CanInterceptAddOpenApi#OpenApiXmlCommentSupport.generated.verified.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AddOpenApiTests.CanInterceptAddOpenApi#OpenApiXmlCommentSupport.generated.verified.cs
index ce2763fd112a..c235ae4c3688 100644
--- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AddOpenApiTests.CanInterceptAddOpenApi#OpenApiXmlCommentSupport.generated.verified.cs
+++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AddOpenApiTests.CanInterceptAddOpenApi#OpenApiXmlCommentSupport.generated.verified.cs
@@ -426,7 +426,8 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
             foreach (var parameterDescription in context.Description.ParameterDescriptions)
             {
                 var metadata = parameterDescription.ModelMetadata;
-                if (metadata.MetadataKind == ModelMetadataKind.Property
+                if (metadata is not null
+                    && metadata.MetadataKind == ModelMetadataKind.Property
                     && metadata.ContainerType is { } containerType
                     && metadata.PropertyName is { } propertyName)
                 {
diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AdditionalTextsTests.CanHandleXmlForSchemasInAdditionalTexts#OpenApiXmlCommentSupport.generated.verified.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AdditionalTextsTests.CanHandleXmlForSchemasInAdditionalTexts#OpenApiXmlCommentSupport.generated.verified.cs
index 42aff6ae7205..3affbf940068 100644
--- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AdditionalTextsTests.CanHandleXmlForSchemasInAdditionalTexts#OpenApiXmlCommentSupport.generated.verified.cs
+++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/AdditionalTextsTests.CanHandleXmlForSchemasInAdditionalTexts#OpenApiXmlCommentSupport.generated.verified.cs
@@ -455,7 +455,8 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
             foreach (var parameterDescription in context.Description.ParameterDescriptions)
             {
                 var metadata = parameterDescription.ModelMetadata;
-                if (metadata.MetadataKind == ModelMetadataKind.Property
+                if (metadata is not null
+                    && metadata.MetadataKind == ModelMetadataKind.Property
                     && metadata.ContainerType is { } containerType
                     && metadata.PropertyName is { } propertyName)
                 {
diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/CompletenessTests.SupportsAllXmlTagsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/CompletenessTests.SupportsAllXmlTagsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs
index 03379781d78f..7bb176e85405 100644
--- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/CompletenessTests.SupportsAllXmlTagsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs
+++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/CompletenessTests.SupportsAllXmlTagsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs
@@ -553,7 +553,8 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
             foreach (var parameterDescription in context.Description.ParameterDescriptions)
             {
                 var metadata = parameterDescription.ModelMetadata;
-                if (metadata.MetadataKind == ModelMetadataKind.Property
+                if (metadata is not null
+                    && metadata.MetadataKind == ModelMetadataKind.Property
                     && metadata.ContainerType is { } containerType
                     && metadata.PropertyName is { } propertyName)
                 {
diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsRouteParametersFromControllers#OpenApiXmlCommentSupport.generated.verified.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsRouteParametersFromControllers#OpenApiXmlCommentSupport.generated.verified.cs
new file mode 100644
index 000000000000..9f2b1de95ca8
--- /dev/null
+++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsRouteParametersFromControllers#OpenApiXmlCommentSupport.generated.verified.cs
@@ -0,0 +1,610 @@
+//HintName: OpenApiXmlCommentSupport.generated.cs
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+#nullable enable
+// Suppress warnings about obsolete types and members
+// in generated code
+#pragma warning disable CS0612, CS0618
+
+namespace System.Runtime.CompilerServices
+{
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
+    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+    file sealed class InterceptsLocationAttribute : System.Attribute
+    {
+        public InterceptsLocationAttribute(int version, string data)
+        {
+        }
+    }
+}
+
+namespace Microsoft.AspNetCore.OpenApi.Generated
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Globalization;
+    using System.Linq;
+    using System.Reflection;
+    using System.Text;
+    using System.Text.Json;
+    using System.Text.Json.Nodes;
+    using System.Threading;
+    using System.Threading.Tasks;
+    using Microsoft.AspNetCore.OpenApi;
+    using Microsoft.AspNetCore.Mvc.Controllers;
+    using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
+    using Microsoft.Extensions.DependencyInjection;
+    using Microsoft.OpenApi;
+
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
+    file record XmlComment(
+        string? Summary,
+        string? Description,
+        string? Remarks,
+        string? Returns,
+        string? Value,
+        bool Deprecated,
+        List? Examples,
+        List? Parameters,
+        List? Responses);
+
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
+    file record XmlParameterComment(string? Name, string? Description, string? Example, bool Deprecated);
+
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
+    file record XmlResponseComment(string Code, string? Description, string? Example);
+
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
+    file static class XmlCommentCache
+    {
+        private static Dictionary? _cache;
+        public static Dictionary Cache => _cache ??= GenerateCacheEntries();
+
+        private static Dictionary GenerateCacheEntries()
+        {
+            var cache = new Dictionary();
+
+            cache.Add(@"M:TestController.Get", new XmlComment(null, null, null, null, null, false, null, [new XmlParameterComment(@"userId", @"The id of the user.", null, false)], null));
+
+            return cache;
+        }
+    }
+
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
+    file static class DocumentationCommentIdHelper
+    {
+        /// 
+        /// Generates a documentation comment ID for a type.
+        /// Example: T:Namespace.Outer+Inner`1 becomes T:Namespace.Outer.Inner`1
+        /// 
+        public static string CreateDocumentationId(this Type type)
+        {
+            if (type == null)
+            {
+                throw new ArgumentNullException(nameof(type));
+            }
+
+            return "T:" + GetTypeDocId(type, includeGenericArguments: false, omitGenericArity: false);
+        }
+
+        /// 
+        /// Generates a documentation comment ID for a property.
+        /// Example: P:Namespace.ContainingType.PropertyName or for an indexer P:Namespace.ContainingType.Item(System.Int32)
+        /// 
+        public static string CreateDocumentationId(this PropertyInfo property)
+        {
+            if (property == null)
+            {
+                throw new ArgumentNullException(nameof(property));
+            }
+
+            var sb = new StringBuilder();
+            sb.Append("P:");
+
+            if (property.DeclaringType != null)
+            {
+                sb.Append(GetTypeDocId(property.DeclaringType, includeGenericArguments: false, omitGenericArity: false));
+            }
+
+            sb.Append('.');
+            sb.Append(property.Name);
+
+            // For indexers, include the parameter list.
+            var indexParams = property.GetIndexParameters();
+            if (indexParams.Length > 0)
+            {
+                sb.Append('(');
+                for (int i = 0; i < indexParams.Length; i++)
+                {
+                    if (i > 0)
+                    {
+                        sb.Append(',');
+                    }
+
+                    sb.Append(GetTypeDocId(indexParams[i].ParameterType, includeGenericArguments: true, omitGenericArity: false));
+                }
+                sb.Append(')');
+            }
+
+            return sb.ToString();
+        }
+
+        /// 
+        /// Generates a documentation comment ID for a property given its container type and property name.
+        /// Example: P:Namespace.ContainingType.PropertyName
+        /// 
+        public static string CreateDocumentationId(Type containerType, string propertyName)
+        {
+            if (containerType == null)
+            {
+                throw new ArgumentNullException(nameof(containerType));
+            }
+            if (string.IsNullOrEmpty(propertyName))
+            {
+                throw new ArgumentException("Property name cannot be null or empty.", nameof(propertyName));
+            }
+
+            var sb = new StringBuilder();
+            sb.Append("P:");
+            sb.Append(GetTypeDocId(containerType, includeGenericArguments: false, omitGenericArity: false));
+            sb.Append('.');
+            sb.Append(propertyName);
+
+            return sb.ToString();
+        }
+
+        /// 
+        /// Generates a documentation comment ID for a method (or constructor).
+        /// For example:
+        ///   M:Namespace.ContainingType.MethodName(ParamType1,ParamType2)~ReturnType
+        ///   M:Namespace.ContainingType.#ctor(ParamType)
+        /// 
+        public static string CreateDocumentationId(this MethodInfo method)
+        {
+            if (method == null)
+            {
+                throw new ArgumentNullException(nameof(method));
+            }
+
+            var sb = new StringBuilder();
+            sb.Append("M:");
+
+            // Append the fully qualified name of the declaring type.
+            if (method.DeclaringType != null)
+            {
+                sb.Append(GetTypeDocId(method.DeclaringType, includeGenericArguments: false, omitGenericArity: false));
+            }
+
+            sb.Append('.');
+
+            // Append the method name, handling constructors specially.
+            if (method.IsConstructor)
+            {
+                sb.Append(method.IsStatic ? "#cctor" : "#ctor");
+            }
+            else
+            {
+                sb.Append(method.Name);
+                if (method.IsGenericMethod)
+                {
+                    sb.Append("``");
+                    sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", method.GetGenericArguments().Length);
+                }
+            }
+
+            // Append the parameter list, if any.
+            var parameters = method.GetParameters();
+            if (parameters.Length > 0)
+            {
+                sb.Append('(');
+                for (int i = 0; i < parameters.Length; i++)
+                {
+                    if (i > 0)
+                    {
+                        sb.Append(',');
+                    }
+
+                    // Omit the generic arity for the parameter type.
+                    sb.Append(GetTypeDocId(parameters[i].ParameterType, includeGenericArguments: true, omitGenericArity: true));
+                }
+                sb.Append(')');
+            }
+
+            // Append the return type after a '~' (if the method returns a value).
+            if (method.ReturnType != typeof(void))
+            {
+                sb.Append('~');
+                // Omit the generic arity for the return type.
+                sb.Append(GetTypeDocId(method.ReturnType, includeGenericArguments: true, omitGenericArity: true));
+            }
+
+            return sb.ToString();
+        }
+
+        /// 
+        /// Generates a documentation ID string for a type.
+        /// This method handles nested types (replacing '+' with '.'),
+        /// generic types, arrays, pointers, by-ref types, and generic parameters.
+        /// The  flag controls whether
+        /// constructed generic type arguments are emitted, while 
+        /// controls whether the generic arity marker (e.g. "`1") is appended.
+        /// 
+        private static string GetTypeDocId(Type type, bool includeGenericArguments, bool omitGenericArity)
+        {
+            if (type.IsGenericParameter)
+            {
+                // Use `` for method-level generic parameters and ` for type-level.
+                if (type.DeclaringMethod != null)
+                {
+                    return "``" + type.GenericParameterPosition;
+                }
+                else if (type.DeclaringType != null)
+                {
+                    return "`" + type.GenericParameterPosition;
+                }
+                else
+                {
+                    return type.Name;
+                }
+            }
+
+            if (type.IsGenericType)
+            {
+                Type genericDef = type.GetGenericTypeDefinition();
+                string fullName = genericDef.FullName ?? genericDef.Name;
+
+                var sb = new StringBuilder(fullName.Length);
+
+                // Replace '+' with '.' for nested types
+                for (var i = 0; i < fullName.Length; i++)
+                {
+                    char c = fullName[i];
+                    if (c == '+')
+                    {
+                        sb.Append('.');
+                    }
+                    else if (c == '`')
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        sb.Append(c);
+                    }
+                }
+
+                if (!omitGenericArity)
+                {
+                    int arity = genericDef.GetGenericArguments().Length;
+                    sb.Append('`');
+                    sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", arity);
+                }
+
+                if (includeGenericArguments && !type.IsGenericTypeDefinition)
+                {
+                    var typeArgs = type.GetGenericArguments();
+                    sb.Append('{');
+
+                    for (int i = 0; i < typeArgs.Length; i++)
+                    {
+                        if (i > 0)
+                        {
+                            sb.Append(',');
+                        }
+
+                        sb.Append(GetTypeDocId(typeArgs[i], includeGenericArguments, omitGenericArity));
+                    }
+
+                    sb.Append('}');
+                }
+
+                return sb.ToString();
+            }
+
+            // For non-generic types, use FullName (if available) and replace nested type separators.
+            return (type.FullName ?? type.Name).Replace('+', '.');
+        }
+
+        /// 
+        /// Normalizes a documentation comment ID to match the compiler-style format.
+        /// Strips the return type suffix for ordinary methods but retains it for conversion operators.
+        /// 
+        /// The documentation comment ID to normalize.
+        /// The normalized documentation comment ID.
+        public static string NormalizeDocId(string docId)
+        {
+            // Find the tilde character that indicates the return type suffix
+            var tildeIndex = docId.IndexOf('~');
+            if (tildeIndex == -1)
+            {
+                // No return type suffix, return as-is
+                return docId;
+            }
+
+            // Check if this is a conversion operator (op_Implicit or op_Explicit)
+            // For these operators, we need to keep the return type suffix
+            if (docId.Contains("op_Implicit") || docId.Contains("op_Explicit"))
+            {
+                return docId;
+            }
+
+            // For ordinary methods, strip the return type suffix
+            return docId.Substring(0, tildeIndex);
+        }
+    }
+
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
+    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().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)
+                                    {
+                                        mediaType.Example = jsonString.Parse();
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                // Applies `` 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 `` 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 is not null
+                    && 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)
+                                    {
+                                        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;
+        }
+
+        private static OpenApiParameter UnwrapOpenApiParameter(IOpenApiParameter sourceParameter)
+        {
+            if (sourceParameter is OpenApiParameterReference parameterReference)
+            {
+                if (parameterReference.Target is OpenApiParameter target)
+                {
+                    return target;
+                }
+                else
+                {
+                    throw new InvalidOperationException($"The input schema must be an {nameof(OpenApiParameter)} or {nameof(OpenApiParameterReference)}.");
+                }
+            }
+            else if (sourceParameter is OpenApiParameter directParameter)
+            {
+                return directParameter;
+            }
+            else
+            {
+                throw new InvalidOperationException($"The input schema must be an {nameof(OpenApiParameter)} or {nameof(OpenApiParameterReference)}.");
+            }
+        }
+    }
+
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
+    file class XmlCommentSchemaTransformer : IOpenApiSchemaTransformer
+    {
+        public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext context, CancellationToken cancellationToken)
+        {
+            // Apply comments from the type
+            if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(context.JsonTypeInfo.Type.CreateDocumentationId()), out var typeComment))
+            {
+                schema.Description = typeComment.Summary;
+                if (typeComment.Examples?.FirstOrDefault() is { } jsonString)
+                {
+                    schema.Example = jsonString.Parse();
+                }
+            }
+
+            if (context.JsonPropertyInfo is { AttributeProvider: PropertyInfo propertyInfo })
+            {
+                // Apply comments from the property
+                if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment))
+                {
+                    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 (schema.Metadata is null
+                        || !schema.Metadata.TryGetValue("x-schema-id", out var schemaId)
+                        || string.IsNullOrEmpty(schemaId as string))
+                    {
+                        // Inlined schema
+                        schema.Description = description;
+                        if (propertyComment.Examples?.FirstOrDefault() is { } jsonString)
+                        {
+                            schema.Example = jsonString.Parse();
+                        }
+                    }
+                    else
+                    {
+                        // Schema Reference
+                        if (!string.IsNullOrEmpty(description))
+                        {
+                            schema.Metadata["x-ref-description"] = description;
+                        }
+                        if (propertyComment.Examples?.FirstOrDefault() is { } jsonString)
+                        {
+                            schema.Metadata["x-ref-example"] = jsonString.Parse()!;
+                        }
+                    }
+                }
+            }
+            return Task.CompletedTask;
+        }
+    }
+
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
+    file static class JsonNodeExtensions
+    {
+        public static JsonNode? Parse(this string? json)
+        {
+            if (json is null)
+            {
+                return null;
+            }
+
+            try
+            {
+                return JsonNode.Parse(json);
+            }
+            catch (JsonException)
+            {
+                try
+                {
+                    // If parsing fails, try wrapping in quotes to make it a valid JSON string
+                    return JsonNode.Parse($"\"{json.Replace("\"", "\\\"")}\"");
+                }
+                catch (JsonException)
+                {
+                    return null;
+                }
+            }
+        }
+    }
+
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.OpenApi.SourceGenerators, Version=42.42.42.42, Culture=neutral, PublicKeyToken=adb9793829ddae60", "42.42.42.42")]
+    file static class GeneratedServiceCollectionExtensions
+    {
+        [InterceptsLocation]
+        public static IServiceCollection AddOpenApi(this IServiceCollection services)
+        {
+            return services.AddOpenApi("v1", options =>
+            {
+                options.AddSchemaTransformer(new XmlCommentSchemaTransformer());
+                options.AddOperationTransformer(new XmlCommentOperationTransformer());
+            });
+        }
+
+    }
+}
diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromControllers#OpenApiXmlCommentSupport.generated.verified.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromControllers#OpenApiXmlCommentSupport.generated.verified.cs
index 0c2836cc9f2f..753c09661ae8 100644
--- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromControllers#OpenApiXmlCommentSupport.generated.verified.cs
+++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromControllers#OpenApiXmlCommentSupport.generated.verified.cs
@@ -430,7 +430,8 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
             foreach (var parameterDescription in context.Description.ParameterDescriptions)
             {
                 var metadata = parameterDescription.ModelMetadata;
-                if (metadata.MetadataKind == ModelMetadataKind.Property
+                if (metadata is not null
+                    && metadata.MetadataKind == ModelMetadataKind.Property
                     && metadata.ContainerType is { } containerType
                     && metadata.PropertyName is { } propertyName)
                 {
diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromMinimalApis#OpenApiXmlCommentSupport.generated.verified.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromMinimalApis#OpenApiXmlCommentSupport.generated.verified.cs
index c8da228d94d8..fe7be155d841 100644
--- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromMinimalApis#OpenApiXmlCommentSupport.generated.verified.cs
+++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/OperationTests.SupportsXmlCommentsOnOperationsFromMinimalApis#OpenApiXmlCommentSupport.generated.verified.cs
@@ -474,7 +474,8 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
             foreach (var parameterDescription in context.Description.ParameterDescriptions)
             {
                 var metadata = parameterDescription.ModelMetadata;
-                if (metadata.MetadataKind == ModelMetadataKind.Property
+                if (metadata is not null
+                    && metadata.MetadataKind == ModelMetadataKind.Property
                     && metadata.ContainerType is { } containerType
                     && metadata.PropertyName is { } propertyName)
                 {
diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.SupportsXmlCommentsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.SupportsXmlCommentsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs
index e192067879b7..9ae384e0e245 100644
--- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.SupportsXmlCommentsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs
+++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.SupportsXmlCommentsOnSchemas#OpenApiXmlCommentSupport.generated.verified.cs
@@ -456,7 +456,8 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
             foreach (var parameterDescription in context.Description.ParameterDescriptions)
             {
                 var metadata = parameterDescription.ModelMetadata;
-                if (metadata.MetadataKind == ModelMetadataKind.Property
+                if (metadata is not null
+                    && metadata.MetadataKind == ModelMetadataKind.Property
                     && metadata.ContainerType is { } containerType
                     && metadata.PropertyName is { } propertyName)
                 {
diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.XmlCommentsOnPropertiesShouldApplyToSchemaReferences#OpenApiXmlCommentSupport.generated.verified.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.XmlCommentsOnPropertiesShouldApplyToSchemaReferences#OpenApiXmlCommentSupport.generated.verified.cs
index 62eca1ce5fa6..86f754cd6cd6 100644
--- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.XmlCommentsOnPropertiesShouldApplyToSchemaReferences#OpenApiXmlCommentSupport.generated.verified.cs
+++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/SchemaTests.XmlCommentsOnPropertiesShouldApplyToSchemaReferences#OpenApiXmlCommentSupport.generated.verified.cs
@@ -435,7 +435,8 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
             foreach (var parameterDescription in context.Description.ParameterDescriptions)
             {
                 var metadata = parameterDescription.ModelMetadata;
-                if (metadata.MetadataKind == ModelMetadataKind.Property
+                if (metadata is not null
+                    && metadata.MetadataKind == ModelMetadataKind.Property
                     && metadata.ContainerType is { } containerType
                     && metadata.PropertyName is { } propertyName)
                 {
diff --git a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/XmlCommentDocumentationIdTests.CanMergeXmlCommentsWithDifferentDocumentationIdFormats#OpenApiXmlCommentSupport.generated.verified.cs b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/XmlCommentDocumentationIdTests.CanMergeXmlCommentsWithDifferentDocumentationIdFormats#OpenApiXmlCommentSupport.generated.verified.cs
index 2bea3547fc7b..44baeee7116b 100644
--- a/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/XmlCommentDocumentationIdTests.CanMergeXmlCommentsWithDifferentDocumentationIdFormats#OpenApiXmlCommentSupport.generated.verified.cs
+++ b/src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/snapshots/XmlCommentDocumentationIdTests.CanMergeXmlCommentsWithDifferentDocumentationIdFormats#OpenApiXmlCommentSupport.generated.verified.cs
@@ -427,7 +427,8 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
             foreach (var parameterDescription in context.Description.ParameterDescriptions)
             {
                 var metadata = parameterDescription.ModelMetadata;
-                if (metadata.MetadataKind == ModelMetadataKind.Property
+                if (metadata is not null
+                    && metadata.MetadataKind == ModelMetadataKind.Property
                     && metadata.ContainerType is { } containerType
                     && metadata.PropertyName is { } propertyName)
                 {