0
votes

I'm currently using OData v3, but this seems to fail (just differently) in OData v4 as well.

Let's say I have the following Uri:
http://myurl.com/odata/SomeEndpoint?$filter=FieldId eq 1&$top=10

Perfect, type that into Postman or a browser, works great. But If I encode the Uri it fails.

HTML Encoding:
http://myurl.com/odata/SomeEndpoint?$filter=FieldId eq 1&$top=10

Everything before the escaped character will get applied to the query (so $filter still works), but everything after the escaped character is ignored ($top is not applied).

URI Encoding (I tried both):
http://myurl.com/odata/SomeEndpoint?$filter=FieldId eq 1%26$top=10 http://myurl.com/odata/SomeEndpoint?$filter=FieldId eq 1%26%$top=10

Both cause OData to throw an exception when trying to apply the query options with the following error (paraphrased since this is from memory):

'&' is in invalid character in query string.
$filter=FieldId eq 1&$top=10

As you can see, this is undesired and an issue. If my client's encode their Uri before sending a request it won't work. Also, the links generated by OData in the result are encoded, for instance, the next page link:

<link rel="next" href="http://myurl.com/odata/SomeEndpoint?$filter=FieldId%20eq%201&amp;$skip=1" />

OData doesn't seem to mind the %20 (space) that works fine, but $skip is actually ignored because of the escaped ampersand (&amp;) if you just change it to a real ampersand (&) it works fine.

Is there a way to fix this? It seems to be an issue with OData.

For reference here is how I'm mapping my routes:

#pragma warning disable CS0618 // OData v3 route mapping.
config.Routes.MapODataRoute(
    routeName: "odata",
    routePrefix: "odata",
    model: model);
#pragma warning restore CS0618

I'm not doing anything custom.

UPDATE:
When I set my ACCEPT header to XML I get:
<link rel="next" href="http://myurl.com/odata/SomeEndpoint?$filter=FieldId%20eq%201&amp;$skip=1" />

When I set my ACCEPT header to JSON I get:
odata.nextLink": "http://webapi.mydlweb.com/api/test/odata/v3/Checks?$filter=StoreId%20eq%2040&pagesize=1&$skip=1"

Per the comment below, the JSON link is generated correctly. I can click it and it works because the ampersand is not encoded. However the XML link DOES encode the ampersand and is thus causing it to not work. Is that normal when encoding XML then? How then does the client know which ampersands to "unencode" and which to leave encoded? For instance, if you use an ampersand inside of a filter (not to separate query strings) then it DOES need to be encoded.

UPDATE 2: I guess it is XML encoding, and that's just the way it is.

enter image description here

1
At a glance, it seems like this is how it should work. By escaping the ampersand, you are telling the parser to not interpret it as a querystring delimiter but as a literal value. So, in your example, it appears you are trying to include the ampersand (and therefore the request of the querystring) as part of the $filter. - snow_FFFFFF
the filter should be JUST $filter=StoreId eq 40 the rest of it such as "$skip" or "pagesize" are not part of the filter but are rather other query strings - Rabid Penguin

1 Answers

2
votes

You can't escape the ampersand in a querystring and expect it to behave like an unescaped ampersand in a querystring. This doesn't have anything to do with odata, just normal querystring behavior. By escaping it, the parser will not interpret it as a delimiter of key/value pairs but as a literal ampersand in the value.

EXAMPLE: This google search works:

https://www.google.com/search?safe=off&q=test

But, this one does not:

https://www.google.com/search?safe=off%26q=test