Skip to content

Commit beae2e8

Browse files
authored
Merge pull request #520 from microsoft/corranrogue9/filterassegment
Add guidance to use composable functions instead of filter-as-segment feature
2 parents fcbe872 + dc86042 commit beae2e8

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

graph/articles/filter-as-segment.md

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Filter as segment
2+
3+
There is an [OData feature](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_AddressingaSubsetofaCollection) which allows having a `$filter` in a URL segment.
4+
This feature is useful whenever there are operations on a collection and the client wants to perform those operations on a *subset* of the collection.
5+
For example, the `riskyUsers` API on Microsoft Graph has an action defined to let clients "dismiss" risky users (i.e. consider those users "not risky"):
6+
7+
```xml
8+
<Action Name="dismiss" IsBound="true">
9+
<Parameter Name="bindingParameter" Type="Collection(microsoft.graph.riskyUser)" />
10+
<Parameter Name="userIds" Type="Collection(Edm.String)" />
11+
</Action>
12+
```
13+
14+
Using this action, clients can call
15+
16+
```http
17+
POST /identityProtection/riskyUsers/dismiss
18+
{
19+
"userIds": [
20+
"{userId1}",
21+
"{userId2}",
22+
...
23+
]
24+
}
25+
```
26+
27+
in order to dismiss the risky users with the provided IDs. Using the filter-as-segment OData feature, the action could instead be defined as:
28+
29+
```xml
30+
<Action Name="dismiss" IsBound="true">
31+
<Parameter Name="bindingParameter" Type="Collection(self.riskyUser)" />
32+
</Action>
33+
```
34+
35+
and clients could call
36+
37+
```http
38+
POST /identityProtection/riskyUsers/$filter=@f/dismiss?@f=id IN ('{userId1}','{userId2}',...)
39+
```
40+
41+
Doing this is beneficial due to the robust nature of OData filter expressions: clients will be able to dismiss risky users based on any supported filter without the service team needing to implement a new `dismiss` overload that filters based on the new criteria.
42+
However, there are some concerns about the discoverability of using the filter-as-segment feature, as well as the support of [parameter aliasing](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_ParameterAliases) that's required.
43+
As a result, functions should be introduced that act in the same way as the filter-as-segment:
44+
45+
```xml
46+
<Function Name="filter" IsBound="true" IsComposable="true">
47+
<Parameter Name="bindingParameter" Type="Collection(microsoft.graph.riskyUser)" Nullable="false" />
48+
<Parameter Name="expression" Type="Edm.String" Nullable="false" />
49+
<ReturnType Type="Collection(microsoft.graph.riskyUser)" />
50+
</Function>
51+
```
52+
53+
Clients would now be able to call
54+
55+
```http
56+
POST /identityProtection/riskyUsers/filter(expression='id IN (''{userId1}'',''{userId2}'',...)')/dismiss
57+
```
58+
59+
NOTE: the `'` literal in the filter expression must be escaped with `''`
60+
61+
An example implementation of a filter function using OData WebApi can be found [here](https://github.com/OData/AspNetCoreOData/commit/7732f7e6b812d9a79a73529562f2e74b68e2794f).

0 commit comments

Comments
 (0)