200 / 204 would be correct, and providing the "no operation" would be even better. But definitely not a 400 - because you're causing the script or application to fail because of their previous state - and RESTful methodology would say that is wrong...
Like you said, 200 / 204 would be correct, and providing the "no operation" would be even better. So this means you more expect 200 + "no operation" message instead of 204 No Content?
Like you said, 200 / 204 would be correct, and providing the "no operation" would be even better. So this means you more expect 200 + "no operation" message instead of 204 No Content?
Thanks, Archer.
Yes, and looking at the Specification, that is also consistent with the statements shown for Action responses where nothing is changed. Respond with HTTP 200 and the `NoOperation` message from the Base message registry.
For every service, if we PATCH multiple properties. Are our case correct?
[case1] In a Request: 1. PATCH same value for property A 2. PATCH same value for property B 3. and so on... >> Return 200 + NoOperation message.
[case2] In a Request: 1. PATCH same value for property A 2. PATCH same value for property B 3. PATCH invalid value for property C >> Return 400 + Error Message for property C (We don't need to show NoOperation message for A & B).
[case3] In a Request: 1. PATCH same value for property A 2. PATCH same value for property B 3. PATCH valid value for property C >> Return 204 No Content (We don't need to show NoOperation message for A & B).
[case4] In a Request: 1. PATCH same value for property A 2. PATCH same value for property B 3. PATCH valid value for property C 4. PATCH invalid value for property D >> Return 200 + Error Message for property D (We don't need to show NoOperation message for A & B).
Last Edit: Apr 27, 2022 2:57:18 GMT by AMI_archerwen
That looks correct although for [case3] we would want to see a 200 along with the updated payload in that response, since the resource was changed by the successful PATCH of "property C".
We list more case and would like to confirm with you the correct behavior. Hope you can guide us to figure out it.
We might have two kind of messages format to correspond the status code 200 or 400. (1) error.@message.ExtendedInfo: { "error": { "@message.ExtendedInfo": [ { correct_message_for_some_property } ], "code": "xxx.1.0.xxx", "message": "string" } } >> This format is for 400 status code.
(2) @message.ExtendedInfo: "@message.ExtendedInfo": [ { correct_message_for_some_property } ] >> This format is for 200 status code.
[case1] In a Request: 1. PATCH same value for property A 2. PATCH same value for property B >> Return 200 + NoOperation message.
[case2] In a Request: 1. PATCH same value for property A 2. PATCH same value for property B 3. PATCH invalid value for property C >> Return 400 + error.@message.ExtendedInfo(only for property C)
[case3] In a Request: 1. PATCH same value for property A 2. PATCH same value for property B 3. PATCH valid value for property C >> Return 204 No Content
[case4] In a Request: 1. PATCH same value for property A 2. PATCH same value for property B 3. PATCH valid value for property C 4. PATCH invalid value for property D >> Return 200 + correct response body(property C changed) + @message.ExtendedInfo(only for property D)
[case5] In a Request: 1. PATCH valid value for property A >> Return 204
[case6] In a Request: 1. PATCH invalid value for property A >> Return 400 + error.@message.ExtendedInfo(for property A)
[case7] In a Request: 1. PATCH valid value for property A 2. PATCH invalid value for property B >> Return 200 + correct response body(property B changed) + @message.ExtendedInfo(only for property B)
[case8] In a Request: empty table without property >> Return 200 + NoOperation message
Also I saw the spec have a place that defined 400 + NoOperation message. But this is different with 200 + NoOperation message. Is this a special case? or we can choose what status code (200 or 400) for NoOperation message?
Your [case3] and [case5] should both be 200 with the modified payload returned as the response. That matches what you already show in [case7] where you return the payload for a partial success.
The others look to be correct.
The 400 + NoOperation statement was added when it was discovered that there valid payloads that would contain only "annotations", since a writeable "@odata.id" object is technically an "annotation". As we had to cover that case, we decided to give more explicit guidance since those messages have been defined (they were not all defined in the early days of the specification). We certainly wanted to encourage error responses to include some message - hopefully a standard one - rather than just an HTTP response code - to help users figure out the problem.
1. About [case3] and [case5], we might keep return 204 because this is also the one of response defined in spec. We always return 204 before, so we hope to not make confusion to users as much as possible. Unless this is not acceptable?
2. About the 400 + NoOperation So you mean if we provide Odata annotations to our every case (case1 - 8), it doesn't affect our current result? The only condition is "Only Odata annotations in the request".
3. Also I have one more doubt for another case. [case9] In a Request: 1. PATCH same value for array property A >> Is this also Return 200 + NoOperation message?
4. Could we display 200 + NoOperation message for every property? Example: { "error": { "@message.ExtendedInfo": [ { "@odata.type": "#Message.v1_0_8.Message", "Message": "The request body submitted contain no data to act upon and no changes to the resource took place.", "MessageArgs": [ "AccountLockoutDuration" ], "MessageId": "Base.1.5.NoOperation", "RelatedProperties": [ "#/AccountLockoutDuration" ], "Resolution": "Add properties in the JSON object and resubmit the request.", "Severity": "Warning" }, { "@odata.type": "#Message.v1_0_8.Message", "Message": "The request body submitted contain no data to act upon and no changes to the resource took place.", "MessageArgs": [ "AccountLockoutThreshold" ], "MessageId": "Base.1.5.NoOperation", "RelatedProperties": [ "#/AccountLockoutThreshold" ], "Resolution": "Add properties in the JSON object and resubmit the request.", "Severity": "Warning" } ], "code": "Base.1.5.GeneralError", "message": "A general error has occurred. See Resolution for information on how to resolve the error." } }
Last Edit: May 6, 2022 10:40:05 GMT by AMI_archerwen
1. About [case3] and [case5], we might keep return 204 because this is also the one of response defined in spec. We always return 204 before, so we hope to not make confusion to users as much as possible. Unless this is not acceptable?
Yes, returning a 204 is acceptable here and it is more efficient for the service (assuming the client can assume that nothing else changed in the resource).
2. About the 400 + NoOperation So you mean if we provide Odata annotations to our every case (case1 - 8), it doesn't affect our current result? The only condition is "Only Odata annotations in the request".
Correct. The corner case of "only OData annotations" is called out separately (and I can't remember why, it may have just been something that was realized early on in the development of the specification before we had explained all of these PATCH cases).
3. Also I have one more doubt for another case. [case9] In a Request: 1. PATCH same value for array property A >> Is this also Return 200 + NoOperation message?
Yes.
4. Could we display 200 + NoOperation message for every property? Example: { "error": { "@message.ExtendedInfo": [ { "@odata.type": "#Message.v1_0_8.Message", "Message": "The request body submitted contain no data to act upon and no changes to the resource took place.", "MessageArgs": [ "AccountLockoutDuration" ], "MessageId": "Base.1.5.NoOperation", "RelatedProperties": [ "#/AccountLockoutDuration" ], "Resolution": "Add properties in the JSON object and resubmit the request.", "Severity": "Warning" }, { "@odata.type": "#Message.v1_0_8.Message", "Message": "The request body submitted contain no data to act upon and no changes to the resource took place.", "MessageArgs": [ "AccountLockoutThreshold" ], "MessageId": "Base.1.5.NoOperation", "RelatedProperties": [ "#/AccountLockoutThreshold" ], "Resolution": "Add properties in the JSON object and resubmit the request.", "Severity": "Warning" } ], "code": "Base.1.5.GeneralError", "message": "A general error has occurred. See Resolution for information on how to resolve the error." } }
If this is a case where the same value was supplied (so no operation on those), but another property had an invalid value, or caused some error, then yes, that would be fine. That would be a case of partial success - if the first 3 PATCH properties succeeded, but the 4th one failed - this would be a similar response. But in this case, those first 3 "didn't do anything".
About 4, If the case is "PATCH same value for all property", we still can display for every properties?
Yes, you certainly can. If that reduces the code paths, then it's a reasonable answer.
Thanks for the reply.
But I have one doubt if we PATCH same value for array property, how do we shows the message in this situation?
For example, we have an array property like below. "SupportedCollectionFunctions": [ "Average", "Maximum", "Summation", "Minimum" ]
Ex1. { "error": { "@message.ExtendedInfo": [ { "@odata.type": "#Message.v1_0_8.Message", "Message": "The request body submitted contain no data to act upon and no changes to the resource took place.", "MessageArgs": [ "SupportedCollectionFunctions/1" ], "MessageId": "Base.1.5.NoOperation", "RelatedProperties": [ "#/SupportedCollectionFunctions/1" ], "Resolution": "Add properties in the JSON object and resubmit the request.", "Severity": "Warning" }, { "@odata.type": "#Message.v1_0_8.Message", "Message": "The request body submitted contain no data to act upon and no changes to the resource took place.", "MessageArgs": [ "SupportedCollectionFunctions/2" ], "MessageId": "Base.1.5.NoOperation", "RelatedProperties": [ "#/SupportedCollectionFunctions/2" ], "Resolution": "Add properties in the JSON object and resubmit the request.", "Severity": "Warning" }, { "@odata.type": "#Message.v1_0_8.Message", "Message": "The request body submitted contain no data to act upon and no changes to the resource took place.", "MessageArgs": [ "SupportedCollectionFunctions/3" ], "MessageId": "Base.1.5.NoOperation", "RelatedProperties": [ "#/SupportedCollectionFunctions/3" ], "Resolution": "Add properties in the JSON object and resubmit the request.", "Severity": "Warning" }, { "@odata.type": "#Message.v1_0_8.Message", "Message": "The request body submitted contain no data to act upon and no changes to the resource took place.", "MessageArgs": [ "SupportedCollectionFunctions/4" ], "MessageId": "Base.1.5.NoOperation", "RelatedProperties": [ "#/SupportedCollectionFunctions/4" ], "Resolution": "Add properties in the JSON object and resubmit the request.", "Severity": "Warning" } ], "code": "Base.1.5.GeneralError", "message": "A general error has occurred. See Resolution for information on how to resolve the error." } }
Ex2. { "error": { "@message.ExtendedInfo": [ { "@odata.type": "#Message.v1_0_8.Message", "Message": "The request body submitted contain no data to act upon and no changes to the resource took place.", "MessageArgs": [ "SupportedCollectionFunctions" ], "MessageId": "Base.1.5.NoOperation", "RelatedProperties": [ "#/SupportedCollectionFunctions" ], "Resolution": "Add properties in the JSON object and resubmit the request.", "Severity": "Warning" } ], "code": "Base.1.5.NoOperation", "message": "The request body submitted contain no data to act upon and no changes to the resource took place." } }
I more prefer the Ex2, is this OK?
Thanks, Archer.
Last Edit: May 25, 2022 9:56:28 GMT by AMI_archerwen