odata.net
odata.net copied to clipboard
ODataError#InstanceAnnotations are ignored for a remote client
From one of my odata endpoint, I am returning a HTTP 400 response with an instance of ODataError
as body. The instance also has InstanceAnnotations
. When the endpoint is invoked locally the InstanceAnnotations
gets serialized and included in the response. However, when the same endpoint is invoked from a remote client those InstanceAnnotations
are not included at all in the response.
Note that in both cases, I am setting the following header in the request.
Prefer: odata.include-annotations="*"
Reference: https://docs.microsoft.com/en-us/odata/client/annotation-support#request-preference-odatainclude-annotations
Assemblies affected
NuGets used:
- Microsoft.AspNet.OData v7.5.1
- Microsoft.OData.Core v7.7.2
- Microsoft.OData.Edm v7.7.2
Reproduce steps
- Create a OData service with an endpoint that respond with HTTP 400 where the body is an
ODataError
withInstanceAnnotations
. - Host the service.
- Invoke the endpoint locally. The annotations should be available as the part of response.
- Invoke the endpoint remotely. The annotations are not available as the part of response.
Expected result
The annotation should be present irrespective of source of the invocation, especially when the Prefer: odata.include-annotations="*"
request header is set.
Actual result
The annotations are only available locally. Even when Prefer: odata.include-annotations="*"
request header is not set.
Additional detail
@Sayan751 Could you please help us understand "locally" vs "remotely"? What Client are you using? What's the version? Would you please share us more detail about your "local" client and "remote" client? Or Fiddler request/response?
@xuzhg Thank you for the reply.
For example, I have hosted the service as https://foo-test.com/odata/v4
.
Now by "local" I mean when I open a RDP to the server and use a REST client to invoke the endpoint. And by "remote" I mean when I use a REST client from my machine (physically different system than the said server) to invoke the endpoint.
Below are the logs from Insomnia REST client.
local
// Request
DELETE /odata/v4/Entities(1) HTTP/1.1
Host: foo-test.com
Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAKAGNFAAAADw==
User-Agent: insomnia/2020.5.2
Accept: */*
// Response
HTTP/1.1 401 Unauthorized
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
WWW-Authenticate: NTLM TlRMTVNTUAACAAAAHAAcADgAAAAFgoqi6Afijr5bfR0AAAAAAAAAAJAAkABUAAAACgBjRQAAAA9DAE8ATgBGAEkARwBUAEUAUwBUAC0ARABFAFYAAgAcAEMATwBOAEYASQBHAFQARQBTAFQALQBEAEUAVgABABwAQwBPAE4ARgBJAEcAVABFAFMAVAAtAEQARQBWAAQAHABjAG8AbgBmAGkAZwB0AGUAcwB0AC0AZABlAHYAAwAcAGMAbwBuAGYAaQBnAHQAZQBzAHQALQBkAGUAdgAHAAgAHz4teErq1gEAAAAA
Date: Thu, 14 Jan 2021 07:54:21 GMT
// Request
DELETE /odata/v4/Entities(1) HTTP/1.1
Host: foo-test.com
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAI4AAABUAVQBpgAAAAAAAABYAAAAGgAaAFgAAAAcABwAcgAAAAAAAAD6AQAABYKIogoAY0UAAAAPwOddg7pZaTQOF03AZghdAEEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIAQwBPAE4ARgBJAEcAVABFAFMAVAAtAEQARQBWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHyMsVg38PZ6SzDJvwcqigcBAQAAAAAAAB8+LXhK6tYBu7fatPVKEq4AAAAAAgAcAEMATwBOAEYASQBHAFQARQBTAFQALQBEAEUAVgABABwAQwBPAE4ARgBJAEcAVABFAFMAVAAtAEQARQBWAAQAHABjAG8AbgBmAGkAZwB0AGUAcwB0AC0AZABlAHYAAwAcAGMAbwBuAGYAaQBnAHQAZQBzAHQALQBkAGUAdgAHAAgAHz4teErq1gEGAAQAAgAAAAgAMAAwAAAAAAAAAAAAAAAAMAAALokgNkDtuJMYdKaA+/KolBKy3U7lkN7PHr/ilYIPj3UKABAAAAAAAAAAAAAAAAAAAAAAAAkAQABIAFQAVABQAC8AYwBvAG4AZgBpAGcAdABlAHMAdAAtAGQAZQB2AC4AbgBlAHQAYQB0AHcAbwByAGsALgBkAGUAAAAAAAAAAAA=
User-Agent: insomnia/2020.5.2
Accept: */*
// Response
HTTP/1.1 400 Bad Request
Content-Length: 164
Content-Type: application/json; odata.metadata=minimal
Server: Microsoft-HTTPAPI/2.0
OData-Version: 4.0
Date: Thu, 14 Jan 2021 07:54:21 GMT
Remote
// Request
DELETE /odata/v4/Entities(1) HTTP/1.1
Host: foo-test.com
Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAKAGFKAAAADw==
User-Agent: insomnia/2020.5.2
Accept: */*
// Response
HTTP/1.1 401 Unauthorized
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
WWW-Authenticate: NTLM TlRMTVNTUAACAAAAHAAcADgAAAAFgoqireZ2zslqzhMAAAAAAAAAAJAAkABUAAAACgBjRQAAAA9DAE8ATgBGAEkARwBUAEUAUwBUAC0ARABFAFYAAgAcAEMATwBOAEYASQBHAFQARQBTAFQALQBEAEUAVgABABwAQwBPAE4ARgBJAEcAVABFAFMAVAAtAEQARQBWAAQAHABjAG8AbgBmAGkAZwB0AGUAcwB0AC0AZABlAHYAAwAcAGMAbwBuAGYAaQBnAHQAZQBzAHQALQBkAGUAdgAHAAgA2O7oPkrq1gEAAAAA
Date: Thu, 14 Jan 2021 07:52:45 GMT
// Request
DELETE /odata/v4/Entities(1) HTTP/1.1
Host: foo-test.com
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAIgAAABUAVQBoAAAAAAAAABYAAAAGgAaAFgAAAAWABYAcgAAAAAAAAD0AQAABYKIogoAYUoAAAAPi3M6qzWWgkvqifuU2QFowkEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIAUwBQAC0ATQBPAEIASQBMAC0AMAAxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMLpj+5tv7DkW6VNi7LsqjYBAQAAAAAAANju6D5K6tYBl2e496WM1sYAAAAAAgAcAEMATwBOAEYASQBHAFQARQBTAFQALQBEAEUAVgABABwAQwBPAE4ARgBJAEcAVABFAFMAVAAtAEQARQBWAAQAHABjAG8AbgBmAGkAZwB0AGUAcwB0AC0AZABlAHYAAwAcAGMAbwBuAGYAaQBnAHQAZQBzAHQALQBkAGUAdgAHAAgA2O7oPkrq1gEGAAQAAgAAAAgAMAAwAAAAAAAAAAEAAAAAIAAAMpRM154PlFnipNneqfvZGAGOPlWWAVG3eIqbt2jXt5UKABAAAAAAAAAAAAAAAAAAAAAAAAkAQABIAFQAVABQAC8AYwBvAG4AZgBpAGcAdABlAHMAdAAtAGQAZQB2AC4AbgBlAHQAYQB0AHcAbwByAGsALgBkAGUAAAAAAAAAAAA=
User-Agent: insomnia/2020.5.2
Accept: */*
// Response
HTTP/1.1 400 Bad Request
Content-Length: 96
Content-Type: application/json; odata.metadata=minimal
Server: Microsoft-HTTPAPI/2.0
OData-Version: 4.0
Date: Thu, 14 Jan 2021 07:52:45 GMT
As you can see that there aren't any significant difference between the requests. But for "remote", I get a smaller response body, which is caused by the missing annotations.
The sample response looks like below, but for "remote", the @MyNs.Error.DependentItems
annotation is missing.
{
"error": {
"code": "EntityHasDependencies",
"message": "The requested resource is still required.",
"@MyNs.Error.DependentItems": [
"Item42",
"Item43"
]
}
}
I have already shared the version of the OData NuGets earlier. If you need more info, please let me know.
@xuzhg Any update on this issue?
It seems that this issue is occurring because of how the CreateErrorResponse
is implemented.
public static HttpResponseMessage CreateErrorResponse(this HttpRequestMessage request,
HttpStatusCode statusCode, ODataError oDataError)
{
if (request.ShouldIncludeErrorDetail())
{
return request.CreateResponse(statusCode, oDataError);
}
else
{
return request.CreateResponse(
statusCode,
new ODataError
{
ErrorCode = oDataError.ErrorCode,
Message = oDataError.Message,
});
}
}
The usage of request.ShouldIncludeErrorDetail()
is actually causing the omission of the error annotations when a remote client is communicating with the service. A direct usage of request.CreateResponse(statusCode, oDataError)
seems to work quite well.
Closing this. Feel free to create a new issue if there are any more questions to be answered.