When handling tokens in .NET applications, it's essential to avoid logging them in full due to the potential exposure of sensitive information. A best practice is to redact tokens before logging by showing only a prefix and/or suffix.
Here’s a robust approach:
Redact tokens safely: Display only the first few and last few characters of the token, separated by ellipses (...
). If the token is too short to show both, consider showing only the prefix followed by ...
, or return a standardized warning.
Implement a helper method: Encapsulate redaction logic in a shared utility to ensure consistent and secure usage throughout the codebase.
public static string RedactToken(string token, int prefixLength = 6, int suffixLength = 4) { if (string.IsNullOrEmpty(token)) return "[null or empty token]"; int minLengthForFullRedaction = prefixLength + suffixLength; if (token.Length >= minLengthForFullRedaction) { var prefix = token.Substring(0, prefixLength); var suffix = token.Substring(token.Length - suffixLength); return $"{prefix}...{suffix}"; } int minLengthForPrefixOnly = prefixLength + 3; // For "..." if (token.Length >= minLengthForPrefixOnly) { var prefix = token.Substring(0, prefixLength); return $"{prefix}..."; } return "[token too short to redact securely]"; }
Optional hashing for debugging: If correlation is needed without revealing the token, hash it using a secure algorithm (e.g., SHA256) and log only the hash.
By centralizing redaction in a reusable helper and applying consistent rules, applications can balance debugging needs with security best practices.
If you encounter issues with dual audio output:
These steps can help resolve common issues related to multiple audio outputs.
The msDS-UserPasswordExpiryTimeComputed
attribute in Active Directory stores the user’s password expiration time as a large integer in Windows FileTime format. This format counts 100-nanosecond intervals from January 1, 1601 (UTC). To get a readable date and time, you must convert this number to a standard datetime format using the appropriate method for your platform.
How to Convert:
FromFileTimeUtc
in PowerShell or .NET.Example in PowerShell:
[DateTime]::FromFileTimeUtc($filetimeValue)
Handling the Special “Magic” Number:
If the value equals 9223372036854775807
(the maximum 64-bit integer), it is a special indicator that the password never expires. This number is not a real timestamp and should not be converted to a date. Instead, treat it as a flag meaning “no expiration.”
Summary:
9223372036854775807
as a sentinel meaning “password never expires.” Avoid converting this sentinel to a datetime.This solution demonstrates how to retrieve the password expiration date of a user account in Active Directory using PowerShell. It uses the Get-ADUser
cmdlet from the Active Directory module and queries the msDS-UserPasswordExpiryTimeComputed
property, which holds the computed expiration date in FILETIME format.
If querying by -Identity
returns an error such as "Cannot find an object with identity," switching to a -Filter
approach with the SamAccountName
is recommended. Also, ensure that the Active Directory module is imported, the domain context is correct, and the executing user has appropriate permissions.
# Import the Active Directory module if not already loaded
Import-Module ActiveDirectory
# Replace 'username' with the actual SamAccountName of the user
$user = Get-ADUser -Filter {SamAccountName -eq "username"} -Properties msDS-UserPasswordExpiryTimeComputed
# Convert the FILETIME to a readable DateTime object
$passwordExpiry = if ($user."msDS-UserPasswordExpiryTimeComputed") {
[datetime]::FromFileTime($user."msDS-UserPasswordExpiryTimeComputed")
} else {
"Password does not expire or no expiration set."
}
# Output the result
[PSCustomObject]@{
UserName = $user.SamAccountName
PasswordExpiry = $passwordExpiry
}
Key Points:
-Filter
with SamAccountName
to avoid identity resolution issues.msDS-UserPasswordExpiryTimeComputed
returns the expiration time as FILETIME.When working with collections in C#, it's common to extract and concatenate specific property values for display or logging purposes. For instance, if you have a list of objects and want to join the values of a particular string property, you can use LINQ in combination with string.Join
.
You have a list of objects, each with a Name
property, and you want to create a single comma-separated string of all names.
Use LINQ to project the property and string.Join
to concatenate the results.
var names = string.Join(", ", items.Select(i => i.Name));
items
is a List<T>
where T
has a Name
property.Select(i => i.Name)
projects the desired property Name
from each Item Item
.string.Join
concatenates the values with a defined separator (e.g., ", "
in this case)..Where(x => !string.IsNullOrEmpty(x.Name))
.This method is clean, efficient, and readable—ideal for transforming object data into user-friendly output or log formats.
DelegatingHandlers can be tested in isolation:
Mock the Inner Handler:
Inject into DelegatingHandler:
Create HttpClient:
This approach allows for unit testing the DelegatingHandler's logic without making actual HTTP calls.
This video tutorial provides a hands-on introduction to jsTree. The walkthrough covers the setup process, basic configuration, and demonstrates how to create a simple tree structure using the library. It’s aimed at developers looking for a quick start with jsTree and practical examples of how it integrates into HTML pages.
Highlights from the video:
checkbox
and search
While the video is specific to jsTree, the concepts are transferable to similar tree view libraries.
Multiple DelegatingHandlers can be chained to create a pipeline:
services.AddTransient<LoggingHandler>(); services.AddTransient<AuthenticationHandler>(); services.AddHttpClient("ChainedClient") .AddHttpMessageHandler<LoggingHandler>() .AddHttpMessageHandler<AuthenticationHandler>();
In this setup, LoggingHandler
processes the request first, followed by AuthenticationHandler
. The order of registration determines the sequence of execution.
After enabling Stereo Mix, configure your playback devices:
This configuration routes audio through both selected devices simultaneously.
C#'s async/await
pattern simplifies asynchronous programming, but integrating it into console applications poses a challenge. The traditional static void Main()
method can't be marked as async
, leading to compiler errors when attempting to use await
directly.
Workaround Strategies:
Separate Async Method: Encapsulate asynchronous operations within a separate method marked as async
. Then, invoke this method from Main()
using .GetAwaiter().GetResult()
to execute it synchronously. This approach ensures exceptions are unwrapped properly, avoiding the AggregateException
that occurs with .Result
or .Wait()
.
Async Main (C# 7.1 and Later): Starting with C# 7.1, you can define the entry point as static async Task Main()
, allowing the use of await
directly within Main()
. This modernizes the approach and simplifies asynchronous code execution in console applications.
For a detailed explanation and code examples see Async/await in a console application.