Repository: dotnet/aspnetcore (language: python)

Issue:
`FromKeyedServices` Causes Generated Code to Fail to Compile
### Is there an existing issue for this?

- [x] I have searched the existing issues

### Describe the bug

With the request delegate generator enabled, injecting a keyed service which is defined in a namespace "Http" will cause the request delegate generator to generate code that doesn't compile.

The call to `GetRequiredKeyedService` doesn't `global`-root its type parameter, so it looks for the injected service in the "Microsoft.AspNetCore.Http" namespace:

```c#
var e_local = httpContext.RequestServices.GetRequiredKeyedService<Http.ExampleService>("example");
```

### Expected Behavior

The code compiles and retrieves the injected service by key.

### Steps To Reproduce

I've committed [a reproduction](https://github.com/chrisoverzero/keyed-service-http-repro). I've also committed the generated code, and the place where the error occurs is line 115 of "Generated/Microsoft.AspNetCore.Http.RequestDelegateGenerator/Microsoft.AspNetCore.Http.RequestDelegateGenerator.RequestDelegateGenerator/GeneratedRouteBuilderExtensions.g.cs"

### Exceptions (if any)

None.

### .NET Version

9.0.100-rc.2.24474.11

### Anything else?

<details>

<summary>

`dotnet --info` shows:

</summary>

```
.NET SDK:
 Version:           9.0.100-rc.2.24474.11
 Commit:            315e1305db
 Workload version:  9.0.100-manifests.82b7fac4
 MSBuild version:   17.12.0-preview-24473-03+fea15fbd1

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  14.5
 OS Platform: Darwin
 RID:         osx-arm64
 Base Path:   /usr/local/share/dotnet/sdk/9.0.100-rc.2.24474.11/

.NET workloads installed:
There are no installed workloads to display.
Configured to use loose manifests when installing new manifests.

Host:
  Version:      9.0.0-rc.2.24473.5
  Architecture: arm64
  Commit:       990ebf52fc

.NET SDKs installed:
  6.0.417 [/usr/local/share/dotnet/sdk]
  6.0.418 [/usr/local/share/dotnet/sdk]
  7.0.404 [/usr/local/share/dotnet/sdk]
  8.0.100 [/usr/local/share/dotnet/sdk]
  8.0.101 [/usr/local/share/dotnet/sdk]
  8.0.203 [/usr/local/share/dotnet/sdk]
  8.0.301 [/usr/local/share/dotnet/sdk]
  9.0.100-preview.3.24204.13 [/usr/local/share/dotnet/sdk]
  9.0.100-preview.6.24328.19 [/usr/local/share/dotnet/sdk]
  9.0.100-rc.1.24452.12 [/usr/local/share/dotnet/sdk]
  9.0.100-rc.2.24474.11 [/usr/local/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.25 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.26 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.14 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.1 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.6 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 9.0.0-preview.3.24172.13 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 9.0.0-preview.6.24328.4 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 9.0.0-rc.1.24452.1 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 9.0.0-rc.2.24474.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.25 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.26 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.14 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.1 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.6 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 9.0.0-preview.3.24172.9 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 9.0.0-preview.6.24327.7 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 9.0.0-rc.1.24431.7 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 9.0.0-rc.2.24473.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

Other architectures found:
  None

Environment variables:
  Not set

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

```

</details>


Discussion / hints:
I've discovered that adding `FromServices` explicitly behaves the same way, but leaving the parameter unattributed succeeds. In case that helps track it down.

