LINQFilter Filtering Syntax
Overview
Many Origami API endpoints accept a LINQFilter query parameter alongside the standard filter parameter. While filter uses Origami's colon-delimited Advanced Search syntax, LINQFilter accepts C#-style expressions that are parsed and translated to SQL at runtime.
LINQFilter is useful when you need expression capabilities not covered by the standard filter syntax (method calls, arithmetic, conditional logic, navigation properties).
Basic Syntax
Pass LINQFilter as a query string parameter on GET requests:
GET /api/{domain}/Query?LINQFilter=Status == "Open"
The expression references entity property names directly and uses C#-like operators and method calls.
⚠️ Combining filter and LINQFilter ⚠️
When both filter and LINQFilter are provided on the same request, they are applied as an AND combination. The standard filter is applied first, then LINQFilter is applied as an additional WHERE clause on the already-filtered result set.
Both conditions must be satisfied for a record to be included in the response.
If the two filters contradict each other, the result set will be empty. For example:
GET /api/Claim/Query?filter=Status:eq:Open&LINQFilter=Status == "Closed"
This returns zero records because no claim can have Status equal to both "Open" and "Closed" simultaneously.
Supported Operators
Comparison
| Operator | Meaning | Example |
|---|---|---|
== or = | Equals | Status == "Open" |
!= or <> | Not equals | Status != "Closed" |
> | Greater than | TotalIncurred > 50000 |
>= | Greater than or equal | ReserveAmount >= 5000 |
< | Less than | TotalIncurred < 100000 |
<= | Less than or equal | DaysOpen <= 30 |
Logical
| Operator | Meaning | Example |
|---|---|---|
&& or and | AND | Status == "Open" && Amount > 1000 |
|| or or | OR | Status == "Open" || Status == "Pending" |
! or not | NOT | !(Status == "Closed") |
Arithmetic
| Operator | Meaning | Example |
|---|---|---|
+ | Addition | PaidAmount + ReserveAmount > 100000 |
- | Subtraction | TotalIncurred - PaidAmount < 5000 |
* | Multiplication | Rate * Units > 500 |
/ | Division | TotalIncurred / ClaimCount > 10000 |
% or mod | Modulo | RecordID % 2 == 0 |
Other
| Operator | Meaning | Example |
|---|---|---|
?? | Null coalescing | (CustomText1 ?? "") != "" |
iif(cond, t, f) | Conditional (ternary) | iif(Amount > 1000, "High", "Low") == "High" |
String Methods
Call methods directly on string properties:
| Method | Example |
|---|---|
.Contains("value") | Claimant.Contains("Smith") |
.StartsWith("value") | PolicyNumber.StartsWith("WC-") |
.EndsWith("value") | ClaimNumber.EndsWith("-01") |
.ToUpper() | Status.ToUpper() == "OPEN" |
.ToLower() | Claimant.ToLower().Contains("smith") |
.Trim() | CustomText1.Trim() != "" |
.Substring(start, len) | ClaimNumber.Substring(0, 2) == "WC" |
.Length | Description.Length > 100 |
Collection Methods
For properties that represent child collections or multi-value associations:
| Method | Example |
|---|---|
.Any() | Transactions.Any() |
.Any(expr) | Transactions.Any(Amount > 5000) |
.All(expr) | Tasks.All(Status == "Complete") |
.Count() | Transactions.Count() > 3 |
.Sum(expr) | Transactions.Sum(Amount) > 100000 |
.Min(expr) | Transactions.Min(TransactionDate) > DateTime(2025,1,1) |
.Max(expr) | Transactions.Max(Amount) < 50000 |
Type Conversions and Constructors
| Type | Example |
|---|---|
DateTime | LossDate > DateTime(2025, 1, 1) |
Int32 | Int32(CustomText1) > 100 |
Decimal | Decimal(CustomText2) >= 50.5 |
Literals
| Type | Syntax |
|---|---|
| String | "value" (double quotes) |
| Character | 'c' (single quotes) |
| Integer | 42 |
| Decimal/Float | 3.14, 3.14f |
| Boolean | true, false |
| Null | null |
Keywords
| Keyword | Meaning |
|---|---|
it | The current entity being evaluated |
new | Create anonymous types (used in projections) |
Navigation Properties
Access related entity properties using dot notation:
Policy.PolicyType == "Workers Comp"
AdjusterUser.Email.Contains("@origami")
Null Handling
Always account for nullable fields to avoid runtime errors:
CustomText1 != null && CustomText1.Contains("important")
(CustomDate1 ?? DateTime(1900,1,1)) > DateTime(2025,1,1)
Complete Examples
Open claims with incurred over $50,000:
Status == "Open" && TotalIncurred > 50000
Claims where the claimant name contains "Smith" (case-insensitive):
Claimant.ToLower().Contains("smith")
Claims with a loss date in 2025:
LossDate >= DateTime(2025, 1, 1) && LossDate < DateTime(2026, 1, 1)
Claims where paid exceeds reserve:
PaidAmount > ReserveAmount
Claims with non-empty custom field that starts with a specific prefix:
CustomText1 != null && CustomText1.StartsWith("REF-")
Claims with any transaction over $10,000:
Transactions.Any(Amount > 10000)
Using conditional logic:
iif(TotalIncurred > 100000, "Critical", "Normal") == "Critical"
Restrictions
- Only properties that exist on the queried entity type can be referenced. Accessing non-existent properties results in a parse error.
- Method calls are limited to predefined types (String, Math, Convert, DateTime, numeric types). Arbitrary .NET method invocation is not supported.
- The expression is translated to SQL by the query provider; some complex expressions may not translate if they lack a SQL equivalent.
- Standard HTTP query string length limits apply.
Updated 12 days ago