Skip to content

Commit 97da818

Browse files
committed
Add OData Query Options documentation for REST APIs
1 parent 6763574 commit 97da818

File tree

2 files changed

+341
-0
lines changed

2 files changed

+341
-0
lines changed
Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
---
2+
uid: WebApi.OData
3+
---
4+
5+
# OData Query Options for REST APIs
6+
7+
2sxc supports **OData system query options** to filter, sort, paginate, and select data from both [Data](xref:WebApi.Data.Index) and [Query](xref:WebApi.Query) REST endpoints. This allows you to append standard OData parameters to your URLs for powerful data querying.
8+
9+
> [!TIP]
10+
> OData query options work on both:
11+
>
12+
> - **Data endpoints**: `.../app/auto/data/[ContentType]`
13+
> - **Query endpoints**: `.../app/auto/query/[QueryName]`
14+
15+
## Quick Examples
16+
17+
Filter and sort blog posts:
18+
19+
```url
20+
/app/auto/data/BlogPost?$filter=ShowOnStartPage eq true&$orderby=UrlKey
21+
```
22+
23+
Get the second blog post (pagination):
24+
25+
```url
26+
/app/auto/data/BlogPost?$orderby=UrlKey&$skip=1&$top=1
27+
```
28+
29+
Query with filter and sort:
30+
31+
```url
32+
/app/auto/query/nameOfQuery?$filter=EntityType eq 'blogpost' and ShowOnStartPage eq true&$orderby=UrlKey
33+
```
34+
35+
## How OData Works with 2sxc Endpoints
36+
37+
### Data Endpoint with OData
38+
39+
The [Data REST API](xref:WebApi.Data.Index) endpoint lets you query content-types directly:
40+
41+
```url
42+
[root-path]/app/auto/data/BlogPost?$filter=ShowOnStartPage eq true&$orderby=Created desc&$top=10
43+
```
44+
45+
This returns the 10 most recent blog posts where `ShowOnStartPage` is true.
46+
47+
### Query Endpoint with OData
48+
49+
The [Query REST API](xref:WebApi.Query) endpoint lets you query [VisualQuery](xref:Basics.Query.VisualQuery.Index) pipelines:
50+
51+
```url
52+
[root-path]/app/auto/query/BlogPostsFiltered?$orderby=Title&$skip=20&$top=10
53+
```
54+
55+
This executes your predefined query and then applies additional OData filtering/sorting on top of the results.
56+
57+
## Supported OData System Query Options
58+
59+
2sxc uses the **ToSic.Sys.OData** parser which supports a practical subset of OData v4 system query options.
60+
61+
### $filter - Filter Data
62+
63+
Filter results based on conditions.
64+
65+
**Supported Operators:**
66+
67+
- Comparison: `eq` (equals), `ne` (not equals), `gt` (greater than), `ge` (greater or equal), `lt` (less than), `le` (less or equal)
68+
- Logical: `and` (combine conditions)
69+
- Negation: `not` (negate an expression)
70+
71+
**Supported Functions:**
72+
73+
- `contains(field, 'text')` - check if field contains text
74+
- `startswith(field, 'text')` - check if field starts with text
75+
76+
**Examples:**
77+
78+
Simple equality:
79+
80+
```odata
81+
$filter=Title eq 'Hello World'
82+
```
83+
84+
Multiple conditions:
85+
86+
```odata
87+
$filter=EntityType eq 'blogpost' and ShowOnStartPage eq true
88+
```
89+
90+
Contains function:
91+
92+
```odata
93+
$filter=contains(Description, 'world')
94+
```
95+
96+
Starts with function:
97+
98+
```odata
99+
$filter=startswith(Name, 'Acme')
100+
```
101+
102+
Negated contains:
103+
104+
```odata
105+
$filter=not contains(Description, 'deprecated')
106+
```
107+
108+
Numeric comparison:
109+
110+
```odata
111+
$filter=Rating gt 4 and Rating le 5
112+
```
113+
114+
> [!IMPORTANT]
115+
> **Not Currently Supported:**
116+
>
117+
> - Logical `or` operator (only `and` is supported)
118+
> - Arithmetic operators (`add`, `sub`, `mul`, `div`, `mod`)
119+
> - Complex nested expressions with mixed `and`/`or`
120+
> - Many OData functions like `endswith`, `indexof`, `tolower`, etc.
121+
122+
### $orderby - Sort Results
123+
124+
Sort results by one or more fields.
125+
126+
**Syntax:** `$orderby=Field1 [asc|desc], Field2 [asc|desc]`
127+
128+
**Examples:**
129+
130+
Sort by single field ascending (default):
131+
132+
```odata
133+
$orderby=Title
134+
```
135+
136+
Sort descending:
137+
138+
```odata
139+
$orderby=Created desc
140+
```
141+
142+
Sort by multiple fields:
143+
144+
```odata
145+
$orderby=Category asc, Created desc
146+
```
147+
148+
### $top - Limit Results
149+
150+
Limit the number of results returned.
151+
152+
**Syntax:** `$top=number`
153+
154+
**Examples:**
155+
156+
Get first 10 items:
157+
158+
```odata
159+
$top=10
160+
```
161+
162+
Combine with ordering:
163+
164+
```odata
165+
$orderby=Created desc&$top=5
166+
```
167+
168+
### $skip - Skip Results (Pagination)
169+
170+
Skip a specified number of results (useful for pagination).
171+
172+
**Syntax:** `$skip=number`
173+
174+
**Examples:**
175+
176+
Skip first 20 items:
177+
178+
```odata
179+
$skip=20
180+
```
181+
182+
Pagination (page 2 with 10 items per page):
183+
184+
```odata
185+
$skip=10&$top=10
186+
```
187+
188+
### $select - Select Specific Fields
189+
190+
Return only specific fields instead of all entity data.
191+
192+
**Syntax:** `$select=Field1,Field2,Field3`
193+
194+
**Examples:**
195+
196+
Select specific fields:
197+
198+
```odata
199+
$select=Title,Created,Id
200+
```
201+
202+
Select with filter:
203+
204+
```odata
205+
$select=Title,Description&$filter=ShowOnStartPage eq true
206+
```
207+
208+
**Special Field Aliases:**
209+
210+
2sxc provides convenient aliases for common system fields:
211+
212+
- `Id` or `EntityId` - Entity ID
213+
- `Guid` or `EntityGuid` - Entity GUID
214+
- `Created` - Creation date
215+
- `Modified` - Last modified date
216+
- `Title` - Title field
217+
218+
### Combining Multiple Options
219+
220+
You can combine multiple OData options in a single request:
221+
222+
```url
223+
/app/auto/data/BlogPost?$filter=ShowOnStartPage eq true&$orderby=Created desc&$skip=10&$top=5&$select=Title,Created,UrlKey
224+
```
225+
226+
This example:
227+
228+
1. Filters for posts where `ShowOnStartPage` is true
229+
2. Sorts by `Created` date descending
230+
3. Skips the first 10 results
231+
4. Returns the next 5 results
232+
5. Returns only `Title`, `Created`, and `UrlKey` fields
233+
234+
## Real-World Examples
235+
236+
### Example 1: Latest Published Blog Posts
237+
238+
```url
239+
/app/auto/data/BlogPost?$filter=ShowOnStartPage eq true and contains(Title,'2sxc')&$orderby=Created desc&$top=5&$select=Title,Created,UrlKey
240+
```
241+
242+
This returns the 5 most recent blog posts that:
243+
244+
- Have `ShowOnStartPage` set to true
245+
- Contain "2sxc" in the title
246+
- Returns only Title, Created date, and UrlKey
247+
248+
### Example 2: Paginated Product List
249+
250+
```url
251+
/app/auto/data/Product?$filter=InStock eq true&$orderby=Name&$skip=20&$top=10
252+
```
253+
254+
This returns products 21-30 (page 3 with 10 per page) that are in stock, sorted by name.
255+
256+
### Example 3: Search Results
257+
258+
```url
259+
/app/auto/query/SearchResults?$filter=startswith(Title,'Getting Started')&$orderby=Title&$select=Title,Description,Url
260+
```
261+
262+
This executes a predefined query and then filters for items starting with "Getting Started".
263+
264+
## URL Encoding
265+
266+
When using OData query options in URLs, special characters must be URL-encoded:
267+
268+
| Character | Encoded |
269+
|-----------|---------|
270+
| Space | `%20` |
271+
| `'` (single quote) | `%27` |
272+
| `eq` | (no encoding needed) |
273+
274+
**Example with encoding:**
275+
276+
```url
277+
/app/auto/data/BlogPost?$filter=Title eq 'Hello World'
278+
```
279+
280+
Becomes:
281+
282+
```url
283+
/app/auto/data/BlogPost?$filter=Title%20eq%20%27Hello%20World%27
284+
```
285+
286+
> [!TIP]
287+
> Most HTTP libraries and browsers handle URL encoding automatically.
288+
289+
## Limitations and Not Supported
290+
291+
The 2sxc OData implementation focuses on practical, commonly-used features. The following are **not currently supported**:
292+
293+
### Not Parsed/Not Executed
294+
295+
- `$expand` - Expanding related entities
296+
- `$compute` - Computed properties
297+
- `$search` - Free-text search
298+
- `$count` - Inline count
299+
- Logical `or` operator in `$filter`
300+
- Arithmetic operators in `$filter` (`add`, `sub`, `mul`, `div`, `mod`)
301+
- Lambda operators (`any`, `all`)
302+
- OData functions: `endswith`, `indexof`, `substring`, `toupper`, `tolower`, `length`, `trim`, `concat`, `year`, `month`, `day`, `hour`, `minute`, `second`, `date`, `time`, etc.
303+
- Spatial/geographic functions
304+
- Type casting and `$it` references
305+
- Deep `$select` with nested options
306+
307+
### Technical Notes
308+
309+
- The parser is permissive and syntax-oriented; it doesn't perform semantic validation
310+
- The execution engine supports a pragmatic subset for stable, predictable behavior
311+
- Filter expressions expect: attribute identifier on the left, literal/value on the right
312+
313+
## Performance Considerations
314+
315+
- **Use $select** to return only needed fields (reduces payload size)
316+
- **Filter early** using `$filter` rather than retrieving all data and filtering client-side
317+
- **Limit results** with `$top` to avoid large responses
318+
319+
## Technical Implementation
320+
321+
The OData system is built on:
322+
323+
- **ToSic.Sys.OData** - Minimal, permissive parser based on OASIS OData ABNF
324+
- **ODataQueryEngine** - Execution engine for the EAV/2sxc data stack
325+
- **DataSource Pipeline** - Integrates with 2sxc's [DataSource](xref:NetCode.DataSources.Index) architecture
326+
327+
The parser generates an AST (Abstract Syntax Tree) which is then executed against the data source pipeline.
328+
329+
## History
330+
331+
1. OData support introduced in 2sxc 17 (basic select)
332+
1. Enhanced OData parser in 2sxc 20.x
333+
334+
---
335+
336+
## See Also
337+
338+
- [Official OData Documentation](http://www.odata.org/)
339+
- [OData v4 URL Conventions](http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html)

docs-src/pages/web-api/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
topicUid: WebApi.Data.Index
1111
- name: Query REST API
1212
topicUid: WebApi.Query
13+
- name: OData REST API
14+
topicUid: WebApi.OData
1315

1416
# Detailed Specifications
1517
- name: " "

0 commit comments

Comments
 (0)