In the realm of C# and ASP.NET development, extension methods serve as invaluable tools, empowering developers to enhance the expressiveness and efficiency of their code. In this blog post, we will delve into some of the basic extension methods that any ASP.Net Core project needs and can elevate your web development projects.
HTTPContext Extensions
Get Base Path
public static string GetBasePath(this HttpContext httpContext)
{
return $"{httpContext.Request.Scheme}://{httpContext.Request.Host}";
}
Check if the Request Header has a particular key
public static bool HasRequestHeader(this HttpContext httpContext, string headerName)
{
return httpContext.Request.Headers.ContainsKey(headerName);
}
Check if the Response Header has a particular key
public static bool HasResponseHeader(this HttpContext httpContext, string headerName)
{
return httpContext.Response.Headers.ContainsKey(headerName);
}
Check if the Request Header key has the required value
public static bool HasRequestHeaderValue(this HttpContext httpContext, string headerName, string headerValue)
{
return httpContext.Request.Headers.TryGetValue(headerName, out var header)
&& header.Any(a => a.Equals(headerValue, StringComparison.OrdinalIgnoreCase));
}
Check if the Response Header key has the required value
public static bool HasResponseHeaderValue(this HttpContext httpContext, string headerName, string headerValue)
{
return httpContext.Response.Headers.TryGetValue(headerName, out var header)
&& header.Any(a => a.Equals(headerValue, StringComparison.OrdinalIgnoreCase));
}
IEnumerable Extensions
Convert any IEnumerable to CSV String
public static string ConvertToCSVString<T>(this IEnumerable<T> items)
{
if (items.Any())
{
var lines = new List<string>();
var header = string.Empty;
if (items.FirstOrDefault().GetType() == typeof(JObject))
{
var jObject = (JObject)Convert.ChangeType(items.FirstOrDefault(), typeof(JObject));
header = string.Join(",", jObject.Properties().Select(x => x.Name));
lines.Add(header);
////DO NOT include the starting and ending quotes inside the $ string interpolation.
var valueLines = items.Select(row =>
string.Join(",", header.Split(',')
.Select(a => "\"" + $"{((JObject)Convert.ChangeType(row, typeof(JObject))).GetValue(a)}"?
.Replace(Environment.NewLine, string.Empty, StringComparison.OrdinalIgnoreCase)
.Replace("\"", "\"\"", StringComparison.OrdinalIgnoreCase)
+ "\""
)));
lines.AddRange(valueLines);
}
else
{
var props = items.FirstOrDefault().GetType().GetProperties();
header = string.Join(",", props.Select(x => x.Name));
lines.Add(header);
//DO NOT include the starting and ending quotes inside the $ string interpolation.
var valueLines = items.Select(row =>
string.Join(",", header.Split(',')
.Select(a => "\"" + $"{row.GetType().GetProperty(a).GetValue(row, null)}"?
.Replace(Environment.NewLine, string.Empty, StringComparison.OrdinalIgnoreCase)
.Replace("\"", "\"\"", StringComparison.OrdinalIgnoreCase)
+ "\""
)));
lines.AddRange(valueLines);
}
var csvString = string.Join("\r\n", lines.ToArray());
return csvString;
}
else
{
return string.Empty;
}
}
Convert any IEnumerable to DataTable
public static DataTable ToDataTable<T>(this IEnumerable<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name);
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in Props)
{
dataTable.Columns.Add(prop.Name);
}
foreach (T item in items)
{
var values = new object[Props.Length];
for (int i = 0; i < Props.Length; i++)
{
values[i] = Props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
Session Extensions
Replace a value in a Session key
public static void Replace(this ISession session, string key, object data)
{
if (session.Keys.Any(x => x.Equals(key, StringComparison.OrdinalIgnoreCase)))
{
session.Remove(key);
}
session.SetString(key, JsonConvert.SerializeObject(data));
}
Get value from a Session key
public static bool TryGet<T>(this ISession session, string key, out T data, bool removeKey = false)
{
if (session.Keys.Any(x => x.Equals(key, StringComparison.OrdinalIgnoreCase)))
{
var objString = session.GetString(key);
data = JsonConvert.DeserializeObject<T>(objString);
if (removeKey)
{
session.Remove(key);
}
return true;
}
data = default;
return false;
}
ClaimsPrincipal Extensions
Check if the claims has a particular Role
public static bool HasRole(this ClaimsPrincipal principal, string role)
{
return principal.HasClaim(c =>
c.Type == ClaimTypes.Role &&
c.Value.Equals(role, StringComparison.OrdinalIgnoreCase));
}
Get Roles from the claims
public static IEnumerable<string> GetRoles(this ClaimsPrincipal principal)
{
return principal.Claims.Where(c => c.Type == ClaimTypes.Role).Select(s => s.Value);
}
Get a particular claim from the claims
public static T GetClaim<T>(this ClaimsPrincipal principal, string claim)
{
var result = principal?.Claims?.FirstOrDefault(f => f.Type.Equals(claim, StringComparison.OrdinalIgnoreCase))?.Value;
return (T)Convert.ChangeType(result, typeof(T));
}
DateTime Extensions
Convert to a different TimeZone
public static DateTime ConvertToTimeZone(this DateTime dateTime, string timeZoneId)
{
return TimeZoneInfo.ConvertTimeFromUtc(dateTime, TimeZoneInfo.FindSystemTimeZoneById(timeZoneId));
}
Check if a given DateTime is between a time range
public static bool IsBetweenTimeRange(this DateTime comparisonTime, DateTime? startDate, DateTime? endDate)
{
return (startDate.HasValue ? comparisonTime >= startDate.Value : true) && (endDate.HasValue ? comparisonTime <= endDate.Value : true);
}
Check if a give DateTimeOffset is between a time range
public static bool IsBetweenTimeRange(this DateTime comparisonTime, DateTimeOffset? startDate, DateTimeOffset? endDate)
{
return comparisonTime.IsBetweenTimeRange(startDate.HasValue ? startDate.Value.DateTime : null, endDate.HasValue ? endDate.Value.DateTime : null);
}
Convert to a DateTimeOffset based on a TimeZone
public static DateTimeOffset? ToDateTimeOffset(this DateTime? dateTime, string timeZoneId)
{
return dateTime.HasValue ? new DateTimeOffset(dateTime.Value, TimeZoneInfo.FindSystemTimeZoneById(timeZoneId).BaseUtcOffset) : null;
}
Enum Extensions
Get display name of an Enum
public static string GetDisplayName(this Enum enumValue)
{
var displayName = enumValue.GetType().GetMember(enumValue.ToString()).FirstOrDefault().GetCustomAttribute<DisplayAttribute>()?.GetName();
return string.IsNullOrWhiteSpace(displayName) ? enumValue.ToString() : displayName;
}
HTTPResponseMessage Extensions
Ensure the HTTPResponseMessage has a Success Status code and log failures
public static async Task EnsureSuccessStatusCodeAndLogFailures(this HttpResponseMessage httpResponseMessage, ILogger logger)
{
if (httpResponseMessage == null)
{
throw new ArgumentNullException(nameof(httpResponseMessage));
}
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
if (!httpResponseMessage.IsSuccessStatusCode)
{
var response = await httpResponseMessage.Content?.ReadAsStringAsync();
var requestUri = httpResponseMessage.RequestMessage?.RequestUri;
logger.LogError($"HTTP call to {requestUri} returned status code {httpResponseMessage.StatusCode} with response {response}");
}
httpResponseMessage.EnsureSuccessStatusCode();
}
TokenResponse Extensions
Ensure the TokenResponse has a Success Status and log failures
public static void CheckResponseAndLogFailures(this TokenResponse tokenResponse, ILogger logger)
{
if (tokenResponse == null)
{
throw new ArgumentNullException(nameof(tokenResponse));
}
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
if (tokenResponse.IsError)
{
var response = JsonConvert.SerializeObject(tokenResponse);
logger.LogError("Access Token call to returned with error and data: {data}", response);
}
}
String Extensions
Slugify
public static string Slugify(this string phrase)
{
if (string.IsNullOrWhiteSpace(phrase))
{
return string.Empty;
}
var output = phrase.RemoveAccents().ToLower();
output = Regex.Replace(output, @"[^A-Za-z0-9\s-]", "");
output = Regex.Replace(output, @"\s+", " ").Trim();
output = Regex.Replace(output, @"\s", "-");
return output;
}
public static string RemoveAccents(this string text)
{
if (string.IsNullOrWhiteSpace(text))
return text;
text = text.Normalize(NormalizationForm.FormD);
char[] chars = text
.Where(c => CharUnicodeInfo.GetUnicodeCategory(c)
!= UnicodeCategory.NonSpacingMark).ToArray();
return new string(chars).Normalize(NormalizationForm.FormC);
}
Check if a email is valid
public static bool IsValidEmail(this string email)
{
var isValid = true;
try
{
var emailAddress = new MailAddress(email.Trim());
}
catch
{
isValid = false;
}
return isValid;
}