Skip to content

Relative @odata.nextLink gives invalid context uri error #932

@m2307

Description

@m2307

We're having some trouble with responses that contain a relative @odata.nextLink in the response. This is on the latest nuget version 6.0.1.

As an example, the following response body:

{
	"@odata.context": "$metadata#Products",
	"@odata.metadataEtag": "W/\"20240208144657\"",
	"value": [{
			"ProductID": 1,
			"ProductName": "VersaTray Essentials",
			"Discontinued": false,
			"UnitPrice": 19.99
		}, 

...

		{
			"ProductID": 10,
			"ProductName": "VelvetLuxe Lip Stains",
			"Discontinued": false,
			"UnitPrice": 17.5
		}
	],
	"@odata.nextLink": "Products?$skiptoken=10"
}

from this code snippet:

    var annotations = new ODataFeedAnnotations();
    var results = await odataClient.For("Products").FindEntriesAsync(annotations);

will give us this error:

Microsoft.OData.ODataException: The context URL '$metadata#Products' is invalid.
   at Microsoft.OData.JsonLight.ODataJsonLightContextUriParser.Parse(IEdmModel model, String contextUriFromPayload, ODataPayloadKind payloadKind, Func`3 clientCustomTypeResolver, Boolean needParseFragment, Boolean throwIfMetadataConflict, Uri baseUri, IEdmNavigationSource navigationSource)
   at Microsoft.OData.JsonLight.ODataJsonLightDeserializer.ReadPayloadStart(ODataPayloadKind payloadKind, PropertyAndAnnotationCollector propertyAndAnnotationCollector, Boolean isReadingNestedPayload, Boolean allowEmptyPayload, IEdmNavigationSource navigationSource)
   at Microsoft.OData.JsonLight.ODataJsonLightReader.ReadAtStartImplementation()
   at Microsoft.OData.ODataReaderCore.ReadImplementation()
   at Microsoft.OData.ODataReaderCore.ReadSynchronously()
   at Microsoft.OData.ODataReaderCore.InterceptException[T](Func`1 action)
   at Microsoft.OData.ODataReaderCore.Read()
   at Simple.OData.Client.V4.Adapter.ResponseReader.ReadResponse(ODataReader odataReader, IODataResponseMessageAsync responseMessage)
   at Simple.OData.Client.V4.Adapter.ResponseReader.<GetResponseAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Simple.OData.Client.ODataClient.<ExecuteRequestWithResultAsync>d__161`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Simple.OData.Client.ODataClient.<FindAnnotatedEntriesAsync>d__89.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Simple.OData.Client.ODataClient.<FindEntriesAsync>d__88.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Simple.OData.Client.FluentClientBase`2.<FilterAndTypeColumnsAsync>d__97.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Simple.OData.Client.BoundClient`1.<FindEntriesAsync>d__7.MoveNext()

In testing, we found the issue is related to the "@odata.context": "$metadata#Products", since the issue does not occur when an absolute uri is present.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions