Support for custom filters #187
Replies: 1 comment 4 replies
-
Hi @vukispasic,
With Gridify, custom filters are rarely necessary as it supports nearly all logical scenarios right out of the box, so no Gridify doesn't have this feature yet.
The latest versions of Gridify include a Validate("PatientId=3F5CF33E-FB79-4DF9-BE55-B1AA008F2146"); // it is valid
Validate("PhysicianId=2041f0a7-edc8-4ad2-9132-8025cb0a0461,DateTime>=2024-07-01,DateTime<2024-08-01"); // it is valid
Validate("PhysicianId=2041f0a7-edc8-4ad2-9132-8025cb0a0461"); // throws Invalid query, DateTime is not specified
Validate("PhysicianId=2041f0a7-edc8-4ad2-9132-8025cb0a0461,DateTime>=2023-07-01,DateTime<2024-08-01"); // throws Invalid query, DateTime range exceeds one month
void Validate(string filter)
{
var tree = SyntaxTree.Parse(filter); // access to the whole query Syntax Tree
var fields = GetFields(tree.Root).ToList();
// check whether query has PhysicianId
if (fields.Any(f => f.FieldToken.Text.Equals(nameof(Appointment.PhysicianId), StringComparison.InvariantCultureIgnoreCase)))
{
var dateTimeFields = fields.Where(f => f.FieldToken.Text.Equals(nameof(Appointment.DateTime), StringComparison.InvariantCultureIgnoreCase));
// make sure we only have two dateTime conditions
if (dateTimeFields.Count() != 2)
{
throw new GridifyQueryException("Invalid query, DateTime is not specified");
}
var dateTimes = GetDateTimes(tree.Root).ToArray();
// make sure dates are less than 1 month
if (dateTimes[0].Date > dateTimes[1].Date)
{
(dateTimes[0], dateTimes[1]) = (dateTimes[1], dateTimes[0]);
}
var start = dateTimes[0];
var end = dateTimes[1];
if ((end - start).TotalDays > 31)
{
throw new GridifyQueryException("Invalid query, DateTime range exceeds one month");
}
}
}
IEnumerable<FieldExpressionSyntax> GetFields(ISyntaxNode parentNode)
{
foreach (var node in parentNode.GetChildren())
{
if (node.Kind == SyntaxKind.FieldExpression)
{
yield return (node as FieldExpressionSyntax)!;
}
foreach (var subNode in GetFields(node))
{
yield return subNode;
}
}
}
IEnumerable<DateTime> GetDateTimes(ISyntaxNode parentNode)
{
foreach (var node in parentNode.GetChildren().OfType<BinaryExpressionSyntax>())
{
if (node.Left is FieldExpressionSyntax fExp && fExp.FieldToken.Text.Equals(nameof(Appointment.DateTime), StringComparison.InvariantCultureIgnoreCase))
{
var value = node.Right as ValueExpressionSyntax;
yield return DateTime.Parse(value!.ValueToken.Text);
}
foreach (var subNode in GetDateTimes(node))
{
yield return subNode;
}
}
}
public class Appointment
{
public Guid PatientId { get; set; }
public Guid PhysicianId { get; set; }
public DateTimeOffset DateTime { get; set; }
} |
Beta Was this translation helpful? Give feedback.
-
Hello,
We are considering to use Gridify in our Web API project instead Sieve but we are missing possibility to configure custom filters.
For example, Sieve library supports registration of custom filters as following:
Basically idea is to expose some custom filters for API consumers so they can get required data in simpler way.
Is there a possibility to generate this kind of filters with Gridify?
Second possibility is support to validate filter values from query. For example we want to validate if consumer query is valid in a way that if one filter parameter is used then other is required. Let me explain in more details:
We have a model:
In case filter query contains PatientId (ex. filter=PatientId=3F5CF33E-FB79-4DF9-BE55-B1AA008F2146 ) then DateTime filter is not mandatory, but if query contains ResourceId then DateTime range is mandatory and can't be longer then 1 month (ex. filter=PhysicianId=2041f0a7-edc8-4ad2-9132-8025cb0a0461,DateTime>=2024-07-01,DateTime<2024-08-01 )
We could manually parse filter query string and implement validation logic, but we would like to know is there a neater way with Gridify?
Thank you for your answer
Beta Was this translation helpful? Give feedback.
All reactions