diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationAuthHandler.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationAuthHandler.cs index a4f44f9ae0..4a970ec273 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationAuthHandler.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationAuthHandler.cs @@ -29,9 +29,13 @@ public RemoteAppAuthenticationAuthHandler(IRemoteAppAuthenticationService authSe IEnumerable resultProcessors, IOptionsMonitor options, ILoggerFactory loggerFactory, - UrlEncoder encoder, - ISystemClock clock) + UrlEncoder encoder +#if NET8_0_OR_GREATER + ) : base(options, loggerFactory, encoder) +#else + , ISystemClock clock) : base(options, loggerFactory, encoder, clock) +#endif { _logger = loggerFactory.CreateLogger(); _authService = authService; diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationResultFactory.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationResultFactory.cs index affa995948..cf3fe6e6c3 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationResultFactory.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationResultFactory.cs @@ -8,6 +8,7 @@ using System.Net.Http; using System.Security.Claims; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.SystemWebAdapters.Authentication; @@ -44,7 +45,7 @@ public async Task CreateRemoteAppAuthenticationRe { if (forwardAllResponseHeaders || options.ResponseHeadersToForward.Contains(responseHeader.Key)) { - ret.ResponseHeaders.Add(responseHeader.Key, responseHeader.Value.ToArray()); + ret.ResponseHeaders.AppendList(responseHeader.Key, responseHeader.Value.ToList()); } } diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/ResultProcessors/RedirectUrlProcessor.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/ResultProcessors/RedirectUrlProcessor.cs index 9104d743f4..c8be78d800 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/ResultProcessors/RedirectUrlProcessor.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/ResultProcessors/RedirectUrlProcessor.cs @@ -43,7 +43,7 @@ public Task ProcessAsync(RemoteAppAuthenticationResult result, HttpContext conte } } result.ResponseHeaders.Remove(LocationHeaderName); - result.ResponseHeaders.Add(LocationHeaderName, processedRedirectLocations.ToArray()); + result.ResponseHeaders.AppendList(LocationHeaderName, processedRedirectLocations); } return Task.CompletedTask; diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.csproj b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.csproj index b6f342e643..bad6fa9895 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.csproj +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.csproj @@ -1,6 +1,6 @@ - net6.0;net7.0 + net6.0;net7.0;net8.0 true true Microsoft.AspNetCore.SystemWebAdapters @@ -16,6 +16,9 @@ + + + diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SessionState/RemoteSession/RemoteAppSessionStateManager.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SessionState/RemoteSession/RemoteAppSessionStateManager.cs index b81f0ddd4c..ea95f19baa 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SessionState/RemoteSession/RemoteAppSessionStateManager.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SessionState/RemoteSession/RemoteAppSessionStateManager.cs @@ -8,6 +8,7 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.SystemWebAdapters.SessionState.Serialization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -130,7 +131,7 @@ private static void PropagateHeaders(HttpResponseMessage responseMessage, HttpCo { if (context?.Response is not null && responseMessage.Headers.TryGetValues(cookieName, out var cookieValues)) { - context.Response.Headers.Add(cookieName, cookieValues.ToArray()); + context.Response.Headers.AppendList(cookieName, cookieValues.ToArray()); } } diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SetHttpContextTimestampMiddleware.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SetHttpContextTimestampMiddleware.cs index e9025c9692..14907e0db6 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SetHttpContextTimestampMiddleware.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SetHttpContextTimestampMiddleware.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -9,14 +10,26 @@ namespace Microsoft.AspNetCore.SystemWebAdapters; internal class SetHttpContextTimestampMiddleware { private readonly RequestDelegate _next; + private readonly TimeProvider _timeProvider; - public SetHttpContextTimestampMiddleware(RequestDelegate next) => _next = next; + public SetHttpContextTimestampMiddleware(TimeProvider timeProvider, RequestDelegate next) + { + _timeProvider = timeProvider; + _next = next; + } public Task InvokeAsync(HttpContext context) { - // Ensure adapter is created to force timestamp to be set - _ = context.GetAdapter(); + context.Features.Set(new(_timeProvider)); return _next(context); } + + private sealed class TimestampFeature : ITimestampFeature + { + public TimestampFeature(TimeProvider timeProvider) + => Timestamp = timeProvider.GetLocalNow(); + + public DateTimeOffset Timestamp { get; } + } } diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SystemWebAdaptersExtensions.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SystemWebAdaptersExtensions.cs index a8a18e2ee9..94af3c5df8 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SystemWebAdaptersExtensions.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SystemWebAdaptersExtensions.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.SystemWebAdapters; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; namespace Microsoft.Extensions.DependencyInjection; @@ -17,6 +18,7 @@ public static class SystemWebAdaptersExtensions public static ISystemWebAdapterBuilder AddSystemWebAdapters(this IServiceCollection services) { services.AddHttpContextAccessor(); + services.TryAddSingleton(TimeProvider.System); services.AddSingleton(); services.AddSingleton(); services.AddTransient(); diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters/Adapters/ITimestampFeature.cs b/src/Microsoft.AspNetCore.SystemWebAdapters/Adapters/ITimestampFeature.cs new file mode 100644 index 0000000000..43717f7e29 --- /dev/null +++ b/src/Microsoft.AspNetCore.SystemWebAdapters/Adapters/ITimestampFeature.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NET6_0_OR_GREATER +using System; + +namespace Microsoft.AspNetCore.SystemWebAdapters; + +internal interface ITimestampFeature +{ + DateTimeOffset Timestamp { get; } +} +#endif diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters/Generated/Ref.Standard.cs b/src/Microsoft.AspNetCore.SystemWebAdapters/Generated/Ref.Standard.cs index eb6fb4ee79..03cff7487f 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters/Generated/Ref.Standard.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters/Generated/Ref.Standard.cs @@ -147,7 +147,7 @@ internal HttpContext() { } public System.Web.HttpResponse Response { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} } public System.Web.HttpServerUtility Server { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} } public System.Web.SessionState.HttpSessionState Session { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} } - public System.DateTime Timestamp { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} } + public System.DateTime Timestamp { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} } public System.Web.TraceContext Trace { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} } public System.Security.Principal.IPrincipal User { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} set { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} } public void AddError(System.Exception ex) { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters/HttpContext.cs b/src/Microsoft.AspNetCore.SystemWebAdapters/HttpContext.cs index 75f5f7365e..fd2f9e111d 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters/HttpContext.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters/HttpContext.cs @@ -90,7 +90,7 @@ public IPrincipal User public HttpSessionState? Session => _context.Features.Get(); - public DateTime Timestamp { get; } = DateTime.UtcNow.ToLocalTime(); + public DateTime Timestamp => _context.Features.GetRequired().Timestamp.DateTime; public void RewritePath(string path) => RewritePath(path, true); diff --git a/test/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.Tests/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.Tests.csproj b/test/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.Tests/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.Tests.csproj index 8186c472bc..c1ad19d9ac 100644 --- a/test/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.Tests/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.Tests.csproj +++ b/test/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.Tests/Microsoft.AspNetCore.SystemWebAdapters.CoreServices.Tests.csproj @@ -1,6 +1,6 @@ - net6.0 + net6.0;net8.0