diff --git a/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs index 90e132a652..084ef16588 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs @@ -485,6 +485,37 @@ await SetupAndRunRestApiTest( ); } + /// + /// Tests that a PATCH request with an invalid If-Match header value + /// (anything other than "*") returns a 400 Bad Request response + /// because ETags are not supported. + /// + [TestMethod] + public virtual async Task PatchOne_Update_InvalidIfMatchHeader_Returns400_Test() + { + Dictionary headerDictionary = new(); + headerDictionary.Add("If-Match", "\"abc123\""); + string requestBody = @" + { + ""title"": ""The Hobbit Returns to The Shire"", + ""publisher_id"": 1234 + }"; + + await SetupAndRunRestApiTest( + primaryKeyRoute: "id/1", + queryString: null, + entityNameOrPath: _integrationEntityName, + sqlQuery: string.Empty, + operationType: EntityActionOperation.UpsertIncremental, + headers: new HeaderDictionary(headerDictionary), + requestBody: requestBody, + exceptionExpected: true, + expectedErrorMessage: "Etags not supported, use '*'", + expectedStatusCode: HttpStatusCode.BadRequest, + expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest.ToString() + ); + } + /// /// Test to validate successful execution of PATCH operation which satisfies the database policy for the update operation it resolves into. /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs index 5ee3654897..9989eac099 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs @@ -1114,6 +1114,37 @@ await SetupAndRunRestApiTest( ); } + /// + /// Tests that a PUT request with an invalid If-Match header value + /// (anything other than "*") returns a 400 Bad Request response + /// because ETags are not supported. + /// + [TestMethod] + public virtual async Task PutOne_Update_InvalidIfMatchHeader_Returns400_Test() + { + Dictionary headerDictionary = new(); + headerDictionary.Add("If-Match", "\"abc123\""); + string requestBody = @" + { + ""title"": ""The Return of the King"", + ""publisher_id"": 1234 + }"; + + await SetupAndRunRestApiTest( + primaryKeyRoute: "id/1", + queryString: null, + entityNameOrPath: _integrationEntityName, + sqlQuery: string.Empty, + operationType: EntityActionOperation.Upsert, + headers: new HeaderDictionary(headerDictionary), + requestBody: requestBody, + exceptionExpected: true, + expectedErrorMessage: "Etags not supported, use '*'", + expectedStatusCode: HttpStatusCode.BadRequest, + expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest.ToString() + ); + } + /// /// Tests that a PUT request with If-Match header (strict update semantics) /// still requires a primary key route. When If-Match is present, the operation diff --git a/src/Service/Controllers/RestController.cs b/src/Service/Controllers/RestController.cs index 48a1b98e49..2fadc636d0 100644 --- a/src/Service/Controllers/RestController.cs +++ b/src/Service/Controllers/RestController.cs @@ -161,7 +161,7 @@ public async Task Upsert( { return await HandleOperation( route, - DeterminePatchPutSemantics(EntityActionOperation.Upsert)); + EntityActionOperation.Upsert); } /// @@ -181,7 +181,7 @@ public async Task UpsertIncremental( { return await HandleOperation( route, - DeterminePatchPutSemantics(EntityActionOperation.UpsertIncremental)); + EntityActionOperation.UpsertIncremental); } /// @@ -206,6 +206,11 @@ private async Task HandleOperation( { TelemetryMetricsHelper.IncrementActiveRequests(ApiType.REST); + if (operationType is EntityActionOperation.Upsert or EntityActionOperation.UpsertIncremental) + { + operationType = DeterminePatchPutSemantics(operationType); + } + if (activity is not null) { activity.TrackMainControllerActivityStarted(