Skip to content

Instantly share code, notes, and snippets.

@vSzemkel
Last active July 19, 2017 09:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vSzemkel/7f74819f02fede9851dab53262d316fc to your computer and use it in GitHub Desktop.
Save vSzemkel/7f74819f02fede9851dab53262d316fc to your computer and use it in GitHub Desktop.
QueryStringObjectSerializer enables caching sophisticated results of GET search requests in favor of POST noncachable ones
// -----------------------------------------------------------------------
// <copyright file="QueryStringObjectSerializer.cs" company="Agora SA">
// Copyright (c) TDE - Development IT , lipiec 2017
// <author>Marcin Buchwald</author>
// </copyright>
// -----------------------------------------------------------------------
namespace NewsMavens.Models.Helpers
{
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
public static class QueryStringObjectSerializer
{
/// <summary>
/// Serializer
/// </summary>
/// <typeparam name="T">Flat structure of primitive types or List of bytes</typeparam>
/// <param name="nameValueCollection">output </param>
/// <param name="parm">Search structure</param>
public static void Serialize<T>(Dictionary<string,string> nameValueCollection, T parm) where T : class
{
var type = typeof(T);
var fields = type.GetRuntimeFields();
var patern = Activator.CreateInstance(type);
foreach (var field in fields) {
var value = field.GetValue(parm);
if (value == null || value.ToString() == field.GetValue(patern)?.ToString())
continue;
var key = field.Name;
var valType = value.GetType();
if (valType.GetTypeInfo().IsEnum)
nameValueCollection.Add(key, ((byte) value).ToString());
else if (valType == typeof(List<byte>))
nameValueCollection.Add(key, JsonConvert.SerializeObject(value));
else
nameValueCollection.Add(key, value.ToString());
}
}
/// <summary>
/// Deserialize query string to an instance of T
/// </summary>
/// <typeparam name="T">Flat structure of primitive types or List of bytes</typeparam>
/// <param name="queryString">query string</param>
/// <returns>an instance of T</returns>
public static T Deserialize<T>(string queryString) where T : class, new()
{
var result = new T();
var parms = queryString.Split('&');
var fields = typeof(T).GetRuntimeFields();
foreach (var query in parms)
foreach (var field in fields)
if (query.StartsWith(field.Name)) {
var valueType = field.FieldType;
var stringValue = GetQueryValue(query);
if (valueType == typeof(List<byte>))
field.SetValue(result, JsonConvert.DeserializeObject<List<byte>>(stringValue));
else if (valueType.GetTypeInfo().IsEnum)
field.SetValue(result, byte.Parse(stringValue));
else {
var baseType = Nullable.GetUnderlyingType(valueType);
var value = Convert.ChangeType(stringValue, baseType ?? valueType);
field.SetValue(result, value);
}
}
return result;
}
/// <summary>
/// Appends query string to base url
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="url">Valid URL prefix ending with '?' or '&'</param>
/// <param name="queryStringParams">Structure to serialize in query string</param>
/// <returns></returns>
public static string BuildCall<T>(string url, T queryStringParams) where T : class
{
var queryStringBuilder = new Dictionary<string, string>();
QueryStringObjectSerializer.Serialize(queryStringBuilder, queryStringParams);
var qs = new StringBuilder(url);
if (url.Contains('?')) {
if (!url.EndsWith("&"))
qs.Append('&');
} else
qs.Append('?');
foreach (var keyVal in queryStringBuilder)
qs.Append($"{keyVal.Key}={keyVal.Value}&");
qs.Length--;
return qs.ToString();
}
/// <summary>
/// Generates string hash of queryStringParams
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="queryStringParams">Structure to serialize in query string</param>
/// <returns></returns>
public static string GenerateQueryStringHash<T>(T queryStringParams) where T : class
{
var queryStringBuilder = new Dictionary<string, string>();
QueryStringObjectSerializer.Serialize(queryStringBuilder, queryStringParams);
var qs = new StringBuilder(100);
foreach (var keyVal in queryStringBuilder)
qs.Append($"{keyVal.Key}{keyVal.Value}");
return qs.ToString();
}
/// <summary>
/// Extracts a value from "key=value" string
/// </summary>
/// <param name="query">query string</param>
/// <returns>value part of the input string</returns>
private static string GetQueryValue(string query)
{
string value = string.Empty;
var pos = query.IndexOf('=');
if (pos > 0) value = query.Substring(pos + 1);
return value;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment