Skip to content
42 changes: 24 additions & 18 deletions src/Caching/StackExchangeRedis/src/RedisCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,29 +323,35 @@ private void TryRegisterProfiler()

// This also resets the LRU status as desired.
// TODO: Can this be done in one operation on the server side? Probably, the trick would just be the DateTimeOffset math.
RedisValue[] results;
if (getData)
{
results = _cache.HashMemberGet(_instance + key, AbsoluteExpirationKey, SlidingExpirationKey, DataKey);
}
else
try
{
results = _cache.HashMemberGet(_instance + key, AbsoluteExpirationKey, SlidingExpirationKey);
}
RedisValue[] results;
if (getData)
{
results = _cache.HashMemberGet(_instance + key, AbsoluteExpirationKey, SlidingExpirationKey, DataKey);
}
else
{
results = _cache.HashMemberGet(_instance + key, AbsoluteExpirationKey, SlidingExpirationKey);
}

// TODO: Error handling
if (results.Length >= 2)
{
MapMetadata(results, out DateTimeOffset? absExpr, out TimeSpan? sldExpr);
Refresh(_cache, key, absExpr, sldExpr);
}
if (results.Length >= 2)
{
MapMetadata(results, out DateTimeOffset? absExpr, out TimeSpan? sldExpr);
Refresh(_cache, key, absExpr, sldExpr);
}

if (results.Length >= 3 && results[2].HasValue)
if (results.Length >= 3 && results[2].HasValue)
{
return results[2];
}

return null;
}
catch (RedisConnectionException ex)
{
return results[2];
throw new InvalidOperationException("Redis cache connection failed. See inner exception for details.", ex);
}

return null;
}

private async Task<byte[]?> GetAndRefreshAsync(string key, bool getData, CancellationToken token = default(CancellationToken))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class RedisCacheSetAndRemoveTests
"These tests require Redis server to be started on the machine. Make sure to change the value of" +
"\"RedisTestConfig.RedisPort\" accordingly.";

[Fact(Skip = SkipReason)]
[Fact]
public void GetMissingKeyReturnsNull()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -23,7 +23,7 @@ public void GetMissingKeyReturnsNull()
Assert.Null(result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void SetAndGetReturnsObject()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -36,7 +36,7 @@ public void SetAndGetReturnsObject()
Assert.Equal(value, result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void SetAndGetWorksWithCaseSensitiveKeys()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -53,7 +53,7 @@ public void SetAndGetWorksWithCaseSensitiveKeys()
Assert.Null(result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void SetAlwaysOverwrites()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -70,7 +70,7 @@ public void SetAlwaysOverwrites()
Assert.Equal(value2, result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void RemoveRemoves()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -86,7 +86,7 @@ public void RemoveRemoves()
Assert.Null(result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void SetNullValueThrows()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand Down
26 changes: 13 additions & 13 deletions src/Caching/StackExchangeRedis/test/TimeExpirationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class TimeExpirationTests
"These tests require Redis server to be started on the machine. Make sure to change the value of" +
"\"RedisTestConfig.RedisPort\" accordingly.";

[Fact(Skip = SkipReason)]
[Fact]
public void AbsoluteExpirationInThePastThrows()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -34,7 +34,7 @@ public void AbsoluteExpirationInThePastThrows()
expected);
}

[Fact(Skip = SkipReason)]
[Fact]
public void AbsoluteExpirationExpires()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -55,7 +55,7 @@ public void AbsoluteExpirationExpires()
Assert.Null(result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void AbsoluteSubSecondExpirationExpiresImmidately()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -68,7 +68,7 @@ public void AbsoluteSubSecondExpirationExpiresImmidately()
Assert.Null(result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void NegativeRelativeExpirationThrows()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -84,7 +84,7 @@ public void NegativeRelativeExpirationThrows()
TimeSpan.FromMinutes(-1));
}

[Fact(Skip = SkipReason)]
[Fact]
public void ZeroRelativeExpirationThrows()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -101,7 +101,7 @@ public void ZeroRelativeExpirationThrows()
TimeSpan.Zero);
}

[Fact(Skip = SkipReason)]
[Fact]
public void RelativeExpirationExpires()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -121,7 +121,7 @@ public void RelativeExpirationExpires()
Assert.Null(result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void RelativeSubSecondExpirationExpiresImmediately()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -134,7 +134,7 @@ public void RelativeSubSecondExpirationExpiresImmediately()
Assert.Null(result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void NegativeSlidingExpirationThrows()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -147,7 +147,7 @@ public void NegativeSlidingExpirationThrows()
}, nameof(DistributedCacheEntryOptions.SlidingExpiration), "The sliding expiration value must be positive.", TimeSpan.FromMinutes(-1));
}

[Fact(Skip = SkipReason)]
[Fact]
public void ZeroSlidingExpirationThrows()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -164,7 +164,7 @@ public void ZeroSlidingExpirationThrows()
TimeSpan.Zero);
}

[Fact(Skip = SkipReason)]
[Fact]
public void SlidingExpirationExpiresIfNotAccessed()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -182,7 +182,7 @@ public void SlidingExpirationExpiresIfNotAccessed()
Assert.Null(result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void SlidingSubSecondExpirationExpiresImmediately()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -195,7 +195,7 @@ public void SlidingSubSecondExpirationExpiresImmediately()
Assert.Null(result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void SlidingExpirationRenewedByAccess()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand All @@ -220,7 +220,7 @@ public void SlidingExpirationRenewedByAccess()
Assert.Null(result);
}

[Fact(Skip = SkipReason)]
[Fact]
public void SlidingExpirationRenewedByAccessUntilAbsoluteExpiration()
{
var cache = RedisTestConfig.CreateCacheInstance(GetType().Name);
Expand Down
7 changes: 5 additions & 2 deletions src/Http/WebUtilities/src/FormReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Microsoft.AspNetCore.Internal;
using Microsoft.Extensions.Primitives;

namespace Microsoft.AspNetCore.WebUtilities;
Expand Down Expand Up @@ -264,10 +265,12 @@ private bool ReadChar(char separator, int limit, [NotNullWhen(true)] out string?
// '+' un-escapes to ' ', %HH un-escapes as ASCII (or utf-8?)
private string BuildWord()
{
_builder.Replace('+', ' ');
var result = _builder.ToString();
_builder.Clear();
return Uri.UnescapeDataString(result); // TODO: Replace this, it's not completely accurate.

var bytes = Encoding.UTF8.GetBytes(result);
var decodedLength = UrlDecoder.DecodeInPlace(bytes, isFormEncoding: true);
return Encoding.UTF8.GetString(bytes, 0, decodedLength);
}

private void Buffer()
Expand Down
2 changes: 1 addition & 1 deletion src/Middleware/RateLimiting/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.OnRejected.set -> void
Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.RateLimiterOptions() -> void
Microsoft.AspNetCore.RateLimiting.RateLimitingApplicationBuilderExtensions
static Microsoft.AspNetCore.RateLimiting.RateLimitingApplicationBuilderExtensions.UseRateLimiter(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app) -> Microsoft.AspNetCore.Builder.IApplicationBuilder!
static Microsoft.AspNetCore.RateLimiting.RateLimitingApplicationBuilderExtensions.UseRateLimiter(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, Microsoft.AspNetCore.RateLimiting.RateLimiterOptions! options) -> Microsoft.AspNetCore.Builder.IApplicationBuilder!
static Microsoft.AspNetCore.RateLimiting.RateLimitingApplicationBuilderExtensions.UseRateLimiter(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, System.Action<Microsoft.AspNetCore.RateLimiting.RateLimiterOptions!>! options) -> Microsoft.AspNetCore.Builder.IApplicationBuilder!
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ public static IApplicationBuilder UseRateLimiter(this IApplicationBuilder app)
/// <param name="app"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IApplicationBuilder UseRateLimiter(this IApplicationBuilder app, RateLimiterOptions options)
public static IApplicationBuilder UseRateLimiter(this IApplicationBuilder app, Action<RateLimiterOptions> options)
{
ArgumentNullException.ThrowIfNull(app, nameof(app));
ArgumentNullException.ThrowIfNull(options, nameof(options));

return app.UseMiddleware<RateLimitingMiddleware>(Options.Create(options));
var rateLimiterOptions = new RateLimiterOptions();
options.Invoke(rateLimiterOptions);

return app.UseMiddleware<RateLimitingMiddleware>(Options.Create(rateLimiterOptions));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ public void UseRateLimiter_ThrowsOnNullOptions()
public void UseRateLimiter_RespectsOptions()
{
// These are the options that should get used
var options = new RateLimiterOptions();
options.DefaultRejectionStatusCode = 429;
options.Limiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
var configureOptions = new Action<RateLimiterOptions>(opt =>
{
opt.DefaultRejectionStatusCode = 429;
opt.Limiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
});

// These should not get used
var services = new ServiceCollection();
Expand All @@ -44,7 +46,7 @@ public void UseRateLimiter_RespectsOptions()
var appBuilder = new ApplicationBuilder(serviceProvider);

// Act
appBuilder.UseRateLimiter(options);
appBuilder.UseRateLimiter(configureOptions);
var app = appBuilder.Build();
var context = new DefaultHttpContext();
app.Invoke(context);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#Sun Aug 02 04:22:06 BDT 2026
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=23e7d37e9bb4f8dabb8a3ea7fdee9dd0428b9b1a71d298aefd65b11dccea220f
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public AddCommand(Application parent, IHttpClientWrapper httpClient)
: base(parent, CommandName, httpClient)
{
Commands.Add(new AddFileCommand(this, httpClient));
//TODO: Add AddprojectComand here: https://github.com/dotnet/aspnetcore/issues/12738
Commands.Add(new AddProjectCommand(this, httpClient));
Commands.Add(new AddURLCommand(this, httpClient));
}

Expand Down
Loading