Fix patch:
diff --git a/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/Emitters/EndpointParameterEmitter.cs b/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/Emitters/EndpointParameterEmitter.cs
index e68aeb559e94..0aafd008c5d1 100644
--- a/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/Emitters/EndpointParameterEmitter.cs
+++ b/src/Http/Http.Extensions/gen/StaticRouteHandlerModel/Emitters/EndpointParameterEmitter.cs
@@ -389,8 +389,8 @@ internal static void EmitServiceParameterPreparation(this EndpointParameter endp
         // Unlike other scenarios, this will result in an exception being thrown
         // at runtime.
         var assigningCode = endpointParameter.IsOptional ?
-            $"httpContext.RequestServices.GetService<{endpointParameter.Type}>();" :
-            $"httpContext.RequestServices.GetRequiredService<{endpointParameter.Type}>()";
+            $"httpContext.RequestServices.GetService<{endpointParameter.Type.ToDisplayString(EmitterConstants.DisplayFormat)}>();" :
+            $"httpContext.RequestServices.GetRequiredService<{endpointParameter.Type.ToDisplayString(EmitterConstants.DisplayFormat)}>()";
         codeWriter.WriteLine($"var {endpointParameter.EmitHandlerArgument()} = {assigningCode};");
     }
 
@@ -404,8 +404,8 @@ internal static void EmitKeyedServiceParameterPreparation(this EndpointParameter
         codeWriter.EndBlock();
 
         var assigningCode = endpointParameter.IsOptional ?
-            $"httpContext.RequestServices.GetKeyedService<{endpointParameter.Type}>({endpointParameter.KeyedServiceKey});" :
-            $"httpContext.RequestServices.GetRequiredKeyedService<{endpointParameter.Type}>({endpointParameter.KeyedServiceKey})";
+            $"httpContext.RequestServices.GetKeyedService<{endpointParameter.Type.ToDisplayString(EmitterConstants.DisplayFormat)}>({endpointParameter.KeyedServiceKey});" :
+            $"httpContext.RequestServices.GetRequiredKeyedService<{endpointParameter.Type.ToDisplayString(EmitterConstants.DisplayFormat)}>({endpointParameter.KeyedServiceKey})";
         codeWriter.WriteLine($"var {endpointParameter.EmitHandlerArgument()} = {assigningCode};");
     }
 


