1
0

Updated to C# 12

This commit is contained in:
2024-01-14 13:10:33 +01:00
parent 9cd1344266
commit 27cd54fb30
51 changed files with 637 additions and 379 deletions

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<LangVersion>10.0</LangVersion>
<LangVersion>12.0</LangVersion>
<NrtTagMatch>asp/v[0-9]*</NrtTagMatch>
<AssemblyName>AMWD.Common.AspNetCore</AssemblyName>

View File

@@ -12,12 +12,12 @@ namespace Microsoft.AspNetCore.Http
public static class HttpContextExtensions
{
// Search these additional headers for a remote client ip address.
private static readonly string[] _defaultIpHeaderNames = new[]
{
private static readonly string[] _defaultIpHeaderNames =
[
"Cf-Connecting-Ip", // set by Cloudflare
"X-Real-IP", // wide-spread alternative to X-Forwarded-For
"X-Forwarded-For", // commonly used on all known proxies
};
];
/// <summary>
/// Retrieves the antiforgery token.

View File

@@ -9,26 +9,19 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
/// <summary>
/// Custom floating point ModelBinder as the team of Microsoft is not capable of fixing their <see href="https://github.com/dotnet/aspnetcore/issues/6566">issue</see> with other cultures than en-US.
/// </summary>
/// <remarks>
/// Initializes a new instance of <see cref="InvariantFloatingPointModelBinder"/>.
/// </remarks>
/// <param name="supportedStyles">The <see cref="NumberStyles"/>.</param>
/// <param name="cultureInfo">The <see cref="CultureInfo"/>.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public class InvariantFloatingPointModelBinder : IModelBinder
public class InvariantFloatingPointModelBinder(NumberStyles supportedStyles, CultureInfo cultureInfo, ILoggerFactory loggerFactory)
: IModelBinder
{
private readonly NumberStyles _supportedNumberStyles;
private readonly ILogger _logger;
private readonly CultureInfo _cultureInfo;
/// <summary>
/// Initializes a new instance of <see cref="InvariantFloatingPointModelBinder"/>.
/// </summary>
/// <param name="supportedStyles">The <see cref="NumberStyles"/>.</param>
/// <param name="cultureInfo">The <see cref="CultureInfo"/>.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
public InvariantFloatingPointModelBinder(NumberStyles supportedStyles, CultureInfo cultureInfo, ILoggerFactory loggerFactory)
{
_cultureInfo = cultureInfo ?? throw new ArgumentNullException(nameof(cultureInfo));
_supportedNumberStyles = supportedStyles;
_logger = loggerFactory?.CreateLogger<InvariantFloatingPointModelBinder>();
}
private readonly NumberStyles _supportedNumberStyles = supportedStyles;
private readonly ILogger _logger = loggerFactory?.CreateLogger<InvariantFloatingPointModelBinder>();
private readonly CultureInfo _cultureInfo = cultureInfo ?? throw new ArgumentNullException(nameof(cultureInfo));
/// <inheritdoc />
public Task BindModelAsync(ModelBindingContext bindingContext)

View File

@@ -13,49 +13,39 @@ using Microsoft.Extensions.Options;
namespace AMWD.Common.AspNetCore.Security.BasicAuthentication
{
#if NET8_0_OR_GREATER
/// <summary>
/// Implements the <see cref="AuthenticationHandler{TOptions}"/> for Basic Authentication.
/// </summary>
/// <remarks>
/// Initializes a new instance of the <see cref="BasicAuthenticationHandler"/> class.
/// </remarks>
/// <param name="options" > The monitor for the options instance.</param>
/// <param name="logger">The <see cref="ILoggerFactory"/>.</param>
/// <param name="encoder">The <see cref="UrlEncoder"/>.</param>
/// <param name="validator">An basic autentication validator implementation.</param>
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
public class BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, IBasicAuthenticationValidator validator)
: AuthenticationHandler<AuthenticationSchemeOptions>(options, logger, encoder)
#else
/// <summary>
/// Implements the <see cref="AuthenticationHandler{TOptions}"/> for Basic Authentication.
/// </summary>
/// <remarks>
/// Initializes a new instance of the <see cref="BasicAuthenticationHandler"/> class.
/// </remarks>
/// <param name="options" > The monitor for the options instance.</param>
/// <param name="logger">The <see cref="ILoggerFactory"/>.</param>
/// <param name="encoder">The <see cref="UrlEncoder"/>.</param>
/// <param name="clock">The <see cref="ISystemClock"/>.</param>
/// <param name="validator">An basic autentication validator implementation.</param>
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public class BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IBasicAuthenticationValidator validator)
: AuthenticationHandler<AuthenticationSchemeOptions>(options, logger, encoder, clock)
#endif
{
private readonly ILogger _logger;
private readonly IBasicAuthenticationValidator _validator;
#if NET8_0_OR_GREATER
/// <summary>
/// Initializes a new instance of the <see cref="BasicAuthenticationHandler"/> class.
/// </summary>
/// <param name="options">The monitor for the options instance.</param>
/// <param name="logger">The <see cref="ILoggerFactory"/>.</param>
/// <param name="encoder">The <see cref="UrlEncoder"/>.</param>
/// <param name="validator">An basic autentication validator implementation.</param>
public BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, IBasicAuthenticationValidator validator)
: base(options, logger, encoder)
{
_logger = logger.CreateLogger<BasicAuthenticationHandler>();
_validator = validator;
}
#endif
#if NET6_0
/// <summary>
/// Initializes a new instance of the <see cref="BasicAuthenticationHandler"/> class.
/// </summary>
/// <param name="options" > The monitor for the options instance.</param>
/// <param name="logger">The <see cref="ILoggerFactory"/>.</param>
/// <param name="encoder">The <see cref="UrlEncoder"/>.</param>
/// <param name="clock">The <see cref="ISystemClock"/>.</param>
/// <param name="validator">An basic autentication validator implementation.</param>
public BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IBasicAuthenticationValidator validator)
: base(options, logger, encoder, clock)
{
_logger = logger.CreateLogger<BasicAuthenticationHandler>();
_validator = validator;
}
#endif
private readonly ILogger _logger = logger.CreateLogger<BasicAuthenticationHandler>();
private readonly IBasicAuthenticationValidator _validator = validator;
/// <inheritdoc/>
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()

