I need to write a generic method that will take any object, loop over its values, and, for each string, modify it (HtmlEncode it in this case). (this need to execute on all objects submitted to my.net 4.7 API controllers)
So I created an ActionFilterAttribute, and added it to my global filters, and it works fine on "flat" objects.
However, the object can be something like an object with an IList member (each of which will need to be modified) or a nested object/s with its own string properties.
Anyone done anything like this? Got like 10 commented out failed experiments. lol
public override void OnActionExecuting(HttpActionContext actionContext)
{
// Decode strings from PUT or POST requests
if (actionContext.Request.Method.ToString() == WebRequestMethods.Http.Post
|| actionContext.Request.Method.ToString() == WebRequestMethods.Http.Put)
{
// For each of the items in the PUT/POST
foreach (var item in actionContext.ActionArguments.Values)
{
try
{
var type = item.GetType();
// For each property of this object, html decode it if it is of type string
foreach (PropertyInfo propertyInfo in type.GetProperties())
{
var prop = propertyInfo.GetValue(item);
if (prop is string str)
{
propertyInfo.SetValue(item, WebUtility.HtmlEncode(str));
}
}
}
catch (Exception)
{
// ignored
}
}
}
base.OnActionExecuting(actionContext);
}
UPDATE:
Currently testing this: update: no good...an Int will be identified as Object
public class HttpStringDecodeFilter : ActionFilterAttribute
{
private void HtmlEncodeAllStringsInObject(Object obj)
{
var type = obj.GetType();
var properties = type.GetProperties();
foreach (var property in properties)
{
var propValue = property.GetValue(obj);
if (property.PropertyType.IsAssignableFrom(typeof(string)))
{
property.SetValue(obj, WebUtility.HtmlEncode(propValue?.ToString()));
}
else if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(IList<>))
{
if (propValue is not List<string> list) continue;
for (var i = 0; i < list.Count; i++)
{
list[i] = WebUtility.HtmlEncode(list[i]);
}
property.SetValue(obj, list);
} else
{
var typeCode = Type.GetTypeCode(property.PropertyType);
if (typeCode.Equals(TypeCode.Object))
{
HtmlEncodeAllStringsInObject(property);
}
}
}
}