/// Gets or sets the name for the handler. The name is used to match
diff --git a/src/Components/test/E2ETest/ServerRenderingTests/RenderingTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/RenderingTest.cs
index ce616f81d0ee..21c3e01d4712 100644
--- a/src/Components/test/E2ETest/ServerRenderingTests/RenderingTest.cs
+++ b/src/Components/test/E2ETest/ServerRenderingTests/RenderingTest.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Net;
+using System.Net.Http;
using Components.TestServer.RazorComponents;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
@@ -25,6 +27,7 @@ public RenderingTest(
public override Task InitializeAsync()
=> InitializeAsync(BrowserFixture.StreamingContext);
+ [Fact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/49975")]
public void CanRenderLargeComponentsWithServerRenderMode()
{
@@ -35,4 +38,16 @@ public void CanRenderLargeComponentsWithServerRenderMode()
Assert.Equal(result, Browser.FindElement(By.Id("server-prerender")).Text);
Assert.Equal(result, Browser.FindElement(By.Id("server-prerender")).Text);
}
+
+ [Fact]
+ public async Task CanUseHttpContextRequestAndResponse()
+ {
+ Navigate($"{ServerPathBase}/httpcontext");
+ Browser.Equal("GET", () => Browser.FindElement(By.Id("request-method")).Text);
+ Browser.Equal("/httpcontext", () => Browser.FindElement(By.Id("request-path")).Text);
+
+ // We can't see the response status code using Selenium, so make a direct request
+ var response = await new HttpClient().GetAsync(Browser.Url);
+ Assert.Equal(HttpStatusCode.Created, response.StatusCode);
+ }
}
diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/AccessHttpContext.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/AccessHttpContext.razor
new file mode 100644
index 000000000000..96c89cfd0da4
--- /dev/null
+++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/AccessHttpContext.razor
@@ -0,0 +1,20 @@
+@page "/httpcontext"
+
+HttpContext
+
+
+ Request method: @Ctx.Request.Method
+
+
+ Request path: @Ctx.Request.Path
+
+
+@code {
+ [CascadingParameter] public HttpContext Ctx { get; set; }
+
+ protected override void OnInitialized()
+ {
+ // Show we can change the response status code
+ Ctx.Response.StatusCode = 201;
+ }
+}
diff --git a/src/Mvc/Mvc/test/MvcServiceCollectionExtensionsTest.cs b/src/Mvc/Mvc/test/MvcServiceCollectionExtensionsTest.cs
index 78e32dbaebff..3520e30a01ee 100644
--- a/src/Mvc/Mvc/test/MvcServiceCollectionExtensionsTest.cs
+++ b/src/Mvc/Mvc/test/MvcServiceCollectionExtensionsTest.cs
@@ -162,6 +162,7 @@ public void AddMvc_Twice_DoesNotAddDuplicates()
{
// Arrange
var services = new ServiceCollection();
+ services.AddLogging();
services.AddSingleton(GetHostingEnvironment());
// Act
@@ -177,6 +178,7 @@ public void AddControllersAddRazorPages_Twice_DoesNotAddDuplicates()
{
// Arrange
var services = new ServiceCollection();
+ services.AddLogging();
services.AddSingleton(GetHostingEnvironment());
// Act
@@ -194,6 +196,7 @@ public void AddControllersWithViews_Twice_DoesNotAddDuplicates()
{
// Arrange
var services = new ServiceCollection();
+ services.AddLogging();
services.AddSingleton(GetHostingEnvironment());
// Act
@@ -209,6 +212,7 @@ public void AddRazorPages_Twice_DoesNotAddDuplicates()
{
// Arrange
var services = new ServiceCollection();
+ services.AddLogging();
services.AddSingleton(GetHostingEnvironment());
// Act
@@ -251,6 +255,7 @@ public void AddControllersWithViews_AddsDocumentedServices()
private void VerifyAllServices(IServiceCollection services)
{
var singleRegistrationServiceTypes = SingleRegistrationServiceTypes;
+ var serviceProvider = services.BuildServiceProvider();
foreach (var service in services)
{
if (singleRegistrationServiceTypes.Contains(service.ServiceType))
@@ -258,14 +263,24 @@ private void VerifyAllServices(IServiceCollection services)
// 'single-registration' services should only have one implementation registered.
AssertServiceCountEquals(services, service.ServiceType, 1);
}
- else if (service.ImplementationType != null && !service.ImplementationType.Assembly.FullName.Contains("Mvc"))
- {
- // Ignore types that don't come from MVC
- }
else
{
- // 'multi-registration' services should only have one *instance* of each implementation registered.
- AssertContainsSingle(services, service.ServiceType, service.ImplementationType);
+ var implementationType = service switch
+ {
+ { ImplementationType: { } type } => type,
+ { ImplementationInstance: { } instance } => instance.GetType(),
+ { ImplementationFactory: { } factory } => factory(serviceProvider).GetType(),
+ };
+
+ if (implementationType != null && !implementationType.Assembly.FullName.Contains("Mvc"))
+ {
+ // Ignore types that don't come from MVC
+ }
+ else
+ {
+ // 'multi-registration' services should only have one *instance* of each implementation registered.
+ AssertContainsSingle(services, service.ServiceType, service.ImplementationType);
+ }
}
}
}
@@ -625,6 +640,25 @@ private void AssertContainsSingle(
}
else if (matches.Length > 1)
{
+ var implementations = new List();
+ var sp = services.BuildServiceProvider();
+ foreach ( var service in matches )
+ {
+ if (service.ImplementationType is not null)
+ {
+ implementations.Add(service.ImplementationType);
+ }
+ else if (service.ImplementationInstance is not null)
+ {
+ implementations.Add(service.ImplementationInstance.GetType());
+ }
+ else if (service.ImplementationFactory is not null)
+ {
+ var instance = service.ImplementationFactory(sp);
+ implementations.Add(instance.GetType());
+ }
+ }
+
Assert.True(
false,
$"Found multiple instances of {implementationType} registered as {serviceType}");