View File

@@ -11,21 +11,15 @@ namespace AMWD.Common.AspNetCore.Security.BasicAuthentication
/// <summary>
/// Implements a basic authentication.
/// </summary>
public class BasicAuthenticationMiddleware
/// <remarks>
/// Initializes a new instance of the <see cref="BasicAuthenticationMiddleware"/> class.
/// </remarks>
/// <param name="next">The following delegate in the process chain.</param>
/// <param name="validator">A basic authentication validator.</param>
public class BasicAuthenticationMiddleware(RequestDelegate next, IBasicAuthenticationValidator validator)
{
private readonly RequestDelegate _next;
private readonly IBasicAuthenticationValidator _validator;
/// <summary>
/// Initializes a new instance of the <see cref="BasicAuthenticationMiddleware"/> class.
/// </summary>
/// <param name="next">The following delegate in the process chain.</param>
/// <param name="validator">A basic authentication validator.</param>
public BasicAuthenticationMiddleware(RequestDelegate next, IBasicAuthenticationValidator validator)
{
_next = next;
_validator = validator;
}
private readonly RequestDelegate _next = next;
private readonly IBasicAuthenticationValidator _validator = validator;
/// <summary>
/// The delegate invokation.
@@ -35,15 +29,27 @@ namespace AMWD.Common.AspNetCore.Security.BasicAuthentication
/// <returns>An awaitable task.</returns>
public async Task InvokeAsync(HttpContext httpContext)
{
#if NET8_0_OR_GREATER
if (!httpContext.Request.Headers.TryGetValue("Authorization", out var authHeaderValue))
{
SetAuthenticateRequest(httpContext, _validator.Realm);
return;
}
#else
if (!httpContext.Request.Headers.ContainsKey("Authorization"))
{
SetAuthenticateRequest(httpContext, _validator.Realm);
return;
}
#endif
try
{
#if NET8_0_OR_GREATER
var authHeader = AuthenticationHeaderValue.Parse(authHeaderValue);
#else
var authHeader = AuthenticationHeaderValue.Parse(httpContext.Request.Headers["Authorization"]);
#endif
byte[] decoded = Convert.FromBase64String(authHeader.Parameter);
string plain = Encoding.UTF8.GetString(decoded);
@@ -70,9 +76,9 @@ namespace AMWD.Common.AspNetCore.Security.BasicAuthentication
private static void SetAuthenticateRequest(HttpContext httpContext, string realm)
{
httpContext.Response.Headers["WWW-Authenticate"] = "Basic";
httpContext.Response.Headers.WWWAuthenticate = "Basic";
if (!string.IsNullOrWhiteSpace(realm))
httpContext.Response.Headers["WWW-Authenticate"] = $"Basic realm=\"{realm.Replace("\"", "")}\"";
httpContext.Response.Headers.WWWAuthenticate = $"Basic realm=\"{realm.Replace("\"", "")}\"";
httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
}

