TryCombineUrl
follows the .NET convention for “Try” methods by returning a bool
indicating success and providing the result via an out
parameter. This approach is ideal when logging failures explicitly or when avoiding exceptions is critical. It can be used in structured logging or conditional logging scenarios where fallback logic may be required.
public static class LoggingHelpers
{
public static bool TryCombineUrl(Uri? baseAddress, string path, out string? fullUrl)
{
try
{
if (string.IsNullOrWhiteSpace(path))
{
fullUrl = baseAddress?.ToString() ?? string.Empty;
}
else if (baseAddress == null)
{
fullUrl = path;
}
else
{
fullUrl = new Uri(baseAddress, path).ToString();
}
return true;
}
catch
{
fullUrl = null;
return false;
}
}
}
The CombineUrl
method offers a safe, reusable way to concatenate a base URI and path string for logging purposes. It is wrapped in a try-catch
block to avoid exceptions from malformed input, making it reliable for use in production logging. This method returns a string and can be placed inside a centralized LoggingHelpers
class for consistent use across the codebase.
public static class LoggingHelpers
{
public static string CombineUrl(Uri? baseAddress, string path)
{
try
{
if (string.IsNullOrWhiteSpace(path)) return baseAddress?.ToString() ?? string.Empty;
if (baseAddress == null) return path;
return new Uri(baseAddress, path).ToString();
}
catch (Exception ex)
{
return $"[InvalidUrl: {ex.Message}]";
}
}
}
In structured logging within C#, it's common to log endpoint URLs that consist of a base address and a path. To ensure safe and consistent logging, developers should use a centralized utility method to combine these values without risking exceptions or malformed URLs. This Snipp outlines two recommended approaches for implementing this functionality in a logging-safe way.
Logging in C# is a critical practice for monitoring application behavior, diagnosing issues, and gaining operational insights. Whether building desktop applications, APIs, or cloud-native services, effective logging allows developers and operators to understand how the system behaves in real time and after the fact.
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.
Problem Statement: Extracting extended file properties, such as the Media Created Date, is necessary for certain applications. Utilizing the Microsoft.WindowsAPICodePack.Shell namespace facilitates this task efficiently.
Approach: Utilize the ShellObject class from the WindowsAPICodePack.Shell namespace to access extended file properties. Specifically, retrieve the Media Created Date using the System.Media.DateEncoded property.
using Microsoft.WindowsAPICodePack.Shell;
ShellObject shell = ShellObject.FromParsingName(path);
var mediaCreatedDate = shell.Properties.System.Media.DateEncoded;
Explanation: This code utilizes the ShellObject class to access extended file properties. It fetches the Media Created Date of a file specified by its path using the System.Media.DateEncoded property, providing crucial metadata for various applications.
Further resources
C# is a strongly-typed language. It means we must declare the type of a variable that indicates the kind of values it is going to store, such as integer, float, decimal, text,
Additional reading at Data types in C# (tutorialsteacher.com)
C# includes specialized classes that store series of values or objects are called collections.
There are two types of collections available in C#: non-generic collections and generic collections.
The System.Collections
namespace contains the non-generic collection types and System.Collections.Generic
namespace includes generic collection types.
Additional reading at C# Generic & Non-generic Collections (tutorialsteacher.com)
In C#, a string is a series of characters that is used to represent text. It can be a character, a word or a long passage surrounded with the double quotes ". The following are string literals.
// String Literal Examples
"S"
"String"
"This is a string."
To filter out nullable strings and obtain only non-null strings, you can use LINQ Where
method along with a null check. Here's an example:
IEnumerable<string?> nullableStrings //
List<string> nonNullStringsList = nullableStrings
.Where(s => s != null) // Filter out null values
.Select(s => s!) // Convert nullable strings to non-nullable
.ToList(); // Convert IEnumerable to List
Where
to filter out null values and Select
to convert nullable strings to non-nullable strings (string!
indicates a non-nullable reference type in C# 8.0 and later).ToList()
to convert the filtered enumerable to a List<string>
.