using Microsoft.AspNetCore.Http; using System.Text; using System.Web; using ZelWiki.Library.Interfaces; namespace ZelWiki.Library { public static class QueryStringConverter { /// /// Takes the current page query string and upserts the given order-by field, /// if the string already sorts on the given field then the order is inverted (asc/desc). /// /// public static string OrderHelper(ISessionState context, string value) { string orderByKey = "OrderBy"; string orderByDirectionKey = "OrderByDirection"; string? currentDirection = "asc"; var collection = ToDictionary(context.QueryString); //Check to see if we are sorting on the value that we are already sorted on, this would mean we need to invert the sort. if (collection.TryGetValue(orderByKey, out var currentValue)) { bool invertDirection = string.Equals(currentValue, value, StringComparison.InvariantCultureIgnoreCase); if (invertDirection) { if (collection.TryGetValue(orderByDirectionKey, out currentDirection)) { if (currentDirection == "asc") { currentDirection = "desc"; } else { currentDirection = "asc"; } } } else { currentDirection = "asc"; } } collection.Remove(orderByKey); collection.Add(orderByKey, value); collection.Remove(orderByDirectionKey); collection.Add(orderByDirectionKey, currentDirection ?? "asc"); return FromCollection(collection); } /// /// Takes the current page query string and upserts a query key/value, replacing any conflicting query string entry. /// /// /// /// /// public static string Upsert(IQueryCollection? queryString, string name, string value) { var collection = ToDictionary(queryString); collection.Remove(name); collection.Add(name, value); return FromCollection(collection); } public static Dictionary ToDictionary(IQueryCollection? queryString) { if (queryString == null) { return new Dictionary(); } var dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var item in queryString) { //Technically, keys can be duplicated in a IQueryCollection but we do not //support this. Use .Single() to throw exception if duplicates are found. dictionary.Add(item.Key, item.Value.Single() ?? string.Empty); } return dictionary; } public static Dictionary ToDictionary(QueryString? queryString) => ToDictionary(queryString?.ToString()); public static Dictionary ToDictionary(string? queryString) { var dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrEmpty(queryString)) { return dictionary; } // If the query string starts with '?', remove it if (queryString.StartsWith('?')) { queryString = queryString.Substring(1); } // Split the query string into key-value pairs var keyValuePairs = queryString.Split('&'); foreach (var kvp in keyValuePairs) { var keyValue = kvp.Split('='); if (keyValue.Length == 2) { var key = HttpUtility.UrlDecode(keyValue[0]); var value = HttpUtility.UrlDecode(keyValue[1]); dictionary[key] = value; } } return dictionary; } public static string FromCollection(IQueryCollection? collection) { if (collection == null || collection.Count == 0) { return string.Empty; } var queryString = new StringBuilder(); foreach (var kvp in collection) { if (queryString.Length > 0) { queryString.Append('&'); } queryString.Append($"{Uri.EscapeDataString(kvp.Key)}={Uri.EscapeDataString(kvp.Value.ToString())}"); } return queryString.ToString(); } public static string FromCollection(Dictionary? collection) { if (collection == null || collection.Count == 0) { return string.Empty; } var queryString = new StringBuilder(); foreach (var kvp in collection) { if (queryString.Length > 0) { queryString.Append('&'); } queryString.Append($"{Uri.EscapeDataString(kvp.Key)}={Uri.EscapeDataString(kvp.Value)}"); } return queryString.ToString(); } public static Dictionary Clone(Dictionary? original) { if (original == null) { return new Dictionary(); } var clone = new Dictionary(original.Count, original.Comparer); foreach (var kvp in original) { clone.Add(kvp.Key, kvp.Value); } return clone; } } }