View File

@@ -8,23 +8,16 @@ namespace AMWD.Common.AspNetCore.Security.PathProtection
/// <summary>
/// Implements a check to provide protected paths.
/// </summary>
public class ProtectedPathMiddleware
/// <remarks>
/// Initializes a new instance of the <see cref="ProtectedPathExtensions"/> class.
/// </remarks>
/// <param name="next">The following delegate in the process chain.</param>
/// <param name="options">The options to configure the middleware.</param>
public class ProtectedPathMiddleware(RequestDelegate next, ProtectedPathOptions options)
{
private readonly RequestDelegate _next;
private readonly PathString _path;
private readonly string _policyName;
/// <summary>
/// Initializes a new instance of the <see cref="ProtectedPathExtensions"/> class.
/// </summary>
/// <param name="next">The following delegate in the process chain.</param>
/// <param name="options">The options to configure the middleware.</param>
public ProtectedPathMiddleware(RequestDelegate next, ProtectedPathOptions options)
{
_next = next;
_path = options.Path;
_policyName = options.PolicyName;
}
private readonly RequestDelegate _next = next;
private readonly PathString _path = options.Path;
private readonly string _policyName = options.PolicyName;
/// <summary>
/// The delegate invokation.

View File

@@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
if (items.Any())
{
string classes = string.Join(" ", items.ToArray());
string classes = string.Join(" ", [.. items]);
output.Attributes.Add("class", classes);
}
}

View File

@@ -13,24 +13,19 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
/// <summary>
/// A tag helper to dynamically create integrity checks for linked sources.
/// </summary>
/// <remarks>
/// Initializes a new instance of the <see cref="IntegrityHashTagHelper"/> class.
/// </remarks>
/// <param name="env">The web host environment.</param>
/// <param name="configuration">The application configuration.</param>
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
[HtmlTargetElement("link")]
[HtmlTargetElement("script")]
public class IntegrityHashTagHelper : TagHelper
public class IntegrityHashTagHelper(IWebHostEnvironment env, IConfiguration configuration)
: TagHelper
{
private readonly IWebHostEnvironment _env;
private readonly string _hostUrl;
/// <summary>
/// Initializes a new instance of the <see cref="IntegrityHashTagHelper"/> class.
/// </summary>
/// <param name="env">The web host environment.</param>
/// <param name="configuration">The application configuration.</param>
public IntegrityHashTagHelper(IWebHostEnvironment env, IConfiguration configuration)
{
_env = env;
_hostUrl = configuration.GetValue("ASPNETCORE_APPL_URL", "http://localhost/");
}
private readonly IWebHostEnvironment _env = env;
private readonly string _hostUrl = configuration.GetValue("ASPNETCORE_APPL_URL", "http://localhost/");
/// <summary>
/// Gets or sets a value indicating whether the integrity should be calculated.
@@ -118,7 +113,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
}
string type;
byte[] hashBytes = Array.Empty<byte>();
byte[] hashBytes = [];
switch (IntegrityStrength)
{
case 512:

View File

@@ -9,17 +9,15 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
/// <summary>
/// Adds additional behavior to the modelbinding for numeric properties.
/// </summary>
/// <remarks>
/// Initializes a new instance of the <see cref="NumberInputTagHelper"/> class.
/// </remarks>
/// <param name="generator">The HTML generator.</param>
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
[HtmlTargetElement("input", Attributes = "asp-for")]
public class NumberInputTagHelper : InputTagHelper
public class NumberInputTagHelper(IHtmlGenerator generator)
: InputTagHelper(generator)
{
/// <summary>
/// Initializes a new instance of the <see cref="NumberInputTagHelper"/> class.
/// </summary>
/// <param name="generator">The HTML generator.</param>
public NumberInputTagHelper(IHtmlGenerator generator)
: base(generator)
{ }
/// <inheritdoc />
public override void Process(TagHelperContext context, TagHelperOutput output)