I need to List/Get/Update/Create/Destroy (ie perform CRUD activites) on data from an external REST API.
This API has a custom filter syntax, which looks like this:
{{BaseUrl}}/V1.0/<Entity>/query?search={"filter":[{"op":"eq","field":"id","value":"68275"}]}
This filter syntax is quite flexible, and basically allows you to do fieldA == x
AND/OR
fieldB != y
queries.
id <= 1000 && Title == "Some title"
{
"filter": [
{
"op": "le",
"field": "id",
"value": 1000
},
{
"op": "eq",
"field": "Title",
"value": "Some title"
}
]
}
firstname == "john" || lastname != "Jones"
{
"filter": [
{
"op": "or",
"items": [
{
"op": "eq",
"field": "firstname",
"value": "John"
},
{
"op": "ne",
"field": "lastname",
"value": "Jones"
}
]
}
]
}
If you're curious, it's the Autotask API: https://ww3.autotask.net/help/DeveloperHelp/Content/APIs/REST/General_Topics/REST_Swagger_UI.htm
At the moment, I have some classes which can convert to the first example query id <= 1000 && Title == "Some title"
.
public interface IAutotaskFilter
{
string Field { get; }
string Value { get; }
string ComparisonOperator { get; }
}
public interface IAutotaskQuery
{
void AddFilter(IAutotaskFilter autotaskFilter);
void AddFilters(IList<IAutotaskFilter> filters);
void RemoveFilter(IAutotaskFilter autotaskFilter);
}
The problem is that this violates the clean architecture I have.
Clean Architecture Example from Microsoft
If I use these classes (through the above interfaces), then my Application Layer will depend on an implementation detail of my Infrastructure Layer. In other words, my business logic will know how to construct queries for this specific external API.
As far as I can tell, I have a few options:
Implement a custom LINQ provider that will translate linq queries to this syntax. From what I can tell, this is very difficult. I didn't find any recent information on this. Any libraries that have tried haven't been touched in at least 7 years. If this is possible, I would love to do it. Having that fluent syntax for queries is very appealing to me.
Suck it up and use as is.
Cache API entities locally and do cache invalidation using their webhooks 'updated'/'created'/'destroyed' events. That's a lot of processing, data transfer and complexity, so probably not worth it.
I am hoping there's a better option, that I haven't found. Please let me know.
If it helps, the Autotask API provides an OpenAPI v1 doc.