This is an example of an attribute that I created to validate that required parameters have been assigned in the request object receive in a POST route. I decided on this approach because the standard ModelState.IsValid approach was not valid. This is because the required attributes vary based on what action is being called.
// ATTRIBUTE ONLY VALID FOR METHODS [AttributeUsage(AttributeTargets.Method)] // INHERIT ActionFilterAttribute public class EnsurePresencesOfAttribute : ActionFilterAttribute { // ReSharper disable once InconsistentNaming public string required { get; set; }
// VALIDATE REQUIRED ATTRIBUTES
// FOR NON-ASYNC REQUESTS
public override void OnActionExecuting(HttpActionContext context)
{
Dictionary<string, object> model = context.ActionArguments;
var serialstring = JsonConvert.SerializeObject(model);
foreach (var requirement in required.Split(','))
{
if (serialstring.Contains($"{requirement}\":null"))
{
ValueError(context, requirement);
return;
}
}
base.OnActionExecuting(context);
}
// VALIDATE THE REQUIRED ATTRIBUTES ARE PRESENT
// FOR ASYNC REQUESTS
public override Task OnActionExecutingAsync(HttpActionContext context, CancellationToken token)
{
Dictionary<string, object> model = context.ActionArguments;
var serialstring = JsonConvert.SerializeObject(model);
foreach (var requirement in required.Split(','))
{
if (serialstring.Contains($"{requirement}\":null"))
{
ValueError(context, requirement);
return Task.FromResult(0);
}
}
return base.OnActionExecutingAsync(context, token);
}
// LOG ERROR AND RETURN AND SET ERROR RESPONSE
private static void ValueError(HttpActionContext context, string requirement)
{
var action = context.ActionDescriptor.ActionName;
AppUtils.LogError($"{action} Failed : Missing Required Attribute {requirement}. ");
using (var controller = new BaseApiController { Request = new HttpRequestMessage() })
{
controller.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
context.Response = controller.InvalidInputResponse();
}
}