Skip to content

Commit e74faa7

Browse files
committed
Implement a query filter.
1 parent 8cb5169 commit e74faa7

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System.Net;
2+
using System.Reflection;
3+
using Initium.Exceptions;
4+
using Microsoft.AspNetCore.Mvc;
5+
using Microsoft.AspNetCore.Mvc.Filters;
6+
using Microsoft.Extensions.Primitives;
7+
8+
namespace Initium.Attributes;
9+
10+
/// <summary>
11+
/// An attribute to filter query results based on a specified property and enum type.
12+
/// </summary>
13+
/// <typeparam name="T">The type of the objects being filtered.</typeparam>
14+
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
15+
public class QueryFilterAttribute<T>(string propertyName, Type propertyType) : Attribute, IActionFilter
16+
{
17+
/// <summary>
18+
/// Called before the action method executes. No operation is performed in this implementation.
19+
/// </summary>
20+
/// <param name="context">The context for the executed action.</param>
21+
public void OnActionExecuting(ActionExecutingContext context) { }
22+
23+
/// <summary>
24+
/// Executes after the action method is invoked. Filters the result based on the specified property and enum value.
25+
/// </summary>
26+
/// <param name="context">The context for the action filter.</param>
27+
public void OnActionExecuted(ActionExecutedContext context)
28+
{
29+
if (!propertyType.IsEnum)
30+
throw new ApiException(HttpStatusCode.BadRequest, $"QueryFilter only accepts enum types for filters. The property '{propertyName}' is not an enum.");
31+
32+
if (context.Result is not ObjectResult { Value: IEnumerable<T> enumerable } objectResult) return;
33+
34+
var query = context.HttpContext.Request.Query;
35+
if (!query.TryGetValue(propertyName, out var parameterValue)) return;
36+
37+
if (StringValues.IsNullOrEmpty(parameterValue))
38+
throw new ApiException(HttpStatusCode.BadRequest, "FUCK HITLER");
39+
40+
if (!Enum.TryParse(propertyType, parameterValue, ignoreCase: true, out var enumValue))
41+
throw new ApiException(HttpStatusCode.BadRequest, $"Invalid query parameter value: `{parameterValue}` for `{propertyName}`. Allowed values are: {string.Join(", ", Enum.GetNames(propertyType))}.");
42+
43+
objectResult.Value = enumerable.Where(item =>
44+
{
45+
var property = typeof(T).GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
46+
if (property == null) return false;
47+
var value = property.GetValue(item);
48+
return value?.Equals(enumValue) == true;
49+
});
50+
}
51+
}

0 commit comments

Comments
 (0)