Test patch:
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitServiceParam_SimpleReturn_Snapshot.generated.txt b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitServiceParam_SimpleReturn_Snapshot.generated.txt
index 0a2c48bde9b4..a82fa6fb9baf 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitServiceParam_SimpleReturn_Snapshot.generated.txt
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/Baselines/MapAction_ExplicitServiceParam_SimpleReturn_Snapshot.generated.txt
@@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.Http.Generated
                 {
                     var wasParamCheckFailure = false;
                     // Endpoint Parameter: svc (Type = Microsoft.AspNetCore.Http.Generators.Tests.TestService, IsOptional = False, IsParsable = False, IsArray = False, Source = Service)
-                    var svc_local = httpContext.RequestServices.GetRequiredService<Microsoft.AspNetCore.Http.Generators.Tests.TestService>();
+                    var svc_local = httpContext.RequestServices.GetRequiredService<global::Microsoft.AspNetCore.Http.Generators.Tests.TestService>();
 
                     if (wasParamCheckFailure)
                     {
@@ -130,7 +130,7 @@ namespace Microsoft.AspNetCore.Http.Generated
                 {
                     var wasParamCheckFailure = false;
                     // Endpoint Parameter: svc (Type = Microsoft.AspNetCore.Http.Generators.Tests.TestService, IsOptional = False, IsParsable = False, IsArray = False, Source = Service)
-                    var svc_local = httpContext.RequestServices.GetRequiredService<Microsoft.AspNetCore.Http.Generators.Tests.TestService>();
+                    var svc_local = httpContext.RequestServices.GetRequiredService<global::Microsoft.AspNetCore.Http.Generators.Tests.TestService>();
 
                     if (wasParamCheckFailure)
                     {
@@ -207,7 +207,7 @@ namespace Microsoft.AspNetCore.Http.Generated
                 {
                     var wasParamCheckFailure = false;
                     // Endpoint Parameter: svc (Type = System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Http.Generators.Tests.TestService>, IsOptional = False, IsParsable = False, IsArray = False, Source = Service)
-                    var svc_local = httpContext.RequestServices.GetRequiredService<System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Http.Generators.Tests.TestService>>();
+                    var svc_local = httpContext.RequestServices.GetRequiredService<global::System.Collections.Generic.IEnumerable<global::Microsoft.AspNetCore.Http.Generators.Tests.TestService>>();
 
                     if (wasParamCheckFailure)
                     {
@@ -230,7 +230,7 @@ namespace Microsoft.AspNetCore.Http.Generated
                 {
                     var wasParamCheckFailure = false;
                     // Endpoint Parameter: svc (Type = System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Http.Generators.Tests.TestService>, IsOptional = False, IsParsable = False, IsArray = False, Source = Service)
-                    var svc_local = httpContext.RequestServices.GetRequiredService<System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Http.Generators.Tests.TestService>>();
+                    var svc_local = httpContext.RequestServices.GetRequiredService<global::System.Collections.Generic.IEnumerable<global::Microsoft.AspNetCore.Http.Generators.Tests.TestService>>();
 
                     if (wasParamCheckFailure)
                     {
@@ -308,9 +308,9 @@ namespace Microsoft.AspNetCore.Http.Generated
                 {
                     var wasParamCheckFailure = false;
                     // Endpoint Parameter: svc (Type = Microsoft.AspNetCore.Http.Generators.Tests.TestService?, IsOptional = True, IsParsable = False, IsArray = False, Source = Service)
-                    var svc_local = httpContext.RequestServices.GetService<Microsoft.AspNetCore.Http.Generators.Tests.TestService?>();;
+                    var svc_local = httpContext.RequestServices.GetService<global::Microsoft.AspNetCore.Http.Generators.Tests.TestService?>();;
                     // Endpoint Parameter: svcs (Type = System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Http.Generators.Tests.TestService>, IsOptional = False, IsParsable = False, IsArray = False, Source = Service)
-                    var svcs_local = httpContext.RequestServices.GetRequiredService<System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Http.Generators.Tests.TestService>>();
+                    var svcs_local = httpContext.RequestServices.GetRequiredService<global::System.Collections.Generic.IEnumerable<global::Microsoft.AspNetCore.Http.Generators.Tests.TestService>>();
 
                     if (wasParamCheckFailure)
                     {
@@ -333,9 +333,9 @@ namespace Microsoft.AspNetCore.Http.Generated
                 {
                     var wasParamCheckFailure = false;
                     // Endpoint Parameter: svc (Type = Microsoft.AspNetCore.Http.Generators.Tests.TestService?, IsOptional = True, IsParsable = False, IsArray = False, Source = Service)
-                    var svc_local = httpContext.RequestServices.GetService<Microsoft.AspNetCore.Http.Generators.Tests.TestService?>();;
+                    var svc_local = httpContext.RequestServices.GetService<global::Microsoft.AspNetCore.Http.Generators.Tests.TestService?>();;
                     // Endpoint Parameter: svcs (Type = System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Http.Generators.Tests.TestService>, IsOptional = False, IsParsable = False, IsArray = False, Source = Service)
-                    var svcs_local = httpContext.RequestServices.GetRequiredService<System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Http.Generators.Tests.TestService>>();
+                    var svcs_local = httpContext.RequestServices.GetRequiredService<global::System.Collections.Generic.IEnumerable<global::Microsoft.AspNetCore.Http.Generators.Tests.TestService>>();
 
                     if (wasParamCheckFailure)
                     {
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs
index aefa72875046..559e3b422524 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs
@@ -287,6 +287,7 @@ internal static string GetMapActionString(string sources, string className = "Te
 using Microsoft.AspNetCore.Http.Generators.Tests;
 using Microsoft.Extensions.Primitives;
 using Microsoft.Extensions.DependencyInjection;
+using Http;
 
 public static class {{className}}
 {
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.KeyServices.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.KeyServices.cs
index c7dcb131c2c3..08e3f22e9b83 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.KeyServices.cs
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.KeyServices.cs
@@ -3,6 +3,7 @@
 using System.Globalization;
 using Microsoft.AspNetCore.Http.Metadata;
 using Microsoft.AspNetCore.Http.RequestDelegateGenerator;
+using Microsoft.AspNetCore.Http.RequestDelegateGenerator.StaticRouteHandlerModel;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging.Abstractions;
 
@@ -225,6 +226,32 @@ public async Task ThrowsIfDiContainerDoesNotSupportKeyedServices()
         Assert.Equal("Unable to resolve service referenced by FromKeyedServicesAttribute. The service provider doesn't support keyed services.", exception.Message);
     }
 
+    // See: https://github.com/dotnet/aspnetcore/issues/58633
+    [Fact]
+    public async Task RequestDelegateGeneratesCompilableCodeForKeyedServiceInNamespaceHttp()
+    {
+        var source = """
+app.MapGet("/hello", ([FromKeyedServices("example")] global::Http.ExampleService e) => e.Act("To be or not to be…"));
+""";
+        var (results, compilation) = await RunGeneratorAsync(source);
+
+        // Ironically, the same error this is testing would bite us here, so we must globally qualify the type name.
+        var serviceProvider = CreateServiceProvider((serviceCollection) => serviceCollection.AddKeyedSingleton<global::Http.ExampleService>("example"));
+        var endpoint = GetEndpointFromCompilation(compilation, serviceProvider: serviceProvider);
+
+        VerifyStaticEndpointModel(results, endpointModel =>
+        {
+            Assert.Equal("MapGet", endpointModel.HttpMethod);
+            var p = Assert.Single(endpointModel.Parameters);
+            Assert.Equal(EndpointParameterSource.KeyedService, p.Source);
+            Assert.Equal("e", p.SymbolName);
+        });
+
+        var httpContext = CreateHttpContext(serviceProvider);
+        await endpoint.RequestDelegate(httpContext);
+        await VerifyResponseBodyAsync(httpContext, "To be or not to be…");
+    }
+
     private class MockServiceProvider : IServiceProvider, ISupportRequiredService
     {
         public object GetService(Type serviceType)
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.cs
index 8823f162b56b..9e4f803968e8 100644
--- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.cs
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.cs
@@ -599,4 +599,30 @@ public async Task RequestDelegateHandlesStringValuesFromExplicitQueryStringSourc
         Assert.Equal(new[] { 4, 5, 6 }, (int[])httpContext.Items["headers"]!);
         Assert.Equal(new[] { 7, 8, 9 }, (int[])httpContext.Items["form"]!);
     }
+
+    // See: https://github.com/dotnet/aspnetcore/issues/58633
+    [Fact]
+    public async Task RequestDelegateGeneratesCompilableCodeForServiceInNamespaceHttp()
+    {
+        var source = """
+app.MapGet("/hello", ([FromServices] ExampleService e) => e.Act("To be or not to be…"));
+""";
+        var (results, compilation) = await RunGeneratorAsync(source);
+
+        // Ironically, the same error this is testing would bite us here, so we must globally qualify the type name.
+        var serviceProvider = CreateServiceProvider((serviceCollection) => serviceCollection.AddSingleton<global::Http.ExampleService>());
+        var endpoint = GetEndpointFromCompilation(compilation, serviceProvider: serviceProvider);
+
+        VerifyStaticEndpointModel(results, endpointModel =>
+        {
+            Assert.Equal("MapGet", endpointModel.HttpMethod);
+            var p = Assert.Single(endpointModel.Parameters);
+            Assert.Equal(EndpointParameterSource.Service, p.Source);
+            Assert.Equal("e", p.SymbolName);
+        });
+
+        var httpContext = CreateHttpContext(serviceProvider);
+        await endpoint.RequestDelegate(httpContext);
+        await VerifyResponseBodyAsync(httpContext, "To be or not to be…");
+    }
 }
diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/SharedTypes.Http.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/SharedTypes.Http.cs
new file mode 100644
index 000000000000..419a5a8034b9
--- /dev/null
+++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/SharedTypes.Http.cs
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+using System;
+
+namespace Http;
+
+#nullable  enable
+
+public sealed class ExampleService
+{
+    public string Act(string line) => line;
+}